diff --git a/dist/css/styles-min.css b/dist/css/styles-min.css index 1b4d3e6..72ecdca 100644 --- a/dist/css/styles-min.css +++ b/dist/css/styles-min.css @@ -1 +1 @@ -:root{--primary:#6366f1;--primary-hover:#4f46e5;--primary-light:#a5b4fc;--primary-dark:#3730a3;--secondary:#64748b;--secondary-hover:#475569;--success:#10b981;--success-light:#a7f3d0;--warning:#f59e0b;--warning-light:#fef3c7;--error:#ef4444;--error-light:#fecaca;--info:#3b82f6;--info-light:#bfdbfe;--gray-50:#f8fafc;--gray-100:#f1f5f9;--gray-200:#e2e8f0;--gray-300:#cbd5e1;--gray-400:#94a3b8;--gray-500:#64748b;--gray-600:#475569;--gray-700:#334155;--gray-800:#1e293b;--gray-900:#0f172a;--text-primary:var(--gray-900);--text-secondary:var(--gray-600);--text-tertiary:var(--gray-500);--text-muted:var(--gray-400);--bg-primary:#fff;--bg-secondary:var(--gray-50);--bg-tertiary:var(--gray-100);--bg-elevated:#fff;--border-primary:var(--gray-200);--border-secondary:var(--gray-300);--border-focus:var(--primary);--space-px:1px;--space-0-5:0.125rem;--space-1:0.25rem;--space-1-5:0.375rem;--space-2:0.5rem;--space-2-5:0.625rem;--space-3:0.75rem;--space-3-5:0.875rem;--space-4:1rem;--space-5:1.25rem;--space-6:1.5rem;--space-7:1.75rem;--space-8:2rem;--space-9:2.25rem;--space-10:2.5rem;--space-11:2.75rem;--space-12:3rem;--space-14:3.5rem;--space-16:4rem;--space-20:5rem;--space-24:6rem;--space-28:7rem;--space-32:8rem;--text-xs:0.75rem;--text-sm:0.875rem;--text-base:1rem;--text-lg:1.125rem;--text-xl:1.25rem;--text-2xl:1.5rem;--text-3xl:1.875rem;--text-4xl:2.25rem;--text-5xl:3rem;--text-6xl:3.75rem;--text-7xl:4.5rem;--text-8xl:6rem;--text-9xl:8rem;--font-thin:100;--font-extralight:200;--font-light:300;--font-normal:400;--font-medium:500;--font-semibold:600;--font-bold:700;--font-extrabold:800;--font-black:900;--radius-none:0;--radius-sm:0.125rem;--radius-base:0.25rem;--radius-md:0.375rem;--radius-lg:0.5rem;--radius-xl:0.75rem;--radius-2xl:1rem;--radius-3xl:1.5rem;--radius-full:9999px;--shadow-xs:0 1px 2px 0 rgb(0 0 0 / 0.05);--shadow-sm:0 1px 3px 0 rgb(0 0 0 / 0.1),0 1px 2px -1px rgb(0 0 0 / 0.1);--shadow-md:0 4px 6px -1px rgb(0 0 0 / 0.1),0 2px 4px -2px rgb(0 0 0 / 0.1);--shadow-lg:0 10px 15px -3px rgb(0 0 0 / 0.1),0 4px 6px -4px rgb(0 0 0 / 0.1);--shadow-xl:0 20px 25px -5px rgb(0 0 0 / 0.1),0 8px 10px -6px rgb(0 0 0 / 0.1);--shadow-2xl:0 25px 50px -12px rgb(0 0 0 / 0.25);--shadow-inner:inset 0 2px 4px 0 rgb(0 0 0 / 0.05);--shadow-focus:0 0 0 3px rgb(99 102 241 / 0.1);--transition-all:all 0.2s cubic-bezier(0.4, 0, 0.2, 1);--transition-fast:0.15s cubic-bezier(0.4, 0, 0.2, 1);--transition-normal:0.2s cubic-bezier(0.4, 0, 0.2, 1);--transition-slow:0.3s cubic-bezier(0.4, 0, 0.2, 1);--transition-bounce:0.4s cubic-bezier(0.68, -0.55, 0.265, 1.55);--container-max-width:1280px;--header-height:4.5rem;--content-max-width:65ch;--z-hide:-1;--z-auto:auto;--z-base:0;--z-docked:10;--z-dropdown:1000;--z-sticky:1020;--z-banner:1030;--z-overlay:1040;--z-modal:1050;--z-popover:1060;--z-skiplink:1070;--z-toast:1080;--z-tooltip:1090}[data-theme=dark]{--text-primary:var(--gray-50);--text-secondary:var(--gray-300);--text-tertiary:var(--gray-400);--text-muted:var(--gray-500);--bg-primary:var(--gray-900);--bg-secondary:var(--gray-800);--bg-tertiary:var(--gray-700);--bg-elevated:var(--gray-800);--border-primary:var(--gray-700);--border-secondary:var(--gray-600);--border-focus:var(--primary-light);--primary:#818cf8;--primary-hover:#a5b4fc;--primary-light:#c7d2fe;--primary-dark:#6366f1;--shadow-xs:0 1px 2px 0 rgb(0 0 0 / 0.3);--shadow-sm:0 1px 3px 0 rgb(0 0 0 / 0.4),0 1px 2px -1px rgb(0 0 0 / 0.4);--shadow-md:0 4px 6px -1px rgb(0 0 0 / 0.4),0 2px 4px -2px rgb(0 0 0 / 0.4);--shadow-lg:0 10px 15px -3px rgb(0 0 0 / 0.4),0 4px 6px -4px rgb(0 0 0 / 0.4);--shadow-xl:0 20px 25px -5px rgb(0 0 0 / 0.4),0 8px 10px -6px rgb(0 0 0 / 0.4);--shadow-2xl:0 25px 50px -12px rgb(0 0 0 / 0.6);--shadow-focus:0 0 0 3px rgb(129 140 248 / 0.2)}*,::after,::before{box-sizing:border-box;margin:0;padding:0}html{scroll-behavior:smooth;font-size:16px;line-height:1.6;-webkit-text-size-adjust:100%}body{font-family:Inter,system-ui,-apple-system,BlinkMacSystemFont,'Segoe UI',Roboto,sans-serif;font-feature-settings:'cv01','cv03','cv04','cv11';font-variation-settings:'opsz' 32;background-color:var(--bg-primary);color:var(--text-primary);transition:background-color var(--transition-normal),color var(--transition-normal);-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;text-rendering:optimizeLegibility;min-height:100vh;overflow-x:hidden}:focus{outline:2px solid var(--border-focus);outline-offset:2px}:focus:not(:focus-visible){outline:0}:focus-visible{outline:2px solid var(--border-focus);outline-offset:2px}h1,h2,h3,h4,h5,h6{font-weight:var(--font-bold);line-height:1.25;letter-spacing:-.025em;color:var(--text-primary)}h1{font-size:var(--text-4xl);font-weight:var(--font-extrabold)}h2{font-size:var(--text-3xl);font-weight:var(--font-bold)}h3{font-size:var(--text-2xl);font-weight:var(--font-semibold)}p{line-height:1.75;margin-bottom:var(--space-4)}a{color:var(--primary);text-decoration:none;transition:var(--transition-all)}a:hover{color:var(--primary-hover);text-decoration:none}.page-wrapper{min-height:100vh;display:flex;flex-direction:column;position:relative}.container{max-width:var(--container-max-width);margin:0 auto;padding:0 var(--space-6);width:100%}.main-content{flex:1;position:relative}.site-header{position:sticky;top:0;z-index:var(--z-sticky);background:rgb(255 255 255 / .8);backdrop-filter:blur(20px) saturate(180%);border-bottom:1px solid var(--border-primary);height:var(--header-height);transition:var(--transition-all)}[data-theme=dark] .site-header{background:rgb(15 23 42 / .8)}.header-content{display:flex;align-items:center;justify-content:space-between;height:var(--header-height);gap:var(--space-8)}.site-title{display:flex;align-items:center;gap:var(--space-2);font-size:var(--text-xl);font-weight:var(--font-bold);color:var(--text-primary);text-decoration:none;transition:var(--transition-all);position:relative}.site-title:hover{color:var(--primary);transform:translateY(-1px)}.site-title:focus-visible{border-radius:var(--radius-md);padding:var(--space-1) var(--space-2);margin:calc(-1 * var(--space-1)) calc(-1 * var(--space-2))}.logo-icon{font-size:var(--text-2xl);filter:drop-shadow(0 2px 4px rgb(99 102 241 / .2));transition:var(--transition-all)}.site-title:hover .logo-icon{transform:rotate(-5deg) scale(1.1)}.header-nav{display:flex;align-items:center;gap:var(--space-6)}.nav-link{position:relative;display:inline-flex;align-items:center;padding:var(--space-2) var(--space-3);font-size:var(--text-sm);font-weight:var(--font-medium);color:var(--text-secondary);text-decoration:none;border-radius:var(--radius-lg);transition:var(--transition-all);white-space:nowrap}.nav-link::before{content:'';position:absolute;bottom:-2px;left:50%;width:0;height:2px;background:var(--primary);border-radius:var(--radius-full);transition:var(--transition-all);transform:translateX(-50%)}.nav-link:hover{color:var(--primary);background:var(--bg-secondary);transform:translateY(-1px)}.nav-link:hover::before{width:70%}.nav-link:focus-visible{box-shadow:var(--shadow-focus)}.dark-mode-toggle{display:flex;align-items:center;justify-content:center;width:2.75rem;height:2.75rem;border:2px solid var(--border-primary);border-radius:var(--radius-full);background:var(--bg-primary);color:var(--text-primary);cursor:pointer;transition:var(--transition-all);position:relative;overflow:hidden}.dark-mode-toggle:hover{background:var(--bg-secondary);border-color:var(--primary);transform:scale(1.05);box-shadow:var(--shadow-md)}.dark-mode-toggle:focus-visible{box-shadow:var(--shadow-focus)}.moon-icon,.sun-icon{transition:var(--transition-all);position:absolute}.moon-icon{display:none;transform:rotate(180deg)}[data-theme=dark] .sun-icon{display:none}[data-theme=dark] .moon-icon{display:block;transform:rotate(0)}.hero-section{position:relative;padding:var(--space-24) 0 var(--space-20);background:linear-gradient(135deg,var(--bg-primary) 0,var(--bg-secondary) 100%);overflow:hidden}.hero-section::before{content:'';position:absolute;inset:0;background:radial-gradient(circle at 30% 20%,rgb(99 102 241 / .1) 0,transparent 50%),radial-gradient(circle at 70% 80%,rgb(99 102 241 / .05) 0,transparent 50%);pointer-events:none}[data-theme=dark] .hero-section{background:linear-gradient(135deg,var(--bg-primary) 0,var(--bg-secondary) 100%)}[data-theme=dark] .hero-section::before{background:radial-gradient(circle at 30% 20%,rgb(129 140 248 / .15) 0,transparent 50%),radial-gradient(circle at 70% 80%,rgb(129 140 248 / .08) 0,transparent 50%)}.hero-content{text-align:center;max-width:900px;margin:0 auto;position:relative;z-index:1;animation:fadeInUp .8s ease-out}@keyframes fadeInUp{from{opacity:0;transform:translateY(30px)}to{opacity:1;transform:translateY(0)}}.hero-title{font-size:clamp(var(--text-3xl), 8vw, var(--text-6xl));font-weight:var(--font-extrabold);line-height:1.1;margin:0 0 var(--space-6);color:var(--text-primary);letter-spacing:-.02em}.gradient-text{background:linear-gradient(135deg,var(--primary) 0,#8b5cf6 100%);-webkit-background-clip:text;-webkit-text-fill-color:transparent;background-clip:text;position:relative}[data-theme=dark] .gradient-text{background:linear-gradient(135deg,var(--primary-light) 0,#c4b5fd 100%);-webkit-background-clip:text;-webkit-text-fill-color:transparent;background-clip:text}.hero-description{font-size:clamp(var(--text-lg), 4vw, var(--text-xl));color:var(--text-secondary);margin:0 0 var(--space-10);max-width:650px;margin-left:auto;margin-right:auto;line-height:1.6}.hero-actions{display:flex;gap:var(--space-4);justify-content:center;margin-bottom:var(--space-16);flex-wrap:wrap}.hero-stats{display:flex;gap:var(--space-12);justify-content:center;flex-wrap:wrap}.stat-item{text-align:center;position:relative}.stat-item:not(:last-child)::after{content:'';position:absolute;right:calc(-1 * var(--space-6));top:50%;transform:translateY(-50%);width:1px;height:40px;background:var(--border-primary)}.stat-number{display:block;font-size:clamp(var(--text-2xl), 6vw, var(--text-4xl));font-weight:var(--font-extrabold);color:var(--primary);margin-bottom:var(--space-1);background:linear-gradient(135deg,var(--primary) 0,#8b5cf6 100%);-webkit-background-clip:text;-webkit-text-fill-color:transparent;background-clip:text}.stat-label{font-size:var(--text-sm);color:var(--text-secondary);text-transform:uppercase;letter-spacing:.1em;font-weight:var(--font-medium)}.btn{display:inline-flex;align-items:center;gap:var(--space-2);padding:var(--space-4) var(--space-8);border:2px solid transparent;border-radius:var(--radius-xl);font-size:var(--text-base);font-weight:var(--font-semibold);text-decoration:none;cursor:pointer;transition:var(--transition-all);white-space:nowrap;position:relative;overflow:hidden;text-align:center;min-width:140px;justify-content:center}.btn::before{content:'';position:absolute;top:0;left:-100%;width:100%;height:100%;background:linear-gradient(90deg,transparent,rgb(255 255 255 / .2),transparent);transition:left .5s}.btn:hover::before{left:100%}.btn-primary{background:linear-gradient(135deg,var(--primary) 0,var(--primary-dark) 100%);color:#fff;box-shadow:var(--shadow-md)}.btn-primary:hover{background:linear-gradient(135deg,var(--primary-hover) 0,var(--primary) 100%);transform:translateY(-2px);box-shadow:var(--shadow-lg)}.btn-primary:focus-visible{box-shadow:var(--shadow-focus),var(--shadow-lg)}.btn-secondary{background:0 0;color:var(--text-primary);border:2px solid var(--border-primary)}.btn-secondary:hover{border-color:var(--primary);color:var(--primary);background:var(--bg-secondary);transform:translateY(-2px);box-shadow:var(--shadow-md)}.btn-secondary:focus-visible{box-shadow:var(--shadow-focus)}.quick-nav{padding:var(--space-20) 0;background:var(--bg-primary);position:relative}.quick-nav-grid{display:grid;grid-template-columns:repeat(auto-fit,minmax(280px,1fr));gap:var(--space-8)}.quick-nav-card{display:block;padding:var(--space-8);background:var(--bg-elevated);border:2px solid var(--border-primary);border-radius:var(--radius-2xl);text-decoration:none;transition:var(--transition-all);position:relative;overflow:hidden;box-shadow:var(--shadow-sm);backdrop-filter:blur(10px)}.quick-nav-card::before{content:'';position:absolute;inset:0;background:linear-gradient(135deg,var(--primary) 0,transparent 100%);opacity:0;transition:var(--transition-all);z-index:0}.quick-nav-card:hover::before{opacity:.08}.quick-nav-card:hover{border-color:var(--primary);transform:translateY(-6px) scale(1.02);box-shadow:var(--shadow-xl)}.quick-nav-card:focus-visible{box-shadow:var(--shadow-focus),var(--shadow-lg)}.quick-nav-card>*{position:relative;z-index:1}.quick-nav-icon{font-size:var(--text-4xl);margin-bottom:var(--space-4);display:block;filter:drop-shadow(0 2px 4px rgb(0 0 0 / .1));transition:var(--transition-all)}.quick-nav-card:hover .quick-nav-icon{transform:scale(1.1) rotate(-5deg)}.quick-nav-card h3{margin:0 0 var(--space-3);font-size:var(--text-xl);font-weight:var(--font-bold);color:var(--text-primary)}.quick-nav-card p{margin:0;color:var(--text-secondary);font-size:var(--text-base);line-height:1.6}.quick-nav-card a:hover{text-decoration:none}.section{padding:var(--space-24) 0;position:relative}.section:nth-child(2n){background:var(--bg-secondary)}.section-header{text-align:center;margin-bottom:var(--space-20);animation:fadeInUp .6s ease-out}.section-title{font-size:clamp(var(--text-3xl), 6vw, var(--text-5xl));font-weight:var(--font-extrabold);margin:0 0 var(--space-6);color:var(--text-primary);letter-spacing:-.02em}.section-description{font-size:clamp(var(--text-base), 3vw, var(--text-xl));color:var(--text-secondary);margin:0;max-width:700px;margin-inline:auto;line-height:1.7}.data-table-container{background:var(--bg-elevated);border-radius:var(--radius-2xl);box-shadow:var(--shadow-xl);border:1px solid var(--border-primary);margin:var(--space-8) 0;position:relative;overflow:hidden;backdrop-filter:blur(10px)}.table-wrapper{overflow-x:auto;overflow-y:visible;border-radius:var(--radius-2xl);-webkit-overflow-scrolling:touch;scrollbar-width:thin;scrollbar-color:var(--primary) var(--bg-secondary)}.table-wrapper::-webkit-scrollbar{height:10px}.table-wrapper::-webkit-scrollbar-track{background:var(--bg-secondary);border-radius:var(--radius-md)}.table-wrapper::-webkit-scrollbar-thumb{background:var(--primary);border-radius:var(--radius-md);border:2px solid var(--bg-secondary)}.table-wrapper::-webkit-scrollbar-thumb:hover{background:var(--primary-hover)}table{width:100%;border-collapse:collapse;font-size:var(--text-sm);min-width:600px}td,th{padding:var(--space-4) var(--space-6);text-align:left;border-bottom:1px solid var(--border-primary);white-space:nowrap}th{background:var(--primary);color:#fff;font-weight:var(--font-semibold);text-transform:uppercase;letter-spacing:.05em;font-size:var(--text-xs);position:sticky;top:0;z-index:var(--z-sticky)}th:first-child{position:sticky;left:0;z-index:calc(var(--z-sticky) + 1);background:var(--primary)}tr:hover{background:var(--bg-secondary)}td{transition:all var(--transition-fast)}td:first-child{font-weight:var(--font-medium);position:sticky;left:0;background:var(--bg-primary);z-index:1}tr:hover td:first-child{background:var(--bg-secondary)}.status-cell{text-align:center!important}.status-indicator{display:inline-flex;align-items:center;justify-content:center;width:24px;height:24px;border-radius:var(--radius-full);transition:all var(--transition-fast)}.status-indicator.supported{background:rgb(14 236 162 / .1);color:var(--success)}.status-indicator.not-supported{background:rgb(211 29 29 / .1);color:var(--error)}.status-indicator svg{width:16px;height:16px}.search-section{margin-bottom:var(--space-8)}.search-container.enhanced{position:relative;max-width:500px;margin:0 auto}.search-icon{position:absolute;left:var(--space-4);top:50%;transform:translateY(-50%);color:var(--text-tertiary);z-index:1}.search-input{width:100%;padding:var(--space-4) var(--space-12) var(--space-4) var(--space-12);border:2px solid var(--border-primary);border-radius:var(--radius-full);font-size:var(--text-base);background:var(--bg-primary);color:var(--text-primary);transition:all var(--transition-fast);outline:0}.search-input:focus{border-color:var(--primary);box-shadow:0 0 0 3px rgb(99 102 241 / .1)}.clear-icon{position:absolute;right:var(--space-4);top:50%;transform:translateY(-50%);background:0 0;border:none;color:var(--text-tertiary);cursor:pointer;padding:var(--space-1);border-radius:var(--radius-md);transition:all var(--transition-fast);opacity:0;visibility:hidden}.search-input:focus+.clear-icon,.search-input:not(:placeholder-shown)+.clear-icon{opacity:1;visibility:visible}.clear-icon:hover{background:var(--bg-secondary);color:var(--text-primary)}.search-results{text-align:center;padding:var(--space-2) 0;color:var(--text-secondary);font-size:var(--text-sm);margin-bottom:var(--space-4)}.compare-controls{display:flex;align-items:end;gap:var(--space-6);margin-bottom:var(--space-12);flex-wrap:wrap}.compare-select-group{flex:1;min-width:200px}.compare-select-group label{display:block;margin-bottom:var(--space-2);font-weight:var(--font-medium);color:var(--text-primary)}.select-wrapper{position:relative}.select-wrapper::after{content:'';position:absolute;right:var(--space-4);top:50%;transform:translateY(-50%);width:0;height:0;border-left:5px solid transparent;border-right:5px solid transparent;border-top:5px solid var(--text-tertiary);pointer-events:none}select{width:100%;padding:var(--space-3) var(--space-8) var(--space-3) var(--space-4);border:2px solid var(--border-primary);border-radius:var(--radius-lg);background:var(--bg-primary);color:var(--text-primary);font-size:var(--text-base);cursor:pointer;appearance:none;transition:all var(--transition-fast)}select:focus{outline:0;border-color:var(--primary);box-shadow:0 0 0 3px rgb(99 102 241 / .1)}.compare-vs{flex-shrink:0;font-size:var(--text-lg);font-weight:var(--font-bold);color:var(--primary);background:var(--bg-secondary);padding:var(--space-3) var(--space-4);border-radius:var(--radius-lg);border:2px solid var(--border-primary);margin-bottom:var(--space-2)}#compare-table-container{position:relative;background:var(--bg-primary);border-radius:var(--radius-xl);box-shadow:var(--shadow-lg);border:1px solid var(--border-primary);margin-top:var(--space-6);display:none}.comparison-visible{display:block!important;animation:slideIn .3s ease-out}.comparison-hiding{animation:slideOut .3s ease-in}@keyframes slideIn{from{opacity:0;transform:translateY(-20px)}to{opacity:1;transform:translateY(0)}}@keyframes slideOut{from{opacity:1;transform:translateY(0)}to{opacity:0;transform:translateY(-20px)}}.comparison-header{padding:var(--space-6);border-bottom:1px solid var(--border-primary);background:var(--bg-secondary);border-radius:var(--radius-xl) var(--radius-xl) 0 0}.comparison-header h3{margin:0 0 var(--space-4);font-size:var(--text-2xl);font-weight:var(--font-bold);color:var(--text-primary);text-align:center}.comparison-stats{display:flex;gap:var(--space-6);justify-content:center;margin-bottom:var(--space-6);flex-wrap:wrap}.comparison-stats .stat{text-align:center;background:var(--bg-primary);padding:var(--space-3) var(--space-4);border-radius:var(--radius-lg);border:1px solid var(--border-primary);min-width:100px}.stat-label{display:block;font-size:var(--text-xs);color:var(--text-secondary);text-transform:uppercase;letter-spacing:.05em;margin-bottom:var(--space-1)}.stat-value{display:block;font-size:var(--text-xl);font-weight:var(--font-bold);color:var(--primary)}.comparison-actions{display:flex;justify-content:center;gap:var(--space-3)}.comparison-filters{padding:var(--space-4) var(--space-6);background:var(--bg-tertiary);border-bottom:1px solid var(--border-primary);display:flex;gap:var(--space-6);justify-content:center;flex-wrap:wrap}.filter-option{display:flex;align-items:center;gap:var(--space-2);cursor:pointer;font-size:var(--text-sm);font-weight:var(--font-medium);color:var(--text-primary)}.filter-option input[type=radio]{margin:0}.filter-results{text-align:center;padding:var(--space-2) 0;color:var(--text-secondary);font-size:var(--text-sm);background:var(--bg-secondary);border-bottom:1px solid var(--border-primary)}.comparison-table{width:100%;border-collapse:collapse;font-size:var(--text-sm);min-width:700px}.comparison-table td,.comparison-table th{padding:var(--space-4) var(--space-6);border-bottom:1px solid var(--border-primary);text-align:center}.comparison-table td:first-child,.comparison-table th:first-child{text-align:left;font-weight:var(--font-medium)}.comparison-table th{background:var(--primary);color:#fff;font-weight:var(--font-semibold);text-transform:uppercase;letter-spacing:.05em;font-size:var(--text-xs);position:sticky;top:0;z-index:var(--z-sticky)}.provider-header{position:relative}.comparison-row.both-supported{background:rgb(16 185 129 / .05)}.comparison-row.provider1-only{background:rgb(59 130 246 / .05)}.comparison-row.provider2-only{background:rgb(168 85 247 / .05)}.comparison-row.neither-supported{background:rgb(239 68 68 / .05)}.status-badge{display:inline-block;padding:var(--space-1) var(--space-3);border-radius:var(--radius-full);font-size:var(--text-xs);font-weight:var(--font-medium);text-transform:uppercase;letter-spacing:.05em}.status-badge.both-supported{background:rgb(16 185 129 / .1);color:var(--success)}.status-badge.provider1-only{background:rgb(59 130 246 / .1);color:var(--info)}.status-badge.provider2-only{background:rgb(168 85 247 / .1);color:#8b5cf6}.status-badge.neither-supported{background:rgb(239 68 68 / .1);color:var(--error)}#close-compare{background:var(--bg-primary);border:1px solid var(--border-primary);border-radius:var(--radius-lg);padding:var(--space-2) var(--space-4);display:flex;align-items:center;gap:var(--space-2);cursor:pointer;transition:all var(--transition-fast);font-size:var(--text-sm);color:var(--text-primary);font-weight:var(--font-medium)}#close-compare:hover{background:var(--error);color:#fff;border-color:var(--error);transform:translateY(-1px)}.empty-state{text-align:center;padding:var(--space-16)}.empty-state-icon{font-size:var(--text-5xl);margin-bottom:var(--space-4)}.empty-state h3{margin:0 0 var(--space-2);font-size:var(--text-xl);color:var(--text-primary)}.empty-state p{margin:0;color:var(--text-secondary)}.warning-state{text-align:center;padding:var(--space-12);background:rgb(245 158 11 / .05);border-radius:var(--radius-lg);border:1px solid rgb(245 158 11 / .2)}.warning-icon{font-size:var(--text-4xl);margin-bottom:var(--space-3)}.warning-state h3{margin:0 0 var(--space-2);color:var(--warning)}.warning-state p{margin:0;color:var(--text-secondary)}.alert{display:flex;align-items:flex-start;gap:var(--space-3);padding:var(--space-4);border-radius:var(--radius-lg);margin:var(--space-4) 0}.alert-info{background:rgb(59 130 246 / .1);border:1px solid rgb(59 130 246 / .2);color:var(--info)}.alert-icon{flex-shrink:0;margin-top:2px}.referral-section{margin-block:var(--space-16);padding:var(--space-8);background:var(--bg-secondary);border-radius:var(--radius-xl);border:1px solid var(--border-primary);text-align:center}.referral-header h3{margin:0 0 var(--space-2);color:var(--text-primary);font-size:var(--text-2xl);font-weight:var(--font-bold)}.referral-header p{margin:0 auto var(--space-6);color:var(--text-secondary);max-width:var(--content-max-width)}.referral-grid{display:grid;grid-template-columns:repeat(auto-fit,minmax(180px,1fr));gap:var(--space-4);justify-items:center}.referral-card{display:flex;flex-direction:column;align-items:center;justify-content:center;gap:var(--space-2);padding:var(--space-4) var(--space-3);background:var(--bg-primary);border:1px solid var(--border-primary);border-radius:var(--radius-lg);text-decoration:none;transition:var(--transition-all);width:100%;max-width:200px;box-shadow:var(--shadow-sm)}.referral-card:hover{border-color:var(--primary);transform:translateY(-2px);box-shadow:var(--shadow-md)}.service-name{font-weight:var(--font-semibold);color:var(--text-primary);font-size:var(--text-base)}.referral-badge{font-size:var(--text-xs);color:var(--primary);background:rgb(99 102 241 / .1);padding:var(--space-1) var(--space-2);border-radius:var(--radius-md);font-weight:var(--font-medium)}.service-name{font-weight:var(--font-medium);color:var(--text-primary)}.status-grid{display:grid;grid-template-columns:repeat(auto-fit,minmax(280px,1fr));gap:var(--space-6)}.status-card{display:block;padding:var(--space-6);background:var(--bg-primary);border:1px solid var(--border-primary);border-radius:var(--radius-xl);text-decoration:none;transition:all var(--transition-normal)}.status-card:hover{border-color:var(--primary);transform:translateY(-2px);box-shadow:var(--shadow-lg)}.status-header{display:flex;align-items:center;justify-content:space-between;margin-bottom:var(--space-3)}.service-status-indicator{width:12px;height:12px;border-radius:var(--radius-full);background:var(--success);box-shadow:0 0 0 2px rgb(16 185 129 / .2)}.status-indicator.online{background:var(--success);box-shadow:0 0 0 2px rgb(16 185 129 / .2)}.status-card p{margin:0;color:var(--text-secondary);font-size:var(--text-sm)}.loading-state{display:flex;flex-direction:column;align-items:center;justify-content:center;padding:var(--space-12);color:var(--text-secondary)}.loading-spinner{width:32px;height:32px;border:3px solid var(--border-primary);border-top:3px solid var(--primary);border-radius:var(--radius-full);animation:spin 1s linear infinite;margin-bottom:var(--space-4)}@keyframes spin{0%{transform:rotate(0)}100%{transform:rotate(360deg)}}.site-footer{background:var(--bg-secondary);border-top:1px solid var(--border-primary);padding:var(--space-16) 0 var(--space-8);margin-top:auto}.footer-content{display:grid;grid-template-columns:repeat(auto-fit,minmax(250px,1fr));gap:var(--space-8);margin-bottom:var(--space-8)}.footer-section h4{margin:0 0 var(--space-4);font-size:var(--text-lg);font-weight:var(--font-semibold);color:var(--text-primary)}.footer-section p{margin:0;color:var(--text-secondary)}.footer-section ul{list-style:none;padding:0;margin:0}.footer-section li{margin-bottom:var(--space-2)}.footer-section a{color:var(--text-secondary);text-decoration:none;transition:color var(--transition-fast)}.footer-section a:hover{color:var(--primary)}.footer-bottom{text-align:center;padding-top:var(--space-8);border-top:1px solid var(--border-primary)}.footer-bottom p{margin:0;color:var(--text-tertiary);font-size:var(--text-sm)}.footer-bottom a{color:var(--primary);text-decoration:none}.back-to-top{position:fixed;bottom:var(--space-6);right:var(--space-6);width:48px;height:48px;background:var(--primary);color:#fff;border:none;border-radius:var(--radius-full);cursor:pointer;display:flex;align-items:center;justify-content:center;box-shadow:var(--shadow-lg);transition:all var(--transition-normal);opacity:0;visibility:hidden;transform:translateY(20px);z-index:var(--z-docked)}.back-to-top.visible{opacity:1;visibility:visible;transform:translateY(0)}.back-to-top:hover{background:var(--primary-hover);transform:translateY(-2px);box-shadow:var(--shadow-xl)}.loading-overlay{position:absolute;inset:0;background:rgb(255 255 255 / .9);backdrop-filter:blur(2px);display:flex;align-items:center;justify-content:center;z-index:var(--z-modal);opacity:0;visibility:hidden;transition:all var(--transition-normal)}[data-theme=dark] .loading-overlay{background:rgb(15 23 42 / .9)}.loading-overlay--visible{opacity:1;visibility:visible}.loading-overlay--hiding{opacity:0}.loading-content{text-align:center;color:var(--text-primary)}.spinner-ring{width:40px;height:40px;border:4px solid var(--border-primary);border-top:4px solid var(--primary);border-radius:var(--radius-full);animation:spin 1s linear infinite;margin:0 auto var(--space-3)}.loading-text{margin:0;font-size:var(--text-sm);color:var(--text-secondary)}@media (width <= 1024px){.container{padding:0 var(--space-4)}.comparison-stats{gap:var(--space-4)}.comparison-stats .stat{min-width:80px;padding:var(--space-2) var(--space-3)}}@media (width <= 768px){.header-nav{display:none}.hero-title{font-size:var(--text-3xl)}.hero-description{font-size:var(--text-lg)}.hero-actions{flex-direction:column;align-items:center}.hero-stats{gap:var(--space-6)}.section-title{font-size:var(--text-3xl)}.compare-controls{flex-direction:column}.compare-vs{align-self:center;margin:var(--space-2) 0}.quick-nav-grid{grid-template-columns:1fr}.footer-content{grid-template-columns:1fr;text-align:center}.data-table-container{margin:var(--space-2) calc(-1 * var(--space-4));border-radius:0;border-left:none;border-right:none}.table-wrapper{border-radius:0}table{font-size:var(--text-xs);min-width:500px}td,th{padding:var(--space-2) var(--space-3)}td:first-child,th:first-child{min-width:120px;max-width:150px;white-space:normal;word-break:break-word}.comparison-header{padding:var(--space-4)}.comparison-header h3{font-size:var(--text-lg)}.comparison-stats{flex-direction:column;gap:var(--space-3)}.comparison-stats .stat{margin:0 auto;max-width:200px}.comparison-filters{flex-direction:column;align-items:center;gap:var(--space-3)}.comparison-table{min-width:500px}.comparison-table td,.comparison-table th{padding:var(--space-2) var(--space-3);font-size:var(--text-xs)}td,th{padding:var(--space-3) var(--space-4)}.header-content{gap:var(--space-4)}.nav-link{padding:var(--space-1-5) var(--space-2);font-size:var(--text-xs)}}@media (width <= 480px){.hero-section{padding:var(--space-16) 0 var(--space-12)}.section{padding:var(--space-12) 0}.btn{width:100%;justify-content:center}.hero-stats{flex-direction:column;gap:var(--space-4)}.comparison-stats{gap:var(--space-2)}.comparison-stats .stat{min-width:60px;padding:var(--space-1) var(--space-2)}.stat-value{font-size:var(--text-lg)}.stat-label{font-size:10px}table{min-width:400px}td:first-child,th:first-child{min-width:100px;max-width:120px}.stat-item:not(:last-child)::after{display:none}}@media (width <= 640px){.container{padding:0 var(--space-4)}.hero-actions{flex-direction:column;align-items:center;gap:var(--space-3)}.hero-stats{gap:var(--space-8)}.nav-link{padding:var(--space-1-5) var(--space-2);font-size:var(--text-xs)}.btn{width:100%;max-width:280px;padding:var(--space-4) var(--space-6)}}@media print{#close-compare,.back-to-top,.comparison-actions,.comparison-filters,.dark-mode-toggle,.hero-section,.quick-nav,.referral-section,.site-footer,.site-header{display:none!important}.section{page-break-inside:avoid}.data-table-container{box-shadow:none;border:1px solid #000}.table-wrapper{overflow:visible}table{min-width:auto}td,th{border:1px solid #000}}@media (prefers-reduced-motion:reduce){*,::after,::before{animation-duration:0s!important;animation-iteration-count:1!important;transition-duration:0s!important}html{scroll-behavior:auto}}@media (prefers-contrast:high){:root{--border-primary:#000;--text-secondary:#000}[data-theme=dark]{--border-primary:#fff;--text-secondary:#fff}} \ No newline at end of file +:root{--primary:#6366f1;--primary-hover:#4f46e5;--primary-light:#a5b4fc;--primary-dark:#3730a3;--secondary:#64748b;--secondary-hover:#475569;--success:#10b981;--success-light:#a7f3d0;--warning:#f59e0b;--warning-light:#fef3c7;--error:#ef4444;--error-light:#fecaca;--info:#3b82f6;--info-light:#bfdbfe;--gray-50:#f8fafc;--gray-100:#f1f5f9;--gray-200:#e2e8f0;--gray-300:#cbd5e1;--gray-400:#94a3b8;--gray-500:#64748b;--gray-600:#475569;--gray-700:#334155;--gray-800:#1e293b;--gray-900:#0f172a;--text-primary:var(--gray-900);--text-secondary:var(--gray-600);--text-tertiary:var(--gray-500);--text-muted:var(--gray-400);--bg-primary:#fff;--bg-secondary:var(--gray-50);--bg-tertiary:var(--gray-100);--bg-elevated:#fff;--border-primary:var(--gray-200);--border-secondary:var(--gray-300);--border-focus:var(--primary);--space-px:1px;--space-0-5:0.125rem;--space-1:0.25rem;--space-1-5:0.375rem;--space-2:0.5rem;--space-2-5:0.625rem;--space-3:0.75rem;--space-3-5:0.875rem;--space-4:1rem;--space-5:1.25rem;--space-6:1.5rem;--space-7:1.75rem;--space-8:2rem;--space-9:2.25rem;--space-10:2.5rem;--space-11:2.75rem;--space-12:3rem;--space-14:3.5rem;--space-16:4rem;--space-20:5rem;--space-24:6rem;--space-28:7rem;--space-32:8rem;--text-xs:0.75rem;--text-sm:0.875rem;--text-base:1rem;--text-lg:1.125rem;--text-xl:1.25rem;--text-2xl:1.5rem;--text-3xl:1.875rem;--text-4xl:2.25rem;--text-5xl:3rem;--text-6xl:3.75rem;--text-7xl:4.5rem;--text-8xl:6rem;--text-9xl:8rem;--font-thin:100;--font-extralight:200;--font-light:300;--font-normal:400;--font-medium:500;--font-semibold:600;--font-bold:700;--font-extrabold:800;--font-black:900;--radius-none:0;--radius-sm:0.125rem;--radius-base:0.25rem;--radius-md:0.375rem;--radius-lg:0.5rem;--radius-xl:0.75rem;--radius-2xl:1rem;--radius-3xl:1.5rem;--radius-full:9999px;--shadow-xs:0 1px 2px 0 rgb(0 0 0 / 0.05);--shadow-sm:0 1px 3px 0 rgb(0 0 0 / 0.1),0 1px 2px -1px rgb(0 0 0 / 0.1);--shadow-md:0 4px 6px -1px rgb(0 0 0 / 0.1),0 2px 4px -2px rgb(0 0 0 / 0.1);--shadow-lg:0 10px 15px -3px rgb(0 0 0 / 0.1),0 4px 6px -4px rgb(0 0 0 / 0.1);--shadow-xl:0 20px 25px -5px rgb(0 0 0 / 0.1),0 8px 10px -6px rgb(0 0 0 / 0.1);--shadow-2xl:0 25px 50px -12px rgb(0 0 0 / 0.25);--shadow-inner:inset 0 2px 4px 0 rgb(0 0 0 / 0.05);--shadow-focus:0 0 0 3px rgb(99 102 241 / 0.1);--transition-all:all 0.2s cubic-bezier(0.4, 0, 0.2, 1);--transition-fast:0.15s cubic-bezier(0.4, 0, 0.2, 1);--transition-normal:0.2s cubic-bezier(0.4, 0, 0.2, 1);--transition-slow:0.3s cubic-bezier(0.4, 0, 0.2, 1);--transition-bounce:0.4s cubic-bezier(0.68, -0.55, 0.265, 1.55);--container-max-width:1280px;--header-height:4.5rem;--content-max-width:65ch;--z-hide:-1;--z-auto:auto;--z-base:0;--z-docked:10;--z-dropdown:1000;--z-sticky:1020;--z-banner:1030;--z-overlay:1040;--z-modal:1050;--z-popover:1060;--z-skiplink:1070;--z-toast:1080;--z-tooltip:1090}[data-theme=dark]{--text-primary:var(--gray-50);--text-secondary:var(--gray-300);--text-tertiary:var(--gray-400);--text-muted:var(--gray-500);--bg-primary:var(--gray-900);--bg-secondary:var(--gray-800);--bg-tertiary:var(--gray-700);--bg-elevated:var(--gray-800);--border-primary:var(--gray-700);--border-secondary:var(--gray-600);--border-focus:var(--primary-light);--primary:#818cf8;--primary-hover:#a5b4fc;--primary-light:#c7d2fe;--primary-dark:#6366f1;--shadow-xs:0 1px 2px 0 rgb(0 0 0 / 0.3);--shadow-sm:0 1px 3px 0 rgb(0 0 0 / 0.4),0 1px 2px -1px rgb(0 0 0 / 0.4);--shadow-md:0 4px 6px -1px rgb(0 0 0 / 0.4),0 2px 4px -2px rgb(0 0 0 / 0.4);--shadow-lg:0 10px 15px -3px rgb(0 0 0 / 0.4),0 4px 6px -4px rgb(0 0 0 / 0.4);--shadow-xl:0 20px 25px -5px rgb(0 0 0 / 0.4),0 8px 10px -6px rgb(0 0 0 / 0.4);--shadow-2xl:0 25px 50px -12px rgb(0 0 0 / 0.6);--shadow-focus:0 0 0 3px rgb(129 140 248 / 0.2)}*,::after,::before{box-sizing:border-box;margin:0;padding:0}html{scroll-behavior:smooth;font-size:16px;line-height:1.6;-webkit-text-size-adjust:100%}body{font-family:Inter,system-ui,-apple-system,BlinkMacSystemFont,'Segoe UI',Roboto,sans-serif;font-feature-settings:'cv01','cv03','cv04','cv11';font-variation-settings:'opsz' 32;background-color:var(--bg-primary);color:var(--text-primary);transition:background-color var(--transition-normal),color var(--transition-normal);-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;text-rendering:optimizeLegibility;min-height:100vh;overflow-x:hidden}:focus{outline:2px solid var(--border-focus);outline-offset:2px}:focus:not(:focus-visible){outline:0}:focus-visible{outline:2px solid var(--border-focus);outline-offset:2px}h1,h2,h3,h4,h5,h6{font-weight:var(--font-bold);line-height:1.25;letter-spacing:-.025em;color:var(--text-primary)}h1{font-size:var(--text-4xl);font-weight:var(--font-extrabold)}h2{font-size:var(--text-3xl);font-weight:var(--font-bold)}h3{font-size:var(--text-2xl);font-weight:var(--font-semibold)}p{line-height:1.75;margin-bottom:var(--space-4)}a{color:var(--primary);text-decoration:none;transition:var(--transition-all)}a:hover{color:var(--primary-hover);text-decoration:none}.page-wrapper{min-height:100vh;display:flex;flex-direction:column;position:relative}.container{max-width:var(--container-max-width);margin:0 auto;padding:0 var(--space-6);width:100%}.main-content{flex:1;position:relative}.site-header{position:sticky;top:0;z-index:var(--z-sticky);background:rgb(255 255 255 / .8);backdrop-filter:blur(20px) saturate(180%);border-bottom:1px solid var(--border-primary);height:var(--header-height);transition:var(--transition-all)}[data-theme=dark] .site-header{background:rgb(15 23 42 / .8)}.header-content{display:flex;align-items:center;justify-content:space-between;height:var(--header-height);gap:var(--space-8)}.site-title{display:flex;align-items:center;gap:var(--space-2);font-size:var(--text-xl);font-weight:var(--font-bold);color:var(--text-primary);text-decoration:none;transition:var(--transition-all);position:relative}.site-title:hover{color:var(--primary);transform:translateY(-1px)}.site-title:focus-visible{border-radius:var(--radius-md);padding:var(--space-1) var(--space-2);margin:calc(-1 * var(--space-1)) calc(-1 * var(--space-2))}.logo-icon{font-size:var(--text-2xl);filter:drop-shadow(0 2px 4px rgb(99 102 241 / .2));transition:var(--transition-all)}.site-title:hover .logo-icon{transform:rotate(-5deg) scale(1.1)}.header-nav{display:flex;align-items:center;gap:var(--space-6)}.nav-link{position:relative;display:inline-flex;align-items:center;padding:var(--space-2) var(--space-3);font-size:var(--text-sm);font-weight:var(--font-medium);color:var(--text-secondary);text-decoration:none;border-radius:var(--radius-lg);transition:var(--transition-all);white-space:nowrap}.nav-link::before{content:'';position:absolute;bottom:-2px;left:50%;width:0;height:2px;background:var(--primary);border-radius:var(--radius-full);transition:var(--transition-all);transform:translateX(-50%)}.nav-link:hover{color:var(--primary);background:var(--bg-secondary);transform:translateY(-1px)}.nav-link:hover::before{width:70%}.nav-link:focus-visible{box-shadow:var(--shadow-focus)}.dark-mode-toggle{display:flex;align-items:center;justify-content:center;width:2.75rem;height:2.75rem;border:2px solid var(--border-primary);border-radius:var(--radius-full);background:var(--bg-primary);color:var(--text-primary);cursor:pointer;transition:var(--transition-all);position:relative;overflow:hidden}.dark-mode-toggle:hover{background:var(--bg-secondary);border-color:var(--primary);transform:scale(1.05);box-shadow:var(--shadow-md)}.dark-mode-toggle:focus-visible{box-shadow:var(--shadow-focus)}.moon-icon,.sun-icon{transition:var(--transition-all);position:absolute}.moon-icon{display:none;transform:rotate(180deg)}[data-theme=dark] .sun-icon{display:none}[data-theme=dark] .moon-icon{display:block;transform:rotate(0)}.hero-section{position:relative;padding:var(--space-24) 0 var(--space-20);background:linear-gradient(135deg,var(--bg-primary) 0,var(--bg-secondary) 100%);overflow:hidden}.hero-section::before{content:'';position:absolute;inset:0;background:radial-gradient(circle at 30% 20%,rgb(99 102 241 / .1) 0,transparent 50%),radial-gradient(circle at 70% 80%,rgb(99 102 241 / .05) 0,transparent 50%);pointer-events:none}[data-theme=dark] .hero-section{background:linear-gradient(135deg,var(--bg-primary) 0,var(--bg-secondary) 100%)}[data-theme=dark] .hero-section::before{background:radial-gradient(circle at 30% 20%,rgb(129 140 248 / .15) 0,transparent 50%),radial-gradient(circle at 70% 80%,rgb(129 140 248 / .08) 0,transparent 50%)}.hero-content{text-align:center;max-width:900px;margin:0 auto;position:relative;z-index:1;animation:fadeInUp .8s ease-out}@keyframes fadeInUp{from{opacity:0;transform:translateY(30px)}to{opacity:1;transform:translateY(0)}}.hero-title{font-size:clamp(var(--text-3xl), 8vw, var(--text-6xl));font-weight:var(--font-extrabold);line-height:1.1;margin:0 0 var(--space-6);color:var(--text-primary);letter-spacing:-.02em}.gradient-text{background:linear-gradient(135deg,var(--primary) 0,#8b5cf6 100%);-webkit-background-clip:text;-webkit-text-fill-color:transparent;background-clip:text;position:relative}[data-theme=dark] .gradient-text{background:linear-gradient(135deg,var(--primary-light) 0,#c4b5fd 100%);-webkit-background-clip:text;-webkit-text-fill-color:transparent;background-clip:text}.hero-description{font-size:clamp(var(--text-lg), 4vw, var(--text-xl));color:var(--text-secondary);margin:0 0 var(--space-10);max-width:650px;margin-left:auto;margin-right:auto;line-height:1.6}.hero-actions{display:flex;gap:var(--space-4);justify-content:center;margin-bottom:var(--space-16);flex-wrap:wrap}.hero-stats{display:flex;gap:var(--space-12);justify-content:center;flex-wrap:wrap}.stat-item{text-align:center;position:relative}.stat-item:not(:last-child)::after{content:'';position:absolute;right:calc(-1 * var(--space-6));top:50%;transform:translateY(-50%);width:1px;height:40px;background:var(--border-primary)}.stat-number{display:block;font-size:clamp(var(--text-2xl), 6vw, var(--text-4xl));font-weight:var(--font-extrabold);color:var(--primary);margin-bottom:var(--space-1);background:linear-gradient(135deg,var(--primary) 0,#8b5cf6 100%);-webkit-background-clip:text;-webkit-text-fill-color:transparent;background-clip:text}.stat-label{font-size:var(--text-sm);color:var(--text-secondary);text-transform:uppercase;letter-spacing:.1em;font-weight:var(--font-medium)}.btn{display:inline-flex;align-items:center;gap:var(--space-2);padding:var(--space-4) var(--space-8);border:2px solid transparent;border-radius:var(--radius-xl);font-size:var(--text-base);font-weight:var(--font-semibold);text-decoration:none;cursor:pointer;transition:var(--transition-all);white-space:nowrap;position:relative;overflow:hidden;text-align:center;min-width:140px;justify-content:center}.btn::before{content:'';position:absolute;top:0;left:-100%;width:100%;height:100%;background:linear-gradient(90deg,transparent,rgb(255 255 255 / .2),transparent);transition:left .5s}.btn:hover::before{left:100%}.btn-primary{background:linear-gradient(135deg,var(--primary) 0,var(--primary-dark) 100%);color:#fff;box-shadow:var(--shadow-md)}.btn-primary:hover{background:linear-gradient(135deg,var(--primary-hover) 0,var(--primary) 100%);transform:translateY(-2px);box-shadow:var(--shadow-lg)}.btn-primary:focus-visible{box-shadow:var(--shadow-focus),var(--shadow-lg)}.btn-secondary{background:0 0;color:var(--text-primary);border:2px solid var(--border-primary)}.btn-secondary:hover{border-color:var(--primary);color:var(--primary);background:var(--bg-secondary);transform:translateY(-2px);box-shadow:var(--shadow-md)}.btn-secondary:focus-visible{box-shadow:var(--shadow-focus)}.quick-nav{padding:var(--space-20) 0;background:var(--bg-primary);position:relative}.quick-nav-grid{display:grid;grid-template-columns:repeat(auto-fit,minmax(280px,1fr));gap:var(--space-8)}.quick-nav-card{display:block;padding:var(--space-8);background:var(--bg-elevated);border:2px solid var(--border-primary);border-radius:var(--radius-2xl);text-decoration:none;transition:var(--transition-all);position:relative;overflow:hidden;box-shadow:var(--shadow-sm);backdrop-filter:blur(10px)}.quick-nav-card::before{content:'';position:absolute;inset:0;background:linear-gradient(135deg,var(--primary) 0,transparent 100%);opacity:0;transition:var(--transition-all);z-index:0}.quick-nav-card:hover::before{opacity:.08}.quick-nav-card:hover{border-color:var(--primary);transform:translateY(-6px) scale(1.02);box-shadow:var(--shadow-xl)}.quick-nav-card:focus-visible{box-shadow:var(--shadow-focus),var(--shadow-lg)}.quick-nav-card>*{position:relative;z-index:1}.quick-nav-icon{font-size:var(--text-4xl);margin-bottom:var(--space-4);display:block;filter:drop-shadow(0 2px 4px rgb(0 0 0 / .1));transition:var(--transition-all)}.quick-nav-card:hover .quick-nav-icon{transform:scale(1.1) rotate(-5deg)}.quick-nav-card h3{margin:0 0 var(--space-3);font-size:var(--text-xl);font-weight:var(--font-bold);color:var(--text-primary)}.quick-nav-card p{margin:0;color:var(--text-secondary);font-size:var(--text-base);line-height:1.6}.quick-nav-card a:hover{text-decoration:none}.section{padding:var(--space-24) 0;position:relative}.section:nth-child(2n){background:var(--bg-secondary)}.section-header{text-align:center;margin-bottom:var(--space-20);animation:fadeInUp .6s ease-out}.section-title{font-size:clamp(var(--text-3xl), 6vw, var(--text-5xl));font-weight:var(--font-extrabold);margin:0 0 var(--space-6);color:var(--text-primary);letter-spacing:-.02em}.section-description{font-size:clamp(var(--text-base), 3vw, var(--text-xl));color:var(--text-secondary);margin:0;max-width:700px;margin-inline:auto;line-height:1.7}.data-table-container{background:var(--bg-elevated);border-radius:var(--radius-2xl);box-shadow:var(--shadow-xl);border:1px solid var(--border-primary);margin:var(--space-8) 0;position:relative;overflow:hidden;backdrop-filter:blur(10px)}.table-wrapper{overflow-x:auto;overflow-y:visible;border-radius:var(--radius-2xl);-webkit-overflow-scrolling:touch;scrollbar-width:thin;scrollbar-color:var(--primary) var(--bg-secondary);scroll-behavior:smooth;scroll-snap-type:x mandatory;overscroll-behavior-x:contain}.table-wrapper::-webkit-scrollbar{height:10px}.table-wrapper::-webkit-scrollbar-track{background:var(--bg-secondary);border-radius:var(--radius-md)}.table-wrapper::-webkit-scrollbar-thumb{background:var(--primary);border-radius:var(--radius-md);border:2px solid var(--bg-secondary)}.table-wrapper::-webkit-scrollbar-thumb:hover{background:var(--primary-hover)}table{width:100%;border-collapse:collapse;font-size:var(--text-sm);min-width:600px}td,th{padding:var(--space-4) var(--space-6);text-align:left;border-bottom:1px solid var(--border-primary);white-space:nowrap;transition:all var(--transition-normal);min-height:44px}@media (width <= 768px){td,th{padding:var(--space-3) var(--space-4);font-size:var(--text-xs);min-height:48px}td,th{scroll-snap-align:start}td:first-child,th:first-child{box-shadow:2px 0 4px rgb(0 0 0 / .1);border-right:1px solid var(--border-primary)}}th{background:var(--primary);color:#fff;font-weight:var(--font-semibold);text-transform:uppercase;letter-spacing:.05em;font-size:var(--text-xs);position:sticky;top:0;z-index:var(--z-sticky)}th:first-child{position:sticky;left:0;z-index:calc(var(--z-sticky) + 1);background:var(--primary)}tr:hover{background:var(--bg-secondary)}td{transition:all var(--transition-fast)}td:first-child{font-weight:var(--font-medium);position:sticky;left:0;background:var(--bg-primary);z-index:1}tr:hover td:first-child{background:var(--bg-secondary)}.status-cell{text-align:center!important}.status-indicator{display:inline-flex;align-items:center;justify-content:center;width:24px;height:24px;border-radius:var(--radius-full);transition:all var(--transition-fast)}.status-indicator.supported{background:rgb(14 236 162 / .1);color:var(--success)}.status-indicator.not-supported{background:rgb(211 29 29 / .1);color:var(--error)}.status-indicator svg{width:16px;height:16px}.search-section{margin-bottom:var(--space-8)}.search-container.enhanced{position:relative;max-width:500px;margin:0 auto}.search-icon{position:absolute;left:var(--space-4);top:50%;transform:translateY(-50%);color:var(--text-tertiary);z-index:1}.search-input{width:100%;padding:var(--space-4) var(--space-12) var(--space-4) var(--space-12);border:2px solid var(--border-primary);border-radius:var(--radius-full);font-size:var(--text-base);background:var(--bg-primary);color:var(--text-primary);transition:all var(--transition-fast);outline:0}.search-input:focus{border-color:var(--primary);box-shadow:0 0 0 3px rgb(99 102 241 / .1)}.clear-icon{position:absolute;right:var(--space-4);top:50%;transform:translateY(-50%);background:0 0;border:none;color:var(--text-tertiary);cursor:pointer;padding:var(--space-1);border-radius:var(--radius-md);transition:all var(--transition-fast);opacity:0;visibility:hidden}.search-input:focus+.clear-icon,.search-input:not(:placeholder-shown)+.clear-icon{opacity:1;visibility:visible}.clear-icon:hover{background:var(--bg-secondary);color:var(--text-primary)}.search-results{text-align:center;padding:var(--space-2) 0;color:var(--text-secondary);font-size:var(--text-sm);margin-bottom:var(--space-4)}.compare-controls{display:flex;align-items:end;gap:var(--space-6);margin-bottom:var(--space-12);flex-wrap:wrap}.compare-select-group{flex:1;min-width:200px}.compare-select-group label{display:block;margin-bottom:var(--space-2);font-weight:var(--font-medium);color:var(--text-primary)}.select-wrapper{position:relative}.select-wrapper::after{content:'';position:absolute;right:var(--space-4);top:50%;transform:translateY(-50%);width:0;height:0;border-left:5px solid transparent;border-right:5px solid transparent;border-top:5px solid var(--text-tertiary);pointer-events:none}select{width:100%;padding:var(--space-3) var(--space-8) var(--space-3) var(--space-4);border:2px solid var(--border-primary);border-radius:var(--radius-lg);background:var(--bg-primary);color:var(--text-primary);font-size:var(--text-base);cursor:pointer;appearance:none;transition:all var(--transition-fast)}select:focus{outline:0;border-color:var(--primary);box-shadow:0 0 0 3px rgb(99 102 241 / .1)}.compare-vs{flex-shrink:0;font-size:var(--text-lg);font-weight:var(--font-bold);color:var(--primary);background:var(--bg-secondary);padding:var(--space-3) var(--space-4);border-radius:var(--radius-lg);border:2px solid var(--border-primary);margin-bottom:var(--space-2)}#compare-table-container{position:relative;background:var(--bg-primary);border-radius:var(--radius-xl);box-shadow:var(--shadow-lg);border:1px solid var(--border-primary);margin-top:var(--space-6);display:none}.comparison-visible{display:block!important;animation:slideIn .3s ease-out}.comparison-hiding{animation:slideOut .3s ease-in}@keyframes slideIn{from{opacity:0;transform:translateY(-20px)}to{opacity:1;transform:translateY(0)}}@keyframes slideOut{from{opacity:1;transform:translateY(0)}to{opacity:0;transform:translateY(-20px)}}.comparison-header{padding:var(--space-6);border-bottom:1px solid var(--border-primary);background:var(--bg-secondary);border-radius:var(--radius-xl) var(--radius-xl) 0 0}.comparison-header h3{margin:0 0 var(--space-4);font-size:var(--text-2xl);font-weight:var(--font-bold);color:var(--text-primary);text-align:center}.comparison-stats{display:flex;gap:var(--space-6);justify-content:center;margin-bottom:var(--space-6);flex-wrap:wrap}.comparison-stats .stat{text-align:center;background:var(--bg-primary);padding:var(--space-3) var(--space-4);border-radius:var(--radius-lg);border:1px solid var(--border-primary);min-width:100px}.stat-label{display:block;font-size:var(--text-xs);color:var(--text-secondary);text-transform:uppercase;letter-spacing:.05em;margin-bottom:var(--space-1)}.stat-value{display:block;font-size:var(--text-xl);font-weight:var(--font-bold);color:var(--primary)}.comparison-actions{display:flex;justify-content:center;gap:var(--space-3)}.comparison-filters{padding:var(--space-4) var(--space-6);background:var(--bg-tertiary);border-bottom:1px solid var(--border-primary);display:flex;gap:var(--space-6);justify-content:center;flex-wrap:wrap}.filter-option{display:flex;align-items:center;gap:var(--space-2);cursor:pointer;font-size:var(--text-sm);font-weight:var(--font-medium);color:var(--text-primary)}.filter-option input[type=radio]{margin:0}.filter-results{text-align:center;padding:var(--space-2) 0;color:var(--text-secondary);font-size:var(--text-sm);background:var(--bg-secondary);border-bottom:1px solid var(--border-primary)}.comparison-table{width:100%;border-collapse:collapse;font-size:var(--text-sm);min-width:700px}.comparison-table td,.comparison-table th{padding:var(--space-4) var(--space-6);border-bottom:1px solid var(--border-primary);text-align:center}.comparison-table td:first-child,.comparison-table th:first-child{text-align:left;font-weight:var(--font-medium)}.comparison-table th{background:var(--primary);color:#fff;font-weight:var(--font-semibold);text-transform:uppercase;letter-spacing:.05em;font-size:var(--text-xs);position:sticky;top:0;z-index:var(--z-sticky)}.provider-header{position:relative}.comparison-row.both-supported{background:rgb(16 185 129 / .05)}.comparison-row.provider1-only{background:rgb(59 130 246 / .05)}.comparison-row.provider2-only{background:rgb(168 85 247 / .05)}.comparison-row.neither-supported{background:rgb(239 68 68 / .05)}.status-badge{display:inline-block;padding:var(--space-1) var(--space-3);border-radius:var(--radius-full);font-size:var(--text-xs);font-weight:var(--font-medium);text-transform:uppercase;letter-spacing:.05em}.status-badge.both-supported{background:rgb(16 185 129 / .1);color:var(--success)}.status-badge.provider1-only{background:rgb(59 130 246 / .1);color:var(--info)}.status-badge.provider2-only{background:rgb(168 85 247 / .1);color:#8b5cf6}.status-badge.neither-supported{background:rgb(239 68 68 / .1);color:var(--error)}#close-compare{background:var(--bg-primary);border:1px solid var(--border-primary);border-radius:var(--radius-lg);padding:var(--space-2) var(--space-4);display:flex;align-items:center;gap:var(--space-2);cursor:pointer;transition:all var(--transition-fast);font-size:var(--text-sm);color:var(--text-primary);font-weight:var(--font-medium)}#close-compare:hover{background:var(--error);color:#fff;border-color:var(--error);transform:translateY(-1px)}.empty-state{text-align:center;padding:var(--space-16)}.empty-state-icon{font-size:var(--text-5xl);margin-bottom:var(--space-4)}.empty-state h3{margin:0 0 var(--space-2);font-size:var(--text-xl);color:var(--text-primary)}.empty-state p{margin:0;color:var(--text-secondary)}.warning-state{text-align:center;padding:var(--space-12);background:rgb(245 158 11 / .05);border-radius:var(--radius-lg);border:1px solid rgb(245 158 11 / .2)}.warning-icon{font-size:var(--text-4xl);margin-bottom:var(--space-3)}.warning-state h3{margin:0 0 var(--space-2);color:var(--warning)}.warning-state p{margin:0;color:var(--text-secondary)}.alert{display:flex;align-items:flex-start;gap:var(--space-3);padding:var(--space-4);border-radius:var(--radius-lg);margin:var(--space-4) 0}.alert-info{background:rgb(59 130 246 / .1);border:1px solid rgb(59 130 246 / .2);color:var(--info)}.alert-icon{flex-shrink:0;margin-top:2px}.referral-section{margin-block:var(--space-16);padding:var(--space-8);background:var(--bg-secondary);border-radius:var(--radius-xl);border:1px solid var(--border-primary);text-align:center}.referral-header h3{margin:0 0 var(--space-2);color:var(--text-primary);font-size:var(--text-2xl);font-weight:var(--font-bold)}.referral-header p{margin:0 auto var(--space-6);color:var(--text-secondary);max-width:var(--content-max-width)}.referral-grid{display:grid;grid-template-columns:repeat(auto-fit,minmax(180px,1fr));gap:var(--space-4);justify-items:center}.referral-card{display:flex;flex-direction:column;align-items:center;justify-content:center;gap:var(--space-2);padding:var(--space-4) var(--space-3);background:var(--bg-primary);border:1px solid var(--border-primary);border-radius:var(--radius-lg);text-decoration:none;transition:var(--transition-all);width:100%;max-width:200px;box-shadow:var(--shadow-sm)}.referral-card:hover{border-color:var(--primary);transform:translateY(-2px);box-shadow:var(--shadow-md)}.service-name{font-weight:var(--font-semibold);color:var(--text-primary);font-size:var(--text-base)}.referral-badge{font-size:var(--text-xs);color:var(--primary);background:rgb(99 102 241 / .1);padding:var(--space-1) var(--space-2);border-radius:var(--radius-md);font-weight:var(--font-medium)}.service-name{font-weight:var(--font-medium);color:var(--text-primary)}.status-grid{display:grid;grid-template-columns:repeat(auto-fit,minmax(280px,1fr));gap:var(--space-6)}.status-card{display:block;padding:var(--space-6);background:var(--bg-primary);border:1px solid var(--border-primary);border-radius:var(--radius-xl);text-decoration:none;transition:all var(--transition-normal)}.status-card:hover{border-color:var(--primary);transform:translateY(-2px);box-shadow:var(--shadow-lg)}.status-header{display:flex;align-items:center;justify-content:space-between;margin-bottom:var(--space-3)}.service-status-indicator{width:12px;height:12px;border-radius:var(--radius-full);background:var(--success);box-shadow:0 0 0 2px rgb(16 185 129 / .2)}.status-indicator.online{background:var(--success);box-shadow:0 0 0 2px rgb(16 185 129 / .2)}.status-card p{margin:0;color:var(--text-secondary);font-size:var(--text-sm)}.loading-state{display:flex;flex-direction:column;align-items:center;justify-content:center;padding:var(--space-12);color:var(--text-secondary);min-height:200px}.loading-spinner{width:32px;height:32px;border:3px solid var(--border-primary);border-top:3px solid var(--primary);border-radius:var(--radius-full);animation:spin 1s linear infinite;margin-bottom:var(--space-4)}.skeleton{background:linear-gradient(90deg,var(--bg-secondary) 0,var(--bg-tertiary) 50%,var(--bg-secondary) 100%);background-size:200% 100%;animation:shimmer 1.5s ease-in-out infinite;border-radius:var(--radius-md)}.skeleton-text{height:1em;margin-bottom:var(--space-2)}.skeleton-text:last-child{width:70%}.skeleton-avatar{width:40px;height:40px;border-radius:var(--radius-full)}.skeleton-card{height:120px;border-radius:var(--radius-lg);margin-bottom:var(--space-4)}@keyframes shimmer{0%{background-position:-200% 0}100%{background-position:200% 0}}@keyframes spin{0%{transform:rotate(0)}100%{transform:rotate(360deg)}}.site-footer{background:var(--bg-secondary);border-top:1px solid var(--border-primary);padding:var(--space-16) 0 var(--space-8);margin-top:auto}.footer-content{display:grid;grid-template-columns:repeat(auto-fit,minmax(250px,1fr));gap:var(--space-8);margin-bottom:var(--space-8)}.footer-section h4{margin:0 0 var(--space-4);font-size:var(--text-lg);font-weight:var(--font-semibold);color:var(--text-primary)}.footer-section p{margin:0;color:var(--text-secondary)}.footer-section ul{list-style:none;padding:0;margin:0}.footer-section li{margin-bottom:var(--space-2)}.footer-section a{color:var(--text-secondary);text-decoration:none;transition:color var(--transition-fast)}.footer-section a:hover{color:var(--primary)}.footer-bottom{text-align:center;padding-top:var(--space-8);border-top:1px solid var(--border-primary)}.footer-bottom p{margin:0;color:var(--text-tertiary);font-size:var(--text-sm)}.footer-bottom a{color:var(--primary);text-decoration:none}.back-to-top{position:fixed;bottom:var(--space-6);right:var(--space-6);width:48px;height:48px;background:var(--primary);color:#fff;border:none;border-radius:var(--radius-full);cursor:pointer;display:flex;align-items:center;justify-content:center;box-shadow:var(--shadow-lg);transition:all var(--transition-normal);opacity:0;visibility:hidden;transform:translateY(20px);z-index:var(--z-docked)}.back-to-top.visible{opacity:1;visibility:visible;transform:translateY(0)}.back-to-top:hover{background:var(--primary-hover);transform:translateY(-2px);box-shadow:var(--shadow-xl)}.loading-overlay{position:absolute;inset:0;background:rgb(255 255 255 / .9);backdrop-filter:blur(2px);display:flex;align-items:center;justify-content:center;z-index:var(--z-modal);opacity:0;visibility:hidden;transition:all var(--transition-normal)}[data-theme=dark] .loading-overlay{background:rgb(15 23 42 / .9)}.loading-overlay--visible{opacity:1;visibility:visible}.loading-overlay--hiding{opacity:0}.loading-content{text-align:center;color:var(--text-primary)}.spinner-ring{width:40px;height:40px;border:4px solid var(--border-primary);border-top:4px solid var(--primary);border-radius:var(--radius-full);animation:spin 1s linear infinite;margin:0 auto var(--space-3)}.loading-text{margin:0;font-size:var(--text-sm);color:var(--text-secondary)}@media (width <= 1024px){.container{padding:0 var(--space-4)}.comparison-stats{gap:var(--space-4)}.comparison-stats .stat{min-width:80px;padding:var(--space-2) var(--space-3)}}@media (width <= 768px){.header-nav{display:none}.hero-title{font-size:var(--text-3xl)}.hero-description{font-size:var(--text-lg)}.hero-actions{flex-direction:column;align-items:center}.hero-stats{gap:var(--space-6)}.section-title{font-size:var(--text-3xl)}.compare-controls{flex-direction:column}.compare-vs{align-self:center;margin:var(--space-2) 0}.quick-nav-grid{grid-template-columns:1fr}.footer-content{grid-template-columns:1fr;text-align:center}.data-table-container{margin:var(--space-2) calc(-1 * var(--space-4));border-radius:0;border-left:none;border-right:none;box-shadow:0 -1px 0 var(--border-primary),0 1px 0 var(--border-primary)}.table-wrapper{border-radius:0;background:linear-gradient(90deg,var(--bg-primary) 70%,transparent),linear-gradient(90deg,transparent,var(--bg-primary) 70%),linear-gradient(90deg,var(--border-primary),transparent 16px),linear-gradient(270deg,var(--border-primary),transparent 16px);background-position:left center,right center,left center,right center;background-repeat:no-repeat;background-size:20px 100%,20px 100%,10px 100%,10px 100%;background-attachment:local,local,scroll,scroll}table{font-size:var(--text-xs);min-width:500px}td,th{padding:var(--space-2) var(--space-3)}td:first-child,th:first-child{min-width:120px;max-width:150px;white-space:normal;word-break:break-word}.comparison-header{padding:var(--space-4)}.comparison-header h3{font-size:var(--text-lg)}.comparison-stats{flex-direction:column;gap:var(--space-3)}.comparison-stats .stat{margin:0 auto;max-width:200px}.comparison-filters{flex-direction:column;align-items:center;gap:var(--space-3)}.comparison-table{min-width:500px}.comparison-table td,.comparison-table th{padding:var(--space-2) var(--space-3);font-size:var(--text-xs)}td,th{padding:var(--space-3) var(--space-4)}.header-content{gap:var(--space-4)}.nav-link{padding:var(--space-1-5) var(--space-2);font-size:var(--text-xs)}}@media (width <= 480px){.hero-section{padding:var(--space-16) 0 var(--space-12)}.section{padding:var(--space-12) 0}.btn{width:100%;justify-content:center}.hero-stats{flex-direction:column;gap:var(--space-4)}.comparison-stats{gap:var(--space-2)}.comparison-stats .stat{min-width:60px;padding:var(--space-1) var(--space-2)}.stat-value{font-size:var(--text-lg)}.stat-label{font-size:10px}table{min-width:400px}td:first-child,th:first-child{min-width:100px;max-width:120px}.stat-item:not(:last-child)::after{display:none}}@media (width <= 640px){.container{padding:0 var(--space-4)}.hero-actions{flex-direction:column;align-items:center;gap:var(--space-3)}.hero-stats{gap:var(--space-8)}.nav-link{padding:var(--space-1-5) var(--space-2);font-size:var(--text-xs)}.btn{width:100%;max-width:280px;padding:var(--space-4) var(--space-6)}}@media print{#close-compare,.back-to-top,.comparison-actions,.comparison-filters,.dark-mode-toggle,.hero-section,.quick-nav,.referral-section,.site-footer,.site-header{display:none!important}.section{page-break-inside:avoid}.data-table-container{box-shadow:none;border:1px solid #000}.table-wrapper{overflow:visible}table{min-width:auto}td,th{border:1px solid #000}}@media (prefers-reduced-motion:reduce){*,::after,::before{animation-duration:0s!important;animation-iteration-count:1!important;transition-duration:0s!important}html{scroll-behavior:auto}}@media (prefers-contrast:high){:root{--border-primary:#000;--text-secondary:#000}[data-theme=dark]{--border-primary:#fff;--text-secondary:#fff}}@media (hover:none) and (pointer:coarse){.btn,[role=button],button{min-height:48px;min-width:48px;padding:var(--space-3) var(--space-5)}.comparison-service:hover,.status-card:hover,tr:hover{background:initial;transform:none}.btn:active,[role=button]:active,button:active{transform:scale(.98);transition:transform .1s ease}}@media (width <= 768px){.mobile-card-view .table-wrapper{display:none}.mobile-card-view .cards-container{display:grid;gap:var(--space-4);padding:var(--space-4)}.service-card{background:var(--bg-elevated);border-radius:var(--radius-lg);padding:var(--space-5);box-shadow:var(--shadow-md);border:1px solid var(--border-primary);transition:all var(--transition-normal)}.service-card:active{transform:scale(.98);box-shadow:var(--shadow-sm)}.service-card-header{display:flex;align-items:center;justify-content:space-between;margin-bottom:var(--space-4);padding-bottom:var(--space-3);border-bottom:1px solid var(--border-primary)}.service-card-title{font-weight:var(--font-semibold);color:var(--text-primary);font-size:var(--text-lg)}.service-card-providers{display:grid;grid-template-columns:repeat(auto-fit,minmax(80px,1fr));gap:var(--space-3)}.provider-status{display:flex;flex-direction:column;align-items:center;text-align:center;padding:var(--space-2);border-radius:var(--radius-md);background:var(--bg-secondary)}.provider-name{font-size:var(--text-xs);color:var(--text-secondary);margin-bottom:var(--space-1)}.provider-support{width:20px;height:20px}}@media (width <= 768px){.pull-to-refresh{position:relative;overflow-y:auto;-webkit-overflow-scrolling:touch}.pull-to-refresh-indicator{position:absolute;top:-60px;left:50%;transform:translateX(-50%);padding:var(--space-4);background:var(--bg-elevated);border-radius:var(--radius-full);box-shadow:var(--shadow-lg);opacity:0;transition:all var(--transition-normal)}.pull-to-refresh.pulling .pull-to-refresh-indicator{opacity:1;top:var(--space-4)}}.search-container{position:relative}.search-suggestions{position:absolute;top:100%;left:0;right:0;background:var(--bg-elevated);border:1px solid var(--border-primary);border-top:none;border-radius:0 0 var(--radius-lg) var(--radius-lg);box-shadow:var(--shadow-lg);max-height:200px;overflow-y:auto;z-index:var(--z-dropdown);display:none}.search-suggestions.visible{display:block;animation:slideInDown .2s ease}.search-suggestion{padding:var(--space-3) var(--space-4);cursor:pointer;border-bottom:1px solid var(--border-primary);transition:background-color var(--transition-fast)}.search-suggestion.highlighted,.search-suggestion:hover{background:var(--bg-secondary)}.search-suggestion:last-child{border-bottom:none}@keyframes slideInDown{from{opacity:0;transform:translateY(-8px)}to{opacity:1;transform:translateY(0)}}.btn.loading{position:relative;color:transparent;pointer-events:none}.btn.loading::after{content:'';position:absolute;top:50%;left:50%;width:16px;height:16px;margin:-8px 0 0 -8px;border:2px solid transparent;border-top:2px solid currentColor;border-radius:var(--radius-full);animation:spin 1s linear infinite}.focus-trap{outline:0}.focus-visible{outline:2px solid var(--primary);outline-offset:2px}.toast-container{position:fixed;top:var(--space-4);right:var(--space-4);z-index:var(--z-modal);pointer-events:none}.toast{background:var(--bg-elevated);border:1px solid var(--border-primary);border-radius:var(--radius-lg);padding:var(--space-4) var(--space-5);margin-bottom:var(--space-3);box-shadow:var(--shadow-xl);max-width:300px;pointer-events:auto;animation:slideInRight .3s ease}.toast.success{border-left:4px solid var(--success)}.toast.error{border-left:4px solid var(--error)}.toast.warning{border-left:4px solid var(--warning)}.toast.info{border-left:4px solid var(--info)}@keyframes slideInRight{from{opacity:0;transform:translateX(100%)}to{opacity:1;transform:translateX(0)}}.virtual-scroll-container{position:relative;overflow-y:auto;will-change:scroll-position}.virtual-scroll-content{position:relative}.virtual-scroll-item{position:absolute;left:0;right:0;will-change:transform}.gpu-accelerated{transform:translateZ(0);will-change:transform}.contain-layout{contain:layout}.contain-style{contain:style}.contain-size{contain:size}@media (width <= 768px){.mobile-nav-toggle{display:block;position:fixed;bottom:var(--space-6);right:var(--space-6);width:56px;height:56px;border-radius:var(--radius-full);background:var(--primary);color:#fff;border:none;box-shadow:var(--shadow-xl);z-index:var(--z-floating);transition:all var(--transition-normal)}.mobile-nav-toggle:active{transform:scale(.9)}.mobile-nav-menu{position:fixed;bottom:80px;right:var(--space-6);background:var(--bg-elevated);border-radius:var(--radius-lg);box-shadow:var(--shadow-xl);border:1px solid var(--border-primary);opacity:0;transform:scale(.8) translateY(20px);transition:all var(--transition-normal);pointer-events:none;z-index:var(--z-floating)}.mobile-nav-menu.visible{opacity:1;transform:scale(1) translateY(0);pointer-events:auto}.mobile-nav-item{display:block;padding:var(--space-4) var(--space-5);color:var(--text-primary);text-decoration:none;border-bottom:1px solid var(--border-primary);transition:background-color var(--transition-fast)}.mobile-nav-item:hover{background:var(--bg-secondary)}.mobile-nav-item:last-child{border-bottom:none}}@supports (container-type:inline-size){.comparison-container{container-type:inline-size}@container (width < 500px){.comparison-selectors{flex-direction:column}.compare-vs{order:-1;align-self:center}}}.scroll-indicator{position:fixed;top:0;left:0;width:100%;height:3px;background:var(--bg-secondary);z-index:var(--z-sticky)}.scroll-indicator-bar{height:100%;background:linear-gradient(90deg,var(--primary),var(--primary-light));transition:width var(--transition-fast)}.empty-state{display:flex;flex-direction:column;align-items:center;justify-content:center;padding:var(--space-16) var(--space-8);text-align:center;color:var(--text-secondary)}.empty-state-icon{width:64px;height:64px;margin-bottom:var(--space-6);opacity:.5}.empty-state-title{font-size:var(--text-xl);font-weight:var(--font-semibold);color:var(--text-primary);margin-bottom:var(--space-3)}.empty-state-description{font-size:var(--text-base);line-height:1.6;max-width:400px} \ No newline at end of file diff --git a/dist/css/styles.css b/dist/css/styles.css index fbacbb7..deedf67 100644 --- a/dist/css/styles.css +++ b/dist/css/styles.css @@ -760,6 +760,10 @@ a:hover { -webkit-overflow-scrolling: touch; scrollbar-width: thin; scrollbar-color: var(--primary) var(--bg-secondary); + /* Mobile-first enhancements */ + scroll-behavior: smooth; + scroll-snap-type: x mandatory; + overscroll-behavior-x: contain; } .table-wrapper::-webkit-scrollbar { @@ -794,6 +798,32 @@ td { text-align: left; border-bottom: 1px solid var(--border-primary); white-space: nowrap; + transition: all var(--transition-normal); + /* Better touch targets for mobile */ + min-height: 44px; +} + +/* Enhanced mobile table interactions */ +@media (width <= 768px) { + th, + td { + padding: var(--space-3) var(--space-4); + font-size: var(--text-xs); + min-height: 48px; /* Larger touch targets on mobile */ + } + + /* Scroll snap for better mobile table navigation */ + th, + td { + scroll-snap-align: start; + } + + /* Enhanced sticky column behavior on mobile */ + th:first-child, + td:first-child { + box-shadow: 2px 0 4px rgb(0 0 0 / 0.1); + border-right: 1px solid var(--border-primary); + } } th { @@ -1429,6 +1459,7 @@ select:focus { justify-content: center; padding: var(--space-12); color: var(--text-secondary); + min-height: 200px; } .loading-spinner { @@ -1441,6 +1472,44 @@ select:focus { margin-bottom: var(--space-4); } +/* Modern skeleton loading states */ +.skeleton { + background: linear-gradient(90deg, var(--bg-secondary) 0%, var(--bg-tertiary) 50%, var(--bg-secondary) 100%); + background-size: 200% 100%; + animation: shimmer 1.5s ease-in-out infinite; + border-radius: var(--radius-md); +} + +.skeleton-text { + height: 1em; + margin-bottom: var(--space-2); +} + +.skeleton-text:last-child { + width: 70%; +} + +.skeleton-avatar { + width: 40px; + height: 40px; + border-radius: var(--radius-full); +} + +.skeleton-card { + height: 120px; + border-radius: var(--radius-lg); + margin-bottom: var(--space-4); +} + +@keyframes shimmer { + 0% { + background-position: -200% 0; + } + 100% { + background-position: 200% 0; + } +} + @keyframes spin { 0% { transform: rotate(0deg); @@ -1664,10 +1733,26 @@ select:focus { border-radius: 0; border-left: none; border-right: none; + /* Enhanced mobile experience */ + box-shadow: 0 -1px 0 var(--border-primary), 0 1px 0 var(--border-primary); } .table-wrapper { border-radius: 0; + /* Enhanced scroll indicators for mobile */ + background: + /* Left shadow */ + linear-gradient(90deg, var(--bg-primary) 70%, transparent), + /* Right shadow */ + linear-gradient(90deg, transparent, var(--bg-primary) 70%), + /* Left shadow cover */ + linear-gradient(90deg, var(--border-primary), transparent 16px), + /* Right shadow cover */ + linear-gradient(270deg, var(--border-primary), transparent 16px); + background-position: left center, right center, left center, right center; + background-repeat: no-repeat; + background-size: 20px 100%, 20px 100%, 10px 100%, 10px 100%; + background-attachment: local, local, scroll, scroll; } table { @@ -1879,4 +1964,426 @@ select:focus { --border-primary: #fff; --text-secondary: #fff; } +} + +/* ===== MODERN MOBILE-FIRST ENHANCEMENTS ===== */ + +/* Enhanced Touch Interactions */ +@media (hover: none) and (pointer: coarse) { + /* Touch device optimizations */ + button, + .btn, + [role="button"] { + min-height: 48px; + min-width: 48px; + padding: var(--space-3) var(--space-5); + } + + /* Remove hover effects on touch devices */ + .status-card:hover, + tr:hover, + .comparison-service:hover { + background: initial; + transform: none; + } + + /* Enhanced tap feedback */ + button:active, + .btn:active, + [role="button"]:active { + transform: scale(0.98); + transition: transform 0.1s ease; + } +} + +/* Modern Card-Based Mobile Layout */ +@media (width <= 768px) { + /* Transform tables to cards on mobile when preferred */ + .mobile-card-view .table-wrapper { + display: none; + } + + .mobile-card-view .cards-container { + display: grid; + gap: var(--space-4); + padding: var(--space-4); + } + + .service-card { + background: var(--bg-elevated); + border-radius: var(--radius-lg); + padding: var(--space-5); + box-shadow: var(--shadow-md); + border: 1px solid var(--border-primary); + transition: all var(--transition-normal); + } + + .service-card:active { + transform: scale(0.98); + box-shadow: var(--shadow-sm); + } + + .service-card-header { + display: flex; + align-items: center; + justify-content: space-between; + margin-bottom: var(--space-4); + padding-bottom: var(--space-3); + border-bottom: 1px solid var(--border-primary); + } + + .service-card-title { + font-weight: var(--font-semibold); + color: var(--text-primary); + font-size: var(--text-lg); + } + + .service-card-providers { + display: grid; + grid-template-columns: repeat(auto-fit, minmax(80px, 1fr)); + gap: var(--space-3); + } + + .provider-status { + display: flex; + flex-direction: column; + align-items: center; + text-align: center; + padding: var(--space-2); + border-radius: var(--radius-md); + background: var(--bg-secondary); + } + + .provider-name { + font-size: var(--text-xs); + color: var(--text-secondary); + margin-bottom: var(--space-1); + } + + .provider-support { + width: 20px; + height: 20px; + } +} + +/* Pull-to-Refresh Enhancement */ +@media (width <= 768px) { + .pull-to-refresh { + position: relative; + overflow-y: auto; + -webkit-overflow-scrolling: touch; + } + + .pull-to-refresh-indicator { + position: absolute; + top: -60px; + left: 50%; + transform: translateX(-50%); + padding: var(--space-4); + background: var(--bg-elevated); + border-radius: var(--radius-full); + box-shadow: var(--shadow-lg); + opacity: 0; + transition: all var(--transition-normal); + } + + .pull-to-refresh.pulling .pull-to-refresh-indicator { + opacity: 1; + top: var(--space-4); + } +} + +/* Enhanced Search Experience */ +.search-container { + position: relative; +} + +.search-suggestions { + position: absolute; + top: 100%; + left: 0; + right: 0; + background: var(--bg-elevated); + border: 1px solid var(--border-primary); + border-top: none; + border-radius: 0 0 var(--radius-lg) var(--radius-lg); + box-shadow: var(--shadow-lg); + max-height: 200px; + overflow-y: auto; + z-index: var(--z-dropdown); + display: none; +} + +.search-suggestions.visible { + display: block; + animation: slideInDown 0.2s ease; +} + +.search-suggestion { + padding: var(--space-3) var(--space-4); + cursor: pointer; + border-bottom: 1px solid var(--border-primary); + transition: background-color var(--transition-fast); +} + +.search-suggestion:hover, +.search-suggestion.highlighted { + background: var(--bg-secondary); +} + +.search-suggestion:last-child { + border-bottom: none; +} + +@keyframes slideInDown { + from { + opacity: 0; + transform: translateY(-8px); + } + to { + opacity: 1; + transform: translateY(0); + } +} + +/* Modern Loading Button States */ +.btn.loading { + position: relative; + color: transparent; + pointer-events: none; +} + +.btn.loading::after { + content: ''; + position: absolute; + top: 50%; + left: 50%; + width: 16px; + height: 16px; + margin: -8px 0 0 -8px; + border: 2px solid transparent; + border-top: 2px solid currentColor; + border-radius: var(--radius-full); + animation: spin 1s linear infinite; +} + +/* Enhanced Focus Management */ +.focus-trap { + outline: none; +} + +.focus-visible { + outline: 2px solid var(--primary); + outline-offset: 2px; +} + +/* Toast Notifications */ +.toast-container { + position: fixed; + top: var(--space-4); + right: var(--space-4); + z-index: var(--z-modal); + pointer-events: none; +} + +.toast { + background: var(--bg-elevated); + border: 1px solid var(--border-primary); + border-radius: var(--radius-lg); + padding: var(--space-4) var(--space-5); + margin-bottom: var(--space-3); + box-shadow: var(--shadow-xl); + max-width: 300px; + pointer-events: auto; + animation: slideInRight 0.3s ease; +} + +.toast.success { + border-left: 4px solid var(--success); +} + +.toast.error { + border-left: 4px solid var(--error); +} + +.toast.warning { + border-left: 4px solid var(--warning); +} + +.toast.info { + border-left: 4px solid var(--info); +} + +@keyframes slideInRight { + from { + opacity: 0; + transform: translateX(100%); + } + to { + opacity: 1; + transform: translateX(0); + } +} + +/* Virtual Scrolling Container */ +.virtual-scroll-container { + position: relative; + overflow-y: auto; + will-change: scroll-position; +} + +.virtual-scroll-content { + position: relative; +} + +.virtual-scroll-item { + position: absolute; + left: 0; + right: 0; + will-change: transform; +} + +/* Performance Optimizations */ +.gpu-accelerated { + transform: translateZ(0); + will-change: transform; +} + +.contain-layout { + contain: layout; +} + +.contain-style { + contain: style; +} + +.contain-size { + contain: size; +} + +/* Enhanced Mobile Navigation */ +@media (width <= 768px) { + .mobile-nav-toggle { + display: block; + position: fixed; + bottom: var(--space-6); + right: var(--space-6); + width: 56px; + height: 56px; + border-radius: var(--radius-full); + background: var(--primary); + color: white; + border: none; + box-shadow: var(--shadow-xl); + z-index: var(--z-floating); + transition: all var(--transition-normal); + } + + .mobile-nav-toggle:active { + transform: scale(0.9); + } + + .mobile-nav-menu { + position: fixed; + bottom: 80px; + right: var(--space-6); + background: var(--bg-elevated); + border-radius: var(--radius-lg); + box-shadow: var(--shadow-xl); + border: 1px solid var(--border-primary); + opacity: 0; + transform: scale(0.8) translateY(20px); + transition: all var(--transition-normal); + pointer-events: none; + z-index: var(--z-floating); + } + + .mobile-nav-menu.visible { + opacity: 1; + transform: scale(1) translateY(0); + pointer-events: auto; + } + + .mobile-nav-item { + display: block; + padding: var(--space-4) var(--space-5); + color: var(--text-primary); + text-decoration: none; + border-bottom: 1px solid var(--border-primary); + transition: background-color var(--transition-fast); + } + + .mobile-nav-item:hover { + background: var(--bg-secondary); + } + + .mobile-nav-item:last-child { + border-bottom: none; + } +} + +/* Container Queries for Component-Based Responsive Design */ +@supports (container-type: inline-size) { + .comparison-container { + container-type: inline-size; + } + + @container (width < 500px) { + .comparison-selectors { + flex-direction: column; + } + + .compare-vs { + order: -1; + align-self: center; + } + } +} + +/* Modern Scroll Indicators */ +.scroll-indicator { + position: fixed; + top: 0; + left: 0; + width: 100%; + height: 3px; + background: var(--bg-secondary); + z-index: var(--z-sticky); +} + +.scroll-indicator-bar { + height: 100%; + background: linear-gradient(90deg, var(--primary), var(--primary-light)); + transition: width var(--transition-fast); +} + +/* Enhanced Empty States */ +.empty-state { + display: flex; + flex-direction: column; + align-items: center; + justify-content: center; + padding: var(--space-16) var(--space-8); + text-align: center; + color: var(--text-secondary); +} + +.empty-state-icon { + width: 64px; + height: 64px; + margin-bottom: var(--space-6); + opacity: 0.5; +} + +.empty-state-title { + font-size: var(--text-xl); + font-weight: var(--font-semibold); + color: var(--text-primary); + margin-bottom: var(--space-3); +} + +.empty-state-description { + font-size: var(--text-base); + line-height: 1.6; + max-width: 400px; } \ No newline at end of file diff --git a/dist/index.html b/dist/index.html index 274c19e..575a954 100644 --- a/dist/index.html +++ b/dist/index.html @@ -3,10 +3,28 @@ - - + + + + + + + + + + + + + + + + + + + + Debrid Services Comparison - Compare Pricing & Hosts diff --git a/dist/js/app-min.js b/dist/js/app-min.js index 3b2abda..01f11dd 100644 --- a/dist/js/app-min.js +++ b/dist/js/app-min.js @@ -1 +1 @@ -const Utils={debounce:(e,t=300,n=!1)=>{let a;return function(...s){const r=n&&!a;clearTimeout(a),a=setTimeout(()=>{a=null,n||e.apply(this,s)},t),r&&e.apply(this,s)}},throttle:(e,t)=>{let n;return function(){const a=arguments,s=this;n||(e.apply(s,a),n=!0,setTimeout(()=>n=!1,t))}},animateOnScroll:(e,t={})=>{const n=new IntersectionObserver(e=>{e.forEach(e=>{e.isIntersecting&&(e.target.classList.add("animate-in"),n.unobserve(e.target))})},{threshold:.1,rootMargin:"0px 0px -50px 0px",...t});e.forEach(e=>n.observe(e))}};class LoadingManager{constructor(){this.activeLoaders=new Set}show(e,t="Loading..."){const n=Date.now().toString(),a=document.createElement("div");return a.className="loading-overlay",a.setAttribute("data-loader-id",n),a.innerHTML=`\n
\n
\n
\n
\n
\n
\n

${t}

\n
\n `,"string"==typeof e&&(e=document.querySelector(e)),e.style.position="relative",e.appendChild(a),this.activeLoaders.add(n),requestAnimationFrame(()=>{a.classList.add("loading-overlay--visible")}),n}hide(e,t){"string"==typeof e&&(e=document.querySelector(e));const n=e.querySelector(`[data-loader-id="${t}"]`);n&&(n.classList.add("loading-overlay--hiding"),this.activeLoaders.delete(t),setTimeout(()=>{n.parentNode&&e.removeChild(n)},300))}hideAll(){this.activeLoaders.forEach(e=>{const t=document.querySelector(`[data-loader-id="${e}"]`);t&&this.hide(t.parentNode,e)})}}class TableManager{constructor(e,t,n,a={}){this.container=document.querySelector(`#${e}`),this.searchInput=document.querySelector(`#${t}`),this.clearIcon=document.querySelector(`#${n}`),this.options={sortable:!0,filterable:!0,pagination:!1,itemsPerPage:50,...a},this.currentData={},this.filteredData={},this.currentSort={column:null,direction:"asc"},this.currentPage=1,this._setupSearchFunctionality(),this._setupKeyboardNavigation()}generateTable(e={}){if(!Object.keys(e).length)return void(this.container.innerHTML='

No data available.

');this.currentData=e,this.filteredData={...e};const t=Object.keys(e[Object.keys(e)[0]]),n=this.container.id.replace("-container","");this.container.innerHTML=`\n
\n \n \n \n \n ${t.map(e=>`\n \n `).join("")}\n \n \n \n ${this._generateTableRows(this.filteredData,t)}\n \n
\n Service Name\n \n \n \n \n ${e}\n \n \n \n
\n
\n ${this.options.pagination?this._createPagination():""}\n `,this._setupTableFeatures(),this._setupAccessibility()}_generateTableRows(e,t){return Object.entries(e).map(([e,n])=>`\n \n \n
\n ${e}\n
\n \n ${t.map(e=>`\n \n \n ${"yes"===n[e]?'':''}\n \n \n `).join("")}\n \n `).join("")}_setupSearchFunctionality(){const e=Utils.debounce(()=>{const e=this.searchInput.value.toLowerCase().trim();e?(this.filteredData={},Object.entries(this.currentData).forEach(([t,n])=>{t.toLowerCase().includes(e)&&(this.filteredData[t]=n)}),this.clearIcon.style.display="block"):(this.filteredData={...this.currentData},this.clearIcon.style.display="none"),this._updateTableContent(),this._updateSearchResults(e)},300);this.searchInput?.addEventListener("input",e),this.searchInput?.addEventListener("keydown",e=>{"Escape"===e.key&&this._clearSearch()}),this.clearIcon?.addEventListener("click",()=>{this._clearSearch()})}_clearSearch(){this.searchInput.value="",this.filteredData={...this.currentData},this.clearIcon.style.display="none",this._updateTableContent(),this._updateSearchResults("")}_updateSearchResults(e){const t=Object.keys(this.filteredData).length,n=Object.keys(this.currentData).length;let a=this.container.querySelector(".search-results");a||(a=document.createElement("div"),a.className="search-results",this.container.insertBefore(a,this.container.querySelector(".table-wrapper"))),e?(a.textContent=`Showing ${t} of ${n} services`,a.style.display="block"):a.style.display="none"}_setupTableFeatures(){this.options.sortable&&this.container.querySelectorAll("th.sortable").forEach(e=>{e.addEventListener("click",()=>this._handleSort(e)),e.addEventListener("keydown",t=>{"Enter"!==t.key&&" "!==t.key||(t.preventDefault(),this._handleSort(e))})})}_handleSort(e){const t=e.getAttribute("data-column"),n="asc"===(this.currentSort.column===t?this.currentSort.direction:"asc")?"desc":"asc";this.currentSort={column:t,direction:n},this.container.querySelectorAll("th.sortable").forEach(e=>{e.setAttribute("aria-sort","none"),e.classList.remove("sorted-asc","sorted-desc")}),e.setAttribute("aria-sort","asc"===n?"ascending":"descending"),e.classList.add(`sorted-${n}`),this._sortData(),this._updateTableContent()}_sortData(){const{column:e,direction:t}=this.currentSort,n=Object.entries(this.filteredData);n.sort(([n,a],[s,r])=>{let i,o;return"service"===e?(i=n.toLowerCase(),o=s.toLowerCase()):(i="yes"===a[e]?1:0,o="yes"===r[e]?1:0),"asc"===t?i>o?1:io?-1:0}),this.filteredData=Object.fromEntries(n)}_updateTableContent(){const e=this.container.querySelector("tbody"),t=Object.keys(this.currentData[Object.keys(this.currentData)[0]]);e&&(e.innerHTML=this._generateTableRows(this.filteredData,t),this._setupTableFeatures())}_setupKeyboardNavigation(){this.container.addEventListener("keydown",e=>{!e.target.matches("th.sortable")||"Enter"!==e.key&&" "!==e.key||(e.preventDefault(),this._handleSort(e.target))})}_setupAccessibility(){const e=this.container.querySelector("table");e&&(e.setAttribute("role","grid"),e.setAttribute("aria-label","Debrid services comparison table"))}_createPagination(){return`\n \n `}}class ComparisonManager{constructor(e,t,n,a){this.container=document.querySelector(`#${e}`),this.select1=document.querySelector(`#${t}`),this.select2=document.querySelector(`#${n}`),this.data=a,this.isComparing=!1,this._populateDropdowns(),this._setupEventListeners(),this._setupKeyboardShortcuts()}_populateDropdowns(){const e=Object.keys(this.data[Object.keys(this.data)[0]]);[this.select1,this.select2].forEach((t,n)=>{t.innerHTML='',setTimeout(()=>{t.innerHTML='',e.forEach(e=>{const n=document.createElement("option");n.value=e,n.textContent=e,t.appendChild(n)})},100*(n+1))})}_generateCompareTable(){const e=this.select1.value,t=this.select2.value;if(!e||!t)return void this._showEmptyState();if(e===t)return void this._showSameProviderWarning();this.isComparing=!0;const n=loadingManager.show(this.container,"Generating comparison...");setTimeout(()=>{this._renderComparisonTable(e,t),loadingManager.hide(this.container,n),this._trackComparison(e,t)},500)}_renderComparisonTable(e,t){const n=this._calculateComparisonStats(e,t);this.container.innerHTML=`\n
\n

Comparing ${e} vs ${t}

\n
\n
\n Shared Support\n ${n.shared}\n
\n
\n ${e} Only\n ${n.provider1Only}\n
\n
\n ${t} Only\n ${n.provider2Only}\n
\n
\n
\n \n
\n
\n \n
\n \n \n \n
\n\n
\n \n \n \n \n \n \n \n \n \n \n ${this._generateComparisonRows(e,t)}\n \n
Service Name${e}${t}Status
\n
\n `,this.container.style.display="block",this._setupComparisonFeatures(),requestAnimationFrame(()=>{this.container.classList.add("comparison-visible")})}_generateComparisonRows(e,t){return Object.entries(this.data).map(([n,a])=>{const s="yes"===a[e],r="yes"===a[t];let i="",o="";return s&&r?(i="both-supported",o="Both"):s?(i="provider1-only",o=`${e} only`):r?(i="provider2-only",o=`${t} only`):(i="neither-supported",o="Neither"),`\n \n ${n}\n \n \n ${s?'':''}\n \n \n \n \n ${r?'':''}\n \n \n \n ${o}\n \n \n `}).join("")}_calculateComparisonStats(e,t){let n=0,a=0,s=0;return Object.values(this.data).forEach(r=>{const i="yes"===r[e],o="yes"===r[t];i&&o?n++:i?a++:o&&s++}),{shared:n,provider1Only:a,provider2Only:s}}_setupComparisonFeatures(){this.container.querySelector("#close-compare")?.addEventListener("click",()=>{this._closeComparison()}),this.container.querySelectorAll('input[name="comparison-filter"]').forEach(e=>{e.addEventListener("change",e=>{this._filterComparison(e.target.value)})})}_filterComparison(e){this.container.querySelectorAll(".comparison-row").forEach(t=>{const n=t.getAttribute("data-status");let a=!0;switch(e){case"both":a="both-supported"===n;break;case"different":a="provider1-only"===n||"provider2-only"===n;break;default:a=!0}t.style.display=a?"":"none"});const t=this.container.querySelectorAll('.comparison-row:not([style*="display: none"])').length;let n=this.container.querySelector(".filter-results");n||(n=document.createElement("div"),n.className="filter-results",this.container.querySelector(".table-wrapper").insertAdjacentElement("beforebegin",n)),n.textContent=`Showing ${t} services`}_closeComparison(){this.container.classList.add("comparison-hiding"),setTimeout(()=>{this.container.style.display="none",this.container.classList.remove("comparison-visible","comparison-hiding"),this.isComparing=!1,this._showEmptyState()},300)}_showEmptyState(){this.container.innerHTML='\n
\n
⚖️
\n

Ready to Compare

\n

Select two services above to see a detailed comparison

\n
\n ',this.container.style.display="block"}_showSameProviderWarning(){this.container.innerHTML='\n
\n
⚠️
\n

Same Service Selected

\n

Please select two different services to compare

\n
\n ',this.container.style.display="block"}_setupEventListeners(){[this.select1,this.select2].forEach(e=>{e?.addEventListener("change",()=>{this._generateCompareTable()})})}_setupKeyboardShortcuts(){document.addEventListener("keydown",e=>{this.isComparing&&"Escape"===e.key&&this._closeComparison()})}_trackComparison(e,t){"undefined"!=typeof gtag&>ag("event","comparison_generated",{provider_1:e,provider_2:t})}}class PricingManager{constructor(e){this.container=document.querySelector(`#${e}-table-container`),this.currentData=null}generatePricingTable(e={}){if(!e.plans?.length)return void(this.container.innerHTML='

Error: Invalid pricing data structure.

');this.currentData=e;const t=Object.keys(e.plans[0]).filter(e=>"name"!==e);this.container.innerHTML=`\n
\n \n \n \n \n ${t.map(e=>`\n \n `).join("")}\n \n \n \n ${e.plans.map((e,n)=>`\n \n \n ${t.map(t=>{const n=e[t],a=!isNaN(parseFloat(n));return`\n \n `}).join("")}\n \n `).join("")}\n \n
Plans\n
\n ${e}\n
\n
\n ${e.name}\n \n
\n ${n}\n ${a?'/month':""}\n
\n
\n
\n `,this._setupPricingFeatures()}_setupPricingFeatures(){this.container.querySelectorAll(".price-cell").forEach(e=>{e.addEventListener("mouseenter",()=>{const t=Array.from(e.parentNode.children).indexOf(e);this._highlightColumn(t)}),e.addEventListener("mouseleave",()=>{this._removeColumnHighlight()})})}_highlightColumn(e){this.container.querySelector("table").querySelectorAll(`td:nth-child(${e+1}), th:nth-child(${e+1})`).forEach(e=>e.classList.add("highlighted"))}_removeColumnHighlight(){this.container.querySelectorAll(".highlighted").forEach(e=>e.classList.remove("highlighted"))}}class PerformanceMonitor{constructor(){this.metrics={loadStart:performance.now(),domReady:null,fullyLoaded:null}}markDOMReady(){this.metrics.domReady=performance.now(),console.log(`DOM Ready: ${(this.metrics.domReady-this.metrics.loadStart).toFixed(2)}ms`)}markFullyLoaded(){this.metrics.fullyLoaded=performance.now(),console.log(`Fully Loaded: ${(this.metrics.fullyLoaded-this.metrics.loadStart).toFixed(2)}ms`)}getMetrics(){return{...this.metrics,totalLoadTime:this.metrics.fullyLoaded-this.metrics.loadStart,domLoadTime:this.metrics.domReady-this.metrics.loadStart}}}const loadingManager=new LoadingManager,performanceMonitor=new PerformanceMonitor;function setupURLComparison(){const e=new URLSearchParams(window.location.search),t=e.get("compare"),n=e.get("with");t&&n&&setTimeout(()=>{const e=document.querySelector("#provider1"),a=document.querySelector("#provider2");e&&a&&(e.value=t,a.value=n,e.dispatchEvent(new Event("change")))},1e3)}function setupScrollAnimations(){const e=document.querySelectorAll(".section, .card, .quick-nav-card");Utils.animateOnScroll(e)}function setupOfflineDetection(){window.addEventListener("online",()=>{console.log("Connection restored")}),window.addEventListener("offline",()=>{console.log("You are offline. Some features may not work.")})}document.addEventListener("DOMContentLoaded",async()=>{performanceMonitor.markDOMReady();try{const e=new TableManager("file-hosts-table-container","host-search-input","clear-host-search",{sortable:!0}),t=new TableManager("adult-hosts-table-container","adult-host-search-input","clear-adult-host-search",{sortable:!0}),n=new PricingManager("pricing"),a=loadingManager.show("#file-hosts-table-container","Loading file hosts..."),s=loadingManager.show("#adult-hosts-table-container","Loading adult hosts..."),r=loadingManager.show("#pricing-table-container","Loading pricing data..."),i=async(e,t=3)=>{for(let n=0;nsetTimeout(e,1e3*(n+1)))}},[o,l,c]=await Promise.allSettled([i("./json/file-hosts.json"),i("./json/adult-hosts.json"),i("./json/pricing.json")]);"fulfilled"===o.status?(loadingManager.hide("#file-hosts-table-container",a),e.generateTable(o.value),new ComparisonManager("compare-table-container","provider1","provider2",o.value)):(loadingManager.hide("#file-hosts-table-container",a),console.error("File hosts error:",o.reason)),"fulfilled"===l.status?(loadingManager.hide("#adult-hosts-table-container",s),t.generateTable(l.value)):(loadingManager.hide("#adult-hosts-table-container",s),console.error("Adult hosts error:",l.reason)),"fulfilled"===c.status?(loadingManager.hide("#pricing-table-container",r),n.generatePricingTable(c.value)):(loadingManager.hide("#pricing-table-container",r),console.error("Pricing error:",c.reason)),setupURLComparison(),setupScrollAnimations(),setupOfflineDetection(),performanceMonitor.markFullyLoaded()}catch(e){console.error("Critical error initializing application:",e),loadingManager.hideAll()}}),window.addEventListener("error",e=>{console.error("Global error:",e.error)}),window.addEventListener("unhandledrejection",e=>{console.error("Unhandled promise rejection:",e.reason),e.preventDefault()}); \ No newline at end of file +const Utils={debounce:(e,t=300,s=!1)=>{let n;return function(...i){const a=s&&!n;clearTimeout(n),n=setTimeout(()=>{n=null,s||e.apply(this,i)},t),a&&e.apply(this,i)}},throttle:(e,t)=>{let s;return function(){const n=arguments,i=this;s||(e.apply(i,n),s=!0,setTimeout(()=>s=!1,t))}},animateOnScroll:(e,t={})=>{const s=new IntersectionObserver(e=>{e.forEach(e=>{e.isIntersecting&&(e.target.classList.add("animate-in"),s.unobserve(e.target))})},{threshold:.1,rootMargin:"0px 0px -50px 0px",...t});e.forEach(e=>s.observe(e))}};class LoadingManager{constructor(){this.activeLoaders=new Set}show(e,t="Loading..."){const s=Date.now().toString(),n=document.createElement("div");return n.className="loading-overlay",n.setAttribute("data-loader-id",s),n.innerHTML=`\n
\n
\n
\n
\n
\n
\n

${t}

\n
\n `,"string"==typeof e&&(e=document.querySelector(e)),e.style.position="relative",e.appendChild(n),this.activeLoaders.add(s),requestAnimationFrame(()=>{n.classList.add("loading-overlay--visible")}),s}hide(e,t){"string"==typeof e&&(e=document.querySelector(e));const s=e.querySelector(`[data-loader-id="${t}"]`);s&&(s.classList.add("loading-overlay--hiding"),this.activeLoaders.delete(t),setTimeout(()=>{s.parentNode&&e.removeChild(s)},300))}hideAll(){this.activeLoaders.forEach(e=>{const t=document.querySelector(`[data-loader-id="${e}"]`);t&&this.hide(t.parentNode,e)})}}class TableManager{constructor(e,t,s,n={}){this.container=document.querySelector(`#${e}`),this.searchInput=document.querySelector(`#${t}`),this.clearIcon=document.querySelector(`#${s}`),this.options={sortable:!0,filterable:!0,pagination:!1,itemsPerPage:50,...n},this.currentData={},this.filteredData={},this.currentSort={column:null,direction:"asc"},this.currentPage=1,this._setupSearchFunctionality(),this._setupKeyboardNavigation()}generateTable(e={}){if(!Object.keys(e).length)return void(this.container.innerHTML='

No data available.

');this.currentData=e,this.filteredData={...e};const t=Object.keys(e[Object.keys(e)[0]]),s=this.container.id.replace("-container","");this.container.innerHTML=`\n
\n \n \n \n \n ${t.map(e=>`\n \n `).join("")}\n \n \n \n ${this._generateTableRows(this.filteredData,t)}\n \n
\n Service Name\n \n \n \n \n ${e}\n \n \n \n
\n
\n ${this.options.pagination?this._createPagination():""}\n `,this._setupTableFeatures(),this._setupAccessibility()}_generateTableRows(e,t){return Object.entries(e).map(([e,s])=>`\n \n \n
\n ${e}\n
\n \n ${t.map(e=>`\n \n \n ${"yes"===s[e]?'':''}\n \n \n `).join("")}\n \n `).join("")}_setupSearchFunctionality(){const e=Utils.debounce(()=>{const e=this.searchInput.value.toLowerCase().trim();e?(this.filteredData={},Object.entries(this.currentData).forEach(([t,s])=>{t.toLowerCase().includes(e)&&(this.filteredData[t]=s)}),this.clearIcon.style.display="block"):(this.filteredData={...this.currentData},this.clearIcon.style.display="none"),this._updateTableContent(),this._updateSearchResults(e)},300);this.searchInput?.addEventListener("input",e),this.searchInput?.addEventListener("keydown",e=>{"Escape"===e.key&&this._clearSearch()}),this.clearIcon?.addEventListener("click",()=>{this._clearSearch()})}_clearSearch(){this.searchInput.value="",this.filteredData={...this.currentData},this.clearIcon.style.display="none",this._updateTableContent(),this._updateSearchResults("")}_updateSearchResults(e){const t=Object.keys(this.filteredData).length,s=Object.keys(this.currentData).length;let n=this.container.querySelector(".search-results");n||(n=document.createElement("div"),n.className="search-results",this.container.insertBefore(n,this.container.querySelector(".table-wrapper"))),e?(n.textContent=`Showing ${t} of ${s} services`,n.style.display="block"):n.style.display="none"}_setupTableFeatures(){this.options.sortable&&this.container.querySelectorAll("th.sortable").forEach(e=>{e.addEventListener("click",()=>this._handleSort(e)),e.addEventListener("keydown",t=>{"Enter"!==t.key&&" "!==t.key||(t.preventDefault(),this._handleSort(e))})})}_handleSort(e){const t=e.getAttribute("data-column"),s="asc"===(this.currentSort.column===t?this.currentSort.direction:"asc")?"desc":"asc";this.currentSort={column:t,direction:s},this.container.querySelectorAll("th.sortable").forEach(e=>{e.setAttribute("aria-sort","none"),e.classList.remove("sorted-asc","sorted-desc")}),e.setAttribute("aria-sort","asc"===s?"ascending":"descending"),e.classList.add(`sorted-${s}`),this._sortData(),this._updateTableContent()}_sortData(){const{column:e,direction:t}=this.currentSort,s=Object.entries(this.filteredData);s.sort(([s,n],[i,a])=>{let r,o;return"service"===e?(r=s.toLowerCase(),o=i.toLowerCase()):(r="yes"===n[e]?1:0,o="yes"===a[e]?1:0),"asc"===t?r>o?1:ro?-1:0}),this.filteredData=Object.fromEntries(s)}_updateTableContent(){const e=this.container.querySelector("tbody"),t=Object.keys(this.currentData[Object.keys(this.currentData)[0]]);e&&(e.innerHTML=this._generateTableRows(this.filteredData,t),this._setupTableFeatures())}_setupKeyboardNavigation(){this.container.addEventListener("keydown",e=>{!e.target.matches("th.sortable")||"Enter"!==e.key&&" "!==e.key||(e.preventDefault(),this._handleSort(e.target))})}_setupAccessibility(){const e=this.container.querySelector("table");e&&(e.setAttribute("role","grid"),e.setAttribute("aria-label","Debrid services comparison table"))}_createPagination(){return`\n \n `}}class ComparisonManager{constructor(e,t,s,n){this.container=document.querySelector(`#${e}`),this.select1=document.querySelector(`#${t}`),this.select2=document.querySelector(`#${s}`),this.data=n,this.isComparing=!1,this._populateDropdowns(),this._setupEventListeners(),this._setupKeyboardShortcuts()}_populateDropdowns(){const e=Object.keys(this.data[Object.keys(this.data)[0]]);[this.select1,this.select2].forEach((t,s)=>{t.innerHTML='',setTimeout(()=>{t.innerHTML='',e.forEach(e=>{const s=document.createElement("option");s.value=e,s.textContent=e,t.appendChild(s)})},100*(s+1))})}_generateCompareTable(){const e=this.select1.value,t=this.select2.value;if(!e||!t)return void this._showEmptyState();if(e===t)return void this._showSameProviderWarning();this.isComparing=!0;const s=loadingManager.show(this.container,"Generating comparison...");setTimeout(()=>{this._renderComparisonTable(e,t),loadingManager.hide(this.container,s),this._trackComparison(e,t)},500)}_renderComparisonTable(e,t){const s=this._calculateComparisonStats(e,t);this.container.innerHTML=`\n
\n

Comparing ${e} vs ${t}

\n
\n
\n Shared Support\n ${s.shared}\n
\n
\n ${e} Only\n ${s.provider1Only}\n
\n
\n ${t} Only\n ${s.provider2Only}\n
\n
\n
\n \n
\n
\n \n
\n \n \n \n
\n\n
\n \n \n \n \n \n \n \n \n \n \n ${this._generateComparisonRows(e,t)}\n \n
Service Name${e}${t}Status
\n
\n `,this.container.style.display="block",this._setupComparisonFeatures(),requestAnimationFrame(()=>{this.container.classList.add("comparison-visible")})}_generateComparisonRows(e,t){return Object.entries(this.data).map(([s,n])=>{const i="yes"===n[e],a="yes"===n[t];let r="",o="";return i&&a?(r="both-supported",o="Both"):i?(r="provider1-only",o=`${e} only`):a?(r="provider2-only",o=`${t} only`):(r="neither-supported",o="Neither"),`\n \n ${s}\n \n \n ${i?'':''}\n \n \n \n \n ${a?'':''}\n \n \n \n ${o}\n \n \n `}).join("")}_calculateComparisonStats(e,t){let s=0,n=0,i=0;return Object.values(this.data).forEach(a=>{const r="yes"===a[e],o="yes"===a[t];r&&o?s++:r?n++:o&&i++}),{shared:s,provider1Only:n,provider2Only:i}}_setupComparisonFeatures(){this.container.querySelector("#close-compare")?.addEventListener("click",()=>{this._closeComparison()}),this.container.querySelectorAll('input[name="comparison-filter"]').forEach(e=>{e.addEventListener("change",e=>{this._filterComparison(e.target.value)})})}_filterComparison(e){this.container.querySelectorAll(".comparison-row").forEach(t=>{const s=t.getAttribute("data-status");let n=!0;switch(e){case"both":n="both-supported"===s;break;case"different":n="provider1-only"===s||"provider2-only"===s;break;default:n=!0}t.style.display=n?"":"none"});const t=this.container.querySelectorAll('.comparison-row:not([style*="display: none"])').length;let s=this.container.querySelector(".filter-results");s||(s=document.createElement("div"),s.className="filter-results",this.container.querySelector(".table-wrapper").insertAdjacentElement("beforebegin",s)),s.textContent=`Showing ${t} services`}_closeComparison(){this.container.classList.add("comparison-hiding"),setTimeout(()=>{this.container.style.display="none",this.container.classList.remove("comparison-visible","comparison-hiding"),this.isComparing=!1,this._showEmptyState()},300)}_showEmptyState(){this.container.innerHTML='\n
\n
⚖️
\n

Ready to Compare

\n

Select two services above to see a detailed comparison

\n
\n ',this.container.style.display="block"}_showSameProviderWarning(){this.container.innerHTML='\n
\n
⚠️
\n

Same Service Selected

\n

Please select two different services to compare

\n
\n ',this.container.style.display="block"}_setupEventListeners(){[this.select1,this.select2].forEach(e=>{e?.addEventListener("change",()=>{this._generateCompareTable()})})}_setupKeyboardShortcuts(){document.addEventListener("keydown",e=>{this.isComparing&&"Escape"===e.key&&this._closeComparison()})}_trackComparison(e,t){"undefined"!=typeof gtag&>ag("event","comparison_generated",{provider_1:e,provider_2:t})}}class PricingManager{constructor(e){this.container=document.querySelector(`#${e}-table-container`),this.currentData=null}generatePricingTable(e={}){if(!e.plans?.length)return void(this.container.innerHTML='

Error: Invalid pricing data structure.

');this.currentData=e;const t=Object.keys(e.plans[0]).filter(e=>"name"!==e);this.container.innerHTML=`\n
\n \n \n \n \n ${t.map(e=>`\n \n `).join("")}\n \n \n \n ${e.plans.map((e,s)=>`\n \n \n ${t.map(t=>{const s=e[t],n=!isNaN(parseFloat(s));return`\n \n `}).join("")}\n \n `).join("")}\n \n
Plans\n
\n ${e}\n
\n
\n ${e.name}\n \n
\n ${s}\n ${n?'/month':""}\n
\n
\n
\n `,this._setupPricingFeatures()}_setupPricingFeatures(){this.container.querySelectorAll(".price-cell").forEach(e=>{e.addEventListener("mouseenter",()=>{const t=Array.from(e.parentNode.children).indexOf(e);this._highlightColumn(t)}),e.addEventListener("mouseleave",()=>{this._removeColumnHighlight()})})}_highlightColumn(e){this.container.querySelector("table").querySelectorAll(`td:nth-child(${e+1}), th:nth-child(${e+1})`).forEach(e=>e.classList.add("highlighted"))}_removeColumnHighlight(){this.container.querySelectorAll(".highlighted").forEach(e=>e.classList.remove("highlighted"))}}class PerformanceMonitor{constructor(){this.metrics={loadStart:performance.now(),domReady:null,fullyLoaded:null}}markDOMReady(){this.metrics.domReady=performance.now(),console.log(`DOM Ready: ${(this.metrics.domReady-this.metrics.loadStart).toFixed(2)}ms`)}markFullyLoaded(){this.metrics.fullyLoaded=performance.now(),console.log(`Fully Loaded: ${(this.metrics.fullyLoaded-this.metrics.loadStart).toFixed(2)}ms`)}getMetrics(){return{...this.metrics,totalLoadTime:this.metrics.fullyLoaded-this.metrics.loadStart,domLoadTime:this.metrics.domReady-this.metrics.loadStart}}}const loadingManager=new LoadingManager,performanceMonitor=new PerformanceMonitor;function setupURLComparison(){const e=new URLSearchParams(window.location.search),t=e.get("compare"),s=e.get("with");t&&s&&setTimeout(()=>{const e=document.querySelector("#provider1"),n=document.querySelector("#provider2");e&&n&&(e.value=t,n.value=s,e.dispatchEvent(new Event("change")))},1e3)}function setupScrollAnimations(){const e=document.querySelectorAll(".section, .card, .quick-nav-card");Utils.animateOnScroll(e)}function setupOfflineDetection(){window.addEventListener("online",()=>{console.log("Connection restored")}),window.addEventListener("offline",()=>{console.log("You are offline. Some features may not work.")})}document.addEventListener("DOMContentLoaded",async()=>{performanceMonitor.markDOMReady();try{const e=new TableManager("file-hosts-table-container","host-search-input","clear-host-search",{sortable:!0}),t=new TableManager("adult-hosts-table-container","adult-host-search-input","clear-adult-host-search",{sortable:!0}),s=new PricingManager("pricing"),n=loadingManager.show("#file-hosts-table-container","Loading file hosts..."),i=loadingManager.show("#adult-hosts-table-container","Loading adult hosts..."),a=loadingManager.show("#pricing-table-container","Loading pricing data..."),r=async(e,t=3)=>{for(let s=0;ssetTimeout(e,1e3*(s+1)))}},[o,l,c]=await Promise.allSettled([r("./json/file-hosts.json"),r("./json/adult-hosts.json"),r("./json/pricing.json")]);"fulfilled"===o.status?(loadingManager.hide("#file-hosts-table-container",n),e.generateTable(o.value),new ComparisonManager("compare-table-container","provider1","provider2",o.value)):(loadingManager.hide("#file-hosts-table-container",n),console.error("File hosts error:",o.reason)),"fulfilled"===l.status?(loadingManager.hide("#adult-hosts-table-container",i),t.generateTable(l.value)):(loadingManager.hide("#adult-hosts-table-container",i),console.error("Adult hosts error:",l.reason)),"fulfilled"===c.status?(loadingManager.hide("#pricing-table-container",a),s.generatePricingTable(c.value)):(loadingManager.hide("#pricing-table-container",a),console.error("Pricing error:",c.reason)),setupURLComparison(),setupScrollAnimations(),setupOfflineDetection(),performanceMonitor.markFullyLoaded()}catch(e){console.error("Critical error initializing application:",e),loadingManager.hideAll()}}),window.addEventListener("error",e=>{console.error("Global error:",e.error)}),window.addEventListener("unhandledrejection",e=>{console.error("Unhandled promise rejection:",e.reason),e.preventDefault()});class TouchGestureManager{constructor(){this.touchStart=null,this.touchEnd=null,this.minSwipeDistance=100,this.maxSwipeTime=300,this.setupTouchListeners()}setupTouchListeners(){document.addEventListener("touchstart",e=>{this.touchStart={x:e.changedTouches[0].screenX,y:e.changedTouches[0].screenY,time:Date.now()}},{passive:!0}),document.addEventListener("touchend",e=>{this.touchStart&&(this.touchEnd={x:e.changedTouches[0].screenX,y:e.changedTouches[0].screenY,time:Date.now()},this.handleSwipe())},{passive:!0})}handleSwipe(){if(!this.touchStart||!this.touchEnd)return;const e=this.touchEnd.x-this.touchStart.x,t=this.touchEnd.y-this.touchStart.y;if(this.touchEnd.time-this.touchStart.time>this.maxSwipeTime)return;Math.sqrt(e*e+t*t)Math.abs(t)?e>0?this.dispatchSwipeEvent("swiperight"):this.dispatchSwipeEvent("swipeleft"):t>0?this.dispatchSwipeEvent("swipedown"):this.dispatchSwipeEvent("swipeup"))}dispatchSwipeEvent(e){document.dispatchEvent(new CustomEvent(e,{detail:{startPos:this.touchStart,endPos:this.touchEnd}}))}}class VirtualScrollManager{constructor(e,t=50){this.container=e,this.itemHeight=t,this.viewportHeight=e.clientHeight,this.totalItems=0,this.visibleStart=0,this.visibleEnd=0,this.scrollContent=null,this.renderCallback=null}init(e,t){this.totalItems=e.length,this.renderCallback=t,this.setupVirtualScroll(),this.updateVisibleRange()}setupVirtualScroll(){this.container.innerHTML=`\n
\n
\n
\n `,this.scrollContent=this.container.querySelector(".virtual-scroll-viewport"),this.container.addEventListener("scroll",Utils.throttle(()=>{this.updateVisibleRange()},16))}updateVisibleRange(){const e=this.container.scrollTop,t=Math.ceil(this.viewportHeight/this.itemHeight);this.visibleStart=Math.max(0,Math.floor(e/this.itemHeight)-t),this.visibleEnd=Math.min(this.totalItems,this.visibleStart+3*t),this.renderVisibleItems()}renderVisibleItems(){if(!this.renderCallback)return;const e=document.createDocumentFragment();for(let t=this.visibleStart;t{this.handleInput(e.target.value)},300)),this.input.addEventListener("keydown",e=>{this.handleKeyDown(e)}),this.input.addEventListener("blur",()=>{setTimeout(()=>this.hideSuggestions(),200)}),document.addEventListener("click",e=>{this.input.contains(e.target)||this.suggestionsContainer.contains(e.target)||this.hideSuggestions()})}async handleInput(e){if(e.length<2)this.hideSuggestions();else try{this.suggestions=await this.fetchSuggestions(e),this.renderSuggestions()}catch(e){console.error("Error fetching suggestions:",e)}}async fetchSuggestions(e){return Object.keys(window.fileHostsData||{}).filter(t=>t.toLowerCase().includes(e.toLowerCase())).slice(0,5)}renderSuggestions(){0!==this.suggestions.length?(this.suggestionsContainer.innerHTML=this.suggestions.map((e,t)=>`\n
\n ${this.highlightMatch(e,this.input.value)}\n
\n `).join(""),this.suggestionsContainer.classList.add("visible"),this.currentIndex=-1,this.suggestionsContainer.querySelectorAll(".search-suggestion").forEach((e,t)=>{e.addEventListener("click",()=>{this.selectSuggestion(t)})})):this.hideSuggestions()}highlightMatch(e,t){const s=new RegExp(`(${t})`,"gi");return e.replace(s,"$1")}handleKeyDown(e){if(this.suggestionsContainer.classList.contains("visible"))switch(e.key){case"ArrowDown":e.preventDefault(),this.navigateSuggestions(1);break;case"ArrowUp":e.preventDefault(),this.navigateSuggestions(-1);break;case"Enter":e.preventDefault(),this.currentIndex>=0&&this.selectSuggestion(this.currentIndex);break;case"Escape":this.hideSuggestions()}}navigateSuggestions(e){const t=this.suggestionsContainer.querySelectorAll(".search-suggestion");this.currentIndex>=0&&t[this.currentIndex].classList.remove("highlighted"),this.currentIndex+=e,this.currentIndex<0&&(this.currentIndex=t.length-1),this.currentIndex>=t.length&&(this.currentIndex=0),t[this.currentIndex].classList.add("highlighted"),t[this.currentIndex].scrollIntoView({block:"nearest"})}selectSuggestion(e){this.input.value=this.suggestions[e],this.hideSuggestions(),this.input.dispatchEvent(new Event("input"))}hideSuggestions(){this.suggestionsContainer.classList.remove("visible"),this.currentIndex=-1}}class PullToRefreshManager{constructor(e,t){this.container=e,this.callback=t,this.isRefreshing=!1,this.startY=0,this.currentY=0,this.threshold=80,this.setupPullToRefresh()}setupPullToRefresh(){this.container.classList.add("pull-to-refresh");const e=document.createElement("div");e.className="pull-to-refresh-indicator",e.innerHTML='
',this.container.appendChild(e),this.container.addEventListener("touchstart",e=>{0!==this.container.scrollTop||this.isRefreshing||(this.startY=e.touches[0].clientY)},{passive:!0}),this.container.addEventListener("touchmove",e=>{if(this.startY&&!this.isRefreshing){this.currentY=e.touches[0].clientY;const t=this.currentY-this.startY;if(t>0&&0===this.container.scrollTop){e.preventDefault();Math.min(t/this.threshold,1);t>this.threshold&&this.container.classList.add("pulling")}}},{passive:!1}),this.container.addEventListener("touchend",()=>{if(this.startY&&this.currentY&&!this.isRefreshing){this.currentY-this.startY>this.threshold&&this.triggerRefresh()}this.container.classList.remove("pulling"),this.startY=0,this.currentY=0},{passive:!0})}async triggerRefresh(){if(!this.isRefreshing){this.isRefreshing=!0;try{await this.callback()}catch(e){console.error("Refresh failed:",e)}finally{this.isRefreshing=!1}}}}class ToastManager{constructor(){this.container=this.createContainer(),this.toasts=new Map}createContainer(){let e=document.querySelector(".toast-container");return e||(e=document.createElement("div"),e.className="toast-container",document.body.appendChild(e)),e}show(e,t="info",s=3e3){const n=Date.now().toString(),i=this.createToast(e,t,n);return this.container.appendChild(i),this.toasts.set(n,i),s>0&&setTimeout(()=>{this.remove(n)},s),n}createToast(e,t,s){const n=document.createElement("div");n.className=`toast ${t}`,n.setAttribute("data-toast-id",s),n.innerHTML=`\n
\n ${e}\n \n
\n `;return n.querySelector(".toast-close").addEventListener("click",()=>{this.remove(s)}),n}remove(e){const t=this.toasts.get(e);t&&(t.style.animation="slideOutRight 0.3s ease forwards",setTimeout(()=>{t.parentNode&&this.container.removeChild(t),this.toasts.delete(e)},300))}success(e,t=3e3){return this.show(e,"success",t)}error(e,t=5e3){return this.show(e,"error",t)}warning(e,t=4e3){return this.show(e,"warning",t)}info(e,t=3e3){return this.show(e,"info",t)}}class MobileNavManager{constructor(){this.setupMobileNav()}setupMobileNav(){window.innerWidth<=768&&this.createMobileNav(),window.addEventListener("resize",Utils.debounce(()=>{window.innerWidth<=768?this.createMobileNav():this.removeMobileNav()},300))}createMobileNav(){if(document.querySelector(".mobile-nav-toggle"))return;const e=document.createElement("button");e.className="mobile-nav-toggle",e.innerHTML="☰",e.setAttribute("aria-label","Toggle mobile navigation");const t=document.createElement("div");t.className="mobile-nav-menu",t.innerHTML='\n Pricing\n File Hosts\n Compare\n Adult Hosts\n Status\n ',document.body.appendChild(e),document.body.appendChild(t),e.addEventListener("click",()=>{t.classList.toggle("visible")}),document.addEventListener("click",s=>{e.contains(s.target)||t.contains(s.target)||t.classList.remove("visible")}),t.querySelectorAll(".mobile-nav-item").forEach(e=>{e.addEventListener("click",()=>{t.classList.remove("visible")})})}removeMobileNav(){const e=document.querySelector(".mobile-nav-toggle"),t=document.querySelector(".mobile-nav-menu");e&&e.remove(),t&&t.remove()}}class ProgressiveEnhancementManager{constructor(){this.features=new Map,this.detectFeatures()}detectFeatures(){this.features.set("intersectionObserver","IntersectionObserver"in window),this.features.set("webp",this.supportsWebP()),this.features.set("serviceWorker","serviceWorker"in navigator),this.features.set("touchEvents","ontouchstart"in window),this.features.set("pointerEvents","PointerEvent"in window),this.features.set("containerQueries",CSS.supports("container-type: inline-size"))}async supportsWebP(){return new Promise(e=>{const t=new Image;t.onload=t.onerror=()=>{e(2===t.height)},t.src="data:image/webp;base64,UklGRjoAAABXRUJQVlA4IC4AAACyAgCdASoCAAIALmk0mk0iIiIiIgBoSygABc6WWgAA/veff/0PP8bA//LwYAAA"})}hasFeature(e){return this.features.get(e)||!1}enhanceIfSupported(e,t){this.hasFeature(e)&&t()}}const touchGestureManager=new TouchGestureManager,toastManager=new ToastManager,mobileNavManager=new MobileNavManager,progressiveEnhancementManager=new ProgressiveEnhancementManager;if(document.addEventListener("DOMContentLoaded",()=>{const e=document.querySelector("#file-host-search"),t=document.createElement("div");t.className="search-suggestions",e&&(e.parentNode.classList.add("search-container"),e.parentNode.appendChild(t),new SearchManager(e,t));const s=document.querySelector("#adult-host-search"),n=document.createElement("div");if(n.className="search-suggestions",s&&(s.parentNode.classList.add("search-container"),s.parentNode.appendChild(n),new SearchManager(s,n)),progressiveEnhancementManager.hasFeature("touchEvents")){const e=document.querySelector("main");e&&new PullToRefreshManager(e,async()=>{toastManager.info("Refreshing data..."),await new Promise(e=>setTimeout(e,1e3)),window.location.reload()})}const i=document.createElement("div");i.className="scroll-indicator",i.innerHTML='
',document.body.appendChild(i);window.addEventListener("scroll",Utils.throttle(()=>{const e=(document.body.scrollTop||document.documentElement.scrollTop)/(document.documentElement.scrollHeight-document.documentElement.clientHeight)*100;i.querySelector(".scroll-indicator-bar").style.width=e+"%"},16))}),document.addEventListener("swipeleft",e=>{console.log("Swiped left")}),document.addEventListener("swiperight",e=>{console.log("Swiped right")}),progressiveEnhancementManager.hasFeature("serviceWorker")&&navigator.serviceWorker.register("/sw.js").then(e=>{console.log("ServiceWorker registration successful"),e.addEventListener("updatefound",()=>{const t=e.installing;t.addEventListener("statechange",()=>{"installed"===t.state&&navigator.serviceWorker.controller&&toastManager.info("New version available! Refresh to update.",0)})})}).catch(e=>{console.log("ServiceWorker registration failed:",e)}),"PerformanceObserver"in window){const e=new PerformanceObserver(e=>{for(const t of e.getEntries())"largest-contentful-paint"===t.entryType&&console.log(`LCP: ${t.startTime}ms`),"first-input"===t.entryType&&console.log(`FID: ${t.processingStart-t.startTime}ms`)});try{e.observe({entryTypes:["largest-contentful-paint","first-input"]})}catch(e){console.log("Performance observation not supported")}} \ No newline at end of file diff --git a/dist/js/app.js b/dist/js/app.js index 88af086..f79fdfe 100644 --- a/dist/js/app.js +++ b/dist/js/app.js @@ -934,4 +934,654 @@ window.addEventListener('error', (event) => { window.addEventListener('unhandledrejection', (event) => { console.error('Unhandled promise rejection:', event.reason); event.preventDefault(); -}); \ No newline at end of file +}); + +// ===== MODERN MOBILE-FIRST ENHANCEMENTS ===== + +// Enhanced Touch Gesture Support +class TouchGestureManager { + constructor() { + this.touchStart = null; + this.touchEnd = null; + this.minSwipeDistance = 100; + this.maxSwipeTime = 300; + this.setupTouchListeners(); + } + + setupTouchListeners() { + document.addEventListener('touchstart', (e) => { + this.touchStart = { + x: e.changedTouches[0].screenX, + y: e.changedTouches[0].screenY, + time: Date.now() + }; + }, { passive: true }); + + document.addEventListener('touchend', (e) => { + if (!this.touchStart) return; + + this.touchEnd = { + x: e.changedTouches[0].screenX, + y: e.changedTouches[0].screenY, + time: Date.now() + }; + + this.handleSwipe(); + }, { passive: true }); + } + + handleSwipe() { + if (!this.touchStart || !this.touchEnd) return; + + const deltaX = this.touchEnd.x - this.touchStart.x; + const deltaY = this.touchEnd.y - this.touchStart.y; + const deltaTime = this.touchEnd.time - this.touchStart.time; + + if (deltaTime > this.maxSwipeTime) return; + + const distance = Math.sqrt(deltaX * deltaX + deltaY * deltaY); + if (distance < this.minSwipeDistance) return; + + // Determine swipe direction + if (Math.abs(deltaX) > Math.abs(deltaY)) { + // Horizontal swipe + if (deltaX > 0) { + this.dispatchSwipeEvent('swiperight'); + } else { + this.dispatchSwipeEvent('swipeleft'); + } + } else { + // Vertical swipe + if (deltaY > 0) { + this.dispatchSwipeEvent('swipedown'); + } else { + this.dispatchSwipeEvent('swipeup'); + } + } + } + + dispatchSwipeEvent(type) { + document.dispatchEvent(new CustomEvent(type, { + detail: { + startPos: this.touchStart, + endPos: this.touchEnd + } + })); + } +} + +// Virtual Scrolling for Large Datasets +class VirtualScrollManager { + constructor(container, itemHeight = 50) { + this.container = container; + this.itemHeight = itemHeight; + this.viewportHeight = container.clientHeight; + this.totalItems = 0; + this.visibleStart = 0; + this.visibleEnd = 0; + this.scrollContent = null; + this.renderCallback = null; + } + + init(items, renderCallback) { + this.totalItems = items.length; + this.renderCallback = renderCallback; + this.setupVirtualScroll(); + this.updateVisibleRange(); + } + + setupVirtualScroll() { + this.container.innerHTML = ` +
+
+
+ `; + + this.scrollContent = this.container.querySelector('.virtual-scroll-viewport'); + + this.container.addEventListener('scroll', Utils.throttle(() => { + this.updateVisibleRange(); + }, 16)); // 60fps + } + + updateVisibleRange() { + const scrollTop = this.container.scrollTop; + const buffer = Math.ceil(this.viewportHeight / this.itemHeight); + + this.visibleStart = Math.max(0, Math.floor(scrollTop / this.itemHeight) - buffer); + this.visibleEnd = Math.min(this.totalItems, this.visibleStart + buffer * 3); + + this.renderVisibleItems(); + } + + renderVisibleItems() { + if (!this.renderCallback) return; + + const fragment = document.createDocumentFragment(); + + for (let i = this.visibleStart; i < this.visibleEnd; i++) { + const item = this.renderCallback(i); + item.style.position = 'absolute'; + item.style.top = `${i * this.itemHeight}px`; + item.style.height = `${this.itemHeight}px`; + item.style.width = '100%'; + fragment.appendChild(item); + } + + this.scrollContent.innerHTML = ''; + this.scrollContent.appendChild(fragment); + } +} + +// Enhanced Search with Debouncing and Suggestions +class SearchManager { + constructor(input, suggestionsContainer) { + this.input = input; + this.suggestionsContainer = suggestionsContainer; + this.currentIndex = -1; + this.suggestions = []; + this.setupEventListeners(); + } + + setupEventListeners() { + this.input.addEventListener('input', Utils.debounce((e) => { + this.handleInput(e.target.value); + }, 300)); + + this.input.addEventListener('keydown', (e) => { + this.handleKeyDown(e); + }); + + this.input.addEventListener('blur', () => { + setTimeout(() => this.hideSuggestions(), 200); + }); + + document.addEventListener('click', (e) => { + if (!this.input.contains(e.target) && !this.suggestionsContainer.contains(e.target)) { + this.hideSuggestions(); + } + }); + } + + async handleInput(query) { + if (query.length < 2) { + this.hideSuggestions(); + return; + } + + try { + this.suggestions = await this.fetchSuggestions(query); + this.renderSuggestions(); + } catch (error) { + console.error('Error fetching suggestions:', error); + } + } + + async fetchSuggestions(query) { + // In a real app, this would fetch from an API + // For now, we'll filter from existing data + const allHosts = Object.keys(window.fileHostsData || {}); + return allHosts + .filter(host => host.toLowerCase().includes(query.toLowerCase())) + .slice(0, 5); + } + + renderSuggestions() { + if (this.suggestions.length === 0) { + this.hideSuggestions(); + return; + } + + this.suggestionsContainer.innerHTML = this.suggestions + .map((suggestion, index) => ` +
+ ${this.highlightMatch(suggestion, this.input.value)} +
+ `) + .join(''); + + this.suggestionsContainer.classList.add('visible'); + this.currentIndex = -1; + + // Add click listeners + this.suggestionsContainer.querySelectorAll('.search-suggestion').forEach((el, index) => { + el.addEventListener('click', () => { + this.selectSuggestion(index); + }); + }); + } + + highlightMatch(text, query) { + const regex = new RegExp(`(${query})`, 'gi'); + return text.replace(regex, '$1'); + } + + handleKeyDown(e) { + if (!this.suggestionsContainer.classList.contains('visible')) return; + + switch (e.key) { + case 'ArrowDown': + e.preventDefault(); + this.navigateSuggestions(1); + break; + case 'ArrowUp': + e.preventDefault(); + this.navigateSuggestions(-1); + break; + case 'Enter': + e.preventDefault(); + if (this.currentIndex >= 0) { + this.selectSuggestion(this.currentIndex); + } + break; + case 'Escape': + this.hideSuggestions(); + break; + } + } + + navigateSuggestions(direction) { + const suggestions = this.suggestionsContainer.querySelectorAll('.search-suggestion'); + + // Remove current highlight + if (this.currentIndex >= 0) { + suggestions[this.currentIndex].classList.remove('highlighted'); + } + + // Update index + this.currentIndex += direction; + if (this.currentIndex < 0) this.currentIndex = suggestions.length - 1; + if (this.currentIndex >= suggestions.length) this.currentIndex = 0; + + // Add new highlight + suggestions[this.currentIndex].classList.add('highlighted'); + suggestions[this.currentIndex].scrollIntoView({ block: 'nearest' }); + } + + selectSuggestion(index) { + this.input.value = this.suggestions[index]; + this.hideSuggestions(); + this.input.dispatchEvent(new Event('input')); + } + + hideSuggestions() { + this.suggestionsContainer.classList.remove('visible'); + this.currentIndex = -1; + } +} + +// Pull-to-Refresh for Mobile +class PullToRefreshManager { + constructor(container, callback) { + this.container = container; + this.callback = callback; + this.isRefreshing = false; + this.startY = 0; + this.currentY = 0; + this.threshold = 80; + this.setupPullToRefresh(); + } + + setupPullToRefresh() { + this.container.classList.add('pull-to-refresh'); + + const indicator = document.createElement('div'); + indicator.className = 'pull-to-refresh-indicator'; + indicator.innerHTML = '
'; + this.container.appendChild(indicator); + + this.container.addEventListener('touchstart', (e) => { + if (this.container.scrollTop === 0 && !this.isRefreshing) { + this.startY = e.touches[0].clientY; + } + }, { passive: true }); + + this.container.addEventListener('touchmove', (e) => { + if (this.startY && !this.isRefreshing) { + this.currentY = e.touches[0].clientY; + const pullDistance = this.currentY - this.startY; + + if (pullDistance > 0 && this.container.scrollTop === 0) { + e.preventDefault(); + const pullRatio = Math.min(pullDistance / this.threshold, 1); + + if (pullDistance > this.threshold) { + this.container.classList.add('pulling'); + } + } + } + }, { passive: false }); + + this.container.addEventListener('touchend', () => { + if (this.startY && this.currentY && !this.isRefreshing) { + const pullDistance = this.currentY - this.startY; + + if (pullDistance > this.threshold) { + this.triggerRefresh(); + } + } + + this.container.classList.remove('pulling'); + this.startY = 0; + this.currentY = 0; + }, { passive: true }); + } + + async triggerRefresh() { + if (this.isRefreshing) return; + + this.isRefreshing = true; + + try { + await this.callback(); + } catch (error) { + console.error('Refresh failed:', error); + } finally { + this.isRefreshing = false; + } + } +} + +// Toast Notification System +class ToastManager { + constructor() { + this.container = this.createContainer(); + this.toasts = new Map(); + } + + createContainer() { + let container = document.querySelector('.toast-container'); + if (!container) { + container = document.createElement('div'); + container.className = 'toast-container'; + document.body.appendChild(container); + } + return container; + } + + show(message, type = 'info', duration = 3000) { + const id = Date.now().toString(); + const toast = this.createToast(message, type, id); + + this.container.appendChild(toast); + this.toasts.set(id, toast); + + // Auto-remove after duration + if (duration > 0) { + setTimeout(() => { + this.remove(id); + }, duration); + } + + return id; + } + + createToast(message, type, id) { + const toast = document.createElement('div'); + toast.className = `toast ${type}`; + toast.setAttribute('data-toast-id', id); + + toast.innerHTML = ` +
+ ${message} + +
+ `; + + const closeBtn = toast.querySelector('.toast-close'); + closeBtn.addEventListener('click', () => { + this.remove(id); + }); + + return toast; + } + + remove(id) { + const toast = this.toasts.get(id); + if (toast) { + toast.style.animation = 'slideOutRight 0.3s ease forwards'; + setTimeout(() => { + if (toast.parentNode) { + this.container.removeChild(toast); + } + this.toasts.delete(id); + }, 300); + } + } + + success(message, duration = 3000) { + return this.show(message, 'success', duration); + } + + error(message, duration = 5000) { + return this.show(message, 'error', duration); + } + + warning(message, duration = 4000) { + return this.show(message, 'warning', duration); + } + + info(message, duration = 3000) { + return this.show(message, 'info', duration); + } +} + +// Mobile Navigation Manager +class MobileNavManager { + constructor() { + this.setupMobileNav(); + } + + setupMobileNav() { + if (window.innerWidth <= 768) { + this.createMobileNav(); + } + + window.addEventListener('resize', Utils.debounce(() => { + if (window.innerWidth <= 768) { + this.createMobileNav(); + } else { + this.removeMobileNav(); + } + }, 300)); + } + + createMobileNav() { + if (document.querySelector('.mobile-nav-toggle')) return; + + const toggle = document.createElement('button'); + toggle.className = 'mobile-nav-toggle'; + toggle.innerHTML = '☰'; + toggle.setAttribute('aria-label', 'Toggle mobile navigation'); + + const menu = document.createElement('div'); + menu.className = 'mobile-nav-menu'; + menu.innerHTML = ` + Pricing + File Hosts + Compare + Adult Hosts + Status + `; + + document.body.appendChild(toggle); + document.body.appendChild(menu); + + toggle.addEventListener('click', () => { + menu.classList.toggle('visible'); + }); + + // Close menu when clicking outside + document.addEventListener('click', (e) => { + if (!toggle.contains(e.target) && !menu.contains(e.target)) { + menu.classList.remove('visible'); + } + }); + + // Close menu when clicking on a link + menu.querySelectorAll('.mobile-nav-item').forEach(link => { + link.addEventListener('click', () => { + menu.classList.remove('visible'); + }); + }); + } + + removeMobileNav() { + const toggle = document.querySelector('.mobile-nav-toggle'); + const menu = document.querySelector('.mobile-nav-menu'); + + if (toggle) toggle.remove(); + if (menu) menu.remove(); + } +} + +// Progressive Enhancement Manager +class ProgressiveEnhancementManager { + constructor() { + this.features = new Map(); + this.detectFeatures(); + } + + detectFeatures() { + // Detect various browser capabilities + this.features.set('intersectionObserver', 'IntersectionObserver' in window); + this.features.set('webp', this.supportsWebP()); + this.features.set('serviceWorker', 'serviceWorker' in navigator); + this.features.set('touchEvents', 'ontouchstart' in window); + this.features.set('pointerEvents', 'PointerEvent' in window); + this.features.set('containerQueries', CSS.supports('container-type: inline-size')); + } + + async supportsWebP() { + return new Promise((resolve) => { + const webP = new Image(); + webP.onload = webP.onerror = () => { + resolve(webP.height === 2); + }; + webP.src = 'data:image/webp;base64,UklGRjoAAABXRUJQVlA4IC4AAACyAgCdASoCAAIALmk0mk0iIiIiIgBoSygABc6WWgAA/veff/0PP8bA//LwYAAA'; + }); + } + + hasFeature(feature) { + return this.features.get(feature) || false; + } + + enhanceIfSupported(feature, enhancementCallback) { + if (this.hasFeature(feature)) { + enhancementCallback(); + } + } +} + +// Initialize modern mobile-first features +const touchGestureManager = new TouchGestureManager(); +const toastManager = new ToastManager(); +const mobileNavManager = new MobileNavManager(); +const progressiveEnhancementManager = new ProgressiveEnhancementManager(); + +// Initialize search enhancements +document.addEventListener('DOMContentLoaded', () => { + // Enhanced search for file hosts + const fileHostSearch = document.querySelector('#file-host-search'); + const fileHostSuggestions = document.createElement('div'); + fileHostSuggestions.className = 'search-suggestions'; + + if (fileHostSearch) { + fileHostSearch.parentNode.classList.add('search-container'); + fileHostSearch.parentNode.appendChild(fileHostSuggestions); + new SearchManager(fileHostSearch, fileHostSuggestions); + } + + // Enhanced search for adult hosts + const adultHostSearch = document.querySelector('#adult-host-search'); + const adultHostSuggestions = document.createElement('div'); + adultHostSuggestions.className = 'search-suggestions'; + + if (adultHostSearch) { + adultHostSearch.parentNode.classList.add('search-container'); + adultHostSearch.parentNode.appendChild(adultHostSuggestions); + new SearchManager(adultHostSearch, adultHostSuggestions); + } + + // Setup pull-to-refresh for mobile + if (progressiveEnhancementManager.hasFeature('touchEvents')) { + const mainContent = document.querySelector('main'); + if (mainContent) { + new PullToRefreshManager(mainContent, async () => { + toastManager.info('Refreshing data...'); + // Simulate refresh + await new Promise(resolve => setTimeout(resolve, 1000)); + window.location.reload(); + }); + } + } + + // Add scroll progress indicator + const scrollIndicator = document.createElement('div'); + scrollIndicator.className = 'scroll-indicator'; + scrollIndicator.innerHTML = '
'; + document.body.appendChild(scrollIndicator); + + const updateScrollProgress = () => { + const winScroll = document.body.scrollTop || document.documentElement.scrollTop; + const height = document.documentElement.scrollHeight - document.documentElement.clientHeight; + const scrolled = (winScroll / height) * 100; + + const bar = scrollIndicator.querySelector('.scroll-indicator-bar'); + bar.style.width = scrolled + '%'; + }; + + window.addEventListener('scroll', Utils.throttle(updateScrollProgress, 16)); +}); + +// Enhanced swipe gesture handling +document.addEventListener('swipeleft', (e) => { + // Handle left swipe - could navigate to next section + console.log('Swiped left'); +}); + +document.addEventListener('swiperight', (e) => { + // Handle right swipe - could navigate to previous section + console.log('Swiped right'); +}); + +// Service Worker registration enhancement +if (progressiveEnhancementManager.hasFeature('serviceWorker')) { + navigator.serviceWorker.register('/sw.js') + .then((registration) => { + console.log('ServiceWorker registration successful'); + + // Check for updates + registration.addEventListener('updatefound', () => { + const newWorker = registration.installing; + newWorker.addEventListener('statechange', () => { + if (newWorker.state === 'installed' && navigator.serviceWorker.controller) { + toastManager.info('New version available! Refresh to update.', 0); + } + }); + }); + }) + .catch((error) => { + console.log('ServiceWorker registration failed:', error); + }); +} + +// Performance monitoring +if ('PerformanceObserver' in window) { + const perfObserver = new PerformanceObserver((list) => { + for (const entry of list.getEntries()) { + if (entry.entryType === 'largest-contentful-paint') { + console.log(`LCP: ${entry.startTime}ms`); + } + if (entry.entryType === 'first-input') { + console.log(`FID: ${entry.processingStart - entry.startTime}ms`); + } + } + }); + + try { + perfObserver.observe({ entryTypes: ['largest-contentful-paint', 'first-input'] }); + } catch (e) { + console.log('Performance observation not supported'); + } +} \ No newline at end of file diff --git a/dist/site.webmanifest b/dist/site.webmanifest index 97135d1..78cc655 100644 --- a/dist/site.webmanifest +++ b/dist/site.webmanifest @@ -1 +1,68 @@ -{"name":"","short_name":"","icons":[{"src":"images/android-chrome-192x192.png","sizes":"192x192","type":"image/png"},{"src":"images/android-chrome-512x512.png","sizes":"512x512","type":"image/png"}],"theme_color":"#ffffff","background_color":"#ffffff","display":"standalone"} \ No newline at end of file +{ + "name": "Debrid Services Comparison", + "short_name": "Debrid Compare", + "description": "Compare pricing and supported hosts across major debrid services", + "start_url": "/", + "display": "standalone", + "background_color": "#ffffff", + "theme_color": "#6366f1", + "orientation": "portrait-primary", + "categories": ["productivity", "utilities"], + "lang": "en", + "dir": "ltr", + "icons": [ + { + "src": "images/android-chrome-192x192.png", + "sizes": "192x192", + "type": "image/png", + "purpose": "any maskable" + }, + { + "src": "images/android-chrome-512x512.png", + "sizes": "512x512", + "type": "image/png", + "purpose": "any maskable" + } + ], + "shortcuts": [ + { + "name": "Pricing Comparison", + "short_name": "Pricing", + "description": "Compare pricing across all debrid services", + "url": "/#pricing", + "icons": [ + { + "src": "images/android-chrome-192x192.png", + "sizes": "192x192", + "type": "image/png" + } + ] + }, + { + "name": "File Hosts", + "short_name": "Hosts", + "description": "Browse supported file hosting services", + "url": "/#file-hosts", + "icons": [ + { + "src": "images/android-chrome-192x192.png", + "sizes": "192x192", + "type": "image/png" + } + ] + }, + { + "name": "Service Comparison", + "short_name": "Compare", + "description": "Side-by-side service comparison", + "url": "/#compare", + "icons": [ + { + "src": "images/android-chrome-192x192.png", + "sizes": "192x192", + "type": "image/png" + } + ] + } + ] +} \ No newline at end of file diff --git a/dist/sw.js b/dist/sw.js index 28d0f62..3feda04 100644 --- a/dist/sw.js +++ b/dist/sw.js @@ -1 +1 @@ -if(!self.define){let e,s={};const n=(n,i)=>(n=new URL(n+".js",i).href,s[n]||new Promise(s=>{if("document"in self){const e=document.createElement("script");e.src=n,e.onload=s,document.head.appendChild(e)}else e=n,importScripts(n),s()}).then(()=>{let e=s[n];if(!e)throw new Error(`Module ${n} didn’t register its module`);return e}));self.define=(i,c)=>{const o=e||("document"in self?document.currentScript.src:"")||location.href;if(s[o])return;let r={};const t=e=>n(e,o),a={module:{uri:o},exports:r,require:t};s[o]=Promise.all(i.map(e=>a[e]||t(e))).then(e=>(c(...e),r))}}define(["./workbox-9d361842"],function(e){"use strict";self.skipWaiting(),e.clientsClaim(),e.precacheAndRoute([{url:"css/styles-min.css",revision:"5e69b90137393a8d5cb4956e35a7f2da"},{url:"css/styles.css",revision:"43b4035d5fb70e03d94fb4ab7b8f8ffb"},{url:"favicon.ico",revision:"99ed2c251efd7e52b890d2de6bf36781"},{url:"favicon.svg",revision:"8abc57869f11bb9299ae22352d3d5e98"},{url:"index.html",revision:"dcda018f14a78efacb6bfed8765db260"},{url:"js/app-min.js",revision:"dc69999b7acb32474abc5c612fb713ff"},{url:"js/app.js",revision:"4ff921ce887c9f6eae87741208b830c3"},{url:"json/adult-hosts.json",revision:"662e2165563840d5b577b58e938e6192"},{url:"json/file-hosts.json",revision:"f297528544c4ce6d6dea7707f171a99f"},{url:"json/pricing.json",revision:"e5940cb226d4beaf92979bfa30f03cda"},{url:"scripts/replace-assets.js",revision:"410d84c1d822559972797f3427d5c292"}],{}),e.registerRoute(/\.json$/,new e.StaleWhileRevalidate({cacheName:"json-cache",plugins:[new e.ExpirationPlugin({maxEntries:50,maxAgeSeconds:86400})]}),"GET"),e.registerRoute(/\.(?:png|css|svg|ico)$/,new e.CacheFirst({cacheName:"static-assets",plugins:[new e.ExpirationPlugin({maxEntries:20,maxAgeSeconds:604800})]}),"GET"),e.registerRoute(/\.html$/,new e.NetworkFirst({cacheName:"html-cache",plugins:[new e.ExpirationPlugin({maxEntries:10,maxAgeSeconds:86400})]}),"GET")}); +if(!self.define){let e,s={};const n=(n,i)=>(n=new URL(n+".js",i).href,s[n]||new Promise(s=>{if("document"in self){const e=document.createElement("script");e.src=n,e.onload=s,document.head.appendChild(e)}else e=n,importScripts(n),s()}).then(()=>{let e=s[n];if(!e)throw new Error(`Module ${n} didn’t register its module`);return e}));self.define=(i,c)=>{const o=e||("document"in self?document.currentScript.src:"")||location.href;if(s[o])return;let r={};const d=e=>n(e,o),t={module:{uri:o},exports:r,require:d};s[o]=Promise.all(i.map(e=>t[e]||d(e))).then(e=>(c(...e),r))}}define(["./workbox-9d361842"],function(e){"use strict";self.skipWaiting(),e.clientsClaim(),e.precacheAndRoute([{url:"css/styles-min.css",revision:"2dcb19fa83958e04c1e3f24de4ceb0f6"},{url:"css/styles.css",revision:"e204e52e82d31f527e985582fd801daf"},{url:"favicon.ico",revision:"99ed2c251efd7e52b890d2de6bf36781"},{url:"favicon.svg",revision:"8abc57869f11bb9299ae22352d3d5e98"},{url:"index.html",revision:"1f3e440d96053aee0f4a2a44c89bc7e8"},{url:"js/app-min.js",revision:"04e00a8d3dec0087e21103db6ffcc990"},{url:"js/app.js",revision:"6aed413e0dd10b73056f70c0595ea94f"},{url:"json/adult-hosts.json",revision:"662e2165563840d5b577b58e938e6192"},{url:"json/file-hosts.json",revision:"f297528544c4ce6d6dea7707f171a99f"},{url:"json/pricing.json",revision:"e5940cb226d4beaf92979bfa30f03cda"},{url:"scripts/replace-assets.js",revision:"410d84c1d822559972797f3427d5c292"}],{}),e.registerRoute(/\.json$/,new e.StaleWhileRevalidate({cacheName:"json-cache",plugins:[new e.ExpirationPlugin({maxEntries:50,maxAgeSeconds:86400})]}),"GET"),e.registerRoute(/\.(?:png|css|svg|ico)$/,new e.CacheFirst({cacheName:"static-assets",plugins:[new e.ExpirationPlugin({maxEntries:20,maxAgeSeconds:604800})]}),"GET"),e.registerRoute(/\.html$/,new e.NetworkFirst({cacheName:"html-cache",plugins:[new e.ExpirationPlugin({maxEntries:10,maxAgeSeconds:86400})]}),"GET")});