Technology, methods, and best practices to protect generation OT networks and digital equipment against cyber-attacks.
Cyber Wiki: Difference between revisions
No edit summary |
Tag: Reverted |
||
| Line 84: | Line 84: | ||
== Explore by Topic == | == Explore by Topic == | ||
<!-- ================================ | |||
EXPLORE BY TOPIC - CYBERSECURITY | |||
MediaWiki carousel | |||
================================ --> | |||
<div class="cyber-topic-carousel"> | |||
<div class="cyber-topic-header"> | |||
<h2>Explore by Topic</h2> | |||
<p>Browse cybersecurity topics and resources.</p> | |||
</div> | |||
<div class="cyber-topic-window"> | |||
<div class="cyber-topic-track" id="cyberTopicTrack"> | |||
<!-- CARD 1 --> | |||
<a class="cyber-topic-card" href="/wiki/Network_Security"> | |||
<div class="cyber-topic-icon">🌐</div> | |||
<div class="cyber-topic-content"> | |||
<h3>Network Security</h3> | |||
<p>Networks, firewalls, protocols, and defensive architecture.</p> | |||
</div> | |||
<span class="cyber-topic-arrow">→</span> | |||
</a> | |||
<!-- CARD 2 --> | |||
<a class="cyber-topic-card" href="/wiki/Threat_Intelligence"> | |||
<div class="cyber-topic-icon">🎯</div> | |||
<div class="cyber-topic-content"> | |||
<h3>Threat Intelligence</h3> | |||
<p>Threat actors, indicators, campaigns, and intelligence analysis.</p> | |||
</div> | |||
<span class="cyber-topic-arrow">→</span> | |||
</a> | |||
<!-- CARD 3 --> | |||
<a class="cyber-topic-card" href="/wiki/Digital_Forensics"> | |||
<div class="cyber-topic-icon">🔎</div> | |||
<div class="cyber-topic-content"> | |||
<h3>Digital Forensics</h3> | |||
<p>Investigations, evidence collection, and forensic analysis.</p> | |||
</div> | |||
<span class="cyber-topic-arrow">→</span> | |||
</a> | |||
<!-- CARD 4 --> | |||
<a class="cyber-topic-card" href="/wiki/Incident_Response"> | |||
<div class="cyber-topic-icon">🚨</div> | |||
<div class="cyber-topic-content"> | |||
<h3>Incident Response</h3> | |||
<p>Detection, containment, eradication, and recovery.</p> | |||
</div> | |||
<span class="cyber-topic-arrow">→</span> | |||
</a> | |||
<!-- CARD 5 --> | |||
<a class="cyber-topic-card" href="/wiki/Malware"> | |||
<div class="cyber-topic-icon">🦠</div> | |||
<div class="cyber-topic-content"> | |||
<h3>Malware</h3> | |||
<p>Viruses, ransomware, trojans, analysis, and prevention.</p> | |||
</div> | |||
<span class="cyber-topic-arrow">→</span> | |||
</a> | |||
<!-- CARD 6 --> | |||
<a class="cyber-topic-card" href="/wiki/Application_Security"> | |||
<div class="cyber-topic-icon">💻</div> | |||
<div class="cyber-topic-content"> | |||
<h3>Application Security</h3> | |||
<p>Secure development, vulnerabilities, APIs, and web security.</p> | |||
</div> | |||
<span class="cyber-topic-arrow">→</span> | |||
</a> | |||
<!-- CARD 7 --> | |||
<a class="cyber-topic-card" href="/wiki/Identity_and_Access_Management"> | |||
<div class="cyber-topic-icon">🔐</div> | |||
<div class="cyber-topic-content"> | |||
<h3>Identity & Access</h3> | |||
<p>Authentication, authorization, credentials, and access control.</p> | |||
</div> | |||
<span class="cyber-topic-arrow">→</span> | |||
</a> | |||
<!-- CARD 8 --> | |||
<a class="cyber-topic-card" href="/wiki/Cloud_Security"> | |||
<div class="cyber-topic-icon">☁️</div> | |||
<div class="cyber-topic-content"> | |||
<h3>Cloud Security</h3> | |||
<p>Cloud infrastructure, workloads, containers, and security controls.</p> | |||
</div> | |||
<span class="cyber-topic-arrow">→</span> | |||
</a> | |||
</div> | |||
</div> | |||
<!-- CONTROLS --> | |||
<div class="cyber-topic-controls"> | |||
<button id="cyberTopicPrev" aria-label="Previous topics">‹</button> | |||
<div class="cyber-topic-dots" id="cyberTopicDots"></div> | |||
<button id="cyberTopicNext" aria-label="Next topics">›</button> | |||
</div> | |||
</div> | |||
<style> | |||
/* ================================ | |||
MAIN CONTAINER | |||
================================ */ | |||
.cyber-topic-carousel { | |||
--cyber-bg: #07111f; | |||
--cyber-card: #0c1b2d; | |||
--cyber-card-hover: #10263d; | |||
--cyber-border: #1b3852; | |||
--cyber-accent: #28d7ff; | |||
--cyber-accent-2: #6875ff; | |||
--cyber-text: #f2f7fc; | |||
--cyber-muted: #91a6ba; | |||
max-width: 1200px; | |||
margin: 30px auto; | |||
padding: 28px; | |||
border-radius: 18px; | |||
background: | |||
radial-gradient( | |||
circle at 10% 0%, | |||
rgba(40, 215, 255, 0.08), | |||
transparent 35% | |||
), | |||
radial-gradient( | |||
circle at 90% 100%, | |||
rgba(104, 117, 255, 0.08), | |||
transparent 35% | |||
), | |||
var(--cyber-bg); | |||
color: var(--cyber-text); | |||
box-sizing: border-box; | |||
} | |||
/* ================================ | |||
HEADER | |||
================================ */ | |||
.cyber-topic-header { | |||
margin-bottom: 22px; | |||
} | |||
.cyber-topic-header h2 { | |||
margin: 0 0 6px; | |||
font-size: 30px; | |||
font-weight: 700; | |||
letter-spacing: -0.5px; | |||
} | |||
.cyber-topic-header h2::before { | |||
content: ""; | |||
display: inline-block; | |||
width: 5px; | |||
height: 27px; | |||
margin-right: 10px; | |||
vertical-align: -3px; | |||
border-radius: 4px; | |||
background: var(--cyber-accent); | |||
box-shadow: 0 0 12px rgba(40, 215, 255, 0.7); | |||
} | |||
.cyber-topic-header p { | |||
margin: 0 0 0 15px; | |||
color: var(--cyber-muted); | |||
font-size: 14px; | |||
} | |||
/* ================================ | |||
SLIDING WINDOW | |||
================================ */ | |||
.cyber-topic-window { | |||
width: 100%; | |||
overflow: hidden; | |||
position: relative; | |||
} | |||
.cyber-topic-track { | |||
display: flex; | |||
gap: 16px; | |||
transition: transform 0.55s cubic-bezier(.22,.61,.36,1); | |||
will-change: transform; | |||
} | |||
/* ================================ | |||
TOPIC CARD | |||
================================ */ | |||
.cyber-topic-card { | |||
position: relative; | |||
flex: 0 0 calc((100% - 32px) / 3); | |||
min-height: 170px; | |||
padding: 24px; | |||
box-sizing: border-box; | |||
display: flex; | |||
flex-direction: column; | |||
text-decoration: none !important; | |||
color: var(--cyber-text) !important; | |||
border: 1px solid var(--cyber-border); | |||
border-radius: 14px; | |||
background: | |||
linear-gradient( | |||
145deg, | |||
rgba(255,255,255,0.035), | |||
rgba(255,255,255,0.01) | |||
), | |||
var(--cyber-card); | |||
transition: | |||
transform 0.25s ease, | |||
border-color 0.25s ease, | |||
background 0.25s ease, | |||
box-shadow 0.25s ease; | |||
overflow: hidden; | |||
} | |||
/* glowing corner */ | |||
.cyber-topic-card::after { | |||
content: ""; | |||
position: absolute; | |||
width: 100px; | |||
height: 100px; | |||
right: -50px; | |||
bottom: -50px; | |||
background: var(--cyber-accent); | |||
opacity: 0.04; | |||
border-radius: 50%; | |||
transition: opacity 0.25s ease; | |||
} | |||
.cyber-topic-card:hover { | |||
transform: translateY(-5px); | |||
border-color: rgba(40, 215, 255, 0.55); | |||
background: | |||
linear-gradient( | |||
145deg, | |||
rgba(40, 215, 255, 0.07), | |||
rgba(104, 117, 255, 0.04) | |||
), | |||
var(--cyber-card-hover); | |||
box-shadow: | |||
0 10px 35px rgba(0,0,0,0.25), | |||
0 0 25px rgba(40, 215, 255, 0.07); | |||
} | |||
.cyber-topic-card:hover::after { | |||
opacity: 0.12; | |||
} | |||
/* ================================ | |||
ICON | |||
================================ */ | |||
.cyber-topic-icon { | |||
width: 48px; | |||
height: 48px; | |||
display: flex; | |||
align-items: center; | |||
justify-content: center; | |||
margin-bottom: 18px; | |||
border-radius: 12px; | |||
background: rgba(40, 215, 255, 0.08); | |||
border: 1px solid rgba(40, 215, 255, 0.16); | |||
font-size: 24px; | |||
box-shadow: | |||
inset 0 0 20px rgba(40, 215, 255, 0.025); | |||
} | |||
/* ================================ | |||
TEXT | |||
================================ */ | |||
.cyber-topic-content { | |||
flex: 1; | |||
} | |||
.cyber-topic-content h3 { | |||
margin: 0 0 8px; | |||
font-size: 18px; | |||
line-height: 1.2; | |||
font-weight: 650; | |||
color: var(--cyber-text); | |||
} | |||
.cyber-topic-content p { | |||
margin: 0; | |||
color: var(--cyber-muted); | |||
font-size: 13px; | |||
line-height: 1.5; | |||
} | |||
/* ================================ | |||
ARROW ON CARD | |||
================================ */ | |||
.cyber-topic-arrow { | |||
position: absolute; | |||
right: 20px; | |||
bottom: 18px; | |||
color: var(--cyber-accent); | |||
font-size: 20px; | |||
opacity: 0.45; | |||
transition: | |||
opacity 0.25s ease, | |||
transform 0.25s ease; | |||
} | |||
.cyber-topic-card:hover .cyber-topic-arrow { | |||
opacity: 1; | |||
transform: translateX(4px); | |||
} | |||
/* ================================ | |||
CONTROLS | |||
================================ */ | |||
.cyber-topic-controls { | |||
display: flex; | |||
align-items: center; | |||
justify-content: center; | |||
gap: 18px; | |||
margin-top: 22px; | |||
} | |||
.cyber-topic-controls button { | |||
width: 38px; | |||
height: 38px; | |||
padding: 0; | |||
border: 1px solid var(--cyber-border); | |||
border-radius: 50%; | |||
background: var(--cyber-card); | |||
color: var(--cyber-text); | |||
font-size: 25px; | |||
line-height: 1; | |||
cursor: pointer; | |||
transition: | |||
background 0.2s ease, | |||
border-color 0.2s ease, | |||
color 0.2s ease; | |||
} | |||
.cyber-topic-controls button:hover { | |||
background: rgba(40, 215, 255, 0.1); | |||
border-color: var(--cyber-accent); | |||
color: var(--cyber-accent); | |||
} | |||
/* ================================ | |||
DOTS | |||
================================ */ | |||
.cyber-topic-dots { | |||
display: flex; | |||
align-items: center; | |||
gap: 7px; | |||
} | |||
.cyber-topic-dot { | |||
width: 7px; | |||
height: 7px; | |||
border-radius: 50%; | |||
background: #30465a; | |||
cursor: pointer; | |||
transition: | |||
width 0.25s ease, | |||
background 0.25s ease; | |||
} | |||
.cyber-topic-dot.active { | |||
width: 22px; | |||
border-radius: 5px; | |||
background: var(--cyber-accent); | |||
box-shadow: 0 0 8px rgba(40, 215, 255, 0.5); | |||
} | |||
/* ================================ | |||
TABLET | |||
================================ */ | |||
@media (max-width: 900px) { | |||
.cyber-topic-card { | |||
flex-basis: calc((100% - 16px) / 2); | |||
} | |||
} | |||
/* ================================ | |||
MOBILE | |||
================================ */ | |||
@media (max-width: 600px) { | |||
.cyber-topic-carousel { | |||
padding: 20px 16px; | |||
border-radius: 12px; | |||
} | |||
.cyber-topic-header h2 { | |||
font-size: 24px; | |||
} | |||
.cyber-topic-card { | |||
flex-basis: 100%; | |||
min-height: 155px; | |||
} | |||
} | |||
/* ================================ | |||
REDUCE MOTION | |||
================================ */ | |||
@media (prefers-reduced-motion: reduce) { | |||
.cyber-topic-track { | |||
transition: none; | |||
} | |||
.cyber-topic-card { | |||
transition: none; | |||
} | |||
} | |||
</style> | |||
<script> | |||
(function () { | |||
const track = document.getElementById("cyberTopicTrack"); | |||
const next = document.getElementById("cyberTopicNext"); | |||
const prev = document.getElementById("cyberTopicPrev"); | |||
const dotsContainer = document.getElementById("cyberTopicDots"); | |||
if (!track || !next || !prev || !dotsContainer) { | |||
return; | |||
} | |||
const cards = Array.from( | |||
track.querySelectorAll(".cyber-topic-card") | |||
); | |||
let current = 0; | |||
let autoPlay; | |||
let cardsVisible = getCardsVisible(); | |||
function getCardsVisible() { | |||
if (window.innerWidth <= 600) { | |||
return 1; | |||
} | |||
if (window.innerWidth <= 900) { | |||
return 2; | |||
} | |||
return 3; | |||
} | |||
function getMaxIndex() { | |||
cardsVisible = getCardsVisible(); | |||
return Math.max( | |||
0, | |||
cards.length - cardsVisible | |||
); | |||
} | |||
function getCardWidth() { | |||
if (!cards.length) { | |||
return 0; | |||
} | |||
const style = window.getComputedStyle(track); | |||
const gap = parseFloat(style.gap) || 0; | |||
return cards[0].offsetWidth + gap; | |||
} | |||
function createDots() { | |||
dotsContainer.innerHTML = ""; | |||
const maxIndex = getMaxIndex(); | |||
for (let i = 0; i <= maxIndex; i++) { | |||
const dot = document.createElement("span"); | |||
dot.className = "cyber-topic-dot"; | |||
dot.setAttribute( | |||
"aria-label", | |||
"Go to topic slide " + (i + 1) | |||
); | |||
dot.addEventListener("click", function () { | |||
current = i; | |||
update(); | |||
restartAutoPlay(); | |||
}); | |||
dotsContainer.appendChild(dot); | |||
} | |||
} | |||
function update() { | |||
const maxIndex = getMaxIndex(); | |||
if (current > maxIndex) { | |||
current = 0; | |||
} | |||
if (current < 0) { | |||
current = maxIndex; | |||
} | |||
const distance = | |||
current * getCardWidth(); | |||
track.style.transform = | |||
"translateX(-" + distance + "px)"; | |||
const dots = | |||
dotsContainer.querySelectorAll(".cyber-topic-dot"); | |||
dots.forEach(function (dot, index) { | |||
dot.classList.toggle( | |||
"active", | |||
index === current | |||
); | |||
}); | |||
} | |||
function goNext() { | |||
const maxIndex = getMaxIndex(); | |||
if (current >= maxIndex) { | |||
current = 0; | |||
} else { | |||
current++; | |||
} | |||
update(); | |||
} | |||
function goPrevious() { | |||
const maxIndex = getMaxIndex(); | |||
if (current <= 0) { | |||
current = maxIndex; | |||
} else { | |||
current--; | |||
} | |||
update(); | |||
} | |||
function startAutoPlay() { | |||
stopAutoPlay(); | |||
autoPlay = setInterval(function () { | |||
goNext(); | |||
}, 4500); | |||
} | |||
function stopAutoPlay() { | |||
if (autoPlay) { | |||
clearInterval(autoPlay); | |||
} | |||
} | |||
function restartAutoPlay() { | |||
startAutoPlay(); | |||
} | |||
next.addEventListener("click", function () { | |||
goNext(); | |||
restartAutoPlay(); | |||
}); | |||
prev.addEventListener("click", function () { | |||
goPrevious(); | |||
restartAutoPlay(); | |||
}); | |||
/* Pause while mouse is over carousel */ | |||
const carousel = | |||
document.querySelector(".cyber-topic-carousel"); | |||
carousel.addEventListener( | |||
"mouseenter", | |||
stopAutoPlay | |||
); | |||
carousel.addEventListener( | |||
"mouseleave", | |||
startAutoPlay | |||
); | |||
/* Recalculate when browser is resized */ | |||
window.addEventListener("resize", function () { | |||
createDots(); | |||
update(); | |||
}); | |||
/* Initial setup */ | |||
createDots(); | |||
update(); | |||
startAutoPlay(); | |||
})(); | |||
</script> | |||
== Program Engagement == | == Program Engagement == | ||
Revision as of 04:02, 21 September 2026
Welcome to the Cyber Security for Electric Power Generation CyberWiki
Welcome to the main page of the Electric Power Research Institute's CyberWiki, a wiki-style hub for cyber security research at EPRI, with a focus on operational technology in power generation. CyberWiki was built using the MediaWiki engine to be an extensible and dynamic educational and knowledge dissemination tool. It supplements the published content that is accessible through the EPRI website, or through each program's cockpit, by providing a flexible, web-based content delivery solution for projects that can benefit from the ability to easily update and add content as a project progresses. EPRI members can log in to access additional content through the EPRI Cyber Security for Generation Assets homepage.
The program addresses strategic focus areas including:
- Protection Technologies, Tools, and Guides
- Detection Technologies, Tools, and Guides
- Response and Recovery Technologies, Tools, and Guides
- Process and Integration, Regulatory Impacts, Workforce Development, Training, and GRC
- Emerging Technology Industry-specific technology use cases, guidance, Testing, and Development.
- Changing Threat Landscape
- Industry Collaboration and Benchmarking
Overview
EPRI’s Cyber Security for Generation Assets Program (P209) performed research and development to improve the security, safety, and resiliency of power generation facilities. Cyber attackers target the critical infrastructure that the public relies on for society to function. Proactive defenses are needed to ensure a reliable and resilient power supply for national security across the globe. Without secure energy, public health and welfare are threatened, and economies cannot function. Energy is uniquely vital because it enables all other critical infrastructure sectors, such as healthcare, transportation, food and agriculture, and others.
It is also crucial for power generation companies" business models and regulatory compliance. Advances in control, digital communication, and computational technology fundamentally changes the security postures and regulation. The objective of the Cyber Security for Generation Assets program (P209) is to provide practical applied tools and long-term technology research for operational technology (OT) systems and integrated information technology (IT) use cases (IT/OT). This 2050 vision informs long-term R&D needs for continued energy security.
Techology, methods, and best practices to detect cyber-attacks in generation OT networks.
Technology, methods, and best practices for responding to and recovering from cyber-attacks in next-generation OT networks.
Evolving threats, vulnerabilities, and trends.
Research and prepare for emerging technologies and power generation trends.
Technical approaches to address process and coordination challenges associated with cyber security. staying apprised of evolving standards, regulations, and guidance
Working with power generation companies, technologies providers, academia, and governments across the cyber security spectrum to facilitate an open exchange of innovation and a technical forum for collaboration.
Explore by Topic
Explore by Topic
Browse cybersecurity topics and resources.
<a class="cyber-topic-card" href="/wiki/Network_Security">
Network Security
Networks, firewalls, protocols, and defensive architecture.
→
</a>
<a class="cyber-topic-card" href="/wiki/Threat_Intelligence">
Threat Intelligence
Threat actors, indicators, campaigns, and intelligence analysis.
→
</a>
<a class="cyber-topic-card" href="/wiki/Digital_Forensics">
Digital Forensics
Investigations, evidence collection, and forensic analysis.
→
</a>
<a class="cyber-topic-card" href="/wiki/Incident_Response">
Incident Response
Detection, containment, eradication, and recovery.
→
</a>
<a class="cyber-topic-card" href="/wiki/Malware">
Malware
Viruses, ransomware, trojans, analysis, and prevention.
→
</a>
<a class="cyber-topic-card" href="/wiki/Application_Security">
Application Security
Secure development, vulnerabilities, APIs, and web security.
→
</a>
<a class="cyber-topic-card" href="/wiki/Identity_and_Access_Management">
Identity & Access
Authentication, authorization, credentials, and access control.
→
</a>
<a class="cyber-topic-card" href="/wiki/Cloud_Security">
Cloud Security
Cloud infrastructure, workloads, containers, and security controls.
→
</a>
<button id="cyberTopicPrev" aria-label="Previous topics">‹</button>
<button id="cyberTopicNext" aria-label="Next topics">›</button>
<style>
/* ================================
MAIN CONTAINER ================================ */
.cyber-topic-carousel {
--cyber-bg: #07111f; --cyber-card: #0c1b2d; --cyber-card-hover: #10263d; --cyber-border: #1b3852; --cyber-accent: #28d7ff; --cyber-accent-2: #6875ff; --cyber-text: #f2f7fc; --cyber-muted: #91a6ba;
max-width: 1200px;
margin: 30px auto;
padding: 28px;
border-radius: 18px;
background:
radial-gradient(
circle at 10% 0%,
rgba(40, 215, 255, 0.08),
transparent 35%
),
radial-gradient(
circle at 90% 100%,
rgba(104, 117, 255, 0.08),
transparent 35%
),
var(--cyber-bg);
color: var(--cyber-text); box-sizing: border-box;
}
/* ================================
HEADER ================================ */
.cyber-topic-header {
margin-bottom: 22px;
}
.cyber-topic-header h2 {
margin: 0 0 6px; font-size: 30px; font-weight: 700; letter-spacing: -0.5px;
}
.cyber-topic-header h2::before {
content: ""; display: inline-block; width: 5px; height: 27px; margin-right: 10px; vertical-align: -3px; border-radius: 4px; background: var(--cyber-accent); box-shadow: 0 0 12px rgba(40, 215, 255, 0.7);
}
.cyber-topic-header p {
margin: 0 0 0 15px; color: var(--cyber-muted); font-size: 14px;
}
/* ================================
SLIDING WINDOW ================================ */
.cyber-topic-window {
width: 100%; overflow: hidden; position: relative;
}
.cyber-topic-track {
display: flex; gap: 16px; transition: transform 0.55s cubic-bezier(.22,.61,.36,1); will-change: transform;
}
/* ================================
TOPIC CARD ================================ */
.cyber-topic-card {
position: relative;
flex: 0 0 calc((100% - 32px) / 3);
min-height: 170px; padding: 24px; box-sizing: border-box;
display: flex; flex-direction: column;
text-decoration: none !important; color: var(--cyber-text) !important;
border: 1px solid var(--cyber-border); border-radius: 14px;
background:
linear-gradient(
145deg,
rgba(255,255,255,0.035),
rgba(255,255,255,0.01)
),
var(--cyber-card);
transition: transform 0.25s ease, border-color 0.25s ease, background 0.25s ease, box-shadow 0.25s ease;
overflow: hidden;
}
/* glowing corner */
.cyber-topic-card::after {
content: ""; position: absolute; width: 100px; height: 100px; right: -50px; bottom: -50px;
background: var(--cyber-accent); opacity: 0.04; border-radius: 50%; transition: opacity 0.25s ease;
}
.cyber-topic-card:hover {
transform: translateY(-5px); border-color: rgba(40, 215, 255, 0.55);
background:
linear-gradient(
145deg,
rgba(40, 215, 255, 0.07),
rgba(104, 117, 255, 0.04)
),
var(--cyber-card-hover);
box-shadow: 0 10px 35px rgba(0,0,0,0.25), 0 0 25px rgba(40, 215, 255, 0.07);
}
.cyber-topic-card:hover::after {
opacity: 0.12;
}
/* ================================
ICON ================================ */
.cyber-topic-icon {
width: 48px; height: 48px;
display: flex; align-items: center; justify-content: center;
margin-bottom: 18px;
border-radius: 12px;
background: rgba(40, 215, 255, 0.08); border: 1px solid rgba(40, 215, 255, 0.16);
font-size: 24px;
box-shadow: inset 0 0 20px rgba(40, 215, 255, 0.025);
}
/* ================================
TEXT ================================ */
.cyber-topic-content {
flex: 1;
}
.cyber-topic-content h3 {
margin: 0 0 8px;
font-size: 18px; line-height: 1.2; font-weight: 650;
color: var(--cyber-text);
}
.cyber-topic-content p {
margin: 0;
color: var(--cyber-muted);
font-size: 13px; line-height: 1.5;
}
/* ================================
ARROW ON CARD ================================ */
.cyber-topic-arrow {
position: absolute;
right: 20px; bottom: 18px;
color: var(--cyber-accent);
font-size: 20px;
opacity: 0.45;
transition: opacity 0.25s ease, transform 0.25s ease;
}
.cyber-topic-card:hover .cyber-topic-arrow {
opacity: 1; transform: translateX(4px);
}
/* ================================
CONTROLS ================================ */
.cyber-topic-controls {
display: flex; align-items: center; justify-content: center;
gap: 18px;
margin-top: 22px;
}
.cyber-topic-controls button {
width: 38px; height: 38px;
padding: 0;
border: 1px solid var(--cyber-border); border-radius: 50%;
background: var(--cyber-card); color: var(--cyber-text);
font-size: 25px; line-height: 1;
cursor: pointer;
transition: background 0.2s ease, border-color 0.2s ease, color 0.2s ease;
}
.cyber-topic-controls button:hover {
background: rgba(40, 215, 255, 0.1); border-color: var(--cyber-accent); color: var(--cyber-accent);
}
/* ================================
DOTS ================================ */
.cyber-topic-dots {
display: flex; align-items: center; gap: 7px;
}
.cyber-topic-dot {
width: 7px; height: 7px;
border-radius: 50%;
background: #30465a;
cursor: pointer;
transition: width 0.25s ease, background 0.25s ease;
}
.cyber-topic-dot.active {
width: 22px; border-radius: 5px; background: var(--cyber-accent);
box-shadow: 0 0 8px rgba(40, 215, 255, 0.5);
}
/* ================================
TABLET ================================ */
@media (max-width: 900px) {
.cyber-topic-card {
flex-basis: calc((100% - 16px) / 2);
}
}
/* ================================
MOBILE ================================ */
@media (max-width: 600px) {
.cyber-topic-carousel {
padding: 20px 16px;
border-radius: 12px;
}
.cyber-topic-header h2 {
font-size: 24px;
}
.cyber-topic-card {
flex-basis: 100%;
min-height: 155px;
}
}
/* ================================
REDUCE MOTION ================================ */
@media (prefers-reduced-motion: reduce) {
.cyber-topic-track {
transition: none;
}
.cyber-topic-card {
transition: none;
}
}
</style>
<script>
(function () {
const track = document.getElementById("cyberTopicTrack");
const next = document.getElementById("cyberTopicNext");
const prev = document.getElementById("cyberTopicPrev");
const dotsContainer = document.getElementById("cyberTopicDots");
if (!track || !next || !prev || !dotsContainer) {
return;
}
const cards = Array.from(
track.querySelectorAll(".cyber-topic-card")
);
let current = 0; let autoPlay; let cardsVisible = getCardsVisible();
function getCardsVisible() {
if (window.innerWidth <= 600) {
return 1;
}
if (window.innerWidth <= 900) {
return 2;
}
return 3; }
function getMaxIndex() {
cardsVisible = getCardsVisible();
return Math.max(
0,
cards.length - cardsVisible
);
}
function getCardWidth() {
if (!cards.length) {
return 0;
}
const style = window.getComputedStyle(track);
const gap = parseFloat(style.gap) || 0;
return cards[0].offsetWidth + gap; }
function createDots() {
dotsContainer.innerHTML = "";
const maxIndex = getMaxIndex();
for (let i = 0; i <= maxIndex; i++) {
const dot = document.createElement("span");
dot.className = "cyber-topic-dot";
dot.setAttribute(
"aria-label",
"Go to topic slide " + (i + 1)
);
dot.addEventListener("click", function () {
current = i;
update();
restartAutoPlay();
});
dotsContainer.appendChild(dot); }
}
function update() {
const maxIndex = getMaxIndex();
if (current > maxIndex) {
current = 0;
}
if (current < 0) {
current = maxIndex;
}
const distance =
current * getCardWidth();
track.style.transform =
"translateX(-" + distance + "px)";
const dots =
dotsContainer.querySelectorAll(".cyber-topic-dot");
dots.forEach(function (dot, index) {
dot.classList.toggle(
"active",
index === current
);
});
}
function goNext() {
const maxIndex = getMaxIndex();
if (current >= maxIndex) {
current = 0;
} else {
current++;
}
update();
}
function goPrevious() {
const maxIndex = getMaxIndex();
if (current <= 0) {
current = maxIndex;
} else {
current--;
}
update();
}
function startAutoPlay() {
stopAutoPlay();
autoPlay = setInterval(function () {
goNext();
}, 4500);
}
function stopAutoPlay() {
if (autoPlay) {
clearInterval(autoPlay);
}
}
function restartAutoPlay() {
startAutoPlay();
}
next.addEventListener("click", function () {
goNext();
restartAutoPlay();
});
prev.addEventListener("click", function () {
goPrevious();
restartAutoPlay();
});
/* Pause while mouse is over carousel */
const carousel =
document.querySelector(".cyber-topic-carousel");
carousel.addEventListener( "mouseenter", stopAutoPlay );
carousel.addEventListener( "mouseleave", startAutoPlay );
/* Recalculate when browser is resized */
window.addEventListener("resize", function () {
createDots(); update();
});
/* Initial setup */
createDots(); update(); startAutoPlay();
})();
</script>
Program Engagement
|
Sharing and Technology Transfer Monthly Member Webcasts: Open to all EPRI members. Peer-to-peer exchange, industry insights, and emerging trends. Contact Jeremy Lawrence for an invite. Workshops & Advisory Meetings: 3 Meetings per year focused on peer exchange and communicating results + needs. |
Technology Application
|
|
Impactful Content
|
Featured Paper/Person SOON TBD |
Meet the Team
Contact the Team
Jeremy Lawrence, Principal Technical Leader
Jason Hollern, Technical Executive
Soomin Militello, Technical Leader
