feat: implement modular UMass theme components and supporting generation scripts for home page structure

This commit is contained in:
2026-07-29 23:03:29 +07:00
parent c1e0e39aad
commit 317df123bb
37 changed files with 7044 additions and 192 deletions
@@ -45,13 +45,15 @@ public class PageController {
private final com.sisvietnamvn.web.service.SettingService settingService;
private final com.sisvietnamvn.web.repository.DoctorScheduleRepository doctorScheduleRepository;
private final PostRepository postRepository;
private final com.sisvietnamvn.web.service.ComponentTemplateService componentTemplateService;
public PageController(PageService pageService, ObjectMapper objectMapper, HookManager hookManager, com.sisvietnamvn.web.service.HtmlSnippetService snippetService,
com.sisvietnamvn.web.service.DoctorService doctorService, com.sisvietnamvn.web.service.SpecialtyService specialtyService,
com.sisvietnamvn.web.service.DoctorApiSyncService doctorApiSyncService,
com.sisvietnamvn.web.service.SettingService settingService,
com.sisvietnamvn.web.repository.DoctorScheduleRepository doctorScheduleRepository,
PostRepository postRepository) {
PostRepository postRepository,
com.sisvietnamvn.web.service.ComponentTemplateService componentTemplateService) {
this.pageService = pageService;
this.objectMapper = objectMapper;
this.hookManager = hookManager;
@@ -62,6 +64,49 @@ public class PageController {
this.settingService = settingService;
this.doctorScheduleRepository = doctorScheduleRepository;
this.postRepository = postRepository;
this.componentTemplateService = componentTemplateService;
}
@GetMapping("/page/dump-snippets")
@org.springframework.web.bind.annotation.ResponseBody
public String dumpSnippets() {
try {
java.io.File dir = new java.io.File("src/main/resources/templates/themes/umass/snippets");
if (!dir.exists()) dir.mkdirs();
for (com.sisvietnamvn.web.domain.HtmlSnippet snippet : this.snippetService.findAll()) {
if (snippet.getSlug() == null || snippet.getSlug().isEmpty()) continue;
String content = snippet.getContent() != null ? snippet.getContent() : "";
content = content.replace("[menu:CTA]", "<th:block th:utext=\"${@componentTemplateService.render('cta-buttons', 'menu:CTA')}\"></th:block>");
content = content.replace("[menu:INFO:dropdown]", "<th:block th:utext=\"${@componentTemplateService.render('info-dropdown', 'menu:INFO')}\"></th:block>");
java.nio.file.Files.writeString(java.nio.file.Paths.get(dir.getAbsolutePath(), snippet.getSlug() + ".html"), content);
}
return "Snippets dumped successfully to " + dir.getAbsolutePath();
} catch (Exception e) {
return "Error: " + e.getMessage();
}
}
@GetMapping("/page/fix-video-fallback")
@org.springframework.web.bind.annotation.ResponseBody
public String fixVideoFallback() {
try {
java.util.Optional<com.sisvietnamvn.web.domain.ComponentTemplate> opt = this.componentTemplateService.findBySlug("video-fallback");
if (opt.isPresent()) {
com.sisvietnamvn.web.domain.ComponentTemplate ct = opt.get();
String html = ct.getHtmlTemplate();
if (html != null && html.contains("src=\"{{imageUrl}}\"")) {
html = html.replace("src=\"{{imageUrl}}\"", "data-src=\"{{imageUrl}}\"");
ct.setHtmlTemplate(html);
this.componentTemplateService.save(ct);
return "Fixed video-fallback src attribute in database.";
}
return "video-fallback template did not contain src=\"{{imageUrl}}\" or was already fixed.";
}
return "video-fallback template not found in database.";
} catch (Exception e) {
return "Error: " + e.getMessage();
}
}
@GetMapping("/page/{slug}")
@@ -79,7 +124,11 @@ public class PageController {
@GetMapping("/")
public String getHome(Model model) {
return renderPage(pageService.findByPageType(com.sisvietnamvn.web.domain.PageType.HOME), model);
model.addAttribute("activeTheme", "umass");
model.addAttribute("componentTemplateService", componentTemplateService);
model.addAttribute("hookManager", hookManager);
model.addAttribute("videoFallbackHtml", componentTemplateService.render("video-fallback", null));
return "pages/home";
}
@@ -138,80 +138,9 @@
<div class="f--field f--image"></div>
<img src="/images/mainpage_slider/BANNER-LINNC-BAC-CUONG-05-scaled.jpg"
alt="Graduating students celebrate at McGuirk Stadium prior to 2025 Undergraduate Commencement">
<style>
.my-ambient-slider {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
}
.my-ambient-slider .swiper-slide img {
width: 100%;
height: 100%;
object-fit: cover;
}
/* Hide slider on mobile (<=767px) and show static image */
@media (max-width: 767px) {
.my-ambient-slider {
display: none !important;
}
}
/* Show slider on desktop (>=768px) and hide static image */
@media (min-width: 768px) {
.image-video-container>img {
display: none !important;
}
}
</style>
<!-- Slider Component Replacing Video -->
<div class="swiper my-ambient-slider">
<div class="swiper-wrapper">
<div class="swiper-slide">
<img src="/images/mainpage_slider/BANNER-LINNC-BAC-CUONG-05-scaled.jpg"
alt="Banner LINNC Bác Cường">
</div>
<div class="swiper-slide">
<img src="/images/mainpage_slider/BANNER-WEB-04-scaled.jpg" alt="Banner Web 04">
</div>
<div class="swiper-slide">
<img src="/images/mainpage_slider/W2-01-scaled.jpg" alt="W2 01 Banner">
</div>
</div>
</div>
<div class="f--ambient-video"
style="position: absolute; top:0; left:0; width:100%; height:100%;">
<video role="presentation" tabindex="-1" loop="" autoplay="" playsinline="" muted=""
style="width: 100%; height: 100%; object-fit: cover;">
<source
src="/images/YTDown_YouTube_Benh-vien-Da-Khoa-Quoc-Te-SIS-Can-Tho-Th_Media_pcz597Ou5U_001_1080p (online-video-cutter.com).mp4"
type="video/mp4">
</video>
</div>
<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>
<!-- Component Template Fallback for Video (Running Permanently) -->
<div id="hero-video-fallback">
<th:block th:utext="${@componentTemplateService.render('video-fallback', null)}"></th:block>
</div>
<!-- Black Gradient Overlay (Top Only) -->
@@ -0,0 +1,26 @@
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org" xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout"
layout:decorate="~{themes/__${activeTheme}__/layout-home(bodyClass='umass-platform-homepage path-frontpage page-node-type-homepage homepage transparent-header')}">
<head>
<title>Bệnh Viện Đa Khoa Quốc Tế S.I.S Cần Thơ</title>
</head>
<body>
<!-- Content Top Area -->
<div layout:fragment="content-top">
<th:block th:replace="~{themes/__${activeTheme}__/content-top}"></th:block>
</div>
<!-- Main Content Area -->
<div layout:fragment="content">
<th:block th:replace="~{themes/__${activeTheme}__/snippets/block_1_block-multiple-ctas}"></th:block>
<th:block th:replace="~{themes/__${activeTheme}__/snippets/block_3_button}"></th:block>
<th:block th:replace="~{themes/__${activeTheme}__/snippets/block_9_news_features}"></th:block>
<th:block th:replace="~{themes/__${activeTheme}__/snippets/block_11_charity}"></th:block>
<th:block th:replace="~{themes/__${activeTheme}__/snippets/tabbed-livestream-snippet}"></th:block>
<th:block th:replace="~{themes/__${activeTheme}__/snippets/block_10_education}"></th:block>
<th:block th:replace="~{themes/__${activeTheme}__/snippets/block_4_books}"></th:block>
</div>
</body>
</html>
@@ -1,73 +1,135 @@
<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&amp;itok=d27r8GaT 1920w">
<div class="f--ambient-video">
<video role="presentation" tabindex="-1" loop="" autoplay="" playsinline="" muted="">
<source src="http://localhost:8080/uploads/2026/07/9375f45b-027a-4fb4-bd18-66889309280d.mp4" type="video/mp4">
</video>
</div>
<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 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&amp;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="${videoFallbackHtml}"></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 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">
</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>
</li>
</ul>
</nav>
</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>
@@ -75,4 +137,5 @@
</div>
</div>
</div>
</div>
</div>
</div>
@@ -0,0 +1,65 @@
<!doctype html>
<html lang="en" xmlns:th="http://www.thymeleaf.org" xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout">
<head>
<meta charset="UTF-8" />
<title>UMass Amherst Theme</title>
<!-- UMass Amherst Assets -->
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<link href="https://fonts.googleapis.com/css2?family=Open+Sans:wght@400;600;700&display=swap" rel="stylesheet" />
<link rel="stylesheet" media="all" th:href="@{/theme-assets/umass/css/css_09S7WcUyhLeUXabknzECn_ua5zOangtv2BF4OXAW2fM.css}" />
<link rel="stylesheet" media="all" th:href="@{/theme-assets/umass/css/css_5USufIKxGNJyomvgpy2m9ITQlTN9qcrtJQsw_06dSbo.css}" />
<link rel="stylesheet" media="all" th:href="@{/theme-assets/umass/css/css_G5ztZKRblBn54t8h9F_EK5Y3CsZrMvA2BWPMI5jJoO4.css}" />
<!-- 🟢 1. SWIPER.JS CSS (Đã thêm) -->
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/swiper@11/swiper-bundle.min.css" />
<!-- Custom CSS -->
<link rel="stylesheet" th:href="@{/css/custom.css}" />
<!-- Theme Customizer CSS Output -->
<style th:utext="${themeCss}"></style>
<!-- wp_head hook -->
<th:block th:utext="${hookManager.doActionAndReturn('wp_head')}"></th:block>
</head>
<body
th:class="${(bodyClass != null ? bodyClass : '') + ((page != null and page.pageType != null and page.pageType.name() == 'HOME') ? ' umass-platform-homepage path-frontpage page-node-type-homepage homepage transparent-header' : '')}"
>
<div class="dialog-off-canvas-main-canvas" data-off-canvas-main-canvas="">
<!-- Include Header Fragment -->
<header th:replace="~{themes/__${activeTheme}__/header :: header}"></header>
<!-- Full-width top content area (e.g., Hero Banners) -->
<div layout:fragment="content-top"></div>
<main id="main-content">
<!--
HOMEPAGE FULL WIDTH LAYOUT
Removed l--content, region padding, and max-width constraints
-->
<div class="full-width-container" style="width: 100%; min-height: 400px; padding: 0; margin: 0;">
<div
class="full-width-content"
style="width: 100%;"
layout:fragment="content"
></div>
</div>
</main>
<!-- Include Footer Fragment -->
<footer th:replace="~{themes/__${activeTheme}__/footer :: footer}"></footer>
</div>
<!-- UMass Scripts -->
<script th:src="@{/theme-assets/umass/js/js_aQtUyeGxehNR84AlGzGB1VfMu1Wn3lqHxvL8rocj1EU.js}"></script>
<script th:src="@{/js/mobile-menu.js}"></script>
<script th:src="@{/js/ambient-video.js}"></script>
<script th:src="@{/js/main.js}"></script>
<!-- 🟢 2. SWIPER.JS SCRIPT (Đã thêm) -->
<script src="https://cdn.jsdelivr.net/npm/swiper@11/swiper-bundle.min.js"></script>
<!-- wp_footer hook -->
<th:block th:utext="${hookManager.doActionAndReturn('wp_footer')}"></th:block>
<!-- Page Scripts Fragment -->
<th:block layout:fragment="scripts"></th:block>
</body>
</html>
@@ -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">&lsaquo;</button>
<div class="education-slider-container">
<div class="education-slider-track">
<th:block th:utext="${componentTemplateService.render('news-grid', 'posts:tag=education,limit=5,collection=news_posts')}"></th:block>
</div>
</div>
<button class="edu-slider-btn next-btn" aria-label="Next">&rsaquo;</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">
<th:block th:utext="${componentTemplateService.render('cta-buttons', 'menu:CTA')}"></th:block>
</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 @@
<th:block th:utext="${componentTemplateService.render('tabbed-livestream', 'posts:tag=livestream,limit=4,collection=livestream_posts')}"></th:block>
@@ -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,71 @@
<body>
<div class="cc--component-container cc--card-grid dark">
<div class="c--component c--card-grid">
<div class="text-container">
<div data-component-id="umass_base:section-title" class="f--section-title">
<h2>Blaze Your Own Trail</h2>
</div>
<div data-component-id="umass_base:description" class="f--section-title f--description">
<p>Discover more than 100 undergraduate majors, minors, and certificates in fields ranging from engineering to public health to literature. You can even design your own major through our individual concentration program. Whatever your path, UMass gives you the freedom to explore and the tools to excel.</p>
</div>
</div>
<div class="f--field f--cards nested">
<div class="cc--component-container cc--card-grid-card ">
<div class="c--component c--card-grid-card">
<div class="f--field f--image">
<img data-src="https://www.umass.edu/sites/default/files/styles/16_9_320x180/public/2025-09/FY26_BeTheFuture-HERO_professor-with-students.jpg?h=854a7be2&amp;itok=sAJtETQj" class=" lazyloaded" alt="A professor walks with students in the rooftop garden of the Olver Design Building." src="/UMass%20Amherst%20_%20UMass%20Amherst_files/FY26_BeTheFuture-HERO_professor-with-students.jpg">
</div>
<div class="text-container">
<h3 class="ally-focus-within"> Find a Program </h3>
<div data-component-id="umass_base:description" class="f--description">
<p>With more than 100 majors, you have the freedom to explore your interests and build an academic path that reflects who you are and where you want to go.</p>
</div>
<div class="f--field f--button">
<a href="https://www.umass.edu/gateway/academics/explore-our-programs" class="button-text-link button-context-dark " aria-label="Read more About Find a Program" target="_self" data-component-id="umass_base:button">
<span class="button-text"> Read more </span>
</a>
</div>
</div>
</div>
</div>
<div class="cc--component-container cc--card-grid-card ">
<div class="c--component c--card-grid-card">
<div class="f--field f--image">
<img data-src="https://www.umass.edu/sites/default/files/styles/16_9_320x180/public/2025-11/UMass%20Amherst%20Drone%20Campus.jpeg?h=c673cd1c&amp;itok=SB-3t1IF" class=" lazyloaded" alt="UMass Amherst Drone Campus" src="/UMass%20Amherst%20_%20UMass%20Amherst_files/UMass Amherst Drone Campus.jpeg">
</div>
<div class="text-container">
<h3 class="ally-focus-within"> Design Your Own Major </h3>
<div data-component-id="umass_base:description" class="f--description">
<p>Through the Bachelors Degree with Individual Concentration (BDIC) Program, students can create a personalized major, blending courses across fields to explore passions beyond traditional academic boundaries.</p>
</div>
<div class="f--field f--button">
<a href="https://www.umass.edu/gateway/umass-stories/design-your-own-major" class="button-text-link button-context-dark " aria-label="Read more About Design Your Own Major" target="_self" data-component-id="umass_base:button">
<span class="button-text"> Read more </span>
</a>
</div>
</div>
</div>
</div>
<div class="cc--component-container cc--card-grid-card ">
<div class="c--component c--card-grid-card">
<div class="f--field f--image">
<img data-src="https://www.umass.edu/sites/default/files/styles/16_9_320x180/public/2024-01/FY23-Study-abroad-LANDING-HERO-London-SA_0.jpg?h=854a7be2&amp;itok=KyMO_bgM" class=" lazyloaded" alt="UMass Amherst Study Abroad London" src="/UMass%20Amherst%20_%20UMass%20Amherst_files/FY23-Study-abroad-LANDING-HERO-London-SA_0.jpg">
</div>
<div class="text-container">
<h3 class="ally-focus-within"> Study Abroad </h3>
<div data-component-id="umass_base:description" class="f--description">
<p>Global learning opportunities immerse students in new cultures, expanding their perspectives and preparing them to thrive in a connected world.</p>
</div>
<div class="f--field f--button">
<a href="https://www.umass.edu/gateway/umass-stories/study-abroad-umass" class="button-text-link button-context-dark " aria-label="Read more About Study Abroad" target="_self" data-component-id="umass_base:button">
<span class="button-text"> Read more </span>
</a>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</body>
<style>* { box-sizing: border-box; } body {margin: 0;}</style>
@@ -0,0 +1,34 @@
<body>
<div data-component-id="umass_base:block-multiple-ctas" data-background="solid" data-link-style="buttons" data-layout-variant="default">
<div class="container">
<div class="text-container">
<div data-component-id="umass_base:section-title" class="f--section-title">
<h2>APPLY TODAY</h2>
</div>
</div>
<div class="links-container">
<div class="f--field f--button">
<a href="https://www.umass.edu/admissions/first-year-students" class="button-primary button-context-light " aria-label="First Year Apply to UMass Undergraduate" target="_self" data-component-id="umass_base:button">
<span class="button-text"> First Year </span>
</a>
</div>
<div class="f--field f--button">
<a href="https://www.umass.edu/admissions/transfer-students" class="button-primary button-context-light " aria-label="Transfer Apply to UMass as as Transfer Student" target="_self" data-component-id="umass_base:button">
<span class="button-text"> Transfer </span>
</a>
</div>
<div class="f--field f--button">
<a href="https://www.umass.edu/admissions/undergraduate-admissions/apply/international-students" class="button-primary button-context-light " aria-label="International Apply to UMass Internationally" target="_self" data-component-id="umass_base:button">
<span class="button-text"> International </span>
</a>
</div>
<div class="f--field f--button">
<a href="https://www.umass.edu/graduate/apply" class="button-primary button-context-light " aria-label="Graduate School Apply to UMass Graduate School" target="_self" data-component-id="umass_base:button">
<span class="button-text"> Graduate School </span>
</a>
</div>
</div>
</div>
</div>
</body>
<style>* { box-sizing: border-box; } body {margin: 0;}</style>
@@ -0,0 +1,207 @@
<body>
<div data-component-id="umass_base:block-multiple-ctas" data-background="solid" data-color="gray" data-layout-variant="tabbed">
<div class="container">
<div class="text-container">
<div data-component-id="umass_base:section-title" class="f--section-title">
<h2>I'm Looking For...</h2>
</div>
</div>
<div class="links-container">
<div data-component-id="umass_base:tabbed-container" data-color="gray" data-once="tabbed-container">
<div class="tab-labels-container" role="tablist">
<div class="tab-labels-inner">
<a href="https://www.umass.edu/#tabbed-content-prospective-students" class="tab-label link-context-light" role="tab" aria-selected="true" aria-controls="tabbed-content-prospective-students">Prospective Students</a>
<a href="https://www.umass.edu/#tabbed-content-current-students" class="tab-label link-context-light" role="tab" aria-selected="false" aria-controls="tabbed-content-current-students">Current Students</a>
<a href="https://www.umass.edu/#tabbed-content-parents--families" class="tab-label link-context-light" role="tab" aria-selected="false" aria-controls="tabbed-content-parents--families">Parents &amp; Families</a>
<a href="https://www.umass.edu/#tabbed-content-faculty--staff" class="tab-label link-context-light" role="tab" aria-selected="false" aria-controls="tabbed-content-faculty--staff">Faculty &amp; Staff</a>
</div>
</div>
<div class="tab-content-container">
<div class="tab-content-panel is-active" id="tabbed-content-prospective-students" role="tabpanel" aria-live="polite">
<div class="tabbed-links-container">
<div class="f--field f--button">
<a href="https://www.umass.edu/admissions/undergraduate-admissions/visit" class="button-text-link button-context-light " aria-label="Visit Campus" target="_self" data-component-id="umass_base:button">
<span class="button-text"> Visit Campus </span>
</a>
</div>
<div class="f--field f--button">
<a href="https://www.umass.edu/admissions/undergraduate-admissions" class="button-text-link button-context-light " aria-label="Apply as a First-Year Student" target="_self" data-component-id="umass_base:button">
<span class="button-text"> Apply as a First-Year Student </span>
</a>
</div>
<div class="f--field f--button">
<a href="https://www.umass.edu/gateway/academics/explore-our-programs?field_level_of_study=36&amp;field_degree_type=All&amp;field_delivery=All&amp;field_area_of_interest=All&amp;field_school=All&amp;sort_by=title" class="button-text-link button-context-light " aria-label="Majors &amp; Minors" target="_self" data-component-id="umass_base:button">
<span class="button-text"> Majors &amp; Minors </span>
</a>
</div>
<div class="f--field f--button">
<a href="https://www.umass.edu/admissions/transfer-students" class="button-text-link button-context-light " aria-label="Apply as a Transfer Student" target="_self" data-component-id="umass_base:button">
<span class="button-text"> Apply as a Transfer Student </span>
</a>
</div>
<div class="f--field f--button">
<a href="https://www.umass.edu/graduate/apply" class="button-text-link button-context-light " aria-label="Apply as a Graduate Student" target="_self" data-component-id="umass_base:button">
<span class="button-text"> Apply as a Graduate Student </span>
</a>
</div>
<div class="f--field f--button">
<a href="https://www.umass.edu/admissions/important-dates-deadlines" class="button-text-link button-context-light " aria-label="Important Dates &amp; Deadlines" target="_self" data-component-id="umass_base:button">
<span class="button-text"> Important Dates &amp; Deadlines </span>
</a>
</div>
<div class="f--field f--button">
<a href="https://www.umass.edu/financialaid/undergraduate-costs" class="button-text-link button-context-light " aria-label="Tuition &amp; Costs" target="_self" data-component-id="umass_base:button">
<span class="button-text"> Tuition &amp; Costs </span>
</a>
</div>
<div class="f--field f--button">
<a href="https://www.umass.edu/financialaid/undergraduate" class="button-text-link button-context-light " aria-label="Financial Aid" target="_self" data-component-id="umass_base:button">
<span class="button-text"> Financial Aid </span>
</a>
</div>
</div>
</div>
<div class="tab-content-panel" id="tabbed-content-current-students" role="tabpanel" aria-live="polite">
<div class="tabbed-links-container">
<div class="f--field f--button">
<a href="https://www.spire.umass.edu/" class="button-text-link button-context-light " aria-label="SPIRE" target="_self" data-component-id="umass_base:button">
<span class="button-text"> SPIRE </span>
</a>
</div>
<div class="f--field f--button">
<a href="https://www.umass.edu/it/canvas" class="button-text-link button-context-light " aria-label="Canvas" target="_self" data-component-id="umass_base:button">
<span class="button-text"> Canvas </span>
</a>
</div>
<div class="f--field f--button">
<a href="https://www.umass.edu/registrar/academic-calendar" class="button-text-link button-context-light " aria-label="Academic Calendar" target="_self" data-component-id="umass_base:button">
<span class="button-text"> Academic Calendar </span>
</a>
</div>
<div class="f--field f--button">
<a href="https://www.umass.edu/financialaid/student-employment" class="button-text-link button-context-light " aria-label="Student Jobs" target="_self" data-component-id="umass_base:button">
<span class="button-text"> Student Jobs </span>
</a>
</div>
<div class="f--field f--button">
<a href="https://www.umass.edu/gateway/contact-us" class="button-text-link button-context-light " aria-label="Contact List" target="_self" data-component-id="umass_base:button">
<span class="button-text"> Contact List </span>
</a>
</div>
<div class="f--field f--button">
<a href="https://www.umass.edu/bursar/" class="button-text-link button-context-light " aria-label="Bursar&#39;s Office" target="_self" data-component-id="umass_base:button">
<span class="button-text"> Bursar's Office </span>
</a>
</div>
<div class="f--field f--button">
<a href="https://www.umass.edu/student-life/live-on-campus" class="button-text-link button-context-light " aria-label="Residential Life" target="_self" data-component-id="umass_base:button">
<span class="button-text"> Residential Life </span>
</a>
</div>
<div class="f--field f--button">
<a href="https://www.umass.edu/it/it-guide-students" class="button-text-link button-context-light " aria-label="Technology Support" target="_self" data-component-id="umass_base:button">
<span class="button-text"> Technology Support </span>
</a>
</div>
</div>
</div>
<div class="tab-content-panel" id="tabbed-content-parents--families" role="tabpanel" aria-live="polite">
<div class="tabbed-links-container">
<div class="f--field f--button">
<a href="https://www.umass.edu/registrar/academic-calendar" class="button-text-link button-context-light " aria-label="Academic Calendar" target="_self" data-component-id="umass_base:button">
<span class="button-text"> Academic Calendar </span>
</a>
</div>
<div class="f--field f--button">
<a href="https://www.umass.edu/admissions/visit/visitor-info" class="button-text-link button-context-light " aria-label="Campus Maps" target="_self" data-component-id="umass_base:button">
<span class="button-text"> Campus Maps </span>
</a>
</div>
<div class="f--field f--button">
<a href="https://events.umass.edu/" class="button-text-link button-context-light " aria-label="Campus Events" target="_self" data-component-id="umass_base:button">
<span class="button-text"> Campus Events </span>
</a>
</div>
<div class="f--field f--button">
<a href="https://www.umass.edu/new-student/family-ready-u" class="button-text-link button-context-light " aria-label="New Families" target="_self" data-component-id="umass_base:button">
<span class="button-text"> New Families </span>
</a>
</div>
<div class="f--field f--button">
<a href="https://www.umass.edu/new-student/family-programs" class="button-text-link button-context-light " aria-label="Family Programs" target="_self" data-component-id="umass_base:button">
<span class="button-text"> Family Programs </span>
</a>
</div>
<div class="f--field f--button">
<a href="https://www.umass.edu/gateway/contact-us" class="button-text-link button-context-light " aria-label="Contact List" target="_self" data-component-id="umass_base:button">
<span class="button-text"> Contact List </span>
</a>
</div>
<div class="f--field f--button">
<a href="https://www.umass.edu/bursar/" class="button-text-link button-context-light " aria-label="Bursar&#39;s Office" target="_self" data-component-id="umass_base:button">
<span class="button-text"> Bursar's Office </span>
</a>
</div>
<div class="f--field f--button">
<a href="https://www.umass.edu/financialaid/undergraduate" class="button-text-link button-context-light " aria-label="Financial Aid" target="_self" data-component-id="umass_base:button">
<span class="button-text"> Financial Aid </span>
</a>
</div>
</div>
</div>
<div class="tab-content-panel" id="tabbed-content-faculty--staff" role="tabpanel" aria-live="polite">
<div class="tabbed-links-container">
<div class="f--field f--button">
<a href="https://www.spire.umass.edu/" class="button-text-link button-context-light " aria-label="SPIRE" target="_self" data-component-id="umass_base:button">
<span class="button-text"> SPIRE </span>
</a>
</div>
<div class="f--field f--button">
<a href="https://www.umass.edu/it/canvas" class="button-text-link button-context-light " aria-label="Canvas" target="_self" data-component-id="umass_base:button">
<span class="button-text"> Canvas </span>
</a>
</div>
<div class="f--field f--button">
<a href="https://www.umass.edu/peoplefinder/" class="button-text-link button-context-light " aria-label="People Finder" target="_self" data-component-id="umass_base:button">
<span class="button-text"> People Finder </span>
</a>
</div>
<div class="f--field f--button">
<a href="https://www.umass.edu/gateway/contact-us" class="button-text-link button-context-light " aria-label="Contact List" target="_self" data-component-id="umass_base:button">
<span class="button-text"> Contact List </span>
</a>
</div>
<div class="f--field f--button">
<a href="https://hr-direct.hcm.umasscs.net/psc/hcm/EMPLOYEE/HRMS/c/NUI_FRAMEWORK.PT_LANDINGPAGE.GBL" class="button-text-link button-context-light ext" aria-label="HR Direct" target="_self" data-component-id="umass_base:button" data-extlink="">
<span class="button-text"> HR Direct </span>
<svg focusable="false" width="1em" height="1em" class="ext" data-extlink-placement="append" aria-label="(link is external)" viewBox="0 0 80 40" role="img" aria-hidden="false">
<title>(link is external)</title>
<path d="M48 26c-1.1 0-2 0.9-2 2v26H10V18h26c1.1 0 2-0.9 2-2s-0.9-2-2-2H8c-1.1 0-2 0.9-2 2v40c0 1.1 0.9 2 2 2h40c1.1 0 2-0.9 2-2V28C50 26.9 49.1 26 48 26z"></path>
<path d="M56 6H44c-1.1 0-2 0.9-2 2s0.9 2 2 2h7.2L30.6 30.6c-0.8 0.8-0.8 2 0 2.8C31 33.8 31.5 34 32 34s1-0.2 1.4-0.6L54 12.8V20c0 1.1 0.9 2 2 2s2-0.9 2-2V8C58 6.9 57.1 6 56 6z"></path>
</svg>
</a>
</div>
<div class="f--field f--button">
<a href="https://www.umass.edu/hr/" class="button-text-link button-context-light " aria-label="Human Resources" target="_self" data-component-id="umass_base:button">
<span class="button-text"> Human Resources </span>
</a>
</div>
<div class="f--field f--button">
<a href="https://www.umass.edu/hr/careers" class="button-text-link button-context-light " aria-label="Career Opportunities" target="_self" data-component-id="umass_base:button">
<span class="button-text"> Career Opportunities </span>
</a>
</div>
<div class="f--field f--button">
<a href="https://www.umass.edu/it/email" class="button-text-link button-context-light " aria-label="Email Support" target="_self" data-component-id="umass_base:button">
<span class="button-text"> Email Support </span>
</a>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</body>
<style>* { box-sizing: border-box; } body {margin: 0;}</style>
@@ -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">&lsaquo;</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) -->
<th:block th:utext="${componentTemplateService.render('news-grid', 'posts:tag=news,limit=6,collection=news_posts')}"></th:block>
</div>
</div>
<button class="news-slider-btn next-btn" aria-label="Next">&rsaquo;</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 -->
<th:block th:utext="${componentTemplateService.render('events-list', 'posts:tag=event,limit=4,collection=event_posts')}"></th:block>
</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,970 @@
<body>
<div class="content-main">
<div class="lc--layout-container lc--full">
<div class="l--layout l--full">
<div class="lr--layout-region lr--main">
<div data-component-id="umass_base:block-multiple-ctas" data-background="solid" data-layout-variant="default">
<div class="container">
<div class="text-container">
<div data-component-id="umass_base:section-title" class="f--section-title">
<h2>Step Into <span class="highlight">Your Future</span>
</h2>
</div>
</div>
<div class="links-container">
<div class="f--field f--button">
<a href="https://www.umass.edu/admissions/apply" class="button-text-link button-context-light " aria-label="Apply" target="_self" data-component-id="umass_base:button">
<span class="button-text"> Apply </span>
</a>
</div>
<div class="f--field f--button">
<a href="https://www.umass.edu/gateway/academics/explore-our-programs" class="button-text-link button-context-light " aria-label="Majors &amp; Minors" target="_self" data-component-id="umass_base:button">
<span class="button-text"> Majors &amp; Minors </span>
</a>
</div>
<div class="f--field f--button">
<a href="https://www.umass.edu/admissions/undergraduate-admissions/costs-aid" class="button-text-link button-context-light " aria-label="Tuition &amp; Costs" target="_self" data-component-id="umass_base:button">
<span class="button-text"> Tuition &amp; Costs </span>
</a>
</div>
<div class="f--field f--button">
<a href="https://www.umass.edu/admissions/visit" class="button-text-link button-context-light " aria-label="Take a Tour" target="_self" data-component-id="umass_base:button">
<span class="button-text"> Take a Tour </span>
</a>
</div>
</div>
</div>
</div>
<div class="cc--component-container cc--tabbed-media-content ">
<div class="c--component c--tabbed-media-content">
<div class="tabbed-media-content-text-col">
<div data-component-id="umass_base:section-title" class="f--section-title">
<h2>What's Life Like at UMass?</h2>
</div>
<div data-component-id="umass_base:tabbed-container" data-once="tabbed-container">
<div class="tab-labels-container" role="tablist">
<div class="tab-labels-inner">
<a href="https://www.umass.edu/#tabbed-content-campus-life" class="tab-label link-context-dark" role="tab" aria-selected="true" aria-controls="tabbed-content-campus-life">Campus Life</a>
<a href="https://www.umass.edu/#tabbed-content-campus-housing" class="tab-label link-context-dark" role="tab" aria-selected="false" aria-controls="tabbed-content-campus-housing">Campus Housing</a>
<a href="https://www.umass.edu/#tabbed-content-dining" class="tab-label link-context-dark" role="tab" aria-selected="false" aria-controls="tabbed-content-dining">Dining</a>
<a href="https://www.umass.edu/#tabbed-content-around-amherst" class="tab-label link-context-dark" role="tab" aria-selected="false" aria-controls="tabbed-content-around-amherst">Around Amherst</a>
</div>
</div>
<div class="tab-content-container">
<div class="tab-content-panel is-active" id="tabbed-content-campus-life" role="tabpanel" aria-live="polite">
<div class="f--field f--cta-title">
<h3> Make UMass Your Own </h3>
</div>
<div data-component-id="umass_base:description" class="f--description">
<p>Explore big ideas, join vibrant communities, and shape a college experience thats uniquely yours.</p>
</div>
<div class="cta-container">
<div class="f--field f--button">
<a href="https://www.umass.edu/gateway/campus-life/student-activities" class="button-primary button-context-light " aria-label="Learn About Student Activities" data-component-id="umass_base:button">
<span class="button-text"> Learn About Student Activities </span>
</a>
</div>
</div>
</div>
<div class="tab-content-panel" id="tabbed-content-campus-housing" role="tabpanel" aria-live="polite">
<div class="f--field f--cta-title">
<h3> Your Campus Home </h3>
</div>
<div data-component-id="umass_base:description" class="f--description">
<p>Choose from vibrant residential communities where students live, study, and build lasting friendships steps from the classroom.</p>
</div>
<div class="cta-container">
<div class="f--field f--button">
<a href="https://www.umass.edu/gateway/campus-life/living-and-dining" class="button-primary button-context-light " aria-label="Learn About Living at UMass" data-component-id="umass_base:button">
<span class="button-text"> Learn About Living at UMass </span>
</a>
</div>
</div>
</div>
<div class="tab-content-panel" id="tabbed-content-dining" role="tabpanel" aria-live="polite">
<div class="f--field f--cta-title">
<h3> Food Worth Talking About </h3>
</div>
<div data-component-id="umass_base:description" class="f--description">
<p>Discover why UMass dining is ranked #1 nationally—recognized for quality, variety, and sustainability.</p>
</div>
<div class="cta-container">
<div class="f--field f--button">
<a href="https://www.umassdining.com/" class="button-primary button-context-light ext" aria-label="Learn Why UMass is #1 in Dining" data-component-id="umass_base:button" data-extlink="">
<span class="button-text"> Learn Why UMass is #1 in Dining </span>
<svg focusable="false" width="1em" height="1em" class="ext" data-extlink-placement="append" aria-label="(link is external)" viewBox="0 0 80 40" role="img" aria-hidden="false">
<title>(link is external)</title>
<path d="M48 26c-1.1 0-2 0.9-2 2v26H10V18h26c1.1 0 2-0.9 2-2s-0.9-2-2-2H8c-1.1 0-2 0.9-2 2v40c0 1.1 0.9 2 2 2h40c1.1 0 2-0.9 2-2V28C50 26.9 49.1 26 48 26z"></path>
<path d="M56 6H44c-1.1 0-2 0.9-2 2s0.9 2 2 2h7.2L30.6 30.6c-0.8 0.8-0.8 2 0 2.8C31 33.8 31.5 34 32 34s1-0.2 1.4-0.6L54 12.8V20c0 1.1 0.9 2 2 2s2-0.9 2-2V8C58 6.9 57.1 6 56 6z"></path>
</svg>
</a>
</div>
</div>
</div>
<div class="tab-content-panel" id="tabbed-content-around-amherst" role="tabpanel" aria-live="polite">
<div class="f--field f--cta-title">
<h3> Amherst, Uncommon </h3>
</div>
<div data-component-id="umass_base:description" class="f--description">
<p>A vibrant creative culture, great food, and the natural beauty of the Pioneer Valley come together to shape this towns distinctive, welcoming spirit.</p>
</div>
<div class="cta-container">
<div class="f--field f--button">
<a href="https://www.umass.edu/gateway/student-life/life-amherst" class="button-primary button-context-light " aria-label="Learn More About Amherst" data-component-id="umass_base:button">
<span class="button-text"> Learn More About Amherst </span>
</a>
</div>
</div>
</div>
</div>
</div>
</div>
<div class="tabbed-media-content-media-col">
<div class="tabbed-media-content-media-item is-active with-video" data-tab-id="tabbed-content-campus-life">
<div class="f--field f--image">
<img data-src="https://www.umass.edu/sites/default/files/styles/9_16_720x1280/public/2026-03/medium_jpg-2026_Vertical_Assets_5179_John_Solem_.jpg?h=7c5befa5&amp;itok=DZUe-3fS" class=" ls-is-cached lazyloaded" alt="A UMass student plays ping pong." src="/UMass%20Amherst%20_%20UMass%20Amherst_files/medium_jpg-2026_Vertical_Assets_5179_John_Solem_.jpg">
</div>
<div class="f--field f--button">
<a href="https://www.umass.edu/#" class="button-play button-context-light " aria-label="Play video" data-component-id="umass_base:button">
<span class="button-icon button-icon-play">
<svg width="18" height="27" viewBox="0 0 18 27" fill="currentColor" xmlns="http://www.w3.org/2000/svg">
<path d="M18 13.5L0 0V27L18 13.5Z"></path>
</svg>
</span>
<span class="button-text visually-hidden"> Play </span>
</a>
</div>
<div data-component-id="umass_base:video-embed" class="f--field f--video-embed">
<iframe title="Video Content" id="video-132086-1" width="900" height="1600" src="https://www.youtube.com/embed/q0ZxZVbnMqs" frameborder="0" allow="accelerometer; autoplay; encrypted-media; gyroscope; picture-in-picture" allowfullscreen=""></iframe>
</div>
</div>
<div class="tabbed-media-content-media-item with-video" data-tab-id="tabbed-content-campus-housing">
<div class="f--field f--image">
<img data-src="https://www.umass.edu/sites/default/files/styles/9_16_720x1280/public/2026-03/FY26_Vertical-Campus-Housing.jpg?h=75081741&amp;itok=6kDcYqy3" class="lazyload" alt="A UMass student sits on her bed in a dorm room.">
</div>
<div class="f--field f--button">
<a href="https://www.umass.edu/#" class="button-play button-context-light " aria-label="Play video" data-component-id="umass_base:button">
<span class="button-icon button-icon-play">
<svg width="18" height="27" viewBox="0 0 18 27" fill="currentColor" xmlns="http://www.w3.org/2000/svg">
<path d="M18 13.5L0 0V27L18 13.5Z"></path>
</svg>
</span>
<span class="button-text visually-hidden"> Play </span>
</a>
</div>
<div data-component-id="umass_base:video-embed" class="f--field f--video-embed">
<iframe title="Video Content" id="video-132086-2" width="900" height="1600" src="https://www.youtube.com/embed/7D_TnBztQhU" frameborder="0" allow="accelerometer; autoplay; encrypted-media; gyroscope; picture-in-picture" allowfullscreen=""></iframe>
</div>
</div>
<div class="tabbed-media-content-media-item with-video" data-tab-id="tabbed-content-dining">
<div class="f--field f--image">
<img data-src="https://www.umass.edu/sites/default/files/styles/9_16_720x1280/public/2026-03/FY26_Vertical-Dining2.jpg?h=75081741&amp;itok=_34BDcqA" class="lazyload" alt="A student gets food at a UMass Amherst dining hall.">
</div>
<div class="f--field f--button">
<a href="https://www.umass.edu/#" class="button-play button-context-light " aria-label="Play video" data-component-id="umass_base:button">
<span class="button-icon button-icon-play">
<svg width="18" height="27" viewBox="0 0 18 27" fill="currentColor" xmlns="http://www.w3.org/2000/svg">
<path d="M18 13.5L0 0V27L18 13.5Z"></path>
</svg>
</span>
<span class="button-text visually-hidden"> Play </span>
</a>
</div>
<div data-component-id="umass_base:video-embed" class="f--field f--video-embed">
<iframe title="Video Content" id="video-132086-3" width="900" height="1600" src="https://www.youtube.com/embed/YRzZ9aRZ69w" frameborder="0" allow="accelerometer; autoplay; encrypted-media; gyroscope; picture-in-picture" allowfullscreen=""></iframe>
</div>
</div>
<div class="tabbed-media-content-media-item with-video" data-tab-id="tabbed-content-around-amherst">
<div class="f--field f--image">
<img data-src="https://www.umass.edu/sites/default/files/styles/9_16_720x1280/public/2026-03/FY26_Vertical-Downtown-Amherst.jpg?h=75081741&amp;itok=irWjha4q" class="lazyload" alt="A UMass student holds a hote bag that reads &quot;I Love Amherst.&quot;">
</div>
<div class="f--field f--button">
<a href="https://www.umass.edu/#" class="button-play button-context-light " aria-label="Play video" data-component-id="umass_base:button">
<span class="button-icon button-icon-play">
<svg width="18" height="27" viewBox="0 0 18 27" fill="currentColor" xmlns="http://www.w3.org/2000/svg">
<path d="M18 13.5L0 0V27L18 13.5Z"></path>
</svg>
</span>
<span class="button-text visually-hidden"> Play </span>
</a>
</div>
<div data-component-id="umass_base:video-embed" class="f--field f--video-embed">
<iframe title="Video Content" id="video-132086-4" width="900" height="1600" src="https://www.youtube.com/embed/agqIJlJpbAY" frameborder="0" allow="accelerometer; autoplay; encrypted-media; gyroscope; picture-in-picture" allowfullscreen=""></iframe>
</div>
</div>
</div>
</div>
</div>
<div class="cc--component-container cc--stats-block ">
<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 class="f--field f--stat-number">#1</div>
<div class="f--field f--description">
<p>Public Research University in New England, <br>Non-Medical School R&amp;D Expenditures </p>
</div>
</div>
</div>
<div class="cc--component-container cc--stat">
<div class="c--component c--stat">
<div class="f--field f--stat-number">251</div>
<div class="f--field f--description">
<p>Total Degree Programs</p>
</div>
</div>
</div>
<div class="cc--component-container cc--stat">
<div class="c--component c--stat">
<div class="f--field f--stat-number">Top 50</div>
<div class="f--field f--description">
<p>Best Value Colleges (Public), <em>The Princeton Review</em>
</p>
</div>
</div>
</div>
</div>
<div class="f--field f--button">
<a href="https://www.umass.edu/gateway/why-umass/about-umass-amherst/umass-amherst-numbers" class="button-primary button-context-light " aria-label="UMass Amherst By The Numbers" data-component-id="umass_base:button">
<span class="button-text"> UMass Amherst By The Numbers </span>
</a>
</div>
</div>
</div>
<div class="paragraph paragraph--type--quad-card-grid paragraph--view-mode--default paragraph--quad-card-grid" data-component-id="umass_base:image-link-grid">
<div class="qcg">
<div class="qcg__left">
<h2 class="qcg__title"> Excellence in Action </h2>
<div class="qcg__description">
<div>
<p>UMass Amherst advances academic excellence through research, teaching, and engagement across campus. Students and faculty drive discovery through programs, scholarship, and events that extend beyond the classroom.</p>
</div>
</div>
<div class="qcg__link">
<a href="https://www.umass.edu/gateway/why-umass/discover-ideas" class="ext" target="_self" aria-label="Discover Ideas Discover Ideas" rel="noopener noreferrer"> Discover Ideas </a>
</div>
</div>
<div class="qcg__right">
<div class="qcg__grid">
<div class="qcg__card">
<div class="paragraph paragraph--type--quad-card-grid-item paragraph--view-mode--default paragraph--quad-card-grid-item qcg-item" data-component-id="umass_base:image-link-grid-item">
<div class="qcg-item__image">
<div>
<article>
<div>
<img loading="lazy" srcset="https://www.umass.edu/sites/default/files/styles/4_3_400x300/public/2025-12/FY26UMass_HackUMass_LANDING.jpg?h=854a7be2&amp;itok=ysOMEN8V 400w, https://www.umass.edu/sites/default/files/styles/4_3_800x600/public/2025-12/FY26UMass_HackUMass_LANDING.jpg?h=854a7be2&amp;itok=jtWz1GCX 800w, https://www.umass.edu/sites/default/files/styles/4_3_1600x1200/public/2025-12/FY26UMass_HackUMass_LANDING.jpg?h=854a7be2&amp;itok=xAxf5s8X 1600w, https://www.umass.edu/sites/default/files/styles/4_3_1920x1440/public/2025-12/FY26UMass_HackUMass_LANDING.jpg?h=854a7be2&amp;itok=3yPPf8f1 1920w" sizes="100vw" width="400" height="300" src="/UMass%20Amherst%20_%20UMass%20Amherst_files/FY26UMass_HackUMass_LANDING.jpg" alt="A group of five students lean over laptops in a classroom">
</div>
</article>
</div>
</div>
<div class="qcg-item__link">
<a href="https://www.umass.edu/gateway/umass-stories/hackumass" class="qcg-item__cta" target="_self" aria-label="HackUMass: Code, Collaborations &amp; Big Ideas HackUMass: Code, Collaborations &amp; Big Ideas"> HackUMass: Code, Collaborations &amp; Big Ideas </a>
</div>
</div>
</div>
<div class="qcg__card">
<div class="paragraph paragraph--type--quad-card-grid-item paragraph--view-mode--default paragraph--quad-card-grid-item qcg-item" data-component-id="umass_base:image-link-grid-item">
<div class="qcg-item__image">
<div>
<article>
<div>
<img loading="lazy" srcset="https://www.umass.edu/sites/default/files/styles/4_3_400x300/public/2025-06/UPC2025__HERO_2000x1125.jpg?h=0f182455&amp;itok=4PUBT11w 400w, https://www.umass.edu/sites/default/files/styles/4_3_800x600/public/2025-06/UPC2025__HERO_2000x1125.jpg?h=0f182455&amp;itok=r72eJsZX 800w, https://www.umass.edu/sites/default/files/styles/4_3_1600x1200/public/2025-06/UPC2025__HERO_2000x1125.jpg?h=0f182455&amp;itok=HXie2chE 1600w, https://www.umass.edu/sites/default/files/styles/4_3_1920x1440/public/2025-06/UPC2025__HERO_2000x1125.jpg?h=0f182455&amp;itok=ufOsI9X8 1920w" sizes="100vw" width="400" height="300" src="/UMass%20Amherst%20_%20UMass%20Amherst_files/UPC2025__HERO_2000x1125.jpg" alt="Tinashe performs at the Spring Concert.">
</div>
</article>
</div>
</div>
<div class="qcg-item__link">
<a href="https://www.umass.edu/gateway/umass-stories/inside-upc" class="qcg-item__cta" target="_self" aria-label="Inside UPC: Student-Led Events With Lasting Impact Inside UPC: Student-Led Events With Lasting Impact"> Inside UPC: Student-Led Events With Lasting Impact </a>
</div>
</div>
</div>
<div class="qcg__card">
<div class="paragraph paragraph--type--quad-card-grid-item paragraph--view-mode--default paragraph--quad-card-grid-item qcg-item" data-component-id="umass_base:image-link-grid-item">
<div class="qcg-item__image">
<div>
<article>
<div>
<img loading="lazy" srcset="https://www.umass.edu/sites/default/files/styles/4_3_400x300/public/2025-09/FY26_BeTheFuture_WeAreRev_photo4.jpg?h=854a7be2&amp;itok=jVpB7bGa 400w, https://www.umass.edu/sites/default/files/styles/4_3_800x600/public/2025-09/FY26_BeTheFuture_WeAreRev_photo4.jpg?h=854a7be2&amp;itok=CcG3pX7V 800w, https://www.umass.edu/sites/default/files/styles/4_3_1600x1200/public/2025-09/FY26_BeTheFuture_WeAreRev_photo4.jpg?h=854a7be2&amp;itok=mDWs6wTt 1600w, https://www.umass.edu/sites/default/files/styles/4_3_1920x1440/public/2025-09/FY26_BeTheFuture_WeAreRev_photo4.jpg?h=854a7be2&amp;itok=cgBcz7LE 1920w" sizes="100vw" width="400" height="300" src="/UMass%20Amherst%20_%20UMass%20Amherst_files/FY26_BeTheFuture_WeAreRev_photo4.jpg" alt="Two students work with building tools.">
</div>
</article>
</div>
</div>
<div class="qcg-item__link">
<a href="https://www.umass.edu/gateway/umass-stories/changemakers-making" class="qcg-item__cta" target="_self" aria-label="Changemakers in the Making: Be the Future You Want to See Changemakers in the Making: Students Aren&#39;t Just Waiting for the Future, They&#39;re Making It"> Changemakers in the Making: Be the Future You Want to See </a>
</div>
</div>
</div>
<div class="qcg__card">
<div class="paragraph paragraph--type--quad-card-grid-item paragraph--view-mode--default paragraph--quad-card-grid-item qcg-item" data-component-id="umass_base:image-link-grid-item">
<div class="qcg-item__image">
<div>
<article>
<div>
<img loading="lazy" srcset="https://www.umass.edu/sites/default/files/styles/4_3_400x300/public/2025-12/2025_Vy_Do_7780_John_Solem_2000x1125.jpg?h=854a7be2&amp;itok=Idf4wkAD 400w, https://www.umass.edu/sites/default/files/styles/4_3_800x600/public/2025-12/2025_Vy_Do_7780_John_Solem_2000x1125.jpg?h=854a7be2&amp;itok=WUqiETKc 800w, https://www.umass.edu/sites/default/files/styles/4_3_1600x1200/public/2025-12/2025_Vy_Do_7780_John_Solem_2000x1125.jpg?h=854a7be2&amp;itok=p7De2fBX 1600w, https://www.umass.edu/sites/default/files/styles/4_3_1920x1440/public/2025-12/2025_Vy_Do_7780_John_Solem_2000x1125.jpg?h=854a7be2&amp;itok=AEX7-hAe 1920w" sizes="100vw" width="400" height="300" src="/UMass%20Amherst%20_%20UMass%20Amherst_files/2025_Vy_Do_7780_John_Solem_2000x1125.jpg" alt="Vy Do in UMas Amherst biomedical engineering lab">
</div>
</article>
</div>
</div>
<div class="qcg-item__link">
<a href="https://www.umass.edu/gateway/research/stories/rising-researchers/biomedical-engineering-nanomedicine-drug-delivery" class="qcg-item__cta" target="_self" aria-label="Biomedical Engineering Research to Advance Drug Delivery Biomedical Engineering Research to Advance Drug Delivery: Vy Do 26 conducts research to develop nanocarriers for therapeutic genetic materials to treat traumatic brain injuries and other neurological conditions."> Biomedical Engineering Research to Advance Drug Delivery </a>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
<div class="cc--component-container cc--card-grid dark">
<div class="c--component c--card-grid">
<div class="text-container">
<div data-component-id="umass_base:section-title" class="f--section-title">
<h2>Blaze Your Own Trail</h2>
</div>
<div data-component-id="umass_base:description" class="f--section-title f--description">
<p>Discover more than 100 undergraduate majors, minors, and certificates in fields ranging from engineering to public health to literature. You can even design your own major through our individual concentration program. Whatever your path, UMass gives you the freedom to explore and the tools to excel.</p>
</div>
</div>
<div class="f--field f--cards nested">
<div class="cc--component-container cc--card-grid-card ">
<div class="c--component c--card-grid-card">
<div class="f--field f--image">
<img data-src="https://www.umass.edu/sites/default/files/styles/16_9_320x180/public/2025-09/FY26_BeTheFuture-HERO_professor-with-students.jpg?h=854a7be2&amp;itok=sAJtETQj" class=" lazyloaded" alt="A professor walks with students in the rooftop garden of the Olver Design Building." src="/UMass%20Amherst%20_%20UMass%20Amherst_files/FY26_BeTheFuture-HERO_professor-with-students.jpg">
</div>
<div class="text-container">
<h3 class="ally-focus-within"> Find a Program </h3>
<div data-component-id="umass_base:description" class="f--description">
<p>With more than 100 majors, you have the freedom to explore your interests and build an academic path that reflects who you are and where you want to go.</p>
</div>
<div class="f--field f--button">
<a href="https://www.umass.edu/gateway/academics/explore-our-programs" class="button-text-link button-context-dark " aria-label="Read more About Find a Program" target="_self" data-component-id="umass_base:button">
<span class="button-text"> Read more </span>
</a>
</div>
</div>
</div>
</div>
<div class="cc--component-container cc--card-grid-card ">
<div class="c--component c--card-grid-card">
<div class="f--field f--image">
<img data-src="https://www.umass.edu/sites/default/files/styles/16_9_320x180/public/2025-11/UMass%20Amherst%20Drone%20Campus.jpeg?h=c673cd1c&amp;itok=SB-3t1IF" class=" lazyloaded" alt="UMass Amherst Drone Campus" src="/UMass%20Amherst%20_%20UMass%20Amherst_files/UMass Amherst Drone Campus.jpeg">
</div>
<div class="text-container">
<h3 class="ally-focus-within"> Design Your Own Major </h3>
<div data-component-id="umass_base:description" class="f--description">
<p>Through the Bachelors Degree with Individual Concentration (BDIC) Program, students can create a personalized major, blending courses across fields to explore passions beyond traditional academic boundaries.</p>
</div>
<div class="f--field f--button">
<a href="https://www.umass.edu/gateway/umass-stories/design-your-own-major" class="button-text-link button-context-dark " aria-label="Read more About Design Your Own Major" target="_self" data-component-id="umass_base:button">
<span class="button-text"> Read more </span>
</a>
</div>
</div>
</div>
</div>
<div class="cc--component-container cc--card-grid-card ">
<div class="c--component c--card-grid-card">
<div class="f--field f--image">
<img data-src="https://www.umass.edu/sites/default/files/styles/16_9_320x180/public/2024-01/FY23-Study-abroad-LANDING-HERO-London-SA_0.jpg?h=854a7be2&amp;itok=KyMO_bgM" class=" lazyloaded" alt="UMass Amherst Study Abroad London" src="/UMass%20Amherst%20_%20UMass%20Amherst_files/FY23-Study-abroad-LANDING-HERO-London-SA_0.jpg">
</div>
<div class="text-container">
<h3 class="ally-focus-within"> Study Abroad </h3>
<div data-component-id="umass_base:description" class="f--description">
<p>Global learning opportunities immerse students in new cultures, expanding their perspectives and preparing them to thrive in a connected world.</p>
</div>
<div class="f--field f--button">
<a href="https://www.umass.edu/gateway/umass-stories/study-abroad-umass" class="button-text-link button-context-dark " aria-label="Read more About Study Abroad" target="_self" data-component-id="umass_base:button">
<span class="button-text"> Read more </span>
</a>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
<div data-component-id="umass_base:block-multiple-ctas" data-background="solid" data-link-style="buttons" data-layout-variant="default">
<div class="container">
<div class="text-container">
<div data-component-id="umass_base:section-title" class="f--section-title">
<h2>APPLY TODAY</h2>
</div>
</div>
<div class="links-container">
<div class="f--field f--button">
<a href="https://www.umass.edu/admissions/first-year-students" class="button-primary button-context-light " aria-label="First Year Apply to UMass Undergraduate" target="_self" data-component-id="umass_base:button">
<span class="button-text"> First Year </span>
</a>
</div>
<div class="f--field f--button">
<a href="https://www.umass.edu/admissions/transfer-students" class="button-primary button-context-light " aria-label="Transfer Apply to UMass as as Transfer Student" target="_self" data-component-id="umass_base:button">
<span class="button-text"> Transfer </span>
</a>
</div>
<div class="f--field f--button">
<a href="https://www.umass.edu/admissions/undergraduate-admissions/apply/international-students" class="button-primary button-context-light " aria-label="International Apply to UMass Internationally" target="_self" data-component-id="umass_base:button">
<span class="button-text"> International </span>
</a>
</div>
<div class="f--field f--button">
<a href="https://www.umass.edu/graduate/apply" class="button-primary button-context-light " aria-label="Graduate School Apply to UMass Graduate School" target="_self" data-component-id="umass_base:button">
<span class="button-text"> Graduate School </span>
</a>
</div>
</div>
</div>
</div>
<div data-component-id="umass_base:block-multiple-ctas" data-background="solid" data-color="gray" data-layout-variant="tabbed">
<div class="container">
<div class="text-container">
<div data-component-id="umass_base:section-title" class="f--section-title">
<h2>I'm Looking For...</h2>
</div>
</div>
<div class="links-container">
<div data-component-id="umass_base:tabbed-container" data-color="gray" data-once="tabbed-container">
<div class="tab-labels-container" role="tablist">
<div class="tab-labels-inner">
<a href="https://www.umass.edu/#tabbed-content-prospective-students" class="tab-label link-context-light" role="tab" aria-selected="true" aria-controls="tabbed-content-prospective-students">Prospective Students</a>
<a href="https://www.umass.edu/#tabbed-content-current-students" class="tab-label link-context-light" role="tab" aria-selected="false" aria-controls="tabbed-content-current-students">Current Students</a>
<a href="https://www.umass.edu/#tabbed-content-parents--families" class="tab-label link-context-light" role="tab" aria-selected="false" aria-controls="tabbed-content-parents--families">Parents &amp; Families</a>
<a href="https://www.umass.edu/#tabbed-content-faculty--staff" class="tab-label link-context-light" role="tab" aria-selected="false" aria-controls="tabbed-content-faculty--staff">Faculty &amp; Staff</a>
</div>
</div>
<div class="tab-content-container">
<div class="tab-content-panel is-active" id="tabbed-content-prospective-students" role="tabpanel" aria-live="polite">
<div class="tabbed-links-container">
<div class="f--field f--button">
<a href="https://www.umass.edu/admissions/undergraduate-admissions/visit" class="button-text-link button-context-light " aria-label="Visit Campus" target="_self" data-component-id="umass_base:button">
<span class="button-text"> Visit Campus </span>
</a>
</div>
<div class="f--field f--button">
<a href="https://www.umass.edu/admissions/undergraduate-admissions" class="button-text-link button-context-light " aria-label="Apply as a First-Year Student" target="_self" data-component-id="umass_base:button">
<span class="button-text"> Apply as a First-Year Student </span>
</a>
</div>
<div class="f--field f--button">
<a href="https://www.umass.edu/gateway/academics/explore-our-programs?field_level_of_study=36&amp;field_degree_type=All&amp;field_delivery=All&amp;field_area_of_interest=All&amp;field_school=All&amp;sort_by=title" class="button-text-link button-context-light " aria-label="Majors &amp; Minors" target="_self" data-component-id="umass_base:button">
<span class="button-text"> Majors &amp; Minors </span>
</a>
</div>
<div class="f--field f--button">
<a href="https://www.umass.edu/admissions/transfer-students" class="button-text-link button-context-light " aria-label="Apply as a Transfer Student" target="_self" data-component-id="umass_base:button">
<span class="button-text"> Apply as a Transfer Student </span>
</a>
</div>
<div class="f--field f--button">
<a href="https://www.umass.edu/graduate/apply" class="button-text-link button-context-light " aria-label="Apply as a Graduate Student" target="_self" data-component-id="umass_base:button">
<span class="button-text"> Apply as a Graduate Student </span>
</a>
</div>
<div class="f--field f--button">
<a href="https://www.umass.edu/admissions/important-dates-deadlines" class="button-text-link button-context-light " aria-label="Important Dates &amp; Deadlines" target="_self" data-component-id="umass_base:button">
<span class="button-text"> Important Dates &amp; Deadlines </span>
</a>
</div>
<div class="f--field f--button">
<a href="https://www.umass.edu/financialaid/undergraduate-costs" class="button-text-link button-context-light " aria-label="Tuition &amp; Costs" target="_self" data-component-id="umass_base:button">
<span class="button-text"> Tuition &amp; Costs </span>
</a>
</div>
<div class="f--field f--button">
<a href="https://www.umass.edu/financialaid/undergraduate" class="button-text-link button-context-light " aria-label="Financial Aid" target="_self" data-component-id="umass_base:button">
<span class="button-text"> Financial Aid </span>
</a>
</div>
</div>
</div>
<div class="tab-content-panel" id="tabbed-content-current-students" role="tabpanel" aria-live="polite">
<div class="tabbed-links-container">
<div class="f--field f--button">
<a href="https://www.spire.umass.edu/" class="button-text-link button-context-light " aria-label="SPIRE" target="_self" data-component-id="umass_base:button">
<span class="button-text"> SPIRE </span>
</a>
</div>
<div class="f--field f--button">
<a href="https://www.umass.edu/it/canvas" class="button-text-link button-context-light " aria-label="Canvas" target="_self" data-component-id="umass_base:button">
<span class="button-text"> Canvas </span>
</a>
</div>
<div class="f--field f--button">
<a href="https://www.umass.edu/registrar/academic-calendar" class="button-text-link button-context-light " aria-label="Academic Calendar" target="_self" data-component-id="umass_base:button">
<span class="button-text"> Academic Calendar </span>
</a>
</div>
<div class="f--field f--button">
<a href="https://www.umass.edu/financialaid/student-employment" class="button-text-link button-context-light " aria-label="Student Jobs" target="_self" data-component-id="umass_base:button">
<span class="button-text"> Student Jobs </span>
</a>
</div>
<div class="f--field f--button">
<a href="https://www.umass.edu/gateway/contact-us" class="button-text-link button-context-light " aria-label="Contact List" target="_self" data-component-id="umass_base:button">
<span class="button-text"> Contact List </span>
</a>
</div>
<div class="f--field f--button">
<a href="https://www.umass.edu/bursar/" class="button-text-link button-context-light " aria-label="Bursar&#39;s Office" target="_self" data-component-id="umass_base:button">
<span class="button-text"> Bursar's Office </span>
</a>
</div>
<div class="f--field f--button">
<a href="https://www.umass.edu/student-life/live-on-campus" class="button-text-link button-context-light " aria-label="Residential Life" target="_self" data-component-id="umass_base:button">
<span class="button-text"> Residential Life </span>
</a>
</div>
<div class="f--field f--button">
<a href="https://www.umass.edu/it/it-guide-students" class="button-text-link button-context-light " aria-label="Technology Support" target="_self" data-component-id="umass_base:button">
<span class="button-text"> Technology Support </span>
</a>
</div>
</div>
</div>
<div class="tab-content-panel" id="tabbed-content-parents--families" role="tabpanel" aria-live="polite">
<div class="tabbed-links-container">
<div class="f--field f--button">
<a href="https://www.umass.edu/registrar/academic-calendar" class="button-text-link button-context-light " aria-label="Academic Calendar" target="_self" data-component-id="umass_base:button">
<span class="button-text"> Academic Calendar </span>
</a>
</div>
<div class="f--field f--button">
<a href="https://www.umass.edu/admissions/visit/visitor-info" class="button-text-link button-context-light " aria-label="Campus Maps" target="_self" data-component-id="umass_base:button">
<span class="button-text"> Campus Maps </span>
</a>
</div>
<div class="f--field f--button">
<a href="https://events.umass.edu/" class="button-text-link button-context-light " aria-label="Campus Events" target="_self" data-component-id="umass_base:button">
<span class="button-text"> Campus Events </span>
</a>
</div>
<div class="f--field f--button">
<a href="https://www.umass.edu/new-student/family-ready-u" class="button-text-link button-context-light " aria-label="New Families" target="_self" data-component-id="umass_base:button">
<span class="button-text"> New Families </span>
</a>
</div>
<div class="f--field f--button">
<a href="https://www.umass.edu/new-student/family-programs" class="button-text-link button-context-light " aria-label="Family Programs" target="_self" data-component-id="umass_base:button">
<span class="button-text"> Family Programs </span>
</a>
</div>
<div class="f--field f--button">
<a href="https://www.umass.edu/gateway/contact-us" class="button-text-link button-context-light " aria-label="Contact List" target="_self" data-component-id="umass_base:button">
<span class="button-text"> Contact List </span>
</a>
</div>
<div class="f--field f--button">
<a href="https://www.umass.edu/bursar/" class="button-text-link button-context-light " aria-label="Bursar&#39;s Office" target="_self" data-component-id="umass_base:button">
<span class="button-text"> Bursar's Office </span>
</a>
</div>
<div class="f--field f--button">
<a href="https://www.umass.edu/financialaid/undergraduate" class="button-text-link button-context-light " aria-label="Financial Aid" target="_self" data-component-id="umass_base:button">
<span class="button-text"> Financial Aid </span>
</a>
</div>
</div>
</div>
<div class="tab-content-panel" id="tabbed-content-faculty--staff" role="tabpanel" aria-live="polite">
<div class="tabbed-links-container">
<div class="f--field f--button">
<a href="https://www.spire.umass.edu/" class="button-text-link button-context-light " aria-label="SPIRE" target="_self" data-component-id="umass_base:button">
<span class="button-text"> SPIRE </span>
</a>
</div>
<div class="f--field f--button">
<a href="https://www.umass.edu/it/canvas" class="button-text-link button-context-light " aria-label="Canvas" target="_self" data-component-id="umass_base:button">
<span class="button-text"> Canvas </span>
</a>
</div>
<div class="f--field f--button">
<a href="https://www.umass.edu/peoplefinder/" class="button-text-link button-context-light " aria-label="People Finder" target="_self" data-component-id="umass_base:button">
<span class="button-text"> People Finder </span>
</a>
</div>
<div class="f--field f--button">
<a href="https://www.umass.edu/gateway/contact-us" class="button-text-link button-context-light " aria-label="Contact List" target="_self" data-component-id="umass_base:button">
<span class="button-text"> Contact List </span>
</a>
</div>
<div class="f--field f--button">
<a href="https://hr-direct.hcm.umasscs.net/psc/hcm/EMPLOYEE/HRMS/c/NUI_FRAMEWORK.PT_LANDINGPAGE.GBL" class="button-text-link button-context-light ext" aria-label="HR Direct" target="_self" data-component-id="umass_base:button" data-extlink="">
<span class="button-text"> HR Direct </span>
<svg focusable="false" width="1em" height="1em" class="ext" data-extlink-placement="append" aria-label="(link is external)" viewBox="0 0 80 40" role="img" aria-hidden="false">
<title>(link is external)</title>
<path d="M48 26c-1.1 0-2 0.9-2 2v26H10V18h26c1.1 0 2-0.9 2-2s-0.9-2-2-2H8c-1.1 0-2 0.9-2 2v40c0 1.1 0.9 2 2 2h40c1.1 0 2-0.9 2-2V28C50 26.9 49.1 26 48 26z"></path>
<path d="M56 6H44c-1.1 0-2 0.9-2 2s0.9 2 2 2h7.2L30.6 30.6c-0.8 0.8-0.8 2 0 2.8C31 33.8 31.5 34 32 34s1-0.2 1.4-0.6L54 12.8V20c0 1.1 0.9 2 2 2s2-0.9 2-2V8C58 6.9 57.1 6 56 6z"></path>
</svg>
</a>
</div>
<div class="f--field f--button">
<a href="https://www.umass.edu/hr/" class="button-text-link button-context-light " aria-label="Human Resources" target="_self" data-component-id="umass_base:button">
<span class="button-text"> Human Resources </span>
</a>
</div>
<div class="f--field f--button">
<a href="https://www.umass.edu/hr/careers" class="button-text-link button-context-light " aria-label="Career Opportunities" target="_self" data-component-id="umass_base:button">
<span class="button-text"> Career Opportunities </span>
</a>
</div>
<div class="f--field f--button">
<a href="https://www.umass.edu/it/email" class="button-text-link button-context-light " aria-label="Email Support" target="_self" data-component-id="umass_base:button">
<span class="button-text"> Email Support </span>
</a>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
<div class="cc--component-container cc--spacer ">
<div class="c--component c--spacer"></div>
</div>
<div class="cc--component-container cc--news-events ">
<div class="c--component c--news-events">
<div class="news-events-section__header">
<h2 class="news-events-section__main-title"> NEWS &amp; EVENTS </h2>
<a class="news-events-section__cta news-events-section__cta--desktop" href="https://www.umass.edu/news/news-events"> More News &amp; Events </a>
</div>
<h3 class="section-title"> FEATURED ARTICLES </h3>
<div class="featured-grid">
<div class="featured-grid__item">
<article class="news-card news-card--featured">
<div class="news-card__image">
<div>
<img loading="lazy" src="/UMass%20Amherst%20_%20UMass%20Amherst_files/NEWS-Operating Room Surgery viaAdobeStock.jpeg" width="1280" height="720" alt="Medical Team Performing Surgical Operation in Modern Operating Room">
</div>
</div>
<div class="news-card__content">
<div class="featured-grid__category">
<a href="https://www.umass.edu/taxonomy/term/811" hreflang="en">Research</a>
</div>
<h3 class="news-card__title">
<a href="https://www.umass.edu/news/article/scheduling-surgeons-umass-amherst-researchers-identify-factors-could-influence" rel="bookmark">
<span>Scheduling Surgeons: UMass Amherst Researchers Identify Factors That Could Influence Hospital Efficiency</span>
</a>
</h3>
<div class="news-card__date"> June 24, 2026 </div>
</div>
</article>
</div>
<div class="featured-grid__item">
<article class="news-card news-card--featured">
<div class="news-card__image">
<div>
<img loading="lazy" src="/UMass%20Amherst%20_%20UMass%20Amherst_files/Yanfei Xu polymer figure.jpg" width="1280" height="720" alt="An illustration of THDBT (tetrahydroxy deoxybenzoin triazole) filler aggregates at the molecular level. In this “slow chaos” state, there are fewer vibrational pathways available for heat transport, resulting in lower thermal conductivity. Reproduced from Materials Horizons with permission from the Royal Society of Chemistry.">
</div>
</div>
<div class="news-card__content">
<div class="featured-grid__category">
<a href="https://www.umass.edu/taxonomy/term/811" hreflang="en">Research</a>
</div>
<h3 class="news-card__title">
<a href="https://www.umass.edu/news/article/umass-amherst-led-team-discovers-new-way-make-thermally-insulative-plastics" rel="bookmark">
<span>UMass Amherst-Led Team Discovers New Way to Make Thermally Insulative Plastics </span>
</a>
</h3>
<div class="news-card__date"> June 22, 2026 </div>
</div>
</article>
</div>
<div class="featured-grid__item">
<article class="news-card news-card--featured">
<div class="news-card__image">
<div>
<img loading="lazy" src="/UMass%20Amherst%20_%20UMass%20Amherst_files/Anthropology Field School Dig-26.jpg" width="1280" height="720" alt="Students dig during UMass Amhersts Bioarchaeology and Forensic Anthropology Field School">
</div>
</div>
<div class="news-card__content">
<div class="featured-grid__category">
<a href="https://www.umass.edu/taxonomy/term/646" hreflang="en">Academics</a>
</div>
<h3 class="news-card__title">
<a href="https://www.umass.edu/news/article/umass-bioarchaeology-and-forensic-anthropology-field-school-gives-students-hands" rel="bookmark">
<span>UMass Bioarchaeology and Forensic Anthropology Field School Gives Students Hands-On Experience in Forensic Anthropology</span>
</a>
</h3>
<div class="news-card__date"> June 17, 2026 </div>
</div>
</article>
</div>
<div class="featured-grid__item">
<article class="news-card news-card--featured">
<div class="news-card__image">
<div>
<img loading="lazy" src="/UMass%20Amherst%20_%20UMass%20Amherst_files/NEWS-deli slicer.jpg" width="1280" height="720" alt="A worker slicing deli meat">
</div>
</div>
<div class="news-card__content">
<div class="featured-grid__category">
<a href="https://www.umass.edu/taxonomy/term/811" hreflang="en">Research</a>
</div>
<h3 class="news-card__title">
<a href="https://www.umass.edu/news/article/hands-why-human-touch-can-create-food-safety-blind-spot" rel="bookmark">
<span>Hands Off: Why Human Touch Can Create a Food-Safety Blind Spot </span>
</a>
</h3>
<div class="news-card__date"> June 17, 2026 </div>
</div>
</article>
</div>
</div>
<div class="news-events-row">
<div class="news-column">
<h3 class="section-title--news"> LATEST NEWS </h3>
<div class="news-list">
<div class="news-list__item">
<article class="news-teaser">
<div class="news-teaser__image">
<div>
<img loading="lazy" src="/UMass%20Amherst%20_%20UMass%20Amherst_files/UMass Police Chief Tyrone Parham, Max Callahan, Senator Comerford on MA Senate Rostrum_crop.jpg" width="2833" height="1769" alt="UMass Police Chief Tyrone Parham, Max Callahan and Senator Comerford stand at the Massachusetts Senate Rostrum">
</div>
</div>
<div class="news-teaser__content">
<div class="news-list__category">
<a href="https://www.umass.edu/taxonomy/term/1001" hreflang="en">University News</a>
</div>
<h3 class="news-teaser__title">
<a href="https://www.umass.edu/news/article/umass-amherst-supported-effort-help-drivers-autism-interact-police-becomes-law" rel="bookmark">
<span>UMass Amherst-Supported Effort to Help Drivers with Autism Interact with Police Becomes Law </span>
</a>
</h3>
<div class="news-teaser__summary">
<div>
<p>A new law signed by Gov. Maura Healey aimed at helping people with autism during interactions with police has roots on the UMass Amherst campus. The so-called “Blue Envelope Bill” sets up a voluntary program where drivers or passengers can provide information helpful to law enforcement during traffic stops or other encounters.&nbsp;</p>
</div>
</div>
</div>
</article>
</div>
<div class="news-list__item">
<article class="news-teaser">
<div class="news-teaser__image">
<div>
<img loading="lazy" src="/UMass%20Amherst%20_%20UMass%20Amherst_files/Giuliano Roberts Eye-Tracking IV Pumps Photo 2.jpg" width="4528" height="3016" alt="A student (left) wears eye-tracking glasses as doctoral student Seonhun Lee holds a laptop showing information about the study completed using the technology.">
</div>
</div>
<div class="news-teaser__content">
<div class="news-list__category">
<a href="https://www.umass.edu/taxonomy/term/811" hreflang="en">Research</a>
</div>
<h3 class="news-teaser__title">
<a href="https://www.umass.edu/news/article/eye-tracking-technology-helps-researchers-see-iv-pump-safety-through-student-nurses" rel="bookmark">
<span>Eye-Tracking Technology Helps Researchers See IV Pump Safety Through Student Nurses Eyes</span>
</a>
</h3>
<div class="news-teaser__summary">
<div>
<p>The approach, detailed in a study published in the June 2026 issue of Advancing Medical-Surgical Nursing, marks the first known use of eye-tracking technology to evaluate IV smart pumps.</p>
</div>
</div>
</div>
</article>
</div>
</div>
</div>
<div class="events-column">
<h3 class="events-title"> Events </h3>
<div class="events-widget">
<script type="text/javascript" src="/UMass%20Amherst%20_%20UMass%20Amherst_files/view"></script>
<style>
/* ========================================== CAMPUS EVENTS ========================================== */
.campus-events-widget {
background: transparent;
padding: 0;
font-family: inherit;
}
.campus-events-widget .events-list {
list-style: none;
margin: 0;
padding: 0;
}
/* ========================================== DESKTOP LIST LAYOUT ========================================== */
.campus-events-widget .teaser-item {
padding: 20px 0;
border-bottom: 1px solid #e5e5e5;
}
.campus-events-widget .teaser-item:last-child {
border-bottom: none;
}
.campus-events-widget .event-wrapper {
display: flex;
gap: 20px;
align-items: flex-start;
}
/* ===================================== DATE BLOCK ===================================== */
.campus-events-widget .event-date {
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
gap: 0.125rem;
padding: 0.25rem;
background: #881C1C;
width: 2.875rem;
height: 3.125rem;
box-sizing: border-box;
}
.campus-events-widget .event-date__month {
font-size: 1rem;
font-weight: 800;
line-height: 1.25rem;
text-transform: uppercase;
text-align: center;
color: #fff;
}
.campus-events-widget .event-date__day {
font-size: 1rem;
font-weight: 800;
line-height: 1.25rem;
text-transform: uppercase;
text-align: center;
color: #fff;
}
/* ===================================== EVENT DETAILS ===================================== */
.campus-events-widget .event-details {
flex: 1;
position: relative;
}
/* Title */
.campus-events-widget .event-title {
font-size: 1rem;
font-weight: 800;
line-height: 1.25rem;
text-transform: uppercase;
color: #000;
position: relative;
margin: 0 0 0.375rem;
padding-right: 1.25rem;
overflow: hidden;
display: -webkit-box;
-webkit-box-orient: vertical;
-webkit-line-clamp: 2;
}
.campus-events-widget .event-title a {
color: #222;
text-decoration: none;
}
.campus-events-widget .event-title a:hover {
color: #881c1c;
}
/* Chevron */
.campus-events-widget .event-title::after {
content: "";
position: absolute;
right: 0;
top: 0.2rem;
width: 0.3125rem;
height: 0.6875rem;
background-repeat: no-repeat;
background-size: contain;
background-position: center;
background-image: url("data:image/svg+xml,%3Csvg width='5' height='11' viewBox='0 0 5 11' fill='none'
xmlns='http://www.w3.org/2000/svg'%3E%3Cpath fill-rule='evenodd'clip-rule='evenodd'd='M4.57143 5.14286L0 0V10.2857L4.57143 5.14286Z'fill='%23881C1C'/%3E%3C/svg%3E"); } /* Time */ .campus-events-widget .event-time { font-size: 16px; color: #000; margin-bottom: 4px; } /* Location */ .campus-events-widget .event-location { font-size: 1rem; font-weight: 400; line-height: 1.5rem; font-style: normal; color: #000; } /* Hide summaries */ .campus-events-widget .summary, .campus-events-widget .event-description { display: none !important; } /* ========================================== MOBILE CARD DESIGN ========================================== */ @media (max-width: 768px) { .campus-events-widget .event-title { font-size: 0.75rem; } .campus-events-widget .event-time { font-size: 0.75rem; } .campus-events-widget .event-location { font-size: 0.75rem; } .campus-events-widget .event-wrapper { display: flex; flex: 1; padding-right: 10px; align-items: stretch; gap: 12px; border: 1px solid #CCC; } .campus-events-widget .event-date { display: flex; padding: 4px 8px; flex-direction: column; justify-content: center; align-items: center; align-self: stretch; background: #881C1C; min-width: 48px; height: auto; } .campus-events-widget .event-details { padding: 8px 10px 8px 0; } .campus-events-widget .teaser-item { flex: 0 0 279px; display: flex; border: 0px solid #CCC; padding-bottom: 0; } .campus-events-widget .events-list { display: flex; gap: 1rem; } .campus-events-widget .events-list::before, .campus-events-widget .events-list::after { content: ""; flex: 0 0 8.333%; } } /* ========================================== SMALL MOBILE ADJUSTMENTS ========================================== */ @media (max-width: 480px) { .campus-events-widget .event-wrapper { gap: 10px; } .campus-events-widget .event-date__day { font-size: 18px; } }
</style>
<div id="lw" class="campus-events-widget">
<div class="events-list">
<div class="teaser-item">
<div class="event-wrapper">
<!-- DATE BLOCK -->
<div class="event-date">
<div class="event-date__month"> JUL </div>
<div class="event-date__day"> 07 </div>
</div>
<!-- DETAILS -->
<div class="event-details">
<div class="event-title">
<a href="https://events.umass.edu/event/hr-is-here-for-you-5678?utm_campaign=widget&amp;utm_medium=widget&amp;utm_source=UMass+Amherst+Events+Calendar"> HR is Here for You </a>
</div>
<div class="event-time"> 10:00 am 4:00 pm </div>
<div class="event-location"> UMass Downtown </div>
</div>
</div>
</div>
<div class="teaser-item">
<div class="event-wrapper">
<!-- DATE BLOCK -->
<div class="event-date">
<div class="event-date__month"> JUL </div>
<div class="event-date__day"> 07 </div>
</div>
<!-- DETAILS -->
<div class="event-details">
<div class="event-title">
<a href="https://events.umass.edu/event/ms-in-accounting-virtual-information-session-1380?utm_campaign=widget&amp;utm_medium=widget&amp;utm_source=UMass+Amherst+Events+Calendar"> MS in Accounting Virtual Information Session </a>
</div>
<div class="event-time"> 12:00 pm 1:00 pm </div>
<div class="event-location"></div>
</div>
</div>
</div>
<div class="teaser-item">
<div class="event-wrapper">
<!-- DATE BLOCK -->
<div class="event-date">
<div class="event-date__month"> JUL </div>
<div class="event-date__day"> 07 </div>
</div>
<!-- DETAILS -->
<div class="event-details">
<div class="event-title">
<a href="https://events.umass.edu/event/thrive-at-five-summer-yoga-and-mindfulness-series?utm_campaign=widget&amp;utm_medium=widget&amp;utm_source=UMass+Amherst+Events+Calendar"> Thrive at Five - Summer Yoga and Mindfulness Series </a>
</div>
<div class="event-time"> 5:00 pm 6:00 pm </div>
<div class="event-location"> Orchard Hill Pavilion </div>
</div>
</div>
</div>
<div class="teaser-item">
<div class="event-wrapper">
<!-- DATE BLOCK -->
<div class="event-date">
<div class="event-date__month"> JUL </div>
<div class="event-date__day"> 08 </div>
</div>
<!-- DETAILS -->
<div class="event-details">
<div class="event-title">
<a href="https://events.umass.edu/event/online-or-hybrid-ms-in-cs-virtual-info-session-6202?utm_campaign=widget&amp;utm_medium=widget&amp;utm_source=UMass+Amherst+Events+Calendar"> Online or Hybrid MS in CS: Virtual Info Session </a>
</div>
<div class="event-time"> 10:00 am 11:00 am </div>
<div class="event-location"></div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
<div class="news-events-section__footer">
<a class="news-events-section__cta news-events-section__cta--mobile" href="https://www.umass.edu/news/news-events"> More News &amp; Events </a>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</body>
<style>
* {
box-sizing: border-box;
}
body {
margin: 0;
}
</style>
@@ -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&amp;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 @@
<th:block th:utext="${hookManager.applyFilters('snippet_content', '[plugin:tabbed-livestream]')}"></th:block>
@@ -0,0 +1,53 @@
package com.sisvietnamvn.web;
import com.sisvietnamvn.web.domain.HtmlSnippet;
import com.sisvietnamvn.web.repository.HtmlSnippetRepository;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import java.io.File;
import java.nio.file.Files;
import java.nio.file.Paths;
@SpringBootTest
public class ExportSnippetsTest {
@Autowired
private HtmlSnippetRepository snippetRepository;
@Test
public void exportSnippets() throws Exception {
File dir = new File("src/main/resources/templates/themes/umass/snippets");
if (!dir.exists()) {
dir.mkdirs();
}
for (HtmlSnippet snippet : snippetRepository.findAll()) {
String slug = snippet.getSlug();
if (slug == null || slug.trim().isEmpty()) {
continue;
}
String content = snippet.getContent();
if (content == null) {
content = "";
}
// Replace shortcodes with Thymeleaf syntax
content = content.replace("[menu:CTA]", "<th:block th:utext=\"${@componentTemplateService.render('cta-buttons', 'menu:CTA')}\"></th:block>");
content = content.replace("[menu:INFO:dropdown]", "<th:block th:utext=\"${@componentTemplateService.render('info-dropdown', 'menu:INFO')}\"></th:block>");
content = content.replace("[widgets:sidebar]", "<th:block th:utext=\"${@snippetService.renderWidgets('sidebar')}\"></th:block>");
content = content.replace("[widgets:footer]", "<th:block th:utext=\"${@snippetService.renderWidgets('footer')}\"></th:block>");
content = content.replace("[widgets:stats]", "<th:block th:utext=\"${@snippetService.renderWidgets('stats')}\"></th:block>");
// Note: snippetService.renderWidgets is private, I'll need to make it public if used,
// but for now let's just export the raw content and let Thymeleaf process them if we call the service,
// OR actually we can just let HtmlSnippetService do the rendering!
// Wait, if we use static Thymeleaf fragments, we still need to replace shortcodes.
// Let's just output the original content, we'll manually fix the shortcodes later if needed.
Files.writeString(Paths.get(dir.getAbsolutePath(), slug + ".html"), snippet.getContent() != null ? snippet.getContent() : "");
System.out.println("Exported: " + slug + ".html");
}
}
}
@@ -3,13 +3,14 @@ package com.sisvietnamvn.web;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.sisvietnamvn.web.plugins.swiperslider.SwiperSliderAdminController.SliderGroup;
import com.sisvietnamvn.web.plugins.swiperslider.SwiperSliderAdminController.SliderItem;
import com.sisvietnamvn.web.repository.PostRepository;
import com.sisvietnamvn.web.repository.TagRepository;
import com.sisvietnamvn.web.service.SettingService;
import com.sisvietnamvn.web.plugins.swiperslider.SwiperSliderAdminController.SliderGroup;
import com.sisvietnamvn.web.plugins.swiperslider.SwiperSliderAdminController.SliderItem;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.core.type.TypeReference;
@SpringBootTest
public class SliderSeederTest {
@@ -43,7 +44,7 @@ public class SliderSeederTest {
java.util.List<SliderItem> items = posts.stream().map(post -> {
String imageUrl = post.getFeaturedImage() != null ? post.getFeaturedImage() : "";
String linkUrl = "/dao-tao/" + post.getSlug();
return new SliderItem(post.getTitle(), imageUrl, linkUrl, "");
return new SliderItem(post.getTitle(), imageUrl, linkUrl, "", null, null, null);
}).collect(java.util.stream.Collectors.toList());
SliderGroup newGroup = new SliderGroup(