{"id":585,"date":"2026-01-23T02:40:58","date_gmt":"2026-01-23T02:40:58","guid":{"rendered":"https:\/\/www.opey.org\/opeyit\/?page_id=585"},"modified":"2026-02-11T15:45:25","modified_gmt":"2026-02-11T15:45:25","slug":"cloud-outage-tracker","status":"publish","type":"page","link":"https:\/\/www.opey.org\/opeyit\/?page_id=585","title":{"rendered":"Cloud Outage Tracker"},"content":{"rendered":"\n<div id=\"wcf-outage-tracker-archive\">\n\n<style>\n#wcf-outage-tracker-archive { font-family: 'Segoe UI', -apple-system, BlinkMacSystemFont, sans-serif; color: #2d3748; line-height: 1.6; background: #f7f8fc; }\n#wcf-outage-tracker-archive * { box-sizing: border-box; }\n@keyframes pulse { 0%, 100% { opacity: 1; } 50% { opacity: 0.5; } }\n\n#wcf-outage-tracker-archive .wcf-hero { background: linear-gradient(145deg, #0f172a 0%, #1e3a5f 40%, #7c2d12 100%); padding: 60px 20px; text-align: center; }\n#wcf-outage-tracker-archive .wcf-hero-inner { max-width: 1000px; margin: 0 auto; }\n#wcf-outage-tracker-archive .wcf-alert-icon { font-size: 56px; color: #f59e0b; font-weight: 700; display: block; margin-bottom: 20px; }\n#wcf-outage-tracker-archive .wcf-label { color: #f59e0b; font-size: 11px; font-weight: 700; letter-spacing: 3px; text-transform: uppercase; margin-bottom: 12px; display: block; }\n#wcf-outage-tracker-archive .wcf-title { color: #fff; font-size: 44px; font-weight: 800; margin: 0 0 12px; line-height: 1.1; }\n#wcf-outage-tracker-archive .wcf-subtitle { color: rgba(255,255,255,0.9); font-size: 20px; margin: 0 0 16px; }\n#wcf-outage-tracker-archive .wcf-hero-desc { color: rgba(255,255,255,0.7); font-size: 15px; max-width: 650px; margin: 0 auto 24px; }\n#wcf-outage-tracker-archive .wcf-last-updated { color: rgba(255,255,255,0.5); font-size: 12px; font-style: italic; }\n#wcf-outage-tracker-archive .wcf-live-badge { display: inline-block; background: #22c55e; color: #fff; padding: 4px 12px; border-radius: 20px; font-size: 10px; font-weight: 700; text-transform: uppercase; margin-left: 10px; animation: pulse 2s infinite; }\n\n#wcf-outage-tracker-archive .wcf-stats-bar { background: #0f172a; padding: 30px 20px; border-bottom: 4px solid #dc2626; }\n#wcf-outage-tracker-archive .wcf-stats-inner { max-width: 1100px; margin: 0 auto; display: flex; justify-content: space-around; flex-wrap: wrap; gap: 24px; text-align: center; }\n#wcf-outage-tracker-archive .wcf-stat { flex: 1; min-width: 130px; }\n#wcf-outage-tracker-archive .wcf-stat-num { font-size: 36px; font-weight: 800; color: #ef4444; display: block; }\n#wcf-outage-tracker-archive .wcf-stat-label { font-size: 10px; color: rgba(255,255,255,0.6); text-transform: uppercase; letter-spacing: 1.5px; }\n\n\/* NEW: Dashboard CTA Banner *\/\n#wcf-outage-tracker-archive .wcf-dashboard-cta { background: linear-gradient(135deg, #1e3a5f 0%, #0f172a 100%); padding: 24px 20px; border-bottom: 1px solid rgba(255,255,255,0.1); }\n#wcf-outage-tracker-archive .wcf-dashboard-cta-inner { max-width: 1100px; margin: 0 auto; display: flex; align-items: center; justify-content: space-between; gap: 20px; flex-wrap: wrap; }\n#wcf-outage-tracker-archive .wcf-dashboard-cta-content { flex: 1; min-width: 280px; }\n#wcf-outage-tracker-archive .wcf-dashboard-cta-label { color: #22c55e; font-size: 10px; font-weight: 700; text-transform: uppercase; letter-spacing: 2px; margin-bottom: 6px; display: flex; align-items: center; gap: 8px; }\n#wcf-outage-tracker-archive .wcf-dashboard-cta-label .wcf-new-badge { background: #22c55e; color: #0f172a; padding: 2px 8px; border-radius: 4px; font-size: 9px; }\n#wcf-outage-tracker-archive .wcf-dashboard-cta-title { color: #fff; font-size: 18px; font-weight: 700; margin: 0 0 4px; }\n#wcf-outage-tracker-archive .wcf-dashboard-cta-desc { color: rgba(255,255,255,0.6); font-size: 13px; margin: 0; }\n\n\/* Dashboard buttons container *\/\n#wcf-outage-tracker-archive .wcf-dashboard-buttons { display: flex; flex-direction: column; gap: 10px; }\n\n#wcf-outage-tracker-archive .wcf-dashboard-btn { display: inline-flex; align-items: center; gap: 10px; padding: 14px 28px; font-size: 14px; font-weight: 700; background: linear-gradient(135deg, #22c55e, #16a34a); color: #fff; border-radius: 8px; text-decoration: none; transition: all 0.3s; white-space: nowrap; justify-content: center; }\n#wcf-outage-tracker-archive .wcf-dashboard-btn:hover { transform: translateY(-2px); box-shadow: 0 8px 24px rgba(34, 197, 94, 0.4); }\n#wcf-outage-tracker-archive .wcf-dashboard-btn svg { width: 18px; height: 18px; }\n\n\/* NEW: Risk Matrix button (purple theme) *\/\n#wcf-outage-tracker-archive .wcf-matrix-btn { display: inline-flex; align-items: center; gap: 10px; padding: 14px 28px; font-size: 14px; font-weight: 700; background: linear-gradient(135deg, #7c3aed, #6d28d9); color: #fff; border-radius: 8px; text-decoration: none; transition: all 0.3s; white-space: nowrap; justify-content: center; }\n#wcf-outage-tracker-archive .wcf-matrix-btn:hover { transform: translateY(-2px); box-shadow: 0 8px 24px rgba(124, 58, 237, 0.4); }\n#wcf-outage-tracker-archive .wcf-matrix-btn svg { width: 18px; height: 18px; }\n\n#wcf-outage-tracker-archive .wcf-filter-section { background: #fff; padding: 30px 20px; border-bottom: 1px solid #e2e8f0; position: relative; z-index: 100; box-shadow: 0 4px 20px rgba(0,0,0,0.08); }\n#wcf-outage-tracker-archive .wcf-filter-inner { max-width: 1100px; margin: 0 auto; display: flex; flex-wrap: wrap; gap: 16px; align-items: center; justify-content: center; }\n#wcf-outage-tracker-archive .wcf-filter-label { font-size: 13px; font-weight: 600; color: #475569; text-transform: uppercase; }\n#wcf-outage-tracker-archive .wcf-year-btn { padding: 10px 20px; font-size: 14px; font-weight: 600; border-radius: 8px; cursor: pointer; border: 2px solid #e2e8f0; background: #fff; color: #475569; transition: all 0.2s; }\n#wcf-outage-tracker-archive .wcf-year-btn:hover { border-color: #dc2626; color: #dc2626; }\n#wcf-outage-tracker-archive .wcf-year-btn.active { background: #dc2626; border-color: #dc2626; color: #fff; }\n#wcf-outage-tracker-archive .wcf-results-count { font-size: 14px; color: #64748b; margin-left: auto; }\n\n#wcf-outage-tracker-archive .wcf-section { padding: 50px 20px; }\n#wcf-outage-tracker-archive .wcf-section-inner { max-width: 1100px; margin: 0 auto; }\n#wcf-outage-tracker-archive .wcf-section-title { text-align: center; font-size: 32px; font-weight: 800; color: #0f172a; margin: 0 0 12px; }\n#wcf-outage-tracker-archive .wcf-section-subtitle { text-align: center; font-size: 16px; color: #64748b; margin: 0 auto 40px; max-width: 750px; }\n\n#wcf-outage-tracker-archive .wcf-incidents { background: #f1f5f9; }\n#wcf-outage-tracker-archive .wcf-incident-card { background: #fff; border-radius: 16px; margin-bottom: 24px; overflow: hidden; box-shadow: 0 4px 20px rgba(0,0,0,0.06); border: 1px solid #e2e8f0; transition: all 0.3s; }\n#wcf-outage-tracker-archive .wcf-incident-card:hover { box-shadow: 0 8px 30px rgba(0,0,0,0.1); transform: translateY(-2px); }\n#wcf-outage-tracker-archive .wcf-incident-card.severity-critical { border-left: 5px solid #dc2626; }\n#wcf-outage-tracker-archive .wcf-incident-card.severity-major { border-left: 5px solid #ea580c; }\n#wcf-outage-tracker-archive .wcf-incident-card.severity-moderate { border-left: 5px solid #f59e0b; }\n#wcf-outage-tracker-archive .wcf-incident-card.severity-minor { border-left: 5px solid #22c55e; }\n\n#wcf-outage-tracker-archive .wcf-incident-header { padding: 24px 28px; background: linear-gradient(180deg, #fafbfc 0%, #fff 100%); border-bottom: 1px solid #f1f5f9; display: flex; flex-wrap: wrap; align-items: center; gap: 16px; }\n#wcf-outage-tracker-archive .wcf-incident-date { background: linear-gradient(135deg, #0f172a, #1e293b); color: #fff; padding: 8px 14px; border-radius: 6px; font-size: 12px; font-weight: 700; white-space: nowrap; }\n#wcf-outage-tracker-archive .wcf-incident-meta { flex: 1; min-width: 220px; }\n#wcf-outage-tracker-archive .wcf-incident-provider { display: flex; flex-wrap: wrap; gap: 8px; margin-bottom: 8px; }\n#wcf-outage-tracker-archive .wcf-provider-badge { padding: 4px 12px; border-radius: 6px; font-size: 10px; font-weight: 700; text-transform: uppercase; background: linear-gradient(135deg, #6366f1, #4f46e5); color: #fff; }\n#wcf-outage-tracker-archive .wcf-incident-title { font-size: 19px; font-weight: 700; color: #0f172a; margin: 0; line-height: 1.3; }\n#wcf-outage-tracker-archive .wcf-incident-badges { display: flex; gap: 10px; flex-wrap: wrap; }\n#wcf-outage-tracker-archive .wcf-severity-badge { padding: 6px 14px; border-radius: 6px; font-size: 11px; font-weight: 700; text-transform: uppercase; }\n#wcf-outage-tracker-archive .wcf-severity-critical { background: linear-gradient(135deg, #dc2626, #b91c1c); color: #fff; }\n#wcf-outage-tracker-archive .wcf-severity-major { background: linear-gradient(135deg, #ea580c, #c2410c); color: #fff; }\n#wcf-outage-tracker-archive .wcf-severity-moderate { background: linear-gradient(135deg, #f59e0b, #d97706); color: #0f172a; }\n#wcf-outage-tracker-archive .wcf-severity-minor { background: linear-gradient(135deg, #22c55e, #16a34a); color: #fff; }\n#wcf-outage-tracker-archive .wcf-scope-badge { background: #f1f5f9; color: #475569; padding: 6px 14px; border-radius: 6px; font-size: 11px; font-weight: 600; }\n\n#wcf-outage-tracker-archive .wcf-incident-body { padding: 28px; }\n#wcf-outage-tracker-archive .wcf-incident-details { display: grid; grid-template-columns: repeat(auto-fit, minmax(150px, 1fr)); gap: 20px; margin-bottom: 20px; padding-bottom: 20px; border-bottom: 1px solid #f1f5f9; }\n#wcf-outage-tracker-archive .wcf-detail-item { text-align: left; }\n#wcf-outage-tracker-archive .wcf-detail-label { font-size: 10px; color: #94a3b8; text-transform: uppercase; letter-spacing: 1px; display: block; margin-bottom: 6px; }\n#wcf-outage-tracker-archive .wcf-detail-value { font-size: 14px; font-weight: 600; color: #0f172a; }\n#wcf-outage-tracker-archive .wcf-incident-desc { font-size: 15px; color: #475569; line-height: 1.75; margin: 0 0 18px; }\n\n#wcf-outage-tracker-archive .wcf-incident-narrative { margin-bottom: 18px; padding: 16px; background: #f8fafc; border-radius: 8px; border-left: 3px solid #e2e8f0; }\n#wcf-outage-tracker-archive .wcf-narrative-item { margin-bottom: 10px; font-size: 14px; line-height: 1.6; color: #475569; }\n#wcf-outage-tracker-archive .wcf-narrative-item:last-child { margin-bottom: 0; }\n#wcf-outage-tracker-archive .wcf-narrative-label { font-weight: 700; color: #334155; text-transform: uppercase; font-size: 10px; letter-spacing: 0.5px; }\n\n#wcf-outage-tracker-archive .wcf-sovereignty-take { background: linear-gradient(135deg, #0f172a, #1e3a5f); padding: 20px; border-radius: 12px; margin-top: 18px; }\n#wcf-outage-tracker-archive .wcf-sovereignty-label { color: #f59e0b; font-size: 10px; font-weight: 700; text-transform: uppercase; letter-spacing: 2px; display: block; margin-bottom: 10px; }\n#wcf-outage-tracker-archive .wcf-sovereignty-text { color: rgba(255,255,255,0.9); font-size: 14px; margin: 0; line-height: 1.7; }\n\n#wcf-outage-tracker-archive .wcf-year-divider { text-align: center; margin: 50px 0 30px; position: relative; }\n#wcf-outage-tracker-archive .wcf-year-divider::before { content: ''; position: absolute; left: 0; right: 0; top: 50%; height: 2px; background: linear-gradient(90deg, transparent, #cbd5e1 30%, #cbd5e1 70%, transparent); }\n#wcf-outage-tracker-archive .wcf-year-divider span { background: #f1f5f9; padding: 12px 32px; font-size: 24px; font-weight: 800; color: #0f172a; position: relative; z-index: 1; border-radius: 50px; border: 2px solid #e2e8f0; }\n\n#wcf-outage-tracker-archive .wcf-provider-aws { background: linear-gradient(135deg, #ff9900, #ec7211); }\n#wcf-outage-tracker-archive .wcf-provider-microsoft, #wcf-outage-tracker-archive .wcf-provider-microsoft-365 { background: linear-gradient(135deg, #00bcf2, #0078d4); }\n#wcf-outage-tracker-archive .wcf-provider-azure { background: linear-gradient(135deg, #0078d4, #005a9e); }\n#wcf-outage-tracker-archive .wcf-provider-google-cloud { background: linear-gradient(135deg, #4285f4, #3367d6); }\n#wcf-outage-tracker-archive .wcf-provider-cloudflare { background: linear-gradient(135deg, #f38020, #e6730f); }\n#wcf-outage-tracker-archive .wcf-provider-crowdstrike { background: linear-gradient(135deg, #e01e5a, #b51a48); }\n#wcf-outage-tracker-archive .wcf-provider-meta, #wcf-outage-tracker-archive .wcf-provider-facebook { background: linear-gradient(135deg, #1877f2, #0d65d9); }\n#wcf-outage-tracker-archive .wcf-provider-verizon { background: linear-gradient(135deg, #cd040b, #a00308); }\n#wcf-outage-tracker-archive .wcf-provider-salesforce { background: linear-gradient(135deg, #00a1e0, #0070d2); }\n#wcf-outage-tracker-archive .wcf-provider-github { background: linear-gradient(135deg, #333, #24292e); }\n#wcf-outage-tracker-archive .wcf-provider-xai, #wcf-outage-tracker-archive .wcf-provider-grok { background: linear-gradient(135deg, #1a1a2e, #16213e); }\n#wcf-outage-tracker-archive .wcf-provider-x { background: linear-gradient(135deg, #000, #14171a); }\n\n#wcf-outage-tracker-archive .wcf-analysis { background: #fff; }\n#wcf-outage-tracker-archive .wcf-analysis-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(300px, 1fr)); gap: 28px; }\n#wcf-outage-tracker-archive .wcf-analysis-card { background: linear-gradient(145deg, #f8fafc, #f1f5f9); padding: 32px; border-radius: 16px; border: 1px solid #e2e8f0; transition: all 0.3s; }\n#wcf-outage-tracker-archive .wcf-analysis-card:hover { box-shadow: 0 12px 40px rgba(0,0,0,0.08); transform: translateY(-4px); }\n#wcf-outage-tracker-archive .wcf-analysis-icon { width: 56px; height: 56px; background: linear-gradient(135deg, #dc2626, #991b1b); border-radius: 14px; display: flex; align-items: center; justify-content: center; margin-bottom: 20px; font-size: 20px; color: #fff; font-weight: 800; }\n#wcf-outage-tracker-archive .wcf-analysis-title { font-size: 20px; font-weight: 700; color: #0f172a; margin: 0 0 12px; }\n#wcf-outage-tracker-archive .wcf-analysis-text { font-size: 15px; color: #475569; line-height: 1.75; margin: 0; }\n\n#wcf-outage-tracker-archive .wcf-costs { background: linear-gradient(145deg, #0f172a, #1e3a5f); color: #fff; }\n#wcf-outage-tracker-archive .wcf-costs .wcf-section-title { color: #fff; }\n#wcf-outage-tracker-archive .wcf-costs .wcf-section-subtitle { color: rgba(255,255,255,0.7); }\n#wcf-outage-tracker-archive .wcf-cost-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(240px, 1fr)); gap: 24px; margin-bottom: 36px; }\n#wcf-outage-tracker-archive .wcf-cost-card { background: rgba(255,255,255,0.08); padding: 28px; border-radius: 16px; text-align: center; border: 1px solid rgba(255,255,255,0.1); }\n#wcf-outage-tracker-archive .wcf-cost-amount { font-size: 38px; font-weight: 800; color: #f87171; display: block; margin-bottom: 6px; }\n#wcf-outage-tracker-archive .wcf-cost-label { font-size: 11px; color: rgba(255,255,255,0.6); text-transform: uppercase; letter-spacing: 1.5px; display: block; margin-bottom: 12px; }\n#wcf-outage-tracker-archive .wcf-cost-desc { font-size: 14px; color: rgba(255,255,255,0.6); margin: 0; }\n#wcf-outage-tracker-archive .wcf-cost-source { text-align: center; font-size: 12px; color: rgba(255,255,255,0.4); font-style: italic; margin-top: 24px; }\n\n#wcf-outage-tracker-archive .wcf-risk-cta { background: linear-gradient(135deg, #7c2d12 0%, #991b1b 50%, #0f172a 100%); padding: 60px 20px; }\n#wcf-outage-tracker-archive .wcf-risk-banner { display: flex; gap: 40px; align-items: center; flex-wrap: wrap; }\n#wcf-outage-tracker-archive .wcf-risk-banner-content { flex: 1; min-width: 300px; }\n#wcf-outage-tracker-archive .wcf-risk-label { display: inline-block; background: rgba(245, 158, 11, 0.2); color: #f59e0b; padding: 6px 14px; border-radius: 20px; font-size: 11px; font-weight: 700; text-transform: uppercase; letter-spacing: 2px; margin-bottom: 16px; }\n#wcf-outage-tracker-archive .wcf-risk-title { color: #fff; font-size: 36px; font-weight: 800; margin: 0 0 16px; line-height: 1.2; }\n#wcf-outage-tracker-archive .wcf-risk-text { color: rgba(255,255,255,0.8); font-size: 16px; line-height: 1.7; margin: 0 0 24px; }\n#wcf-outage-tracker-archive .wcf-risk-stats { display: flex; gap: 32px; margin-bottom: 28px; flex-wrap: wrap; }\n#wcf-outage-tracker-archive .wcf-risk-stat { }\n#wcf-outage-tracker-archive .wcf-risk-stat-num { display: block; font-size: 32px; font-weight: 800; color: #f87171; }\n#wcf-outage-tracker-archive .wcf-risk-stat-label { font-size: 13px; color: rgba(255,255,255,0.6); }\n#wcf-outage-tracker-archive .wcf-risk-btn { display: inline-block; padding: 18px 36px; font-size: 16px; font-weight: 700; background: linear-gradient(135deg, #f59e0b, #d97706); color: #0f172a; border-radius: 8px; text-decoration: none; transition: all 0.3s; }\n#wcf-outage-tracker-archive .wcf-risk-btn:hover { transform: translateY(-3px); box-shadow: 0 12px 30px rgba(245, 158, 11, 0.4); }\n#wcf-outage-tracker-archive .wcf-risk-banner-visual { flex: 0 0 280px; }\n#wcf-outage-tracker-archive .wcf-risk-meter-display { background: rgba(0,0,0,0.3); border: 1px solid rgba(255,255,255,0.1); border-radius: 16px; padding: 28px; text-align: center; }\n#wcf-outage-tracker-archive .wcf-meter-label { font-size: 11px; color: rgba(255,255,255,0.5); text-transform: uppercase; letter-spacing: 1px; margin-bottom: 8px; }\n#wcf-outage-tracker-archive .wcf-meter-value { font-size: 64px; font-weight: 800; color: #f87171; line-height: 1; }\n#wcf-outage-tracker-archive .wcf-meter-rating { font-size: 14px; font-weight: 700; color: #f87171; text-transform: uppercase; letter-spacing: 2px; margin: 8px 0 16px; }\n#wcf-outage-tracker-archive .wcf-meter-bar { height: 8px; background: rgba(255,255,255,0.1); border-radius: 4px; overflow: hidden; }\n#wcf-outage-tracker-archive .wcf-meter-fill { width: 78%; height: 100%; background: linear-gradient(90deg, #22c55e, #f59e0b 50%, #ef4444); border-radius: 4px; }\n#wcf-outage-tracker-archive .wcf-meter-caption { font-size: 12px; color: rgba(255,255,255,0.5); margin-top: 12px; }\n\n#wcf-outage-tracker-archive .wcf-export { background: linear-gradient(145deg, #1e293b, #0f172a); padding: 50px 20px; }\n#wcf-outage-tracker-archive .wcf-export .wcf-section-title { color: #fff; }\n#wcf-outage-tracker-archive .wcf-export .wcf-section-subtitle { color: rgba(255,255,255,0.7); }\n#wcf-outage-tracker-archive .wcf-export-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(200px, 1fr)); gap: 20px; max-width: 900px; margin: 0 auto; }\n#wcf-outage-tracker-archive .wcf-export-card { background: rgba(255,255,255,0.05); border: 1px solid rgba(255,255,255,0.1); border-radius: 12px; padding: 24px; text-align: center; cursor: pointer; transition: all 0.3s; }\n#wcf-outage-tracker-archive .wcf-export-card:hover { background: rgba(255,255,255,0.1); transform: translateY(-4px); box-shadow: 0 12px 40px rgba(0,0,0,0.3); }\n#wcf-outage-tracker-archive .wcf-export-icon { font-size: 32px; margin-bottom: 12px; display: block; color: #f59e0b; font-weight: 700; }\n#wcf-outage-tracker-archive .wcf-export-format { font-size: 18px; font-weight: 700; color: #fff; display: block; margin-bottom: 6px; }\n#wcf-outage-tracker-archive .wcf-export-desc { font-size: 12px; color: rgba(255,255,255,0.5); display: block; }\n#wcf-outage-tracker-archive .wcf-export-note { text-align: center; margin-top: 24px; font-size: 13px; color: rgba(255,255,255,0.4); }\n#wcf-outage-tracker-archive .wcf-export-note a { color: #f59e0b; text-decoration: none; }\n#wcf-outage-tracker-archive .wcf-export-note a:hover { text-decoration: underline; }\n\n#wcf-outage-tracker-archive .wcf-cta { background: linear-gradient(135deg, #f59e0b, #d97706); padding: 60px 20px; text-align: center; }\n#wcf-outage-tracker-archive .wcf-cta-title { font-size: 32px; font-weight: 800; color: #0f172a; margin: 0 0 12px; }\n#wcf-outage-tracker-archive .wcf-cta-text { font-size: 17px; color: #0f172a; opacity: 0.8; margin: 0 0 28px; }\n#wcf-outage-tracker-archive .wcf-cta-buttons { display: flex; justify-content: center; gap: 16px; flex-wrap: wrap; }\n#wcf-outage-tracker-archive .wcf-btn { display: inline-block; padding: 16px 32px; font-size: 15px; font-weight: 700; border-radius: 8px; cursor: pointer; border: none; transition: all 0.2s; text-decoration: none; }\n#wcf-outage-tracker-archive .wcf-btn-dark { background: #0f172a; color: #fff; }\n#wcf-outage-tracker-archive .wcf-btn-dark:hover { background: #1e293b; transform: translateY(-2px); }\n#wcf-outage-tracker-archive .wcf-btn-outline { background: transparent; color: #0f172a; border: 2px solid #0f172a; }\n#wcf-outage-tracker-archive .wcf-btn-outline:hover { background: #0f172a; color: #fff; }\n\n#wcf-outage-tracker-archive .wcf-hidden { display: none; }\n\n\/* DESKTOP ONLY: Sticky filter bar *\/\n@media (min-width: 769px) {\n    #wcf-outage-tracker-archive .wcf-filter-section { position: sticky; top: 0; }\n}\n\n\/* MOBILE: No sticky, normal scroll *\/\n@media (max-width: 768px) {\n    #wcf-outage-tracker-archive .wcf-title { font-size: 32px; }\n    #wcf-outage-tracker-archive .wcf-stat-num { font-size: 28px; }\n    #wcf-outage-tracker-archive .wcf-filter-section { position: relative; }\n    #wcf-outage-tracker-archive .wcf-filter-inner { flex-direction: column; }\n    #wcf-outage-tracker-archive .wcf-incident-header { flex-direction: column; align-items: flex-start; }\n    #wcf-outage-tracker-archive .wcf-incident-details { grid-template-columns: repeat(2, 1fr); }\n    #wcf-outage-tracker-archive .wcf-analysis-grid { grid-template-columns: 1fr; }\n    #wcf-outage-tracker-archive .wcf-cost-grid { grid-template-columns: 1fr; }\n    #wcf-outage-tracker-archive .wcf-export-grid { grid-template-columns: repeat(2, 1fr); }\n    #wcf-outage-tracker-archive .wcf-risk-banner { flex-direction: column; text-align: center; }\n    #wcf-outage-tracker-archive .wcf-risk-title { font-size: 28px; }\n    #wcf-outage-tracker-archive .wcf-risk-stats { justify-content: center; }\n    #wcf-outage-tracker-archive .wcf-risk-banner-visual { flex: 0 0 auto; width: 100%; max-width: 280px; }\n    #wcf-outage-tracker-archive .wcf-dashboard-cta-inner { flex-direction: column; text-align: center; }\n    #wcf-outage-tracker-archive .wcf-dashboard-cta-label { justify-content: center; }\n    #wcf-outage-tracker-archive .wcf-dashboard-buttons { width: 100%; }\n}\n<\/style>\n\n<!-- HERO -->\n<div class=\"wcf-hero\">\n    <div class=\"wcf-hero-inner\">\n        <span class=\"wcf-alert-icon\">\/!\\<\/span>\n        <span class=\"wcf-label\">Comprehensive Archive<\/span>\n        <h1 class=\"wcf-title\">Cloud Outage Database<\/h1>\n        <p class=\"wcf-subtitle\">2020 &#8211; 2026: Seven Years of Cloud Infrastructure Failures<\/p>\n        <p class=\"wcf-hero-desc\">The definitive archive of major cloud service disruptions. A companion resource to &#8220;When Clouds Fail&#8221;.<\/p>\n        <p class=\"wcf-last-updated\">Loading&#8230;<span class=\"wcf-live-badge\">Live Data<\/span><\/p>\n    <\/div>\n<\/div>\n\n<!-- STATS -->\n<div class=\"wcf-stats-bar\">\n    <div class=\"wcf-stats-inner\" id=\"stats-container\">\n        <div class=\"wcf-stat\"><span class=\"wcf-stat-num\">&#8212;<\/span><span class=\"wcf-stat-label\">Major Incidents<\/span><\/div>\n        <div class=\"wcf-stat\"><span class=\"wcf-stat-num\">&#8212;<\/span><span class=\"wcf-stat-label\">Est. Total Impact<\/span><\/div>\n        <div class=\"wcf-stat\"><span class=\"wcf-stat-num\">&#8212;<\/span><span class=\"wcf-stat-label\">Years Documented<\/span><\/div>\n        <div class=\"wcf-stat\"><span class=\"wcf-stat-num\">&#8212;<\/span><span class=\"wcf-stat-label\">Providers Tracked<\/span><\/div>\n    <\/div>\n<\/div>\n\n<!-- NEW: EXECUTIVE DASHBOARD CTA -->\n<div class=\"wcf-dashboard-cta\">\n    <div class=\"wcf-dashboard-cta-inner\">\n        <div class=\"wcf-dashboard-cta-content\">\n            <div class=\"wcf-dashboard-cta-label\">\n                <span class=\"wcf-new-badge\">NEW<\/span>\n                Executive Intelligence Views\n            <\/div>\n            <h3 class=\"wcf-dashboard-cta-title\">See This Data as Your Board Would See It<\/h3>\n            <p class=\"wcf-dashboard-cta-desc\">Interactive heatmaps, provider risk matrix, severity trends, and cost analysis \u2014 all in executive-ready visualizations.<\/p>\n        <\/div>\n        <div class=\"wcf-dashboard-buttons\">\n            <a href=\"https:\/\/www.opey.org\/opeyit\/?page_id=651\" class=\"wcf-dashboard-btn\">\n                <svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\">\n                    <rect x=\"3\" y=\"3\" width=\"7\" height=\"7\"><\/rect>\n                    <rect x=\"14\" y=\"3\" width=\"7\" height=\"7\"><\/rect>\n                    <rect x=\"14\" y=\"14\" width=\"7\" height=\"7\"><\/rect>\n                    <rect x=\"3\" y=\"14\" width=\"7\" height=\"7\"><\/rect>\n                <\/svg>\n                Open Executive Dashboard\n            <\/a>\n            <a href=\"https:\/\/www.opey.org\/opeyit\/?page_id=671\" class=\"wcf-matrix-btn\">\n                <svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\">\n                    <circle cx=\"12\" cy=\"12\" r=\"10\"><\/circle>\n                    <line x1=\"12\" y1=\"8\" x2=\"12\" y2=\"12\"><\/line>\n                    <line x1=\"12\" y1=\"16\" x2=\"12.01\" y2=\"16\"><\/line>\n                <\/svg>\n                Open Risk Matrix\n            <\/a>\n        <\/div>\n    <\/div>\n<\/div>\n\n<!-- FILTERS -->\n<div class=\"wcf-filter-section\">\n    <div class=\"wcf-filter-inner\" id=\"filter-container\">\n        <span class=\"wcf-filter-label\">Loading filters&#8230;<\/span>\n    <\/div>\n<\/div>\n\n<!-- INCIDENTS -->\n<div class=\"wcf-section wcf-incidents\">\n    <div class=\"wcf-section-inner\">\n        <h2 class=\"wcf-section-title\">Complete Incident Archive<\/h2>\n        <p class=\"wcf-section-subtitle\">Every major cloud outage with root cause analysis, impact assessment, and sovereignty implications.<\/p>\n        <div id=\"incidents-container\"><\/div>\n    <\/div>\n<\/div>\n\n<!-- RISK ASSESSMENT CTA -->\n<div class=\"wcf-section wcf-risk-cta\">\n    <div class=\"wcf-section-inner\">\n        <div class=\"wcf-risk-banner\">\n            <div class=\"wcf-risk-banner-content\">\n                <span class=\"wcf-risk-label\">Board-Level Intelligence<\/span>\n                <h2 class=\"wcf-risk-title\">Seen Enough? Calculate Your Risk.<\/h2>\n                <p class=\"wcf-risk-text\">These failures already happened. The question is: how exposed is YOUR organization? Use our Sovereign Risk Assessment to calculate your cloud dependency score and generate a board-ready report.<\/p>\n                <div class=\"wcf-risk-stats\">\n                    <div class=\"wcf-risk-stat\"><span class=\"wcf-risk-stat-num\">73%<\/span><span class=\"wcf-risk-stat-label\">of enterprises lack multi-provider failover<\/span><\/div>\n                    <div class=\"wcf-risk-stat\"><span class=\"wcf-risk-stat-num\">$17K<\/span><span class=\"wcf-risk-stat-label\">average cost per minute of downtime (2026)<\/span><\/div>\n                <\/div>\n                <a href=\"https:\/\/www.opey.org\/opeyit\/?page_id=643\" class=\"wcf-risk-btn\">Calculate Your Sovereignty Score<\/a>\n            <\/div>\n            <div class=\"wcf-risk-banner-visual\">\n                <div class=\"wcf-risk-meter-display\">\n                    <div class=\"wcf-meter-label\">Sample Risk Score<\/div>\n                    <div class=\"wcf-meter-value\">78<\/div>\n                    <div class=\"wcf-meter-rating\">HIGH RISK<\/div>\n                    <div class=\"wcf-meter-bar\"><div class=\"wcf-meter-fill\"><\/div><\/div>\n                    <div class=\"wcf-meter-caption\">Single-provider dependency detected<\/div>\n                <\/div>\n            <\/div>\n        <\/div>\n    <\/div>\n<\/div>\n\n<!-- EXPORT SECTION -->\n<div class=\"wcf-section wcf-export\">\n    <div class=\"wcf-section-inner\">\n        <h2 class=\"wcf-section-title\">Export Data<\/h2>\n        <p class=\"wcf-section-subtitle\">Download the complete outage database for your own analysis, research, or reporting.<\/p>\n        <div class=\"wcf-export-grid\">\n            <div class=\"wcf-export-card\" onclick=\"wcfExportCSV()\">\n                <span class=\"wcf-export-icon\">CSV<\/span>\n                <span class=\"wcf-export-format\">CSV File<\/span>\n                <span class=\"wcf-export-desc\">Excel, Google Sheets, data analysis<\/span>\n            <\/div>\n            <div class=\"wcf-export-card\" onclick=\"wcfExportJSON()\">\n                <span class=\"wcf-export-icon\">{ }<\/span>\n                <span class=\"wcf-export-format\">JSON<\/span>\n                <span class=\"wcf-export-desc\">Developers, APIs, integrations<\/span>\n            <\/div>\n            <div class=\"wcf-export-card\" onclick=\"wcfExportXLSX()\">\n                <span class=\"wcf-export-icon\">XLS<\/span>\n                <span class=\"wcf-export-format\">Excel<\/span>\n                <span class=\"wcf-export-desc\">Formatted spreadsheet with headers<\/span>\n            <\/div>\n            <div class=\"wcf-export-card\" onclick=\"wcfExportPDF()\">\n                <span class=\"wcf-export-icon\">PDF<\/span>\n                <span class=\"wcf-export-format\">PDF Report<\/span>\n                <span class=\"wcf-export-desc\">Professional report for sharing<\/span>\n            <\/div>\n        <\/div>\n        <p class=\"wcf-export-note\">Data provided under <a href=\"https:\/\/creativecommons.org\/licenses\/by\/4.0\/\" target=\"_blank\">CC BY 4.0<\/a> license. Attribution: &#8220;When Clouds Fail&#8221; by Steve Oppenheim<\/p>\n    <\/div>\n<\/div>\n\n<!-- ANALYSIS -->\n<div class=\"wcf-section wcf-analysis\">\n    <div class=\"wcf-section-inner\">\n        <h2 class=\"wcf-section-title\">Strategic Analysis<\/h2>\n        <p class=\"wcf-section-subtitle\">The recurring themes that define cloud infrastructure vulnerability.<\/p>\n        <div class=\"wcf-analysis-grid\" id=\"analysis-container\"><\/div>\n    <\/div>\n<\/div>\n\n<!-- COSTS -->\n<div class=\"wcf-section wcf-costs\">\n    <div class=\"wcf-section-inner\">\n        <h2 class=\"wcf-section-title\">The True Cost of Cloud Dependency<\/h2>\n        <p class=\"wcf-section-subtitle\" id=\"cost-year-label\">Industry data on what outages cost enterprises.<\/p>\n        <div class=\"wcf-cost-grid\" id=\"cost-grid\"><\/div>\n        <p class=\"wcf-cost-source\">Sources: EMA Research, BigPanda 2024, Splunk\/Oxford Economics, ITIC, Gartner<\/p>\n    <\/div>\n<\/div>\n\n<!-- CTA -->\n<div class=\"wcf-cta\">\n    <h2 class=\"wcf-cta-title\">Build Your Sovereign Enterprise<\/h2>\n    <p class=\"wcf-cta-text\">Get the frameworks, templates, and strategies to ensure no single vendor failure becomes an enterprise failure.<\/p>\n    <div class=\"wcf-cta-buttons\">\n        <a href=\"https:\/\/www.amazon.com\/dp\/B0GHP5RV68\" class=\"wcf-btn wcf-btn-dark\">Get the Book<\/a>\n        <a href=\"https:\/\/www.opey.org\/opeyit\/?page_id=327#wcf-downloads-section\" class=\"wcf-btn wcf-btn-dark\">Free Templates (44)<\/a>\n        <a href=\"https:\/\/www.opey.org\/opeyit\/?page_id=14\" class=\"wcf-btn wcf-btn-outline\">Advisory Services<\/a>\n    <\/div>\n<\/div>\n\n<\/div>\n\n<script src=\"https:\/\/cdn.sheetjs.com\/xlsx-0.20.1\/package\/dist\/xlsx.full.min.js\"><\/script>\n<script src=\"https:\/\/cdnjs.cloudflare.com\/ajax\/libs\/jspdf\/2.5.1\/jspdf.umd.min.js\"><\/script>\n<script src=\"https:\/\/cdnjs.cloudflare.com\/ajax\/libs\/jspdf-autotable\/3.8.1\/jspdf.plugin.autotable.min.js\"><\/script>\n\n<script>\n(function() {\n    var SHEET_ID = '11SvFM_W9LB661CrcOVMrOiY0coSV1xIQrKCrOZJnqKE';\n    var incidentData = [];\n\n    var FALLBACK = [\n        { date: \"Jan 23, 2026\", year: \"2026\", providers: [\"xAI\", \"Grok\"], title: \"Grok AI Inference Cluster Outage\", severity: \"moderate\", scope: \"US Regional Hubs (Seattle, Minneapolis, Chicago)\", duration: \"2h 36m\", servicesimpacted: \"Grok-2, Grok-3, API Inference, xAI Dashboard\", rootcause: \"Inference cluster scaling failure following model weight synchronization\", costestimate: \"$2.2M - $5.5M\", userreports: \"8,500+\", affectedusers: \"~4.2M active subscribers\", cascadeeffect: \"Third-party automation bots and Agentic CRM integrations failed globally.\", description: \"A weight update caused auto-scaling logic failures in US hubs, highlighting the just-in-time compute fragility.\", sovereigntytitle: \"Agentic AI Compute Sovereignty:\", sovereigntytext: \"Regional compute failures paralyze automated decision-making. Your AI needs local-inference fallbacks. See Chapter 10.\" },\n        { date: \"Jan 22, 2026\", year: \"2026\", providers: [\"Microsoft\", \"Azure\"], title: \"Microsoft 365 and Azure Infrastructure Failure\", severity: \"critical\", scope: \"Global (Primary North America)\", duration: \"6h 12m\", servicesimpacted: \"Outlook, Teams, Defender XDR, Purview, Azure Compute\", rootcause: \"Centralized control plane infrastructure processing failure\", costestimate: \"$1.1B - $1.6B\", userreports: \"16,000+ (Peak)\", affectedusers: \"Tens of millions (Enterprise\/Government)\", cascadeeffect: \"Downstream failures in Asana and critical fintech clearing houses.\", description: \"Major disruption where infrastructure failed to process traffic as expected. Gov agencies reverted to legacy phones.\", sovereigntytitle: \"Layer 4 (Productivity) Failure:\", sovereigntytext: \"Reveals systemic fragility in centralized control planes. Can you work 48 hours without Microsoft? See Chapter 6.\" },\n        { date: \"Jan 22, 2026\", year: \"2026\", providers: [\"Cloudflare\"], title: \"Cloudflare IPv6 BGP Route Leak (Miami)\", severity: \"major\", scope: \"Regional (Americas)\", duration: \"25 Minutes\", servicesimpacted: \"Edge CDN, WAF, API Gateway\", rootcause: \"Automated routing policy configuration error\", costestimate: \"$80M - $120M\", description: \"A routine change leaked IPv6 prefixes internally, mirroring the 2020 incident.\", sovereigntytitle: \"BGP Fragility:\", sovereigntytext: \"One router configuration can destabilize global flow. Multi-homing is no longer optional. See Chapter 5.\" },\n        { date: \"Jan 14, 2026\", year: \"2026\", providers: [\"Verizon\"], title: \"Verizon Nationwide Wireless Network Collapse\", severity: \"critical\", scope: \"United States\", duration: \"9h 30m\", servicesimpacted: \"Voice, SMS, 5G Data, Emergency (911)\", rootcause: \"Core network software update causing signaling storm\", costestimate: \"$650M - $900M\", userreports: \"180,000+\", affectedusers: \"Millions (SOS mode)\", cascadeeffect: \"Ridesharing and field service fleets offline across US East Coast.\", description: \"NYC and DC issued emergency alerts as massive outages left users without basic connectivity.\", sovereigntytitle: \"Telecom Single Point of Failure:\", sovereigntytext: \"When your carrier fails, your mobile workforce goes dark. Requires multi-carrier eSIM. See Chapter 8.\" },\n        { date: \"Jan 8, 2026\", year: \"2026\", providers: [\"Meta\", \"Facebook\", \"Instagram\"], title: \"Meta Global Infrastructure Blackout\", severity: \"critical\", scope: \"Global\", duration: \"5h 30m\", servicesimpacted: \"Facebook, Instagram, WhatsApp, Ads Manager\", rootcause: \"Critical failure in global network traffic management\", costestimate: \"$1.4B - $2.1B\", userreports: \"2,000,000+\", affectedusers: \"1.5B - 2B users\", cascadeeffect: \"Millions of websites using Login with Facebook were unable to authenticate users.\", description: \"Widespread routing failures made the entire Meta ecosystem invisible to the internet.\", sovereigntytitle: \"Identity Sovereignty Risk:\", sovereigntytext: \"Relying on social providers for identity is a sovereignty failure. See Chapter 4.\" },\n        { date: \"Jan 8, 2026\", year: \"2026\", providers: [\"Google Cloud\"], title: \"Google Cloud Global Hardware\/Power Anomaly\", severity: \"critical\", scope: \"Multi-Region\", duration: \"4h 15m\", servicesimpacted: \"Gmail, Workspace, Maps, YouTube, 75+ GCP products\", rootcause: \"Hardware power anomaly in core hub\", costestimate: \"$750M - $950M\", userreports: \"65,000+\", cascadeeffect: \"Snapchat, Spotify, and thousands of GCP-hosted startups experienced total failure.\", description: \"Massive anomaly broke multi-region resilience assumptions.\", sovereigntytitle: \"Hidden Dependency Chain:\", sovereigntytext: \"Find out which SaaS vendors are just GCP wrappers. Audit N-tier dependencies. See Chapter 2.\" },\n        { date: \"Nov 18, 2025\", year: \"2025\", providers: [\"Cloudflare\"], title: \"Cloudflare Bot Management System Failure\", severity: \"critical\", scope: \"Global\", duration: \"~3 Hours\", servicesimpacted: \"CDN, WAF, Bot Management\", rootcause: \"Bot Management File Overflow\", costestimate: \"$250M - $300M\", cascadeeffect: \"Affected X, OpenAI, Spotify, Discord. Even Downdetector went down.\", description: \"Database permission change caused bot management file to double in size.\", sovereigntytitle: \"Single Point of Failure:\", sovereigntytext: \"When your security provider goes down, you are both unprotected AND offline.\" },\n        { date: \"Oct 29, 2025\", year: \"2025\", providers: [\"Azure\"], title: \"Azure Global Connectivity Failure - Front Door Outage\", severity: \"critical\", scope: \"Global\", duration: \"8h 24m\", servicesimpacted: \"365, Teams, Xbox, Minecraft\", rootcause: \"Latent Bug Bypassed Safety Validation\", costestimate: \"$600M - $900M\", cascadeeffect: \"Costco and Starbucks websites also affected.\", description: \"Azure experienced global connectivity failure where edge nodes refused incoming connections.\", sovereigntytitle: \"Front Door = Front Line:\", sovereigntytext: \"When your entry point fails, everything behind it becomes unreachable.\" },\n        { date: \"Oct 20, 2025\", year: \"2025\", providers: [\"AWS\"], title: \"AWS US-EAST-1 DynamoDB DNS Cascade Failure\", severity: \"critical\", scope: \"US-EAST-1 \/ Global\", duration: \"~15 Hours\", servicesimpacted: \"141+ AWS Services\", rootcause: \"DNS Resolution Failure + Automation Error\", costestimate: \"$1.5B - $2.5B\", userreports: \"4,000,000+\", cascadeeffect: \"WhatsApp, DoorDash, Disney+, McDonald App, Ring doorbells affected.\", description: \"Largest AWS outage to date. Race condition in DynamoDB DNS caused cascade failure.\", sovereigntytitle: \"US-EAST-1 Fragility:\", sovereigntytext: \"This region hosts AWS global control plane. You cannot have true failover that relies on US-EAST-1.\" },\n        { date: \"Jun 12, 2025\", year: \"2025\", providers: [\"Google Cloud\"], title: \"Google Cloud Service Control Null-Pointer Crash Loop\", severity: \"critical\", scope: \"Global Multi-Region\", duration: \"7+ Hours\", servicesimpacted: \"54 GCP Products + Workspace\", rootcause: \"Policy Change + Null-Pointer Bug\", costestimate: \"$700M - $1B\", cascadeeffect: \"Spotify, Discord, Snapchat experienced downstream failures.\", description: \"Policy change to Google Service Control triggered null-pointer crash loop affecting Gmail, Docs, Drive, Maps, Gemini.\", sovereigntytitle: \"Control Plane Criticality:\", sovereigntytext: \"Service Control is foundational. When it fails, the entire ecosystem collapses.\" },\n        { date: \"Jul 19, 2024\", year: \"2024\", providers: [\"CrowdStrike\", \"Microsoft\"], title: \"CrowdStrike Falcon Update - Largest IT Outage in History\", severity: \"critical\", scope: \"Global\", devicesaffected: \"8.5 Million Windows\", servicesimpacted: \"Airlines, Banks, Hospitals\", rootcause: \"Faulty Falcon Sensor Update\", costestimate: \"$5.4B+\", flightscancelled: \"5,078\", cascadeeffect: \"Delta lost $380M in 5 days. Hospitals switched to manual processes.\", description: \"CrowdStrike update caused BSOD on 8.5 million Windows devices. Recovery required manual intervention.\", sovereigntytitle: \"Third-Party Security Dependency:\", sovereigntytext: \"Your security vendor update pipeline is critical infrastructure. 60% of Fortune 500 used CrowdStrike.\" },\n        { date: \"Jul 18, 2024\", year: \"2024\", providers: [\"Azure\"], title: \"Azure Central US Storage Incident\", severity: \"major\", scope: \"Central US\", duration: \"~15 Hours\", servicesimpacted: \"VMs, Microsoft 365\", rootcause: \"Backend Configuration Change\", costestimate: \"$200M - $400M\", description: \"Storage incident blocked backend access. Occurred day before CrowdStrike incident.\", sovereigntytitle: \"Compounding Failures:\", sovereigntytext: \"Two unrelated incidents within 24 hours created multiplicative impact.\" },\n        { date: \"Oct 23, 2024\", year: \"2024\", providers: [\"Google Cloud\"], title: \"Google Cloud Frankfurt Data Center Power Failure\", severity: \"major\", scope: \"Europe-West3\", duration: \"~8 Hours\", servicesimpacted: \"europe-west3-c Zone\", rootcause: \"Power Failure + Electrical Arc\", costestimate: \"$100M - $200M\", description: \"Power failure caused electrical arc, requiring partial shutdown.\", sovereigntytitle: \"Physical Infrastructure Risk:\", sovereigntytext: \"Electrical arcs are physical world problems no software resilience can prevent.\" },\n        { date: \"Jun 13, 2023\", year: \"2023\", providers: [\"AWS\"], title: \"AWS Lambda Capacity Management Failure\", severity: \"critical\", scope: \"US-EAST-1\", duration: \"~4 Hours\", servicesimpacted: \"104+ AWS Services\", rootcause: \"Latent Software Defect in Lambda\", costestimate: \"$300M - $500M\", description: \"Latent software defect in Lambda capacity management caused elevated errors across 104 services.\", sovereigntytitle: \"Serverless Dependency Risk:\", sovereigntytext: \"Lambda is foundational to modern cloud. Consider hybrid serverless strategies.\" },\n        { date: \"Apr 25, 2023\", year: \"2023\", providers: [\"Google Cloud\"], title: \"Google Cloud Paris Data Center Fire\", severity: \"major\", scope: \"Europe-West9\", servicesimpacted: \"europe-west9-a Zone\", rootcause: \"Data Center Fire\", description: \"Fire in Paris data center caused multi-cluster failure. Water damage from suppression extended recovery.\", sovereigntytitle: \"Physical Disaster Reality:\", sovereigntytext: \"Fires happen. Geographic diversity is not just about regions - it is about physical separation.\" },\n        { date: \"Jun 21, 2022\", year: \"2022\", providers: [\"Cloudflare\"], title: \"Cloudflare BGP Network Configuration Error\", severity: \"critical\", scope: \"Global (19 Data Centers)\", duration: \"~1.5 Hours\", servicesimpacted: \"Discord, Shopify, Fitbit, FTX\", rootcause: \"BGP Prefix Reordering Error\", costestimate: \"$250M - $300M\", description: \"Network configuration change in 19 busiest data centers caused BGP prefix reordering. Only 4% of network but 50% of requests.\", sovereigntytitle: \"Concentration Risk:\", sovereigntytext: \"A handful of data centers handle disproportionate traffic. Downdetector itself went down.\" },\n        { date: \"Jul 28, 2022\", year: \"2022\", providers: [\"AWS\"], title: \"AWS US-EAST-2 Power Outage\", severity: \"major\", scope: \"US-EAST-2 (Ohio)\", duration: \"3 Hr Recovery\", servicesimpacted: \"EC2, Network Connectivity\", rootcause: \"Power Outage in AZ1\", downstreamimpact: \"Webex, Okta, Splunk, BambooHR\", description: \"Power outage in AZ1 caused network problems. Power lasted 20 min but recovery took 3 hours.\", sovereigntytitle: \"Recovery Lag:\", sovereigntytext: \"Power issues resolve quickly but service recovery lags significantly.\" },\n        { date: \"Jul 2022\", year: \"2022\", providers: [\"Google Cloud\"], title: \"UK Heat Wave Data Center Cooling Failures\", severity: \"major\", scope: \"UK Region\", servicesimpacted: \"UK-based services\", rootcause: \"Cooling System Failure (40C Heat)\", alsoaffected: \"Oracle Cloud\", description: \"Record 40C temperatures overwhelmed cooling at both Google and Oracle data centers.\", sovereigntytitle: \"Climate Risk:\", sovereigntytext: \"Data centers designed for historical climate are challenged by new temperature extremes.\" },\n        { date: \"Dec 2022\", year: \"2022\", providers: [\"Legacy Systems\"], title: \"Southwest Airlines Scheduling System Meltdown\", severity: \"critical\", scope: \"National\", flightscancelled: \"16,700+\", rootcause: \"Legacy Scheduling System Overload\", costestimate: \"$800M+\", description: \"Winter storm overwhelmed Southwest outdated scheduling system (unchanged since 1990s).\", sovereigntytitle: \"Technical Debt Reality:\", sovereigntytext: \"Legacy systems that work fine become catastrophic under stress. Cost of not modernizing exceeded any reasonable budget.\" },\n        { date: \"Dec 7, 2021\", year: \"2021\", providers: [\"AWS\"], title: \"AWS US-EAST-1 Network Congestion Cascade\", severity: \"critical\", scope: \"US-EAST-1 \/ Global\", duration: \"~7 Hours\", servicesimpacted: \"EC2, DynamoDB, Connect, S3\", rootcause: \"Automated Scaling Triggered Network Flood\", costestimate: \"$500M - $1B\", cascadeeffect: \"Netflix, Disney+, Roomba, Ticketmaster, WSJ affected. AWS Status Dashboard also failed.\", description: \"Automated scaling overwhelmed networking devices. Internal monitoring was blind.\", sovereigntytitle: \"Monitoring Blindness:\", sovereigntytext: \"When monitoring runs on infrastructure it monitors, you are flying blind during the worst moments.\" },\n        { date: \"Oct 4, 2021\", year: \"2021\", providers: [\"Meta\", \"Facebook\"], title: \"Facebook Global BGP\/DNS Configuration Disaster\", severity: \"critical\", scope: \"Global\", duration: \"~6 Hours\", servicesimpacted: \"Facebook, Instagram, WhatsApp\", rootcause: \"Maintenance Error Withdrew BGP Routes\", costestimate: \"$100M+\", description: \"Routine maintenance disconnected data centers from backbone. Employees could not access buildings.\", sovereigntytitle: \"BGP is Foundational:\", sovereigntytext: \"When you withdraw BGP routes, you cease to exist on the internet.\" },\n        { date: \"Jun 8, 2021\", year: \"2021\", providers: [\"Fastly\"], title: \"Fastly CDN Global Configuration Bug\", severity: \"critical\", scope: \"Global\", duration: \"~1 Hour\", servicesimpacted: \"NYT, Guardian, Reddit, Twitch, UK Gov\", rootcause: \"Software Bug + Customer Config Trigger\", costestimate: \"$150M - $250M\", description: \"Software bug caused CPU spike when triggered by customer configuration.\", sovereigntytitle: \"CDN Concentration:\", sovereigntytext: \"A single CDN serves massive swaths of the internet. Multi-CDN strategies are no longer optional.\" },\n        { date: \"Mar 15, 2021\", year: \"2021\", providers: [\"Azure\"], title: \"Azure Active Directory Global Authentication Failure\", severity: \"critical\", scope: \"Global\", servicesimpacted: \"Teams, Office 365, Dynamics, Azure Portal\", rootcause: \"Token Validation Bug (Race Condition)\", costestimate: \"$300M - $500M\", description: \"Configuration error introduced token validation bug. MFA stopped working. Admins locked out.\", sovereigntytitle: \"Identity = Everything:\", sovereigntytext: \"When identity provider fails, you cannot access anything - including tools to fix the problem.\" },\n        { date: \"Dec 14, 2020\", year: \"2020\", providers: [\"Google Cloud\"], title: \"Google Global Authentication Quota Exhaustion\", severity: \"critical\", scope: \"Global\", duration: \"~50 Minutes\", servicesimpacted: \"Gmail, YouTube, Drive, GCP, Workspace\", rootcause: \"Internal Storage Quota Issue\", costestimate: \"$200M - $400M\", description: \"Quota system upgrade left old checks in place. Grace period expired, triggering storage reduction for User ID service.\", sovereigntytitle: \"Quota System Complexity:\", sovereigntytext: \"Changes to quota systems have delayed effects. Outage started with October upgrade but manifested in December.\" },\n        { date: \"Nov 25, 2020\", year: \"2020\", providers: [\"AWS\"], title: \"AWS Kinesis Thread Exhaustion Cascade\", severity: \"critical\", scope: \"US-EAST-1\", duration: \"~8 Hours\", servicesimpacted: \"Kinesis, CloudWatch, Cognito, Lambda\", rootcause: \"OS Thread Limit Exceeded\", costestimate: \"$300M - $500M\", description: \"Adding capacity caused servers to exceed OS thread limit, cascading to CloudWatch and Cognito.\", sovereigntytitle: \"Latent Bug Trigger:\", sovereigntytext: \"Scaling up can be as dangerous as scaling down if it exposes untested limits.\" },\n        { date: \"Aug 24, 2020\", year: \"2020\", providers: [\"Zoom\"], title: \"Zoom US\/UK Video Service Outage\", severity: \"major\", scope: \"US and UK\", duration: \"~5 Hours\", servicesimpacted: \"Meetings, Webinars, Website\", rootcause: \"Undisclosed\", context: \"Peak Remote Work Era\", description: \"During height of COVID-19 remote work, US and UK users could not access Zoom as East Coast workday kicked off.\", sovereigntytitle: \"Single Communication Channel Risk:\", sovereigntytext: \"Organizations dependent on Zoom found themselves without fallback. Communication diversity is business continuity.\" },\n        { date: \"Aug 2020\", year: \"2020\", providers: [\"Google Cloud\"], title: \"Google Cloud IAM Bulk Update Cascade\", severity: \"major\", scope: \"Global\", duration: \"~3.5 Hours\", servicesimpacted: \"IAM, Multiple GCP Services\", rootcause: \"Bulk Permission Update Backlog\", costestimate: \"$100M - $200M\", description: \"Bulk update expanded to unexpectedly high number of modified permissions, generating massive backlog.\", sovereigntytitle: \"Administrative Actions at Scale:\", sovereigntytext: \"Routine admin operations can cascade when touching foundational services like IAM.\" },\n        { date: \"Sep 2020\", year: \"2020\", providers: [\"Azure\"], title: \"Azure US East Data Center Cooling Failure\", severity: \"major\", scope: \"US East\", duration: \"~6 Hours\", servicesimpacted: \"Compute, Storage Instances\", rootcause: \"Cooling System Failure\", recovery: \"Hardware Power-Cycle Required\", description: \"Cooling failure caused temperatures to rise, preventing network devices from performing.\", sovereigntytitle: \"Thermal Dependency:\", sovereigntytext: \"Digital services run on physical hardware that generates heat. You cannot just restart an overheated data center.\" }\n    ];\n\n    var downtimeCostData = {\n        '2020': { perMinute: 11000, perHour: 660000, largeEnterprise: 16500, annualGlobal: 320 },\n        '2021': { perMinute: 11800, perHour: 708000, largeEnterprise: 17700, annualGlobal: 340 },\n        '2022': { perMinute: 12900, perHour: 774000, largeEnterprise: 19350, annualGlobal: 360 },\n        '2023': { perMinute: 13500, perHour: 810000, largeEnterprise: 20250, annualGlobal: 380 },\n        '2024': { perMinute: 14056, perHour: 843360, largeEnterprise: 23750, annualGlobal: 400 },\n        '2025': { perMinute: 15500, perHour: 930000, largeEnterprise: 26125, annualGlobal: 440 },\n        '2026': { perMinute: 17000, perHour: 1020000, largeEnterprise: 28700, annualGlobal: 485 }\n    };\n\n    var analysisData = [\n        { number: 1, title: \"US-EAST-1 Fragility\", text: \"AWS Northern Virginia hosts global control plane services. When it fails, multi-region deployments are still impacted.\" },\n        { number: 2, title: \"Identity as Foundation\", text: \"When authentication fails, everything fails. Emergency admin access must be separate from primary auth.\" },\n        { number: 3, title: \"Configuration Change Risk\", text: \"Routine configuration changes triggered catastrophic failures at Cloudflare, Facebook, Fastly, and AWS.\" },\n        { number: 4, title: \"Third-Party Cascade\", text: \"CrowdStrike (2024) proved your security vendor deployment pipeline is critical infrastructure.\" },\n        { number: 5, title: \"Physical Infrastructure\", text: \"Cooling failures, fires, power outages - digital services run on physical hardware.\" },\n        { number: 6, title: \"Monitoring Blindness\", text: \"When monitoring runs on the infrastructure it monitors, you are blind during the worst moments.\" }\n    ];\n\n    var exportColumns = [\n        { key: 'date', label: 'Date' },\n        { key: 'year', label: 'Year' },\n        { key: 'providers', label: 'Providers' },\n        { key: 'title', label: 'Incident Title' },\n        { key: 'severity', label: 'Severity' },\n        { key: 'scope', label: 'Scope' },\n        { key: 'duration', label: 'Duration' },\n        { key: 'servicesimpacted', label: 'Services Impacted' },\n        { key: 'rootcause', label: 'Root Cause' },\n        { key: 'costestimate', label: 'Est. Cost Impact' },\n        { key: 'description', label: 'Description' },\n        { key: 'sovereigntytitle', label: 'Sovereignty Theme' },\n        { key: 'sovereigntytext', label: 'Sovereignty Analysis' }\n    ];\n\n    function getField(obj, fieldName) {\n        if (obj[fieldName] && String(obj[fieldName]).trim()) return String(obj[fieldName]);\n        var lower = fieldName.toLowerCase();\n        for (var key in obj) {\n            if (key.toLowerCase() === lower && obj[key] && String(obj[key]).trim()) {\n                return String(obj[key]);\n            }\n        }\n        return '';\n    }\n\n    function prepareExportData() {\n        return incidentData.map(function(inc) {\n            var row = {};\n            exportColumns.forEach(function(col) {\n                var val = getField(inc, col.key);\n                if (col.key === 'providers' && Array.isArray(inc.providers)) {\n                    val = inc.providers.join(', ');\n                }\n                row[col.label] = val;\n            });\n            return row;\n        });\n    }\n\n    function getDateStamp() {\n        var d = new Date();\n        return d.getFullYear() + '-' + String(d.getMonth() + 1).padStart(2, '0') + '-' + String(d.getDate()).padStart(2, '0');\n    }\n\n    function downloadBlob(blob, filename) {\n        var link = document.createElement('a');\n        link.href = URL.createObjectURL(blob);\n        link.download = filename;\n        document.body.appendChild(link);\n        link.click();\n        document.body.removeChild(link);\n        URL.revokeObjectURL(link.href);\n    }\n\n    window.wcfExportCSV = function() {\n        if (incidentData.length === 0) { alert('No data available to export.'); return; }\n        var data = prepareExportData();\n        var headers = exportColumns.map(function(c) { return c.label; });\n        var csvContent = headers.map(function(h) { return '\"' + h.replace(\/\"\/g, '\"\"') + '\"'; }).join(',') + '\\n';\n        data.forEach(function(row) {\n            var line = headers.map(function(h) {\n                var val = row[h] || '';\n                return '\"' + String(val).replace(\/\"\/g, '\"\"') + '\"';\n            }).join(',');\n            csvContent += line + '\\n';\n        });\n        var blob = new Blob([csvContent], { type: 'text\/csv;charset=utf-8;' });\n        downloadBlob(blob, 'cloud-outage-database-' + getDateStamp() + '.csv');\n    };\n\n    window.wcfExportJSON = function() {\n        if (incidentData.length === 0) { alert('No data available to export.'); return; }\n        var data = {\n            metadata: {\n                title: 'Cloud Outage Database',\n                source: 'When Clouds Fail by Steve Oppenheim',\n                website: 'https:\/\/www.opey.org',\n                exportDate: new Date().toISOString(),\n                totalIncidents: incidentData.length,\n                license: 'CC BY 4.0'\n            },\n            incidents: prepareExportData()\n        };\n        var blob = new Blob([JSON.stringify(data, null, 2)], { type: 'application\/json' });\n        downloadBlob(blob, 'cloud-outage-database-' + getDateStamp() + '.json');\n    };\n\n    window.wcfExportXLSX = function() {\n        if (incidentData.length === 0) { alert('No data available to export.'); return; }\n        if (typeof XLSX === 'undefined') { alert('Excel export library not loaded. Please try again or use CSV format.'); return; }\n        var data = prepareExportData();\n        var ws = XLSX.utils.json_to_sheet(data);\n        var wb = XLSX.utils.book_new();\n        XLSX.utils.book_append_sheet(wb, ws, 'Cloud Outages');\n        XLSX.writeFile(wb, 'cloud-outage-database-' + getDateStamp() + '.xlsx');\n    };\n\n    window.wcfExportPDF = function() {\n        if (incidentData.length === 0) { alert('No data available to export.'); return; }\n        if (typeof window.jspdf === 'undefined') { alert('PDF export library not loaded. Please try again.'); return; }\n        var jsPDF = window.jspdf.jsPDF;\n        var doc = new jsPDF('l', 'mm', 'a4');\n        doc.setFontSize(20);\n        doc.text('Cloud Outage Database', 14, 20);\n        doc.setFontSize(10);\n        doc.text('Source: When Clouds Fail by Steve Oppenheim | www.opey.org', 14, 28);\n        var pdfColumns = ['Date', 'Providers', 'Incident Title', 'Severity', 'Duration', 'Est. Cost Impact'];\n        var data = prepareExportData();\n        var tableData = data.map(function(row) {\n            return pdfColumns.map(function(col) { return row[col] || '-'; });\n        });\n        doc.autoTable({\n            head: [pdfColumns],\n            body: tableData,\n            startY: 35,\n            styles: { fontSize: 8 },\n            headStyles: { fillColor: [15, 23, 42] }\n        });\n        doc.save('cloud-outage-database-' + getDateStamp() + '.pdf');\n    };\n\n    function formatDate(value) {\n        if (!value) return value;\n        var months = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'];\n        if (typeof value === 'string' && value.indexOf('Date(') === 0) {\n            var match = value.match(\/Date\\((\\d+),(\\d+),(\\d+)\\)\/);\n            if (match) return months[parseInt(match[2])] + ' ' + match[3] + ', ' + match[1];\n        }\n        if (typeof value === 'string' && \/^[A-Z][a-z]{2}\\s+\\d\/.test(value)) return value;\n        if (typeof value === 'string' && \/^\\d{4}-\\d{2}-\\d{2}\/.test(value)) {\n            var d = new Date(value);\n            return months[d.getMonth()] + ' ' + d.getDate() + ', ' + d.getFullYear();\n        }\n        return value;\n    }\n\n    function loadData() {\n        var container = document.getElementById('incidents-container');\n        container.innerHTML = '<div style=\"text-align:center;padding:60px 20px;color:#64748b;\"><p style=\"font-size:18px;\">Loading Outage Database...<\/p><\/div>';\n\n        var url = 'https:\/\/docs.google.com\/spreadsheets\/d\/' + SHEET_ID + '\/gviz\/tq?tqx=out:json&gid=0&headers=1';\n\n        fetch(url)\n            .then(function(response) {\n                if (!response.ok) throw new Error('HTTP ' + response.status);\n                return response.text();\n            })\n            .then(function(text) {\n                var start = text.indexOf('{');\n                var end = text.lastIndexOf('}');\n                if (start === -1) throw new Error('No JSON in response');\n                \n                var json = JSON.parse(text.substring(start, end + 1));\n                var headers = json.table.cols.map(function(c) { \n                    return (c.label || c.id || '').trim(); \n                });\n                \n                if (headers.every(function(h) { return \/^[A-Za-z]$\/.test(h); })) {\n                    headers = json.table.rows[0].c.map(function(c) { \n                        return c ? String(c.v || '').trim() : ''; \n                    });\n                    json.table.rows.shift();\n                }\n                \n                incidentData = json.table.rows.map(function(row) {\n                    if (!row || !row.c) return null;\n                    var obj = {};\n                    row.c.forEach(function(cell, i) {\n                        if (headers[i]) {\n                            var val = cell ? (cell.f || (cell.v != null ? String(cell.v) : '')) : '';\n                            if (headers[i] === 'date') val = formatDate(val);\n                            obj[headers[i]] = val.trim();\n                        }\n                    });\n                    obj.providers = obj.providers ? obj.providers.split(',').map(function(p) { return p.trim(); }).filter(Boolean) : [];\n                    return obj;\n                }).filter(function(o) { return o && o.date && o.title && o.severity; });\n                \n                if (incidentData.length === 0) throw new Error('No valid incidents');\n                renderAll();\n            })\n            .catch(function(err) {\n                console.error('Load failed:', err.message);\n                incidentData = FALLBACK;\n                \n                var errMsg = document.createElement('div');\n                errMsg.style.cssText = 'background:#fef2f2;border:1px solid #fecaca;padding:12px 20px;border-radius:8px;margin-bottom:20px;color:#991b1b;font-size:14px;';\n                errMsg.innerHTML = '<strong>Note:<\/strong> Live data unavailable. Showing sample data. <a href=\"https:\/\/docs.google.com\/spreadsheets\/d\/' + SHEET_ID + '\" target=\"_blank\" style=\"color:#1d4ed8;\">Check sheet permissions<\/a>';\n                container.innerHTML = '';\n                container.appendChild(errMsg);\n                \n                renderAll();\n            });\n    }\n\n    function renderAll() {\n        incidentData.sort(function(a, b) { return new Date(b.date) - new Date(a.date); });\n        renderStats();\n        renderFilters();\n        renderIncidents();\n        renderAnalysis();\n        renderCosts('all');\n        \n        var lastUpdated = document.querySelector('.wcf-last-updated');\n        if (lastUpdated && incidentData.length > 0) {\n            lastUpdated.innerHTML = 'Data through: ' + incidentData[0].date + '<span class=\"wcf-live-badge\">Live<\/span>';\n        }\n    }\n\n    function getYears() {\n        var years = [];\n        incidentData.forEach(function(i) { if (years.indexOf(i.year) === -1) years.push(i.year); });\n        return years.sort(function(a, b) { return b - a; });\n    }\n\n    function getProviderCount() {\n        var providers = [];\n        incidentData.forEach(function(i) {\n            (i.providers || []).forEach(function(p) {\n                var n = p.toLowerCase();\n                if (providers.indexOf(n) === -1) providers.push(n);\n            });\n        });\n        return providers.length;\n    }\n\n    function calcTotalImpact() {\n        var total = 0;\n        incidentData.forEach(function(i) {\n            var cost = i.costEstimate || i.costestimate || '';\n            if (cost) {\n                var m = cost.match(\/([\\d.]+)\\s*([BMK])?\/gi);\n                if (m && m.length > 0) {\n                    var last = m[m.length - 1];\n                    var nm = last.match(\/([\\d.]+)\\s*([BMK])?\/i);\n                    if (nm) {\n                        var n = parseFloat(nm[1]);\n                        var s = (nm[2] || '').toUpperCase();\n                        if (s === 'B') n *= 1000;\n                        else if (s === 'K') n \/= 1000;\n                        total += n;\n                    }\n                }\n            }\n        });\n        return total;\n    }\n\n    function renderStats() {\n        var c = document.getElementById('stats-container');\n        var years = getYears();\n        c.innerHTML = '<div class=\"wcf-stat\"><span class=\"wcf-stat-num\">' + incidentData.length + '+<\/span><span class=\"wcf-stat-label\">Major Incidents<\/span><\/div>' +\n            '<div class=\"wcf-stat\"><span class=\"wcf-stat-num\">$' + Math.round(calcTotalImpact()) + 'B+<\/span><span class=\"wcf-stat-label\">Est. Total Impact<\/span><\/div>' +\n            '<div class=\"wcf-stat\"><span class=\"wcf-stat-num\">' + years.length + '<\/span><span class=\"wcf-stat-label\">Years Documented<\/span><\/div>' +\n            '<div class=\"wcf-stat\"><span class=\"wcf-stat-num\">' + getProviderCount() + '+<\/span><span class=\"wcf-stat-label\">Providers Tracked<\/span><\/div>';\n    }\n\n    function renderFilters() {\n        var c = document.getElementById('filter-container');\n        var years = getYears();\n        var html = '<span class=\"wcf-filter-label\">Filter by Year:<\/span><button class=\"wcf-year-btn active\" onclick=\"wcfFilter(\\'all\\')\">All Years<\/button>';\n        years.forEach(function(y) { html += '<button class=\"wcf-year-btn\" onclick=\"wcfFilter(\\'' + y + '\\')\">' + y + '<\/button>'; });\n        html += '<span class=\"wcf-results-count\" id=\"results-count\">Showing all ' + incidentData.length + ' incidents<\/span>';\n        c.innerHTML = html;\n    }\n\n    function getProviderClass(p) { return 'wcf-provider-' + p.replace(\/[\\s\\\/]+\/g, '-').toLowerCase(); }\n\n    function renderIncidents() {\n        var c = document.getElementById('incidents-container');\n        var years = getYears();\n        var html = '';\n        \n        years.forEach(function(year) {\n            var yi = incidentData.filter(function(i) { return i.year === year; });\n            if (yi.length > 0) {\n                html += '<div class=\"wcf-year-divider\" data-year=\"' + year + '\"><span>' + year + '<\/span><\/div>';\n                yi.forEach(function(inc) {\n                    var badges = (inc.providers || []).map(function(p) { return '<span class=\"wcf-provider-badge ' + getProviderClass(p) + '\">' + p + '<\/span>'; }).join('');\n                    \n                    var details = '';\n                    var statFields = [\n                        ['duration','Duration'],\n                        ['servicesImpacted','Services Impacted'],\n                        ['rootCause','Root Cause'],\n                        ['costEstimate','Est. Cost Impact'],\n                        ['userReports','User Reports'],\n                        ['affectedUsers','Affected Users'],\n                        ['devicesAffected','Devices Affected'],\n                        ['flightsCancelled','Flights Cancelled']\n                    ];\n                    statFields.forEach(function(f) {\n                        var val = getField(inc, f[0]);\n                        if (val && val.trim()) {\n                            details += '<div class=\"wcf-detail-item\"><span class=\"wcf-detail-label\">' + f[1] + '<\/span><span class=\"wcf-detail-value\">' + val + '<\/span><\/div>';\n                        }\n                    });\n                    \n                    var narrative = '';\n                    var narrativeFields = [\n                        ['cascadeEffect','Cascade Effect'],\n                        ['downstreamImpact','Downstream Impact'],\n                        ['context','Context'],\n                        ['alsoAffected','Also Affected'],\n                        ['impact','Impact'],\n                        ['recovery','Recovery']\n                    ];\n                    narrativeFields.forEach(function(f) {\n                        var val = getField(inc, f[0]);\n                        if (val && val.trim()) {\n                            narrative += '<div class=\"wcf-narrative-item\"><span class=\"wcf-narrative-label\">' + f[1] + ':<\/span> ' + val + '<\/div>';\n                        }\n                    });\n                    \n                    var sov = '';\n                    var sovTitle = getField(inc, 'sovereigntyTitle');\n                    var sovText = getField(inc, 'sovereigntyText');\n                    if (sovTitle || sovText) {\n                        sov = '<div class=\"wcf-sovereignty-take\"><span class=\"wcf-sovereignty-label\">Sovereignty Take<\/span><p class=\"wcf-sovereignty-text\"><strong>' + sovTitle + '<\/strong> ' + sovText + '<\/p><\/div>';\n                    }\n                    \n                    var sev = (inc.severity || 'moderate').toLowerCase();\n                    var scope = getField(inc, 'scope') || 'Unknown';\n                    \n                    html += '<div class=\"wcf-incident-card severity-' + sev + '\" data-year=\"' + inc.year + '\">' +\n                        '<div class=\"wcf-incident-header\">' +\n                        '<span class=\"wcf-incident-date\">' + inc.date + '<\/span>' +\n                        '<div class=\"wcf-incident-meta\"><div class=\"wcf-incident-provider\">' + badges + '<\/div><h3 class=\"wcf-incident-title\">' + inc.title + '<\/h3><\/div>' +\n                        '<div class=\"wcf-incident-badges\"><span class=\"wcf-severity-badge wcf-severity-' + sev + '\">' + sev.charAt(0).toUpperCase() + sev.slice(1) + '<\/span><span class=\"wcf-scope-badge\">' + scope + '<\/span><\/div><\/div>' +\n                        '<div class=\"wcf-incident-body\">' + \n                        (details ? '<div class=\"wcf-incident-details\">' + details + '<\/div>' : '') +\n                        (inc.description ? '<p class=\"wcf-incident-desc\">' + inc.description + '<\/p>' : '') + \n                        (narrative ? '<div class=\"wcf-incident-narrative\">' + narrative + '<\/div>' : '') +\n                        sov + \n                        '<\/div><\/div>';\n                });\n            }\n        });\n        \n        var errMsg = c.querySelector('div[style*=\"fef2f2\"]');\n        c.innerHTML = html;\n        if (errMsg) c.insertBefore(errMsg, c.firstChild);\n    }\n\n    function renderAnalysis() {\n        var c = document.getElementById('analysis-container');\n        c.innerHTML = analysisData.map(function(a) {\n            return '<div class=\"wcf-analysis-card\"><div class=\"wcf-analysis-icon\">' + a.number + '<\/div><h3 class=\"wcf-analysis-title\">' + a.title + '<\/h3><p class=\"wcf-analysis-text\">' + a.text + '<\/p><\/div>';\n        }).join('');\n    }\n\n    function formatCurrency(n) {\n        if (n >= 1000000) return '$' + (n\/1000000).toFixed(1) + 'M';\n        if (n >= 1000) return '$' + Math.round(n\/1000) + 'K';\n        return '$' + n.toLocaleString();\n    }\n\n    function calcAvgCosts() {\n        var keys = Object.keys(downtimeCostData);\n        var t = { perMinute: 0, perHour: 0, largeEnterprise: 0, annualGlobal: 0 };\n        keys.forEach(function(k) {\n            t.perMinute += downtimeCostData[k].perMinute;\n            t.perHour += downtimeCostData[k].perHour;\n            t.largeEnterprise += downtimeCostData[k].largeEnterprise;\n            t.annualGlobal += downtimeCostData[k].annualGlobal;\n        });\n        return { perMinute: Math.round(t.perMinute\/keys.length), perHour: Math.round(t.perHour\/keys.length), largeEnterprise: Math.round(t.largeEnterprise\/keys.length), annualGlobal: Math.round(t.annualGlobal\/keys.length) };\n    }\n\n    function renderCosts(year) {\n        var cg = document.getElementById('cost-grid');\n        var cl = document.getElementById('cost-year-label');\n        var data = year === 'all' ? calcAvgCosts() : (downtimeCostData[year] || calcAvgCosts());\n        var label = year === 'all' ? '2020-2026 Average' : year;\n        cl.textContent = 'Industry data on what outages cost enterprises (' + label + ').';\n        cg.innerHTML = '<div class=\"wcf-cost-card\"><span class=\"wcf-cost-amount\">$' + data.annualGlobal + 'B<\/span><span class=\"wcf-cost-label\">Annual Global Loss<\/span><p class=\"wcf-cost-desc\">Global 2000 downtime losses<\/p><\/div>' +\n            '<div class=\"wcf-cost-card\"><span class=\"wcf-cost-amount\">' + formatCurrency(data.perHour) + '<\/span><span class=\"wcf-cost-label\">Per Hour Average<\/span><p class=\"wcf-cost-desc\">Enterprise cost\/hour<\/p><\/div>' +\n            '<div class=\"wcf-cost-card\"><span class=\"wcf-cost-amount\">$' + data.perMinute.toLocaleString() + '<\/span><span class=\"wcf-cost-label\">Per Minute Average<\/span><p class=\"wcf-cost-desc\">Average cost\/minute<\/p><\/div>' +\n            '<div class=\"wcf-cost-card\"><span class=\"wcf-cost-amount\">$' + data.largeEnterprise.toLocaleString() + '<\/span><span class=\"wcf-cost-label\">Large Enterprise\/Min<\/span><p class=\"wcf-cost-desc\">10,000+ employees<\/p><\/div>';\n    }\n\n    window.wcfFilter = function(year) {\n        var cards = document.querySelectorAll('#wcf-outage-tracker-archive .wcf-incident-card');\n        var dividers = document.querySelectorAll('#wcf-outage-tracker-archive .wcf-year-divider');\n        var btns = document.querySelectorAll('#wcf-outage-tracker-archive .wcf-year-btn');\n        var count = 0;\n        \n        btns.forEach(function(b) {\n            b.classList.remove('active');\n            if ((year === 'all' && b.textContent === 'All Years') || b.textContent === year) b.classList.add('active');\n        });\n        \n        cards.forEach(function(c) {\n            var cy = c.getAttribute('data-year');\n            if (year === 'all' || cy === year) { c.classList.remove('wcf-hidden'); count++; }\n            else { c.classList.add('wcf-hidden'); }\n        });\n        \n        dividers.forEach(function(d) {\n            var dy = d.getAttribute('data-year');\n            if (year === 'all' || dy === year) d.classList.remove('wcf-hidden');\n            else d.classList.add('wcf-hidden');\n        });\n        \n        document.getElementById('results-count').textContent = year === 'all' ? 'Showing all ' + count + ' incidents' : 'Showing ' + count + ' incidents from ' + year;\n        renderCosts(year);\n    };\n\n    if (document.readyState === 'loading') {\n        document.addEventListener('DOMContentLoaded', loadData);\n    } else {\n        loadData();\n    }\n})();\n<\/script>\n\n\n\n\n<div id=\"elemID031021\" style=\"line-height:16px;text-align:center;z-index:100000;\"><a title=\"wix guests ip\" href=\"https:\/\/www.tracemyip.org\/pv1-3-36447-2\"><img decoding=\"async\" src=\"\/\/s3.tracemyip.org\/vLg\/1217\/4684NR-IPIB\/57003\/9\/njsUrl\/\" alt=\"Wix guests ip\" referrerpolicy=\"no-referrer-when-downgrade\" style=\"border:0px;\"><\/a><div><a href=\"https:\/\/www.tracemyip.org\/pv1-3-36447-2\">ip traffic<\/a><\/div><\/div>\n","protected":false},"excerpt":{"rendered":"<p>\/!\\ Comprehensive Archive Cloud Outage Database 2020 &#8211; 2026: Seven Years of Cloud Infrastructure Failures The definitive archive of major cloud service disruptions. A companion resource to &#8220;When Clouds Fail&#8221;. Loading&#8230;Live Data &#8212;Major Incidents &#8212;Est. Total Impact &#8212;Years Documented &#8212;Providers Tracked NEW Executive Intelligence Views See This Data as Your Board Would See It Interactive [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"parent":0,"menu_order":0,"comment_status":"closed","ping_status":"closed","template":"","meta":{"footnotes":""},"class_list":["post-585","page","type-page","status-publish","hentry"],"_links":{"self":[{"href":"https:\/\/www.opey.org\/opeyit\/index.php?rest_route=\/wp\/v2\/pages\/585","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.opey.org\/opeyit\/index.php?rest_route=\/wp\/v2\/pages"}],"about":[{"href":"https:\/\/www.opey.org\/opeyit\/index.php?rest_route=\/wp\/v2\/types\/page"}],"author":[{"embeddable":true,"href":"https:\/\/www.opey.org\/opeyit\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.opey.org\/opeyit\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=585"}],"version-history":[{"count":43,"href":"https:\/\/www.opey.org\/opeyit\/index.php?rest_route=\/wp\/v2\/pages\/585\/revisions"}],"predecessor-version":[{"id":677,"href":"https:\/\/www.opey.org\/opeyit\/index.php?rest_route=\/wp\/v2\/pages\/585\/revisions\/677"}],"wp:attachment":[{"href":"https:\/\/www.opey.org\/opeyit\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=585"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}