feat: implement modular UMass theme components and supporting generation scripts for home page structure
This commit is contained in:
@@ -0,0 +1,205 @@
|
||||
<style>
|
||||
.education-slider-wrapper {
|
||||
position: relative;
|
||||
padding: 0px;
|
||||
/* Space for buttons */
|
||||
}
|
||||
|
||||
.education-slider-container {
|
||||
overflow: hidden;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.education-slider-wrapper .news-grid,
|
||||
.education-slider-wrapper .row,
|
||||
.education-slider-track {
|
||||
display: flex !important;
|
||||
flex-wrap: nowrap !important;
|
||||
gap: 20px;
|
||||
margin: 0 !important;
|
||||
transition: transform 0.4s ease;
|
||||
}
|
||||
|
||||
/* Force children to be fixed width cards */
|
||||
.education-slider-wrapper .news-grid>*,
|
||||
.education-slider-wrapper .row>*,
|
||||
.education-slider-track>* {
|
||||
flex: 0 0 calc(33.333% - 14px) !important;
|
||||
/* show 3 cards at a time */
|
||||
max-width: none !important;
|
||||
}
|
||||
|
||||
@media (max-width: 992px) {
|
||||
|
||||
.education-slider-wrapper .news-grid>*,
|
||||
.education-slider-wrapper .row>*,
|
||||
.education-slider-track>* {
|
||||
flex: 0 0 calc(50% - 10px) !important;
|
||||
}
|
||||
}
|
||||
|
||||
@media (max-width: 576px) {
|
||||
|
||||
.education-slider-wrapper .news-grid>*,
|
||||
.education-slider-wrapper .row>*,
|
||||
.education-slider-track>* {
|
||||
flex: 0 0 100% !important;
|
||||
}
|
||||
}
|
||||
|
||||
.edu-slider-btn {
|
||||
position: absolute;
|
||||
top: 50%;
|
||||
transform: translateY(-50%);
|
||||
width: 40px;
|
||||
height: 40px;
|
||||
border-radius: 50%;
|
||||
background-color: rgba(200, 200, 200, 0.5);
|
||||
/* mờ / transparent */
|
||||
color: #333;
|
||||
border: none;
|
||||
font-size: 30px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
cursor: pointer;
|
||||
z-index: 10;
|
||||
transition: background-color 0.2s, color 0.2s;
|
||||
line-height: 1;
|
||||
}
|
||||
|
||||
.edu-slider-btn:hover {
|
||||
background-color: rgba(0, 0, 0, 0.7);
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
.edu-slider-btn.prev-btn {
|
||||
left: -10px;
|
||||
}
|
||||
|
||||
.edu-slider-btn.next-btn {
|
||||
right: -10px;
|
||||
}
|
||||
|
||||
.edu-slider-btn:disabled {
|
||||
opacity: 0.2;
|
||||
cursor: not-allowed;
|
||||
}
|
||||
|
||||
/* --- Hiệu ứng crop (zoom) ảnh khi hover --- */
|
||||
.education-slider-wrapper .featured-grid__item .news-card__image {
|
||||
overflow: hidden !important;
|
||||
display: block;
|
||||
}
|
||||
|
||||
.education-slider-wrapper .featured-grid__item .news-card__image img {
|
||||
transition: transform 0.4s ease-in-out !important;
|
||||
}
|
||||
|
||||
.education-slider-wrapper .featured-grid__item:hover .news-card__image img {
|
||||
transform: scale(1.1) !important;
|
||||
}
|
||||
</style>
|
||||
|
||||
<body>
|
||||
<div class="cc--component-container cc--news-events">
|
||||
<div class="c--component c--news-events">
|
||||
<!-- Header -->
|
||||
<div class="news-events-row">
|
||||
<div class="education-column news-column" style="width: 100%;">
|
||||
<div
|
||||
style="display: flex; justify-content: space-between; align-items: baseline; border-bottom: 2px solid var(--color-brand); margin-bottom: 16px;">
|
||||
<!-- Thêm flex-grow: 1 vào style của h2 -->
|
||||
<h2 class="section-title--news"
|
||||
style="font-size: 2rem; margin: 0; padding-bottom: 4px; border-bottom: unset;">ĐÀO TẠO</h2>
|
||||
<a href="/news/education" class="news-events-section__cta news-events-section__cta--desktop"
|
||||
style="color: var(--color-brand); font-weight: 800; font-size: 16px; text-transform: uppercase; text-decoration: none; border-bottom: unset;">XEM
|
||||
THÊM</a>
|
||||
</div>
|
||||
<div class="education-slider-wrapper" style="padding-right: 0;">
|
||||
<button class="edu-slider-btn prev-btn" aria-label="Previous">‹</button>
|
||||
<div class="education-slider-container">
|
||||
<div class="education-slider-track">
|
||||
[component:news-grid data-source="posts:tag=education,limit=5,collection=news_posts"]
|
||||
</div>
|
||||
</div>
|
||||
<button class="edu-slider-btn next-btn" aria-label="Next">›</button>
|
||||
</div>
|
||||
</div>
|
||||
</div><!-- Mobile Footer CTA -->
|
||||
<div class="news-events-section__footer"><a href="/news/education"
|
||||
class="news-events-section__cta news-events-section__cta--mobile">Xem Thêm</a></div>
|
||||
</div>
|
||||
</div>
|
||||
</body>
|
||||
|
||||
<script>
|
||||
document.addEventListener("DOMContentLoaded", function() {
|
||||
const wrappers = document.querySelectorAll('.education-slider-wrapper');
|
||||
wrappers.forEach(wrapper => {
|
||||
const prevBtn = wrapper.querySelector('.prev-btn');
|
||||
const nextBtn = wrapper.querySelector('.next-btn');
|
||||
|
||||
let track = wrapper.querySelector('.education-slider-track');
|
||||
if (track && track.children.length === 1 && (track.children[0].classList.contains('news-grid') || track.children[0].classList.contains('row'))) {
|
||||
track = track.children[0];
|
||||
track.classList.add('education-slider-track');
|
||||
}
|
||||
|
||||
if (!track) return;
|
||||
|
||||
let currentIndex = 0;
|
||||
|
||||
function updateSlider() {
|
||||
const items = track.children;
|
||||
if(items.length === 0) return;
|
||||
const itemWidth = items[0].getBoundingClientRect().width;
|
||||
|
||||
const gap = parseFloat(window.getComputedStyle(track).gap) || 20;
|
||||
track.style.transform = `translateX(-${currentIndex * (itemWidth + gap)}px)`;
|
||||
|
||||
const containerWidth = wrapper.querySelector('.education-slider-container').getBoundingClientRect().width;
|
||||
const visibleCount = Math.max(1, Math.floor((containerWidth + gap) / (itemWidth + gap)));
|
||||
|
||||
prevBtn.disabled = currentIndex === 0;
|
||||
nextBtn.disabled = currentIndex >= items.length - visibleCount;
|
||||
}
|
||||
|
||||
prevBtn.addEventListener('click', () => {
|
||||
if (currentIndex > 0) {
|
||||
currentIndex--;
|
||||
updateSlider();
|
||||
}
|
||||
});
|
||||
|
||||
nextBtn.addEventListener('click', () => {
|
||||
const items = track.children;
|
||||
const itemWidth = items[0].getBoundingClientRect().width;
|
||||
const gap = parseFloat(window.getComputedStyle(track).gap) || 20;
|
||||
const containerWidth = wrapper.querySelector('.education-slider-container').getBoundingClientRect().width;
|
||||
const visibleCount = Math.max(1, Math.floor((containerWidth + gap) / (itemWidth + gap)));
|
||||
|
||||
if (currentIndex < items.length - visibleCount) {
|
||||
currentIndex++;
|
||||
updateSlider();
|
||||
}
|
||||
});
|
||||
|
||||
window.addEventListener('resize', () => {
|
||||
const items = track.children;
|
||||
if(items.length === 0) return;
|
||||
const itemWidth = items[0].getBoundingClientRect().width;
|
||||
const gap = parseFloat(window.getComputedStyle(track).gap) || 20;
|
||||
const containerWidth = wrapper.querySelector('.education-slider-container').getBoundingClientRect().width;
|
||||
const visibleCount = Math.max(1, Math.floor((containerWidth + gap) / (itemWidth + gap)));
|
||||
|
||||
if (currentIndex > items.length - visibleCount) {
|
||||
currentIndex = Math.max(0, items.length - visibleCount);
|
||||
}
|
||||
updateSlider();
|
||||
});
|
||||
|
||||
setTimeout(updateSlider, 200);
|
||||
});
|
||||
});
|
||||
</script>
|
||||
@@ -0,0 +1,727 @@
|
||||
<style>
|
||||
.charity-hero {
|
||||
--red: #d7193f;
|
||||
--red-dark: #a90f2d;
|
||||
--red-soft: #fff0f4;
|
||||
--pink: #ffe3ec;
|
||||
--ink: #36363a;
|
||||
--muted: #74747a;
|
||||
--paper: #f7f7f8;
|
||||
--white: #ffffff;
|
||||
--shadow: 0 24px 70px rgba(174, 23, 55, .18);
|
||||
--shadow-strong: 0 32px 90px rgba(100, 10, 30, .28);
|
||||
}
|
||||
|
||||
.charity-hero {
|
||||
font-family: "Segoe UI", Arial, sans-serif;
|
||||
color: var(--ink);
|
||||
background: #f1f1f2;
|
||||
position: relative;
|
||||
min-height: 546px;
|
||||
overflow: hidden;
|
||||
isolation: isolate;
|
||||
background:
|
||||
radial-gradient(circle at 72% 22%, rgba(255,255,255,.92), transparent 28%),
|
||||
linear-gradient(110deg, #ffeaf0 0%, #f4f4f5 42%, #f9f9fa 100%);
|
||||
}
|
||||
|
||||
.charity-hero * {
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.charity-hero a {
|
||||
text-decoration: none;
|
||||
color: inherit;
|
||||
}
|
||||
|
||||
.charity-hero .hero-bg {
|
||||
position: absolute;
|
||||
inset: 0;
|
||||
z-index: -2;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.charity-hero .blob {
|
||||
position: absolute;
|
||||
border-radius: 999px;
|
||||
filter: blur(3px);
|
||||
opacity: .72;
|
||||
animation: blobFloat 13s ease-in-out infinite alternate;
|
||||
}
|
||||
|
||||
.charity-hero .blob-1 {
|
||||
width: 460px;
|
||||
height: 460px;
|
||||
background: rgba(255,207,221,.75);
|
||||
left: -150px;
|
||||
top: -170px;
|
||||
}
|
||||
|
||||
.charity-hero .blob-2 {
|
||||
width: 520px;
|
||||
height: 520px;
|
||||
background: rgba(255,236,241,.9);
|
||||
right: -180px;
|
||||
bottom: -220px;
|
||||
animation-delay: -3s;
|
||||
}
|
||||
|
||||
.charity-hero .blob-3 {
|
||||
width: 220px;
|
||||
height: 220px;
|
||||
background: rgba(215,25,63,.12);
|
||||
left: 48%;
|
||||
top: 48%;
|
||||
animation-delay: -6s;
|
||||
}
|
||||
|
||||
.charity-hero .soft-grid {
|
||||
position: absolute;
|
||||
inset: 22px 150px;
|
||||
border: 5px solid rgba(255,206,218,.68);
|
||||
border-radius: 6px;
|
||||
mask: linear-gradient(90deg,transparent,black 4%,black 96%,transparent);
|
||||
-webkit-mask: linear-gradient(90deg,transparent,black 4%,black 96%,transparent);
|
||||
opacity: .76;
|
||||
}
|
||||
|
||||
.charity-hero .soft-grid:before,
|
||||
.charity-hero .soft-grid:after {
|
||||
content: "";
|
||||
position: absolute;
|
||||
background: var(--red);
|
||||
border-radius: 50% 50% 48% 48%;
|
||||
transform: rotate(45deg);
|
||||
opacity: .9;
|
||||
}
|
||||
|
||||
.charity-hero .soft-grid:before {
|
||||
width: 36px;
|
||||
height: 36px;
|
||||
left: 22px;
|
||||
bottom: -13px;
|
||||
box-shadow: 34px -1px 0 var(--red);
|
||||
}
|
||||
|
||||
.charity-hero .soft-grid:after {
|
||||
width: 17px;
|
||||
height: 17px;
|
||||
right: 18px;
|
||||
top: 285px;
|
||||
opacity: .55;
|
||||
box-shadow: 20px 19px 0 rgba(215,25,63,.9);
|
||||
}
|
||||
|
||||
.charity-hero .hero-shell {
|
||||
width: min(1580px, calc(100% - 44px));
|
||||
min-height: 546px;
|
||||
margin: 0 auto;
|
||||
display: grid;
|
||||
grid-template-columns: minmax(640px, 1.1fr) minmax(470px, .9fr);
|
||||
gap: 42px;
|
||||
align-items: center;
|
||||
padding: 36px 0;
|
||||
}
|
||||
|
||||
.charity-hero .gallery-panel {
|
||||
position: relative;
|
||||
min-height: 500px;
|
||||
padding: 18px 12px 0;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.charity-hero .gallery-title {
|
||||
position: absolute;
|
||||
left: 22px;
|
||||
top: 10px;
|
||||
z-index: 22;
|
||||
display: inline-flex;
|
||||
flex-direction: column;
|
||||
gap: 4px;
|
||||
padding: 10px 16px;
|
||||
border-radius: 18px;
|
||||
background: rgba(255,255,255,.72);
|
||||
box-shadow: 0 12px 30px rgba(70,40,50,.08);
|
||||
backdrop-filter: blur(10px);
|
||||
transform: translateY(-12px);
|
||||
opacity: 0;
|
||||
animation: fadeDown .7s ease forwards .25s;
|
||||
}
|
||||
|
||||
.charity-hero .gallery-title .eyebrow {
|
||||
font-size: 11px;
|
||||
text-transform: uppercase;
|
||||
letter-spacing: 2px;
|
||||
color: var(--red);
|
||||
font-weight: 800;
|
||||
}
|
||||
|
||||
.charity-hero .gallery-title strong {
|
||||
font-size: 16px;
|
||||
color: #313136;
|
||||
}
|
||||
|
||||
.charity-hero .gallery-stage {
|
||||
position: relative;
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
overflow: hidden;
|
||||
perspective: 1200px;
|
||||
}
|
||||
|
||||
.charity-hero .gallery-light {
|
||||
position: absolute;
|
||||
left: 34%;
|
||||
top: 35%;
|
||||
width: 310px;
|
||||
height: 210px;
|
||||
border-radius: 50%;
|
||||
background: radial-gradient(circle, rgba(255,255,255,.88), rgba(255,255,255,0) 66%);
|
||||
pointer-events: none;
|
||||
opacity: .45;
|
||||
mix-blend-mode: screen;
|
||||
animation: lightPulse 4s ease-in-out infinite;
|
||||
}
|
||||
|
||||
.charity-hero .focus-frame {
|
||||
position: absolute;
|
||||
left: 50%;
|
||||
top: 50%;
|
||||
width: 402px;
|
||||
height: 238px;
|
||||
transform: translate(-50%,-50%) scale(.86);
|
||||
border-radius: 22px;
|
||||
border: 1px solid rgba(215,25,63,.25);
|
||||
box-shadow: 0 0 0 10px rgba(255,255,255,.16), inset 0 0 42px rgba(215,25,63,.07);
|
||||
opacity: 0;
|
||||
transition: .7s ease;
|
||||
pointer-events: none;
|
||||
z-index: 4;
|
||||
}
|
||||
|
||||
.charity-hero .gallery-stage.is-playing .focus-frame {
|
||||
opacity: 1;
|
||||
transform: translate(-50%,-50%) scale(1);
|
||||
}
|
||||
|
||||
.charity-hero .photo-card {
|
||||
position: absolute;
|
||||
left: var(--x);
|
||||
top: var(--y);
|
||||
width: var(--w);
|
||||
background: #fff;
|
||||
border: 4px solid var(--red);
|
||||
border-radius: 3px;
|
||||
overflow: hidden;
|
||||
box-shadow: 0 14px 36px rgba(61,26,34,.22);
|
||||
transform: translate3d(0,0,0) rotate(var(--r)) scale(.92);
|
||||
opacity: 0;
|
||||
z-index: 5;
|
||||
will-change: left, top, width, transform, opacity, filter;
|
||||
animation: cardIntro .85s cubic-bezier(.2,.9,.25,1.12) forwards;
|
||||
animation-delay: var(--delay);
|
||||
transition:
|
||||
opacity 2.5s ease-in-out,
|
||||
filter 2.5s ease-in-out,
|
||||
box-shadow 1.5s cubic-bezier(.2,.8,.2,1),
|
||||
border-color 1.5s cubic-bezier(.2,.8,.2,1),
|
||||
left 1.5s cubic-bezier(.2,.8,.2,1),
|
||||
top 1.5s cubic-bezier(.2,.8,.2,1),
|
||||
width 1.5s cubic-bezier(.2,.8,.2,1),
|
||||
transform 1.5s cubic-bezier(.2,.8,.2,1);
|
||||
}
|
||||
|
||||
.charity-hero .photo-card img {
|
||||
display: block;
|
||||
width: 100%;
|
||||
height: auto;
|
||||
transform: scale(1.035);
|
||||
transition: transform 1s cubic-bezier(.18,.82,.18,1), filter .8s ease;
|
||||
}
|
||||
|
||||
.charity-hero .photo-card:before {
|
||||
content: "";
|
||||
position: absolute;
|
||||
inset: 0;
|
||||
background: linear-gradient(120deg, transparent 20%, rgba(255,255,255,.34) 45%, transparent 70%);
|
||||
transform: translateX(-130%);
|
||||
z-index: 2;
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
.charity-hero .photo-card.is-active:before {
|
||||
animation: shine 1.3s ease .25s;
|
||||
}
|
||||
|
||||
.charity-hero .photo-card.is-active {
|
||||
left: 50%;
|
||||
top: 50%;
|
||||
width: min(480px, 58vw);
|
||||
transform: translate(-50%,-50%) rotate(0deg) scale(1.06) !important;
|
||||
opacity: 1;
|
||||
z-index: 30;
|
||||
border-color: #fff;
|
||||
border-width: 8px;
|
||||
border-radius: 18px;
|
||||
box-shadow: var(--shadow-strong);
|
||||
filter: saturate(1.08) contrast(1.03);
|
||||
}
|
||||
|
||||
.charity-hero .photo-card.is-active img {
|
||||
transform: scale(1.08);
|
||||
}
|
||||
|
||||
.charity-hero .photo-card.is-dim {
|
||||
opacity: .28;
|
||||
filter: grayscale(.08) saturate(.8) blur(.2px);
|
||||
transform: translate3d(0,0,0) rotate(var(--r)) scale(.82);
|
||||
z-index: 2;
|
||||
}
|
||||
|
||||
.charity-hero .photo-card.is-next {
|
||||
opacity: .74;
|
||||
box-shadow: 0 17px 45px rgba(92,24,42,.18);
|
||||
}
|
||||
|
||||
.charity-hero .photo-card.is-exit {
|
||||
opacity: 0;
|
||||
transform: translateY(28px) scale(.74) rotate(var(--r));
|
||||
}
|
||||
|
||||
|
||||
|
||||
.charity-hero .gallery-controls {
|
||||
position: absolute;
|
||||
left: 50%;
|
||||
bottom: 2px;
|
||||
transform: translateX(-50%);
|
||||
display: flex;
|
||||
gap: 8px;
|
||||
z-index: 40;
|
||||
}
|
||||
|
||||
.charity-hero .dot {
|
||||
width: 7px;
|
||||
height: 7px;
|
||||
border-radius: 999px;
|
||||
background: rgba(215,25,63,.22);
|
||||
transition: .35s ease;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.charity-hero .dot.is-active {
|
||||
width: 28px;
|
||||
background: var(--red);
|
||||
box-shadow: 0 0 0 6px rgba(215,25,63,.09);
|
||||
}
|
||||
|
||||
.charity-hero .content-panel {
|
||||
position: relative;
|
||||
min-height: 430px;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: center;
|
||||
padding: 26px 24px 26px 8px;
|
||||
}
|
||||
|
||||
.charity-hero .content-panel:before {
|
||||
content: "";
|
||||
position: absolute;
|
||||
inset: 28px 0 18px 0;
|
||||
border-radius: 34px;
|
||||
background: linear-gradient(145deg, rgba(255,255,255,.54), rgba(255,255,255,.08));
|
||||
border: 1px solid rgba(255,255,255,.55);
|
||||
box-shadow: 0 20px 70px rgba(62,45,54,.06);
|
||||
z-index: -1;
|
||||
}
|
||||
|
||||
.charity-hero .brand-row {
|
||||
display: grid;
|
||||
grid-template-columns: 1fr 170px;
|
||||
gap: 24px;
|
||||
align-items: start;
|
||||
margin-bottom: 54px;
|
||||
}
|
||||
|
||||
.charity-hero .logo-mark {
|
||||
width: 165px;
|
||||
justify-self: end;
|
||||
filter: drop-shadow(0 10px 16px rgba(215,25,63,.15));
|
||||
animation: logoBreath 3.6s ease-in-out infinite;
|
||||
}
|
||||
|
||||
.charity-hero .brand-text {
|
||||
text-align: center;
|
||||
align-self: center;
|
||||
}
|
||||
|
||||
.charity-hero .brand-text h1 {
|
||||
margin: 0 0 8px;
|
||||
text-transform: uppercase;
|
||||
line-height: 1.18;
|
||||
font-size: clamp(20px,1.72vw,30px);
|
||||
letter-spacing: -.3px;
|
||||
color: var(--red);
|
||||
font-weight: 900;
|
||||
}
|
||||
|
||||
.charity-hero .brand-text p {
|
||||
margin: 0;
|
||||
color: #67676c;
|
||||
text-transform: uppercase;
|
||||
font-size: clamp(16px,1.2vw,22px);
|
||||
font-weight: 800;
|
||||
letter-spacing: .3px;
|
||||
}
|
||||
|
||||
.charity-hero .slogan-card {
|
||||
width: min(560px,100%);
|
||||
margin: 0 auto;
|
||||
position: relative;
|
||||
text-align: center;
|
||||
padding: 20px 18px 28px;
|
||||
}
|
||||
|
||||
.charity-hero .slogan-card:before {
|
||||
content: "";
|
||||
position: absolute;
|
||||
left: 50%;
|
||||
top: 50%;
|
||||
width: 86%;
|
||||
height: 86%;
|
||||
transform: translate(-50%,-50%);
|
||||
border-radius: 38px;
|
||||
background: linear-gradient(90deg,rgba(255,255,255,.18),rgba(255,237,243,.72),rgba(255,255,255,.12));
|
||||
filter: blur(.2px);
|
||||
z-index: -1;
|
||||
opacity: .8;
|
||||
}
|
||||
|
||||
.charity-hero .quote-mark {
|
||||
position: absolute;
|
||||
left: 12px;
|
||||
top: -16px;
|
||||
font-size: 74px;
|
||||
line-height: 1;
|
||||
color: rgba(215,25,63,.18);
|
||||
font-family: Georgia,serif;
|
||||
}
|
||||
|
||||
.charity-hero .slogan-card h2 {
|
||||
margin: 0;
|
||||
color: #e13b5e;
|
||||
font-size: clamp(29px,2.2vw,42px);
|
||||
line-height: 1.42;
|
||||
font-family: "Segoe Script","Brush Script MT",cursive;
|
||||
font-weight: 600;
|
||||
text-shadow: 0 8px 20px rgba(215,25,63,.12);
|
||||
}
|
||||
|
||||
.charity-hero .slogan-card h2 em {
|
||||
font-style: normal;
|
||||
font-size: .86em;
|
||||
color: #d9284c;
|
||||
}
|
||||
|
||||
.charity-hero .heart-line {
|
||||
display: block;
|
||||
width: 160px;
|
||||
height: 22px;
|
||||
margin: 12px auto 0;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.charity-hero .heart-line:before {
|
||||
content: "";
|
||||
position: absolute;
|
||||
left: 0;
|
||||
right: 34px;
|
||||
top: 11px;
|
||||
height: 2px;
|
||||
background: linear-gradient(90deg,transparent,var(--red));
|
||||
border-radius: 999px;
|
||||
}
|
||||
|
||||
.charity-hero .heart-line:after {
|
||||
content: "♡";
|
||||
position: absolute;
|
||||
right: 6px;
|
||||
top: -8px;
|
||||
color: var(--red);
|
||||
font-size: 32px;
|
||||
transform: rotate(18deg);
|
||||
animation: heartBeat 1.7s ease-in-out infinite;
|
||||
}
|
||||
|
||||
.charity-hero .action-row {
|
||||
display: flex;
|
||||
gap: 12px;
|
||||
justify-content: center;
|
||||
margin-top: 26px;
|
||||
flex-wrap: wrap;
|
||||
}
|
||||
|
||||
.charity-hero .btn {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
height: 44px;
|
||||
padding: 0 20px;
|
||||
border-radius: 999px;
|
||||
font-weight: 800;
|
||||
font-size: 14px;
|
||||
letter-spacing: .2px;
|
||||
transition: .3s ease;
|
||||
box-shadow: 0 12px 30px rgba(115,21,43,.12);
|
||||
}
|
||||
|
||||
.charity-hero .btn.primary {
|
||||
background: linear-gradient(135deg,var(--red),#ef4769);
|
||||
color: white;
|
||||
}
|
||||
|
||||
.charity-hero .btn.secondary {
|
||||
background: rgba(255,255,255,.74);
|
||||
color: var(--red);
|
||||
border: 1px solid rgba(215,25,63,.18);
|
||||
}
|
||||
|
||||
.charity-hero .reveal-up {
|
||||
opacity: 0;
|
||||
transform: translateY(24px);
|
||||
animation: revealUp .8s ease forwards;
|
||||
}
|
||||
|
||||
.charity-hero .brand-text.reveal-up {
|
||||
animation-delay: .2s;
|
||||
}
|
||||
|
||||
.charity-hero .logo-mark.reveal-up {
|
||||
animation-delay: .38s;
|
||||
}
|
||||
|
||||
.charity-hero .slogan-card.reveal-up {
|
||||
animation-delay: .62s;
|
||||
}
|
||||
|
||||
.charity-hero .action-row.reveal-up {
|
||||
animation-delay: .86s;
|
||||
}
|
||||
|
||||
@keyframes cardIntro {
|
||||
from { opacity: 0; transform: translate3d(-28px,22px,0) rotate(calc(var(--r) - 7deg)) scale(.78); }
|
||||
to { opacity: 1; transform: translate3d(0,0,0) rotate(var(--r)) scale(.92); }
|
||||
}
|
||||
/* Removed microFloat because animating margin-top constantly recalculates layout causing major stutter */
|
||||
@keyframes shine {
|
||||
to { transform: translateX(130%); }
|
||||
}
|
||||
@keyframes revealUp {
|
||||
to { opacity: 1; transform: translateY(0); }
|
||||
}
|
||||
@keyframes fadeDown {
|
||||
to { opacity: 1; transform: translateY(0); }
|
||||
}
|
||||
@keyframes logoBreath {
|
||||
0%,100% { transform: translateY(0) scale(1); }
|
||||
50% { transform: translateY(-6px) scale(1.025); }
|
||||
}
|
||||
@keyframes heartBeat {
|
||||
0%,100% { transform: rotate(18deg) scale(1); }
|
||||
20% { transform: rotate(18deg) scale(1.18); }
|
||||
38% { transform: rotate(18deg) scale(1); }
|
||||
}
|
||||
@keyframes blobFloat {
|
||||
to { transform: translate(26px,20px) scale(1.05); }
|
||||
}
|
||||
@keyframes lightPulse {
|
||||
0%,100% { opacity: .25; transform: scale(.96); }
|
||||
50% { opacity: .58; transform: scale(1.08); }
|
||||
}
|
||||
|
||||
@media (max-width:1200px) {
|
||||
.charity-hero .hero-shell {
|
||||
grid-template-columns: 1fr;
|
||||
gap: 10px;
|
||||
padding: 18px 0 34px;
|
||||
}
|
||||
.charity-hero { min-height: auto; }
|
||||
.charity-hero .content-panel { min-height: auto; }
|
||||
.charity-hero .gallery-panel { min-height: 470px; }
|
||||
.charity-hero .gallery-stage { height: 430px; }
|
||||
.charity-hero .brand-row { grid-template-columns: 1fr 130px; margin-bottom: 20px; }
|
||||
.charity-hero .logo-mark { width: 130px; }
|
||||
}
|
||||
|
||||
@media (max-width:720px) {
|
||||
.charity-hero .hero-shell { width: calc(100% - 24px); }
|
||||
.charity-hero .soft-grid { inset: 12px; border-width: 3px; }
|
||||
.charity-hero .gallery-panel { padding: 12px 0; min-height: 390px; }
|
||||
.charity-hero .gallery-title { display: none; }
|
||||
.charity-hero .gallery-stage { height: 370px; overflow: hidden; }
|
||||
.charity-hero .photo-card { width: calc(var(--w) * .72); }
|
||||
.charity-hero .photo-card.is-active { width: min(86vw,380px); }
|
||||
.charity-hero .content-panel { padding: 8px; }
|
||||
.charity-hero .brand-row { display: flex; flex-direction: column-reverse; align-items: center; gap: 10px; }
|
||||
.charity-hero .brand-text h1 { text-align: center; }
|
||||
.charity-hero .slogan-card h2 { font-size: 29px; }
|
||||
.charity-hero .btn { height: 42px; padding: 0 16px; }
|
||||
}
|
||||
|
||||
@media (prefers-reduced-motion:reduce) {
|
||||
.charity-hero *,
|
||||
.charity-hero *::before,
|
||||
.charity-hero *::after {
|
||||
animation-duration: .01ms !important;
|
||||
animation-iteration-count: 1 !important;
|
||||
scroll-behavior: auto !important;
|
||||
transition-duration: .01ms !important;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
<div class="charity-hero" aria-label="Quỹ từ thiện bệnh nhân nghèo bị đột quỵ">
|
||||
<div class="hero-bg">
|
||||
<span class="blob blob-1"></span>
|
||||
<span class="blob blob-2"></span>
|
||||
<span class="blob blob-3"></span>
|
||||
<span class="soft-grid"></span>
|
||||
</div>
|
||||
|
||||
<section class="hero-shell">
|
||||
<div class="gallery-panel" aria-label="Hình ảnh hoạt động quỹ từ thiện">
|
||||
<div class="gallery-title">
|
||||
<span class="eyebrow">S.I.S Charity Foundation</span>
|
||||
<strong>Những khoảnh khắc sẻ chia</strong>
|
||||
</div>
|
||||
|
||||
<div class="gallery-stage" id="galleryStage">
|
||||
<article class="photo-card p1" data-index="0" style="--x: -4%; --y: 2%; --r: -2.5deg; --w: 205px; --delay: 0.05s;">
|
||||
<img src="/upload/charity_v4/photo-01.jpg" alt="Trao hỗ trợ bệnh nhân 1" />
|
||||
</article>
|
||||
<article class="photo-card p2" data-index="1" style="--x: 18%; --y: -2%; --r: 1.6deg; --w: 298px; --delay: 0.16s;">
|
||||
<img src="/upload/charity_v4/photo-02.jpg" alt="Trao hỗ trợ bệnh nhân 2" />
|
||||
</article>
|
||||
<article class="photo-card p3" data-index="2" style="--x: 63%; --y: 0%; --r: -1.2deg; --w: 410px; --delay: 0.27s;">
|
||||
<img src="/upload/charity_v4/photo-05.jpg" alt="Trao hỗ trợ bệnh nhân 3" />
|
||||
</article>
|
||||
<article class="photo-card p4" data-index="3" style="--x: 0%; --y: 27%; --r: 2.2deg; --w: 245px; --delay: 0.38s">
|
||||
<img src="/upload/charity_v4/photo-03.jpg" alt="Trao hỗ trợ bệnh nhân 4" />
|
||||
</article>
|
||||
<article class="photo-card p5" data-index="4" style="--x: 32%; --y: 32%; --r: -1.8deg; --w: 260px; --delay: 0.49s;">
|
||||
<img src="/upload/charity_v4/photo-04.jpg" alt="Trao hỗ trợ bệnh nhân 5" />
|
||||
</article>
|
||||
<article class="photo-card p6" data-index="5" style="--x: 57%; --y: 35%; --r: 1deg; --w: 195px; --delay: 0.6s">
|
||||
<img src="/upload/charity_v4/photo-06.jpg" alt="Trao hỗ trợ bệnh nhân 6" />
|
||||
</article>
|
||||
<article class="photo-card p7" data-index="6" style="--x: 4%; --y: 62%; --r: -1.4deg; --w: 270px; --delay: 0.71s;">
|
||||
<img src="/upload/charity_v4/photo-07.jpg" alt="Trao hỗ trợ bệnh nhân 7" />
|
||||
</article>
|
||||
<article class="photo-card p8" data-index="7" style="--x: 42%; --y: 73%; --r: 1.2deg; --w: 255px; --delay: 0.82s;">
|
||||
<img src="/upload/charity_v4/photo-08.jpg" alt="Trao hỗ trợ bệnh nhân 8" />
|
||||
</article>
|
||||
<article class="photo-card p9" data-index="8" style="--x: 77%; --y: 66%; --r: -1deg; --w: 338px; --delay: 0.93s">
|
||||
<img src="/upload/charity_v4/photo-09.jpg" alt="Trao hỗ trợ bệnh nhân 9" />
|
||||
</article>
|
||||
<div class="gallery-light" aria-hidden="true"></div>
|
||||
</div>
|
||||
|
||||
<div class="gallery-controls" aria-hidden="true">
|
||||
<span class="dot is-active"></span>
|
||||
<span class="dot"></span>
|
||||
<span class="dot"></span>
|
||||
<span class="dot"></span>
|
||||
<span class="dot"></span>
|
||||
<span class="dot"></span>
|
||||
<span class="dot"></span>
|
||||
<span class="dot"></span>
|
||||
<span class="dot"></span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="content-panel">
|
||||
<div class="brand-row">
|
||||
<div class="brand-text reveal-up">
|
||||
<h1>Quỹ từ thiện bệnh nhân nghèo bị đột quỵ<br />khu vực Đồng bằng sông Cửu Long</h1>
|
||||
<p>S.I.S Charity Foundation</p>
|
||||
</div>
|
||||
<img class="logo-mark reveal-up" src="/upload/charity_v4/logo.png" alt="Stroke International Services Charity Foundation" />
|
||||
</div>
|
||||
|
||||
<div class="slogan-card reveal-up">
|
||||
<span class="quote-mark">“</span>
|
||||
<h2>Sẻ chia yêu thương<br /><em>đến bệnh nhân nghèo bị đột quỵ</em></h2>
|
||||
<span class="heart-line" aria-hidden="true"></span>
|
||||
</div>
|
||||
|
||||
<div class="action-row reveal-up">
|
||||
<a class="btn primary" href="#">Lan tỏa yêu thương</a>
|
||||
<a class="btn secondary" href="#">Xem hoạt động quỹ</a>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
</div>
|
||||
|
||||
<script>
|
||||
(function(){
|
||||
const container = document.querySelector('.charity-hero');
|
||||
if(!container) return;
|
||||
const stage = container.querySelector('.gallery-stage');
|
||||
const cards = Array.from(container.querySelectorAll('.photo-card'));
|
||||
const dots = Array.from(container.querySelectorAll('.dot'));
|
||||
if(!stage || cards.length === 0) return;
|
||||
|
||||
let active = 0;
|
||||
let timer = null;
|
||||
const duration = 4500; /* Tăng thời gian chờ (autoplay) từ 2.8 giây lên 4.5 giây để nhìn rõ ảnh hơn */
|
||||
|
||||
function setActive(index){
|
||||
active = index % cards.length;
|
||||
stage.classList.add('is-playing');
|
||||
|
||||
cards.forEach((card, i) => {
|
||||
card.classList.remove('is-active','is-dim','is-next','is-exit');
|
||||
const diff = (i - active + cards.length) % cards.length;
|
||||
if(i === active){
|
||||
card.classList.add('is-active');
|
||||
}else if(diff === 1 || diff === 2){
|
||||
card.classList.add('is-next');
|
||||
}else if(diff === cards.length - 1){
|
||||
card.classList.add('is-exit');
|
||||
}else{
|
||||
card.classList.add('is-dim');
|
||||
}
|
||||
});
|
||||
|
||||
dots.forEach((dot, i) => dot.classList.toggle('is-active', i === active));
|
||||
}
|
||||
|
||||
function next(){
|
||||
setActive(active + 1);
|
||||
}
|
||||
|
||||
function start(){
|
||||
stop();
|
||||
timer = setInterval(next, duration);
|
||||
}
|
||||
|
||||
function stop(){
|
||||
if(timer) clearInterval(timer);
|
||||
}
|
||||
|
||||
// Hệ thống sẽ chạy tự động 100%
|
||||
|
||||
dots.forEach((dot, i) => {
|
||||
dot.addEventListener('click', () => {
|
||||
setActive(i);
|
||||
start();
|
||||
});
|
||||
});
|
||||
|
||||
// Start immediately or on load if part of a bigger page
|
||||
setTimeout(() => {
|
||||
setActive(0);
|
||||
start();
|
||||
}, 900);
|
||||
})();
|
||||
</script>
|
||||
@@ -0,0 +1,29 @@
|
||||
<div data-component-id="umass_base:block-multiple-ctas" data-background="solid" data-layout-variant="default">
|
||||
<div class="container" th:unless="${ctaMenu != null and not #lists.isEmpty(ctaMenu.items)}">
|
||||
<div class="text-container">
|
||||
<div data-component-id="umass_base:section-title" class="f--section-title">
|
||||
<h2>TÌM HIỂU<span class="highlight">KHOA ĐIỀU TRỊ</span></h2>
|
||||
</div>
|
||||
</div>
|
||||
<div class="links-container">
|
||||
[menu:CTA]
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<style>
|
||||
.links-container {
|
||||
display: grid !important;
|
||||
grid-template-columns: repeat(2, 1fr) !important;
|
||||
gap: 1rem;
|
||||
column-gap: 2rem !important;
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
@media (max-width: 600px) {
|
||||
.links-container {
|
||||
grid-template-columns: 1fr !important;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@@ -0,0 +1,43 @@
|
||||
<body>
|
||||
<div class="cc--component-container cc--stats-block" style="background-color: var(--color-brand)">
|
||||
<div class="c--component c--stats-block">
|
||||
<div class="f--field f--stats-block">
|
||||
<div class="cc--component-container cc--stat">
|
||||
<div class="c--component c--stat">
|
||||
<div id="iuox8" class="f--field f--stat-number">50.000+</div>
|
||||
<div id="iynqf" class="f--field f--description">
|
||||
<p>Tổng số ca cấp cứu</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="cc--component-container cc--stat">
|
||||
<div class="c--component c--stat">
|
||||
<div id="ievo1" class="f--field f--stat-number">1.6tr+</div>
|
||||
<div id="iklnr" class="f--field f--description">
|
||||
<p>Tổng số ca khám bệnh</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="cc--component-container cc--stat">
|
||||
<div class="c--component c--stat">
|
||||
<div id="iz72l" class="f--field f--stat-number">30.000+</div>
|
||||
<div id="i0kg8" class="f--field f--description">
|
||||
<p>Số ca điều trị đột quỵ</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="cc--component-container cc--stat">
|
||||
<div class="c--component c--stat">
|
||||
<div id="iz72l" class="f--field f--stat-number">#1</div>
|
||||
<div id="i0kg8" class="f--field f--description">
|
||||
<p>Về điều trị đột quỵ</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</body>
|
||||
<style>
|
||||
* { box-sizing: border-box; } body {margin: 0;}*{box-sizing:border-box;}body{margin-top:0px;margin-right:0px;margin-bottom:0px;margin-left:0px;}#iuox8{color:white;}#iynqf{color:white;}#ievo1{color:white;}#iklnr{color:white;}#iz72l{color:white;}#i0kg8{color:white;}#iynqf *{color:white;}#iklnr *{color:white;}#i0kg8 *{color:white;}
|
||||
</style>
|
||||
@@ -0,0 +1,172 @@
|
||||
<style>
|
||||
.stroke-book-banner {
|
||||
background-color: #f8f9fa;
|
||||
padding: 36px 20px;
|
||||
font-family: var(--font-family-base, 'Inter', 'Segoe UI', sans-serif);
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.sbb-container {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
align-items: center;
|
||||
max-width: var(--max-width);
|
||||
width: 100%;
|
||||
gap: 50px;
|
||||
/* Faint brain background pattern placeholder */
|
||||
background-image: url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" width="200" height="200" viewBox="0 0 24 24" fill="none" stroke="%23ffe6e6" stroke-width="0.5" stroke-linecap="round" stroke-linejoin="round"><path d="M9.5 2A2.5 2.5 0 0 1 12 4.5v15a2.5 2.5 0 0 1-4.96.44 2.5 2.5 0 0 1-2.96-3.08 3 3 0 0 1-.34-5.58 2.5 2.5 0 0 1 1.32-4.24 2.5 2.5 0 0 1 1.98-3A2.5 2.5 0 0 1 9.5 2Z"/><path d="M14.5 2A2.5 2.5 0 0 0 12 4.5v15a2.5 2.5 0 0 0 4.96.44 2.5 2.5 0 0 0 2.96-3.08 3 3 0 0 0 .34-5.58 2.5 2.5 0 0 0-1.32-4.24 2.5 2.5 0 0 0-1.98-3A2.5 2.5 0 0 0 14.5 2Z"/></svg>');
|
||||
background-position: right center;
|
||||
background-repeat: no-repeat;
|
||||
background-size: 350px;
|
||||
}
|
||||
|
||||
.sbb-left {
|
||||
flex: 1.2;
|
||||
display: flex;
|
||||
justify-content: flex-end;
|
||||
}
|
||||
|
||||
.sbb-left img {
|
||||
max-width: 100%;
|
||||
height: auto;
|
||||
object-fit: contain;
|
||||
filter: drop-shadow(0 15px 25px rgba(0, 0, 0, 0.15));
|
||||
}
|
||||
|
||||
.sbb-right {
|
||||
flex: 1;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: center;
|
||||
align-items: flex-start;
|
||||
padding-right: 20px;
|
||||
}
|
||||
|
||||
.sbb-subtitle {
|
||||
font-size: 1.4rem;
|
||||
font-weight: 700;
|
||||
color: #222;
|
||||
margin-bottom: 5px;
|
||||
text-transform: uppercase;
|
||||
letter-spacing: 0.5px;
|
||||
}
|
||||
|
||||
.sbb-title {
|
||||
font-size: 3.2rem;
|
||||
font-weight: 800;
|
||||
color: #c0272d;
|
||||
margin: 0 0 15px 0;
|
||||
text-transform: uppercase;
|
||||
line-height: 1.1;
|
||||
letter-spacing: -0.5px;
|
||||
}
|
||||
|
||||
.sbb-tagline {
|
||||
font-size: 1.25rem;
|
||||
font-weight: 700;
|
||||
color: #333;
|
||||
margin-bottom: 30px;
|
||||
}
|
||||
|
||||
.sbb-features {
|
||||
list-style: none;
|
||||
padding: 0;
|
||||
margin: 0 0 35px 0;
|
||||
}
|
||||
|
||||
.sbb-features li {
|
||||
font-size: 1.1rem;
|
||||
color: #444;
|
||||
margin-bottom: 14px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
.sbb-features li::before {
|
||||
content: '✓';
|
||||
display: inline-flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
width: 24px;
|
||||
height: 24px;
|
||||
border-radius: 50%;
|
||||
border: 1.5px solid #c0272d;
|
||||
color: #c0272d;
|
||||
font-size: 14px;
|
||||
font-weight: bold;
|
||||
margin-right: 12px;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
.sbb-btn {
|
||||
display: inline-block;
|
||||
background: linear-gradient(180deg, #d81b32 0%, #a11122 100%);
|
||||
color: #fff;
|
||||
font-weight: 700;
|
||||
font-size: 1.15rem;
|
||||
padding: 16px 40px;
|
||||
border-radius: 6px;
|
||||
text-decoration: none;
|
||||
text-transform: uppercase;
|
||||
box-shadow: 0 4px 10px rgba(161, 17, 34, 0.4);
|
||||
transition: all 0.3s ease;
|
||||
letter-spacing: 0.5px;
|
||||
border: 1px solid #8e0b1b;
|
||||
}
|
||||
|
||||
.sbb-btn:hover {
|
||||
background: linear-gradient(180deg, #ee1f38 0%, #b81427 100%);
|
||||
box-shadow: 0 6px 15px rgba(161, 17, 34, 0.5);
|
||||
transform: translateY(-2px);
|
||||
color: #fff !important;
|
||||
}
|
||||
|
||||
@media (max-width: 992px) {
|
||||
.sbb-container {
|
||||
flex-direction: column;
|
||||
text-align: center;
|
||||
gap: 30px;
|
||||
background-image: none;
|
||||
}
|
||||
|
||||
.sbb-left {
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.sbb-right {
|
||||
align-items: center;
|
||||
padding-right: 0;
|
||||
}
|
||||
|
||||
.sbb-title {
|
||||
font-size: 2.5rem;
|
||||
}
|
||||
|
||||
.sbb-features li {
|
||||
text-align: left;
|
||||
justify-content: flex-start;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
<div class="stroke-book-banner">
|
||||
<div class="sbb-container">
|
||||
<div class="sbb-left">
|
||||
<img src="/upload/sach-dot-quy-ngang.png" alt="Cẩm nang sức khỏe phòng chống đột quỵ">
|
||||
</div>
|
||||
<div class="sbb-right">
|
||||
<div class="sbb-subtitle">CẨM NANG SỨC KHỎE</div>
|
||||
<h2 class="sbb-title">PHÒNG CHỐNG ĐỘT QUỴ</h2>
|
||||
<div class="sbb-tagline">Hiểu đúng – Phòng sớm – Sống khỏe mỗi ngày</div>
|
||||
<ul class="sbb-features">
|
||||
<li>Kiến thức khoa học, dễ hiểu</li>
|
||||
<li>Nhận biết sớm dấu hiệu – Xử trí kịp thời</li>
|
||||
<li>Phòng ngừa hiệu quả – Giảm thiểu nguy cơ</li>
|
||||
<li>Dành cho mọi lứa tuổi</li>
|
||||
</ul>
|
||||
<a href="#" class="sbb-btn">TÌM HIỂU NGAY</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -0,0 +1,218 @@
|
||||
<div class="cc--component-container cc--news-events">
|
||||
<div class="c--component c--news-events">
|
||||
|
||||
<!-- Phần 2 cột: Tin mới (Trái) và Sự kiện (Phải) -->
|
||||
<div class="news-events-row">
|
||||
|
||||
<div class="news-column">
|
||||
<h2 class="section-title--news" style="font-size: 2rem;">
|
||||
TIN TỨC
|
||||
</h2>
|
||||
<div class="news-slider-wrapper">
|
||||
<button class="news-slider-btn prev-btn" aria-label="Previous">‹</button>
|
||||
<div class="news-slider-container">
|
||||
<div class="news-slider-track">
|
||||
<!-- Shortcode Tin Tức hiển thị dạng list (limit tăng lên 6 để có thể trượt) -->
|
||||
[component:news-grid data-source="posts:tag=news,limit=6,collection=news_posts"]
|
||||
</div>
|
||||
</div>
|
||||
<button class="news-slider-btn next-btn" aria-label="Next">›</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="events-column">
|
||||
<h2 class="events-title" style="font-size: 2rem;">
|
||||
SỰ KIỆN
|
||||
</h2>
|
||||
<div class="events-widget">
|
||||
<!-- Shortcode Sự kiện -->
|
||||
[component:events-list data-source="posts:tag=event,limit=4,collection=event_posts"]
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
<!-- Header chung (Mobile) -->
|
||||
<div class="news-events-section__footer">
|
||||
<a href="/news/news-events" class="news-events-section__cta news-events-section__cta--mobile">
|
||||
Xem Thêm
|
||||
</a>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<style>
|
||||
.news-slider-wrapper {
|
||||
position: relative;
|
||||
padding: 0px;
|
||||
}
|
||||
|
||||
.news-slider-container {
|
||||
overflow: hidden;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.news-slider-wrapper .news-grid,
|
||||
.news-slider-wrapper .row,
|
||||
.news-slider-track {
|
||||
display: flex !important;
|
||||
flex-wrap: nowrap !important;
|
||||
gap: 20px;
|
||||
margin: 0 !important;
|
||||
transition: transform 0.4s ease;
|
||||
}
|
||||
|
||||
/* Force children to be fixed width cards - 2 cards at a time because this column is narrow */
|
||||
.news-slider-wrapper .news-grid>*,
|
||||
.news-slider-wrapper .row>*,
|
||||
.news-slider-track>* {
|
||||
flex: 0 0 calc(50% - 10px) !important;
|
||||
max-width: none !important;
|
||||
}
|
||||
|
||||
@media (max-width: 992px) {
|
||||
|
||||
.news-slider-wrapper .news-grid>*,
|
||||
.news-slider-wrapper .row>*,
|
||||
.news-slider-track>* {
|
||||
flex: 0 0 calc(50% - 10px) !important;
|
||||
}
|
||||
}
|
||||
|
||||
@media (max-width: 576px) {
|
||||
|
||||
.news-slider-wrapper .news-grid>*,
|
||||
.news-slider-wrapper .row>*,
|
||||
.news-slider-track>* {
|
||||
flex: 0 0 100% !important;
|
||||
}
|
||||
}
|
||||
|
||||
.news-slider-btn {
|
||||
position: absolute;
|
||||
top: 50%;
|
||||
transform: translateY(-50%);
|
||||
width: 40px;
|
||||
height: 40px;
|
||||
border-radius: 50%;
|
||||
background-color: rgba(200, 200, 200, 0.5);
|
||||
color: #333;
|
||||
border: none;
|
||||
font-size: 30px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
cursor: pointer;
|
||||
z-index: 10;
|
||||
transition: background-color 0.2s, color 0.2s;
|
||||
line-height: 1;
|
||||
}
|
||||
|
||||
.news-slider-btn:hover {
|
||||
background-color: rgba(0, 0, 0, 0.7);
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
.news-slider-btn.prev-btn {
|
||||
left: -15px;
|
||||
}
|
||||
|
||||
.news-slider-btn.next-btn {
|
||||
right: -15px;
|
||||
}
|
||||
|
||||
.news-slider-btn:disabled {
|
||||
opacity: 0.2;
|
||||
cursor: not-allowed;
|
||||
}
|
||||
|
||||
/* --- Hiệu ứng crop (zoom) ảnh khi hover --- */
|
||||
/* 1. Thiết lập vùng chứa ảnh sẽ cắt bỏ phần bị lồi ra (overflow: hidden) */
|
||||
.news-slider-wrapper .featured-grid__item .news-card__image {
|
||||
overflow: hidden !important;
|
||||
display: block;
|
||||
}
|
||||
|
||||
/* 2. Thiết lập thời gian chuyển động cho ảnh */
|
||||
.news-slider-wrapper .featured-grid__item .news-card__image img {
|
||||
transition: transform 0.4s ease-in-out !important;
|
||||
}
|
||||
|
||||
/* 3. Phóng to ảnh (scale) khi trỏ chuột vào vùng chứa */
|
||||
.news-slider-wrapper .featured-grid__item:hover .news-card__image img {
|
||||
transform: scale(1.1) !important;
|
||||
}
|
||||
|
||||
</style>
|
||||
|
||||
<script>
|
||||
document.addEventListener("DOMContentLoaded", function() {
|
||||
const wrappers = document.querySelectorAll('.news-slider-wrapper');
|
||||
wrappers.forEach(wrapper => {
|
||||
const prevBtn = wrapper.querySelector('.prev-btn');
|
||||
const nextBtn = wrapper.querySelector('.next-btn');
|
||||
|
||||
let track = wrapper.querySelector('.news-slider-track');
|
||||
if (track && track.children.length === 1 && (track.children[0].classList.contains('news-grid') || track.children[0].classList.contains('row'))) {
|
||||
track = track.children[0];
|
||||
track.classList.add('news-slider-track');
|
||||
}
|
||||
|
||||
if (!track) return;
|
||||
|
||||
let currentIndex = 0;
|
||||
|
||||
function updateSlider() {
|
||||
const items = track.children;
|
||||
if(items.length === 0) return;
|
||||
const itemWidth = items[0].getBoundingClientRect().width;
|
||||
|
||||
const gap = parseFloat(window.getComputedStyle(track).gap) || 20;
|
||||
track.style.transform = `translateX(-${currentIndex * (itemWidth + gap)}px)`;
|
||||
|
||||
const containerWidth = wrapper.querySelector('.news-slider-container').getBoundingClientRect().width;
|
||||
const visibleCount = Math.max(1, Math.floor((containerWidth + gap) / (itemWidth + gap)));
|
||||
|
||||
prevBtn.disabled = currentIndex === 0;
|
||||
nextBtn.disabled = currentIndex >= items.length - visibleCount;
|
||||
}
|
||||
|
||||
prevBtn.addEventListener('click', () => {
|
||||
if (currentIndex > 0) {
|
||||
currentIndex--;
|
||||
updateSlider();
|
||||
}
|
||||
});
|
||||
|
||||
nextBtn.addEventListener('click', () => {
|
||||
const items = track.children;
|
||||
const itemWidth = items[0].getBoundingClientRect().width;
|
||||
const gap = parseFloat(window.getComputedStyle(track).gap) || 20;
|
||||
const containerWidth = wrapper.querySelector('.news-slider-container').getBoundingClientRect().width;
|
||||
const visibleCount = Math.max(1, Math.floor((containerWidth + gap) / (itemWidth + gap)));
|
||||
|
||||
if (currentIndex < items.length - visibleCount) {
|
||||
currentIndex++;
|
||||
updateSlider();
|
||||
}
|
||||
});
|
||||
|
||||
window.addEventListener('resize', () => {
|
||||
const items = track.children;
|
||||
if(items.length === 0) return;
|
||||
const itemWidth = items[0].getBoundingClientRect().width;
|
||||
const gap = parseFloat(window.getComputedStyle(track).gap) || 20;
|
||||
const containerWidth = wrapper.querySelector('.news-slider-container').getBoundingClientRect().width;
|
||||
const visibleCount = Math.max(1, Math.floor((containerWidth + gap) / (itemWidth + gap)));
|
||||
|
||||
if (currentIndex > items.length - visibleCount) {
|
||||
currentIndex = Math.max(0, items.length - visibleCount);
|
||||
}
|
||||
updateSlider();
|
||||
});
|
||||
|
||||
setTimeout(updateSlider, 200);
|
||||
});
|
||||
});
|
||||
</script>
|
||||
@@ -0,0 +1,138 @@
|
||||
<div class="content-top">
|
||||
<div class="lc--layout-container lc--full">
|
||||
<div class="l--layout l--full">
|
||||
<div class="lr--layout-region lr--main">
|
||||
<div class="cc--component-container cc--homepage-hero">
|
||||
<div class="c--component c--homepage-hero">
|
||||
<div class="slides-container">
|
||||
<div class="image-video-container has-video">
|
||||
<img
|
||||
src="https://www.umass.edu/sites/default/files/styles/1_1_1920x1920/public/2025-09/250616_UMASS_4515.jpg"
|
||||
alt="Students collaborate using a driving simulator in the UMass Center for Transportation."
|
||||
srcset="
|
||||
https://www.umass.edu/sites/default/files/styles/1_1_1920x1920/public/2025-09/250616_UMASS_4515.jpg?h=9855f42d&itok=d27r8GaT 1920w
|
||||
"
|
||||
/>
|
||||
<div class="f--ambient-video" id="hero-ambient-video">
|
||||
<video role="presentation" tabindex="-1" loop="" autoplay="" playsinline="" muted=""
|
||||
id="hero-video" onerror="handleVideoError()">
|
||||
<source
|
||||
src="http://localhost:8080/uploads/2026/07/9375f45b-027a-4fb4-bd18-66889309280d.mp4"
|
||||
type="video/mp4" onerror="handleVideoError()" />
|
||||
</video>
|
||||
</div>
|
||||
|
||||
<div id="hero-video-fallback"
|
||||
style="display: none; position: absolute; top:0; left:0; width:100%; height:100%; z-index: 2;">
|
||||
<th:block
|
||||
th:utext="${@hookManager.applyFilters('the_content', '[plugin:swiper-slider slug=''video-fallback'']')}">
|
||||
</th:block>
|
||||
</div>
|
||||
|
||||
<script>
|
||||
function handleVideoError() {
|
||||
var vidContainer = document.getElementById('hero-ambient-video');
|
||||
if(vidContainer) vidContainer.style.display = 'none';
|
||||
|
||||
var controls = document.querySelector('.video-controls');
|
||||
if(controls) controls.style.display = 'none';
|
||||
|
||||
var fallback = document.getElementById('hero-video-fallback');
|
||||
if(fallback) fallback.style.display = 'block';
|
||||
}
|
||||
|
||||
window.addEventListener('DOMContentLoaded', function() {
|
||||
var v = document.getElementById('hero-video');
|
||||
if (v && v.error) {
|
||||
handleVideoError();
|
||||
}
|
||||
});
|
||||
</script>
|
||||
<div class="video-controls" data-once="ambientVideo">
|
||||
<div class="video-controls-inner">
|
||||
<button aria-labelledby="pauseBtn" class="video-button video-pause-button">
|
||||
<svg height="14" viewBox="0 0 10 14" width="10" xmlns="http://www.w3.org/2000/svg">
|
||||
<title id="pauseBtn">Pause Background Video</title>
|
||||
<path
|
||||
d="m1143 711v14h-3v-14zm7 0v14h-3v-14z"
|
||||
fill="#fff"
|
||||
fill-rule="evenodd"
|
||||
transform="translate(-1140 -711)"
|
||||
></path>
|
||||
</svg>
|
||||
</button>
|
||||
<button aria-labelledby="playBtn" class="video-button video-play-button">
|
||||
<svg height="29" viewBox="0 0 29 29" width="29" xmlns="http://www.w3.org/2000/svg">
|
||||
<title id="playBtn">Play Background Video</title>
|
||||
<path
|
||||
d="m17.5 3c-7.99789474 0-14.5 6.50210526-14.5 14.5 0 7.9978947 6.50210526 14.5 14.5 14.5 7.9978947 0 14.5-6.5021053 14.5-14.5 0-7.99789474-6.5021053-14.5-14.5-14.5zm5.6763936 15.2939067-7.3503366 4.5939604c-.6635721.408352-1.5313202-.051044-1.5313202-.8422261v-9.1879207c0-.7911821.8677481-1.2761001 1.5313202-.8422261l7.3503366 4.5939604c.612528.38283.612528 1.3016221 0 1.6844521z"
|
||||
fill="#fff"
|
||||
fill-rule="evenodd"
|
||||
transform="translate(-3 -3)"
|
||||
></path>
|
||||
</svg>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="text-container centered">
|
||||
<div class="slide-text-container-inner">
|
||||
<h3>
|
||||
<a href="https://www.umass.edu/gateway/why-umass">Stroke International School
|
||||
2026.</a>
|
||||
</h3>
|
||||
<div class="f--field f--button">
|
||||
<a href="https://www.umass.edu/gateway/why-umass"
|
||||
class="button-secondary button-context-dark"
|
||||
aria-label="Learn More Learn more about UMass Amherst."
|
||||
data-component-id="umass_base:button">
|
||||
<span class="button-text"> Learn More </span>
|
||||
</a>
|
||||
</div>
|
||||
<nav class="mc--menu mc--info-menu"
|
||||
th:if="${infoMenu != null and not #lists.isEmpty(infoMenu.items)}">
|
||||
<ul class="menu m--menu m--info-menu">
|
||||
<li class="menu-item menu-item--expanded">
|
||||
<details class="utility-button-wrapper mc--info-menu-container">
|
||||
<summary type="button"
|
||||
aria-label="Display submenu for Information menu"
|
||||
aria-expanded="false" aria-haspopup="true"
|
||||
class="utility-button arrow-toggle information-for-toggle">
|
||||
<span th:text="${infoMenu.name}">Info For</span>
|
||||
<svg version="1.1" xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
|
||||
viewBox="0 0 16 7" enable-background="new 0 0 16 7"
|
||||
xml:space="preserve" width="16" height="7" class="arrow">
|
||||
<polygon fill-rule="evenodd" clip-rule="evenodd"
|
||||
fill="#ffffff" points="7,7 0,0 16,0 "></polygon>
|
||||
</svg>
|
||||
</summary>
|
||||
<div class="submenu-wrapper">
|
||||
<ul class="submenu">
|
||||
<li class="menu-item" th:each="item : ${infoMenu.items}">
|
||||
<a th:href="${item.url}"
|
||||
th:text="${item.label}">Prospective Students</a>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</details>
|
||||
<div class="submenu-wrapper-desktop">
|
||||
<ul class="submenu">
|
||||
<li class="menu-item" th:each="item : ${infoMenu.items}">
|
||||
<a th:href="${item.url}" th:text="${item.label}">Prospective
|
||||
Students</a>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</li>
|
||||
</ul>
|
||||
</nav>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -0,0 +1 @@
|
||||
[plugin:tabbed-livestream]
|
||||
Reference in New Issue
Block a user