/*
Theme Name: GTIS — Glad Tidings International School
Theme URI: https://gtis.edu.kh
Author: Glad Tidings International School
Author URI: https://gtis.edu.kh
Description: The website of Glad Tidings International School, a Christian school teaching Grades 1 to 12 in Kampong Speu, Cambodia. Bilingual throughout — English and Khmer, with the reader's choice following them from page to page. The palette is taken from the school crest, whose yellow and green stand for the rice fields of Cambodia. The school's story is told on a timeline drawn as you scroll, and the milestones, student clubs, RICE values and Youth Centre are all editable in the admin under School Content, in both languages at once. Built mobile first, to WCAG 2.2 AA, and it degrades to plain readable pages with JavaScript switched off.
Version: 2.1.0
Requires at least: 6.0
Tested up to: 6.7
Requires PHP: 7.4
License: GNU General Public License v2 or later
License URI: https://www.gnu.org/licenses/gpl-2.0.html
Text Domain: gtis-nisc-style
Tags: education, translation-ready, accessibility-ready, custom-colors, custom-menu, custom-logo, one-column, full-width-template
*/

/* ==========================================================================
   1. DESIGN TOKENS & SYSTEM VARIABLES (PHOTO-MATCHED GTIS PALETTE)
   ========================================================================== */
:root {
  /* --------------------------------------------------------------------
     The palette comes from the school crest, which the school defines as:
     YELLOW and GREEN for the rice fields of Cambodia, WHITE for purity and
     truth, RED for the blood of Christ. Green and gold carry the interface;
     white does the work of making it feel open. Red is a crest colour only —
     never a UI accent.
     -------------------------------------------------------------------- */

  /* Green — the primary brand colour */
  --green-950: #071F12;
  --green-900: #0E3820;
  --green-800: #134B2B;
  --green-700: #1A633B;
  --green-600: #227D4C;
  --green-500: #2E9960;
  --green-100: #E3F0E8;
  --green-50:  #F2F8F4;

  /* Gold — used sparingly, for emphasis rather than decoration */
  --gold-700: #86690F;   /* small text on white and the light bands: 5.2:1 */
  --gold-600: #B08D22;   /* large text and borders only on white: 3.1:1 */
  --gold-500: #D4AF37;
  --gold-400: #E5C564;
  --gold-300: #F3DE8A;
  --gold-100: #FDF6E3;
  --gold-subtle: rgba(212, 175, 55, 0.12);

  /* Neutrals, very slightly warmed towards green so nothing looks grey-blue */
  --ink-900: #14201A;
  --ink-800: #1E2925;
  --ink-700: #33413D;
  --ink-600: #4A5A54;
  --ink-500: #667772;
  --ink-400: #93A29C;
  --ink-300: #C6D2CC;
  --ink-200: #E3EAE5;
  --ink-100: #F0F4F1;
  --ink-50:  #F7FAF8;

  /* Surfaces */
  --bg-main: #FFFFFF;
  --bg-soft: #F7FAF8;
  --surface-white: #FFFFFF;
  --border-soft: #E3EAE5;
  --border-strong: #C6D2CC;

  /* Type */
  --font-display: 'Plus Jakarta Sans', -apple-system, BlinkMacSystemFont, sans-serif;
  --font-heading: 'Plus Jakarta Sans', -apple-system, BlinkMacSystemFont, sans-serif;
  --font-body: 'DM Sans', -apple-system, BlinkMacSystemFont, sans-serif;
  --font-khmer: 'Kantumruy Pro', 'Noto Sans Khmer', sans-serif;
  /* A hand, for the motto only. The pupils painted the motto board themselves,
     so the three words are set as though written rather than typeset. Used in
     exactly one place — it earns its weight by being the signature, not by
     being sprinkled about. */
  --font-script: 'Caveat', 'Segoe Script', cursive;

  /* Fluid type scale — one ramp, used everywhere */
  --text-xs:   0.8125rem;
  --text-sm:   0.875rem;
  --text-md:   0.9375rem;   /* interface text: nav, buttons, footer links */
  --text-base: 1rem;
  --text-lg:   clamp(1.0625rem, 0.4vw + 1rem, 1.1875rem);
  --text-xl:   clamp(1.25rem,  0.6vw + 1.1rem, 1.5rem);
  --text-2xl:  clamp(1.5rem,   1.2vw + 1.2rem, 2rem);
  --text-3xl:  clamp(1.875rem, 2.2vw + 1.3rem, 2.75rem);
  --text-4xl:  clamp(2.25rem,  4vw + 1.2rem,   3.75rem);

  /* Spacing */
  --space-xs: 4px;
  --space-sm: 8px;
  --space-md: 16px;
  --space-lg: 24px;
  --space-xl: 32px;
  --space-2xl: 48px;
  --space-3xl: 64px;
  --space-4xl: 96px;

  /* Section rhythm — tighter on phones, generous on desktop */
  --section-y: clamp(48px, 7vw, 104px);
  --gutter: clamp(16px, 4vw, 32px);
  --measure: 68ch;
  --container: 1200px;

  /* Radii — soft, not bubbly */
  --radius-sm: 8px;
  --radius-md: 12px;
  --radius-lg: 18px;
  --radius-xl: 24px;
  --radius-full: 9999px;

  /* Shadows — light and diffuse, so the page reads as open rather than heavy */
  --shadow-sm: 0 1px 2px rgba(20, 32, 26, 0.05);
  --shadow-md: 0 2px 8px rgba(20, 32, 26, 0.06);
  --shadow-lg: 0 8px 24px rgba(20, 32, 26, 0.08);
  --shadow-xl: 0 16px 40px rgba(20, 32, 26, 0.10);

  /* Minimum comfortable tap target */
  --tap: 44px;

  /* Motion */
  --transition-fast: 150ms cubic-bezier(0.4, 0, 0.2, 1);
  --transition-base: 250ms cubic-bezier(0.4, 0, 0.2, 1);
  --transition-smooth: 400ms cubic-bezier(0.16, 1, 0.3, 1);

  /* ---- Compatibility aliases -------------------------------------------
     Older rules in this file still reference the previous token names.
     Mapping them here keeps one palette in play while the sections are
     migrated, instead of two palettes drifting apart. */
  --navy-950: var(--green-950);
  --navy-900: var(--green-900);
  --navy-800: var(--green-800);
  --navy-700: var(--green-700);
  --navy-600: var(--green-600);
  --slate-50:  var(--ink-50);
  --slate-100: var(--ink-100);
  --slate-200: var(--ink-200);
  --slate-300: var(--ink-300);
  --slate-400: var(--ink-400);
  --slate-500: var(--ink-500);
  --slate-600: var(--ink-600);
  --slate-700: var(--ink-700);
  --slate-800: var(--ink-800);
  --slate-900: var(--ink-900);
  --emerald-500: var(--green-500);
  --emerald-100: var(--green-100);
  --cyan-500: var(--green-600);
  --cyan-100: var(--green-100);
  --glass-card: var(--surface-white);
  --glass-card-border: var(--border-soft);
  --glass-nav: rgba(255, 255, 255, 0.92);
  --glass-nav-border: var(--border-soft);
  --glass-dark: rgba(7, 31, 18, 0.88);
  --glass-dark-border: rgba(212, 175, 55, 0.25);
  --gold-gradient: linear-gradient(135deg, #E5C564 0%, #D4AF37 100%);
  --shadow-gold: 0 6px 20px rgba(212, 175, 55, 0.22);
  --shadow-glow: 0 0 25px rgba(212, 175, 55, 0.15);
}

/* ==========================================================================
   2. MODERN CSS RESET & BASE STYLES
   ========================================================================== */
*, *::before, *::after {
  box-sizing: border-box;
  margin: 0;
  padding: 0;
}

html {
  font-size: 16px;
  scroll-behavior: smooth;
  -webkit-text-size-adjust: 100%;
}

body {
  font-family: var(--font-body);
  background-color: var(--bg-main);
  color: var(--slate-800);
  line-height: 1.65;
  font-feature-settings: 'cv02', 'cv03', 'cv04', 'cv11';
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  overflow-x: hidden;
}

/* Accessible Skip Link */
.skip-link {
  position: absolute;
  top: -60px;
  left: 20px;
  background: var(--gold-gradient);
  color: var(--navy-950);
  font-weight: 700;
  padding: 12px 24px;
  border-radius: var(--radius-sm);
  z-index: 10000;
  text-decoration: none;
  box-shadow: var(--shadow-lg);
  transition: top var(--transition-fast);
}
.skip-link:focus {
  top: 15px;
  outline: 3px solid var(--navy-950);
}


/* Khmer text needs the Khmer face even on an English page — the language
   switcher shows "ខ្មែរ" while the rest of the page is in English, and without
   this it falls back to a font with no Khmer glyphs and renders as boxes. */
[lang="km"] {
  font-family: var(--font-khmer), sans-serif;
}

/* Khmer Localization Support */
html[lang="km"],
html[lang="km"] body,
html[lang="km"] h1,
html[lang="km"] h2,
html[lang="km"] h3,
html[lang="km"] h4,
html[lang="km"] h5,
html[lang="km"] h6,
html[lang="km"] p,
html[lang="km"] a,
html[lang="km"] span,
html[lang="km"] strong,
html[lang="km"] b,
html[lang="km"] em,
html[lang="km"] i,
html[lang="km"] button,
html[lang="km"] input,
html[lang="km"] select,
html[lang="km"] textarea,
html[lang="km"] blockquote,
html[lang="km"] cite,
html[lang="km"] label,
html[lang="km"] dt,
html[lang="km"] dd,
html[lang="km"] figcaption,
html[lang="km"] li {
  font-family: var(--font-khmer) !important;
  line-height: 1.8 !important;
  letter-spacing: normal !important;
}

/* The mirror of the rule above: English text on a Khmer page. The school hymn is
   sung in English and is not translated, so it is marked lang="en" — without
   this the !important above would set those words in the Khmer face. Applies to
   anything marked lang="en", not just the hymn, so it holds for whatever is left
   untranslated next. */
html[lang="km"] [lang="en"],
html[lang="km"] [lang="en"] * {
  font-family: var(--font-body) !important;
}

/* Typography Hierarchy */
h1, h2, h3, h4, h5, h6 {
  font-family: var(--font-heading);
  font-weight: 700;
  color: var(--navy-900);
  line-height: 1.25;
  letter-spacing: -0.02em;
}

a {
  color: inherit;
  text-decoration: none;
  transition: color var(--transition-fast), opacity var(--transition-fast);
}

img {
  max-width: 100%;
  height: auto;
  display: block;
}

/* ==========================================================================
   3. WELCOME BAR
   Written mobile-first: the base rules are the phone layout, and min-width
   queries add to them. Nothing here is hidden behind a max-width override.
   ========================================================================== */
.announce-bar {
  background: var(--green-900);
  color: #FFFFFF;
  font-size: var(--text-xs);
  padding: 7px var(--gutter);
}

.announce-inner {
  max-width: var(--container);
  margin: 0 auto;
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: center;
  gap: 6px 12px;
  text-align: center;
  line-height: 1.45;
}

.announce-motto {
  font-weight: 700;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--gold-300);
  white-space: nowrap;
}

.announce-sep {
  display: none;
  width: 1px;
  height: 12px;
  background: rgba(255, 255, 255, 0.28);
}

/* The announcements. All of them are in the markup; the rotator shows one at a
   time. With no JavaScript every one stays visible and the strip simply wraps,
   which is the right fallback for two or three short lines. */
.announce-messages {
  list-style: none;
  margin: 0;
  padding: 0;
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: 6px 12px;
}

.announce-message {
  color: rgba(255, 255, 255, 0.9);
}

/* Once the rotator takes over, the list becomes a single slot and the messages
   are stacked in it, so the strip does not change height as they change. */
.announce-messages.is-rotating {
  display: grid;
  gap: 0;
}

.announce-messages.is-rotating .announce-message {
  grid-area: 1 / 1;
  opacity: 0;
  visibility: hidden;
  transition: opacity 0.45s ease;
}

.announce-messages.is-rotating .announce-message.is-current {
  opacity: 1;
  visibility: visible;
}

@media (prefers-reduced-motion: reduce) {
  .announce-messages.is-rotating .announce-message {
    transition: none;
  }
}

@media (min-width: 600px) {
  .announce-sep { display: block; }
}

/* ==========================================================================
   4. HEADER & NAVIGATION
   One row on every screen: brand on the left, actions on the right. The link
   list is the only thing that changes — a menu sheet on phones, an inline row
   from 960px up. No mega-menus: five destinations, all one tap away.
   ========================================================================== */
.site-header {
  position: sticky;
  top: 0;
  z-index: 1000;
  background: var(--surface-white);
  border-bottom: 1px solid var(--border-soft);
  transition: box-shadow var(--transition-base);
}

.site-header.is-scrolled {
  box-shadow: var(--shadow-md);
}

.header-inner {
  max-width: var(--container);
  margin: 0 auto;
  padding: 10px var(--gutter);
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-md);
}

/* --- Brand ---------------------------------------------------------------- */
.brand {
  display: flex;
  align-items: center;
  gap: 10px;
  min-width: 0;
  text-decoration: none;
  flex-shrink: 0;
}

@media (max-width: 360px) {
  .brand {
    flex-shrink: 1;
  }
}

.brand-mark {
  width: 40px;
  height: 40px;
  object-fit: contain;
  flex-shrink: 0;
}

.brand-words {
  display: flex;
  flex-direction: column;
  min-width: 0;
}

.brand-name {
  font-family: var(--font-display);
  font-size: 1.0625rem;
  font-weight: 800;
  line-height: 1.1;
  color: var(--green-900);
  letter-spacing: -0.02em;
  white-space: nowrap;
}

.brand-kicker {
  font-size: 0.625rem;
  font-weight: 700;
  line-height: 1.3;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--ink-500);
  white-space: nowrap;
}

@media (min-width: 480px) {
  .brand-mark { width: 46px; height: 46px; }
  .brand-name { font-size: 1.1875rem; }
  .brand-kicker { font-size: 0.6875rem; }
}

/* --- Primary navigation --------------------------------------------------- */
.primary-nav {
  display: none;
}

.nav-list {
  list-style: none;
  display: flex;
  align-items: center;
  gap: 2px;
  margin: 0;
  padding: 0;
}

.nav-list a,
.nav-link {
  display: inline-flex;
  align-items: center;
  padding: 9px 12px;
  border-radius: var(--radius-sm);
  font-size: var(--text-md);
  font-weight: 600;
  color: var(--ink-700);
  text-decoration: none;
  white-space: nowrap;
  transition: color var(--transition-fast), background var(--transition-fast);
}

.nav-list a:hover,
.nav-link:hover {
  color: var(--green-800);
  background: var(--green-50);
}

/* WordPress marks the live page on the menu item it generates. */
.nav-list .current-menu-item > a,
.nav-list .current_page_item > a,
.nav-list a[aria-current="page"] {
  color: var(--green-800);
  box-shadow: inset 0 -2px 0 var(--gold-500);
  border-radius: var(--radius-sm) var(--radius-sm) 0 0;
}

@media (min-width: 1200px) {
  .primary-nav { display: block; }
}

/* Dynamic collision states: when navigation hits or would hit the logo,
   the header automatically follows the mobile design with menu bar toggle. */
.site-header.is-mobile-nav .primary-nav {
  display: none !important;
}

.site-header.is-desktop-nav .primary-nav {
  display: block !important;
}

/* --- Header actions ------------------------------------------------------- */
.header-actions {
  display: flex;
  align-items: center;
  gap: 8px;
  flex-shrink: 0;
}

/* Language toggle: two states, always side by side, never wrapping. */
.lang-toggle {
  display: inline-flex;
  flex-direction: row;
  flex-wrap: nowrap;
  align-items: center;
  gap: 2px;
  padding: 3px;
  border: 1px solid var(--border-soft);
  border-radius: var(--radius-full);
  background: var(--ink-50);
}

.lang-btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-width: 40px;
  min-height: 34px;
  padding: 7px 10px;
  border-radius: var(--radius-full);
  font-size: var(--text-xs);
  font-weight: 700;
  line-height: 1.4;
  color: var(--ink-600);
  text-decoration: none;
  white-space: nowrap;
  transition: color var(--transition-fast), background var(--transition-fast);
}

.lang-btn:hover {
  color: var(--green-800);
}

.lang-btn.is-active {
  background: var(--green-800);
  color: #FFFFFF;
}

/* Stacked full-width variant used inside the menu sheet. */
.lang-toggle--block {
  display: grid;
  grid-template-columns: 1fr 1fr;
  width: 100%;
  gap: 4px;
}

.lang-toggle--block .lang-btn {
  padding: 11px 8px;
  font-size: 0.875rem;
}

/* Primary call to action */
/* ==========================================================================
   CARD RADIUS RULE
   Two radii, chosen by role rather than by feel:
     --radius-lg  content cards      .stat-card-box .roadmap-step-card
                                     .campus-bento-item .story-card
     --radius-xl  feature cards      .program-bento-card .pillar-mission-card
                                     .quick-action-card .contact-detail-box
                                     .contact-form-card
     --radius-md  elements inside a card (thumbnails, icon tiles, map frames)
   Hover lift is -2px for compact cards and -4px for feature cards. Nothing else.
   ========================================================================== */

/* ==========================================================================
   BUTTONS
   One geometry for every pill-shaped button; the variants below carry only
   what actually differs — colour, border and shadow.

   Two constraints shaped this:
   - No `line-height` here. style.css sets `line-height: 1.8 !important` on
     Khmer <a> and <button>, so a line-height in this base would apply in
     English and be discarded in Khmer, making the two languages diverge more
     rather than less. Height comes from min-height and padding, which that
     !important cannot reach.
   - This block sits BEFORE .btn-visit on purpose. That rule is `display: none`
     until 720px, and a `display: inline-flex` here placed after it would put
     the header CTA on every phone screen.

   Every variant carries a transparent border so bordered and unbordered
   buttons compute to the same box.
   ========================================================================== */
.btn,
.btn-hero-primary,
.btn-hero-secondary,
.btn-visit,
.form-submit-btn {
  align-items: center;
  justify-content: center;
  gap: 10px;
  min-height: var(--tap);
  border: 1px solid transparent;
  border-radius: var(--radius-full);
  font-family: inherit;
  font-weight: 700;
  text-align: center;
  text-decoration: none;
  white-space: nowrap;
  cursor: pointer;
}

.btn,
.btn-hero-primary,
.btn-hero-secondary {
  display: inline-flex;
  padding: 13px 31px;
  font-size: 1.05rem;
}

/* Compact tier — the header CTA. */
.btn--compact,
.btn-visit {
  padding: 9px 19px;
  font-size: var(--text-md);
}

.btn-visit {
  display: none;
  background: var(--green-800);
  color: #FFFFFF;
  transition: background var(--transition-fast), transform var(--transition-fast);
}

.btn-visit:hover {
  background: var(--green-700);
  color: #FFFFFF;
  transform: translateY(-2px);
}

.btn-visit--block {
  display: flex;
  width: 100%;
}

@media (min-width: 720px) {
  .btn-visit { display: inline-flex; }
}

/* --- Menu button ---------------------------------------------------------- */
.menu-toggle {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: var(--tap);
  height: var(--tap);
  padding: 0;
  border: 1px solid var(--border-soft);
  border-radius: var(--radius-sm);
  background: var(--surface-white);
  color: var(--green-900);
  cursor: pointer;
}

.menu-toggle-bars {
  display: flex;
  flex-direction: column;
  justify-content: center;
  gap: 4px;
  width: 20px;
}

.menu-toggle-bars span {
  display: block;
  height: 2px;
  width: 100%;
  border-radius: 2px;
  background: currentColor;
}

@media (min-width: 1200px) {
  .menu-toggle { display: none; }
}

.site-header.is-mobile-nav .menu-toggle {
  display: inline-flex !important;
}

.site-header.is-desktop-nav .menu-toggle {
  display: none !important;
}

/* --- Menu sheet ----------------------------------------------------------- */
.mobile-panel {
  position: fixed;
  inset: 0;
  z-index: 1100;
  background: rgba(20, 32, 26, 0.45);
  opacity: 0;
  visibility: hidden;
  /* Hiding waits for the fade to finish; showing happens immediately, so the
     close button is focusable the moment the panel opens. Transitioning
     visibility itself would leave it unfocusable for the whole duration. */
  transition: opacity var(--transition-base), visibility 0s linear 250ms;
}

.mobile-panel.is-open {
  opacity: 1;
  visibility: visible;
  transition: opacity var(--transition-base), visibility 0s linear 0s;
}

.mobile-panel-sheet {
  position: absolute;
  inset: 0 0 0 auto;
  width: min(340px, 88vw);
  display: flex;
  flex-direction: column;
  background: var(--surface-white);
  padding: var(--space-md) var(--space-lg) calc(var(--space-lg) + env(safe-area-inset-bottom));
  overflow-y: auto;
  overscroll-behavior: contain;
  transform: translateX(100%);
  transition: transform var(--transition-smooth);
}

.mobile-panel.is-open .mobile-panel-sheet {
  transform: translateX(0);
}

.mobile-panel-top {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding-bottom: var(--space-md);
  border-bottom: 1px solid var(--border-soft);
}

.mobile-panel-title {
  font-family: var(--font-display);
  font-size: var(--text-xs);
  font-weight: 700;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--ink-500);
}

.menu-close {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: var(--tap);
  height: var(--tap);
  margin-right: -10px;
  padding: 0;
  border: 0;
  background: none;
  color: var(--green-900);
  cursor: pointer;
}

.menu-close svg {
  width: 22px;
  height: 22px;
}

.mobile-nav {
  display: flex;
  flex-direction: column;
  padding: var(--space-sm) 0;
  flex: 1;
}

.mobile-nav-link {
  display: flex;
  align-items: center;
  min-height: var(--tap);
  padding: 13px 0;
  border-bottom: 1px solid var(--border-soft);
  font-family: var(--font-display);
  font-size: var(--text-md);
  font-weight: 600;
  color: var(--green-900);
  text-decoration: none;
}

.mobile-nav-link:hover {
  color: var(--green-600);
}

.mobile-panel-foot {
  display: flex;
  flex-direction: column;
  gap: var(--space-sm);
  padding-top: var(--space-md);
}

body.has-panel-open {
  overflow: hidden;
}


.hero-btn-group {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 16px;
  margin-bottom: 40px;
}

.btn,
.btn--primary,
.btn-hero-primary {
  background: var(--gold-gradient);
  color: var(--green-950);
  font-weight: 800;
  box-shadow: var(--shadow-gold);
  transition: transform var(--transition-fast), box-shadow var(--transition-fast);
}

.btn-hero-primary:hover {
  transform: translateY(-2px);
  box-shadow: 0 10px 30px rgba(212, 175, 55, 0.5);
}

.btn--secondary,
.btn-hero-secondary {
  background: rgba(255, 255, 255, 0.08);
  border-color: rgba(255, 255, 255, 0.2);
  color: #FFFFFF;
  backdrop-filter: blur(10px);
  transition: background var(--transition-fast), border-color var(--transition-fast), transform var(--transition-fast);
}

/* The secondary button assumes a dark backdrop. On a white section it was
   invisible — a transparent fill and a near-white border. This is the same
   button for light surfaces. */
.btn--secondary-on-light {
  background: var(--surface-white);
  border-color: var(--border-strong);
  color: var(--green-800);
  backdrop-filter: none;
}

.btn--secondary-on-light:hover {
  background: var(--green-50);
  border-color: var(--green-600);
  color: var(--green-800);
}

.btn-hero-secondary:hover {
  background: rgba(255, 255, 255, 0.16);
  border-color: rgba(255, 255, 255, 0.4);
  transform: translateY(-2px);
}

/* ==========================================================================
   6. STATS & KEY PILLARS STRIP
   ========================================================================== */
/* Lifts slightly over the hero on wide screens; sits flush on phones, where a
   negative margin would just crop the photograph. */
.stats-strip {
  background: var(--surface-white);
  padding: var(--section-y) var(--gutter) 0;
  position: relative;
  z-index: 10;
}

@media (min-width: 1024px) {
  .stats-strip {
    margin-top: -48px;
    padding-top: 0;
    background: transparent;
  }
}

.stats-grid {
  max-width: 1320px;
  margin: 0 auto;
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: 20px;
}

.stat-card-box {
  background: var(--surface-white);
  border: 1px solid var(--slate-200);
  border-radius: var(--radius-lg);
  padding: 24px 20px;
  box-shadow: var(--shadow-sm);
  display: flex;
  flex-direction: column;
  gap: 8px;
  transition: transform var(--transition-base), box-shadow var(--transition-base), border-color var(--transition-base);
}

.stat-card-box:hover {
  transform: translateY(-2px);
  box-shadow: var(--shadow-md);
  border-color: var(--gold-400);
}

.stat-number-big {
  font-family: var(--font-display);
  font-size: 2.25rem;
  font-weight: 800;
  color: var(--navy-900);
  line-height: 1;
  letter-spacing: -0.02em;
}

.stat-title-lead {
  font-weight: 700;
  font-size: var(--text-md);
  color: var(--navy-900);
}

.stat-desc-muted {
  font-size: var(--text-sm);
  color: var(--slate-500);
  line-height: 1.5;
}

/* ==========================================================================
   7. ACADEMIC & SERVICE PROGRAMS BENTO GRID
   ========================================================================== */
.section-programs {
  padding: var(--section-y) var(--gutter);
  background: var(--slate-50);
}

/* Alternating light band, previously written inline on five sections. */
.section-programs--light {
  background: var(--surface-white);
}

.section-header {
  text-align: center;
  max-width: 760px;
  margin: 0 auto 56px;
}

.section-eyebrow {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  font-size: var(--text-sm);
  font-weight: 800;
  color: var(--gold-500);
  text-transform: uppercase;
  letter-spacing: 0.08em;
  margin-bottom: 12px;
}

.section-main-title {
  font-family: var(--font-display);
  font-size: clamp(2rem, 3.2vw, 2.75rem);
  font-weight: 800;
  color: var(--navy-900);
  line-height: 1.2;
  letter-spacing: -0.025em;
  margin-bottom: 16px;
}

.section-subtitle {
  font-size: 1.1rem;
  color: var(--slate-600);
  line-height: 1.6;
}

.programs-bento-grid {
  max-width: 1320px;
  margin: 0 auto;
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 28px;
}

.program-bento-card {
  background: var(--surface-white);
  border: 1px solid var(--slate-200);
  border-radius: var(--radius-xl);
  overflow: hidden;
  box-shadow: var(--shadow-sm);
  display: flex;
  flex-direction: column;
  transition: transform var(--transition-smooth), box-shadow var(--transition-smooth), border-color var(--transition-smooth);
}

.program-bento-card:hover {
  transform: translateY(-4px);
  box-shadow: var(--shadow-xl);
  border-color: var(--gold-400);
}

.program-img-wrapper {
  position: relative;
  height: 250px;
  overflow: hidden;
}

.program-img-wrapper img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  transition: transform var(--transition-smooth);
}

.program-bento-card:hover .program-img-wrapper img {
  transform: scale(1.06);
}

.program-tag-chip {
  position: absolute;
  top: 16px;
  left: 16px;
  background: rgba(7, 31, 18, 0.85);
  backdrop-filter: blur(8px);
  color: var(--gold-400);
  font-size: var(--text-xs);
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.05em;
  padding: 4px 12px;
  border-radius: var(--radius-full);
  border: 1px solid rgba(212, 175, 55, 0.3);
}

.program-card-body {
  padding: 32px 28px;
  display: flex;
  flex-direction: column;
  flex-grow: 1;
}

.program-card-title {
  font-size: var(--text-xl);
  font-weight: 700;
  color: var(--navy-900);
  margin-bottom: 12px;
  line-height: 1.3;
}

.program-card-desc {
  font-size: var(--text-base);
  color: var(--slate-600);
  line-height: 1.6;
  margin-bottom: 24px;
  flex-grow: 1;
}

.program-card-btn {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  font-size: var(--text-sm);
  font-weight: 700;
  color: var(--navy-900);
  padding: 10px 0;
  transition: gap var(--transition-fast), color var(--transition-fast);
}

.program-card-btn:hover {
  color: var(--gold-500);
  gap: 12px;
}

.program-card-btn svg {
  width: 16px;
  height: 16px;
  transition: transform var(--transition-fast);
}

.program-card-btn:hover svg {
  transform: translateX(4px);
}

/* ==========================================================================
   8. WHY CHOOSE GTIS (VALUES & HOLISTIC EDUCATION)
   ========================================================================== */
.section-why-gtis {
  padding: var(--section-y) var(--gutter);
  background: var(--navy-950);
  background-image: radial-gradient(circle at 50% 0%, rgba(212, 175, 55, 0.08) 0%, transparent 60%);
  color: #FFFFFF;
}

.section-why-gtis .section-main-title {
  color: #FFFFFF;
}

.section-why-gtis .section-subtitle {
  color: var(--slate-300);
}

.roadmap-grid {
  max-width: 1320px;
  margin: 0 auto;
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: 24px;
  position: relative;
}

.roadmap-step-card {
  background: var(--slate-50);
  border: 1px solid var(--slate-200);
  border-radius: var(--radius-lg);
  padding: 32px 24px;
  display: flex;
  flex-direction: column;
  gap: 12px;
  position: relative;
  transition: transform var(--transition-base), box-shadow var(--transition-base), border-color var(--transition-base);
}

.roadmap-step-card:hover {
  background: var(--surface-white);
  border-color: var(--gold-500);
  box-shadow: var(--shadow-lg);
  transform: translateY(-4px);
}

.step-number-badge {
  width: 36px;
  height: 36px;
  border-radius: 50%;
  background: var(--navy-900);
  color: var(--gold-400);
  font-weight: 800;
  font-size: var(--text-sm);
  display: flex;
  align-items: center;
  justify-content: center;
}

.step-card-title {
  font-size: var(--text-lg);
  font-weight: 700;
  color: var(--navy-900);
}

.step-card-desc {
  font-size: var(--text-sm);
  color: var(--slate-600);
  line-height: 1.55;
}

/* ==========================================================================
   10. CAMPUS FACILITIES BENTO GALLERY
   ========================================================================== */
.section-campus {
  padding: var(--section-y) var(--gutter);
  background: var(--slate-50);
}

.campus-bento-grid {
  max-width: 1320px;
  margin: 0 auto;
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  grid-auto-rows: 240px;
  gap: 20px;
}

.campus-bento-item {
  position: relative;
  border-radius: var(--radius-lg);
  overflow: hidden;
  box-shadow: var(--shadow-md);
}

.campus-bento-item.span-2 {
  grid-column: span 2;
}

.campus-bento-item img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  transition: transform var(--transition-smooth);
}

.campus-bento-item:hover img {
  transform: scale(1.08);
}

.campus-bento-overlay {
  position: absolute;
  inset: 0;
  background: linear-gradient(180deg, transparent 40%, rgba(7, 31, 18, 0.85) 100%);
  display: flex;
  flex-direction: column;
  justify-content: flex-end;
  padding: 24px;
  color: #FFFFFF;
}

.campus-bento-title {
  font-size: var(--text-lg);
  font-weight: 700;
  color: #FFFFFF;
}

/* ==========================================================================
   12. HIGH-CONVERTING ADMISSIONS CTA BANNER
   ========================================================================== */
/* The school stands behind the invitation to come and see it.
   The photograph is the section's background with a green wash over it, rather
   than a separate plate below the text — the picture is the setting, not an
   illustration. The URL is relative to this stylesheet, which sits one level
   above assets/, so no PHP is needed to build it.
   The wash is deep enough to carry white body text over a photograph that has
   white rooftops in it; see the measured figures in the commit. */
.section-cta-banner {
  background-color: var(--green-900);
  background-image:
    linear-gradient(180deg, rgba(7, 31, 18, 0.90) 0%, rgba(7, 31, 18, 0.84) 45%, rgba(7, 31, 18, 0.92) 100%),
    url('assets/images/gtis-campus-banner.jpg');
  background-size: auto, cover;
  background-position: center, center;
  background-repeat: no-repeat, no-repeat;
  padding: var(--section-y) var(--gutter);
  color: #FFFFFF;
  text-align: center;
  position: relative;
  overflow: hidden;
}

/* Parallax is a nice touch on a desktop and a jank machine on a phone, where
   fixed attachment forces a repaint on every scroll frame. */
@media (min-width: 900px) and (prefers-reduced-motion: no-preference) {
  .section-cta-banner {
    background-attachment: scroll, fixed;
  }
}

.cta-banner-container {
  max-width: 840px;
  margin: 0 auto;
  position: relative;
  z-index: 2;
}

.cta-banner-title {
  font-family: var(--font-display);
  font-size: clamp(2.2rem, 3.8vw, 3.2rem);
  font-weight: 800;
  color: #FFFFFF;
  line-height: 1.2;
  margin-bottom: 20px;
}

.cta-banner-desc {
  font-size: 1.15rem;
  color: var(--slate-300);
  line-height: 1.65;
  margin-bottom: 36px;
}

.cta-btn-group {
  display: flex;
  justify-content: center;
  flex-wrap: wrap;
  gap: 16px;
}

/* ==========================================================================
   13. MODERN SITE FOOTER
   ========================================================================== */
.site-footer {
  background: var(--green-950);
  color: rgba(255, 255, 255, 0.68);
  padding: var(--section-y) var(--gutter) 28px;
}

.footer-container {
  max-width: var(--container);
  margin: 0 auto clamp(32px, 5vw, 52px);
  display: grid;
  gap: clamp(28px, 4vw, 44px);
}

.footer-col {
  min-width: 0;
}

.footer-brand-title {
  font-family: var(--font-display);
  font-size: 1.125rem;
  font-weight: 800;
  line-height: 1.3;
  color: #FFFFFF;
  margin-bottom: 12px;
}

.footer-mission-text {
  font-size: var(--text-sm);
  line-height: 1.7;
  color: rgba(255, 255, 255, 0.66);
  margin-bottom: 14px;
  max-width: 42ch;
}

.footer-motto-tag {
  font-family: var(--font-display);
  font-weight: 800;
  font-size: var(--text-sm);
  letter-spacing: 0.04em;
  color: var(--gold-400);
}

.footer-col-title {
  font-size: var(--text-xs);
  font-weight: 700;
  color: #FFFFFF;
  text-transform: uppercase;
  letter-spacing: 0.12em;
  margin-bottom: 16px;
}

.footer-links-list {
  list-style: none;
  display: flex;
  flex-direction: column;
  gap: 2px;
  margin: 0;
  padding: 0;
}

.footer-links-list a {
  display: flex;
  align-items: center;
  min-height: 40px;
  font-size: var(--text-md);
  color: rgba(255, 255, 255, 0.72);
  transition: color var(--transition-fast);
}

.footer-links-list a:hover {
  color: var(--gold-300);
}

.footer-contact-item {
  display: flex;
  align-items: flex-start;
  gap: 10px;
  font-size: var(--text-sm);
  line-height: 1.6;
  margin-bottom: 14px;
  color: rgba(255, 255, 255, 0.72);
}

.footer-contact-item svg {
  width: 17px;
  height: 17px;
  color: var(--gold-400);
  flex-shrink: 0;
  margin-top: 4px;
}

.footer-contact-item a {
  display: inline-flex;
  align-items: center;
  min-height: 32px;
  color: #FFFFFF;
  text-decoration: none;
  font-size: var(--text-md);
}

.footer-contact-item a:hover {
  color: var(--gold-300);
}

.footer-map-card {
  border-radius: var(--radius-md);
  overflow: hidden;
  height: 168px;
  border: 1px solid rgba(255, 255, 255, 0.14);
}

.footer-map-link {
  display: inline-flex;
  align-items: center;
  min-height: 36px;
  margin-top: 6px;
  font-size: var(--text-sm);
  color: var(--gold-400);
}

.footer-map-link:hover {
  color: var(--gold-300);
}

.footer-social-bar {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 8px;
  margin-top: 18px;
}

/* Labelled rather than icon-only: clearer for a parent scanning quickly. */
.social-icon-btn {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  min-height: 40px;
  padding: 8px 14px;
  border: 1px solid rgba(255, 255, 255, 0.18);
  border-radius: var(--radius-full);
  background: rgba(255, 255, 255, 0.05);
  color: #FFFFFF;
  font-size: var(--text-sm);
  font-weight: 600;
  transition: background var(--transition-fast), border-color var(--transition-fast);
}

.social-icon-btn:hover {
  background: rgba(255, 255, 255, 0.11);
  border-color: var(--gold-400);
  color: #FFFFFF;
}

.social-icon-btn svg {
  width: 17px;
  height: 17px;
  flex-shrink: 0;
}

.footer-bottom {
  max-width: var(--container);
  margin: 0 auto;
  padding-top: 24px;
  border-top: 1px solid rgba(255, 255, 255, 0.1);
  display: flex;
  justify-content: space-between;
  align-items: center;
  gap: 12px;
  font-size: var(--text-xs);
  color: rgba(255, 255, 255, 0.5);
}

.footer-bottom-links {
  display: flex;
  flex-wrap: wrap;
  gap: 4px 18px;
}

.footer-bottom-links a {
  display: inline-flex;
  align-items: center;
  min-height: 36px;
}

.footer-bottom-links a {
  color: rgba(255, 255, 255, 0.66);
}

.footer-bottom-links a:hover {
  color: var(--gold-300);
}

/* ==========================================================================
   14. LAYOUT: MOBILE FIRST
   Every multi-column grid in this theme collapses to a single column here and
   then earns its columns back at a breakpoint. These rules sit after the
   section definitions on purpose — the phone layout is the baseline, and wider
   screens are the enhancement.
   ========================================================================== */
.stats-grid,
.programs-bento-grid,
  .roadmap-grid,
.campus-bento-grid,
  .pillars-mission-grid,
.footer-container,
.contact-actions-container,
.contact-main-grid,
.form-grid-2 {
  grid-template-columns: 1fr;
}

.campus-bento-item.span-2 {
  grid-column: span 1;
}

/* Two-up: comfortable from the large-phone / small-tablet range. */
@media (min-width: 600px) {
  .stats-grid,
  .roadmap-grid,
  .contact-actions-container,
  .form-grid-2 {
    grid-template-columns: repeat(2, 1fr);
  }
}

@media (min-width: 760px) {
  .programs-bento-grid,
      .campus-bento-grid,
  .footer-container {
    grid-template-columns: repeat(2, 1fr);
  }

  .campus-bento-item.span-2 {
    grid-column: span 2;
  }
}

/* Three- and four-up: desktop. */
@media (min-width: 1024px) {
  .roadmap-grid,
  .contact-actions-container {
    grid-template-columns: repeat(4, 1fr);
  }

  /* The stats strip stays two up. Four across reads as a sequence of steps;
     these are four independent facts about the school. */
  .stats-grid {
    grid-template-columns: repeat(2, 1fr);
    max-width: 900px;
    margin-left: auto;
    margin-right: auto;
  }

  .programs-bento-grid,
      .pillars-mission-grid {
    grid-template-columns: repeat(3, 1fr);
  }

  .campus-bento-grid {
    grid-template-columns: repeat(4, 1fr);
  }

  .contact-main-grid {
    grid-template-columns: 1fr 1.15fr;
  }

  .footer-container {
    grid-template-columns: 1.3fr 0.9fr 1fr 1fr;
  }
}
@media (min-width: 1024px) {
  .hero-btn-group { justify-content: flex-start; }
}

/* Section rhythm and gutters scale with the viewport via the tokens, so the
   only thing left to do per breakpoint is the footer's bottom row. */
.footer-bottom {
  flex-direction: column;
  gap: 16px;
  text-align: center;
}

@media (min-width: 760px) {
  .footer-bottom {
    flex-direction: row;
    text-align: left;
  }
}

/* ==========================================================================
   16. REDUCED MOTION QUERY
   ========================================================================== */
@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: 0.01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.01ms !important;
    scroll-behavior: auto !important;
  }
}

/* ==========================================================================
   ADMISSIONS SCHEDULING STATUS STYLES
   ========================================================================== */
/* ==========================================================================
   OUR STORY — PHOTO TIMELINE
   A single vertical rail on every screen. Each milestone is a photograph and a
   short paragraph; on wider screens the photo moves alongside the text rather
   than above it. One layout, two proportions — nothing appears or disappears.
   ========================================================================== */
.section-history-timeline {
	padding: var(--section-y) var(--gutter);
	background: var(--green-950);
	color: #FFFFFF;
	/* The thread SVG is absolutely positioned with inset: 0 and expects to span
	   this section. Without a containing block here it resolves against the
	   initial containing block instead — the path then lives in document
	   coordinates, so anything that changes the page height above the timeline
	   (a lazy image loading) slides the milestones out from under the line. */
	position: relative;
}

.section-history-timeline .section-main-title {
	color: #FFFFFF;
}

.section-history-timeline .section-subtitle {
	color: rgba(255, 255, 255, 0.72);
}

.section-history-timeline .section-eyebrow {
	color: var(--gold-300);
	border-color: rgba(212, 175, 55, 0.35);
	background: rgba(212, 175, 55, 0.08);
}

/* ==========================================================================
   OUR STORY — FLOWING TIMELINE
   One line runs the whole height of the section and every milestone hangs off
   it, so the eye follows a single thread from 2006 to today rather than reading
   a stack of separate cards.

   Phones keep the line at the left, because a centre line would leave two
   useless columns. From 900px the line moves to the centre and the milestones
   alternate either side of it. Same markup, same order, both ways.
   ========================================================================== */
.story-timeline {
	list-style: none;
	max-width: 1240px;
	margin: clamp(32px, 5vw, 56px) auto 0;
	padding: 0 0 0 34px;
	position: relative;
}

/* The thread. A serpentine rather than a straight rule — it reads as something
   travelling down the page. The amplitude is ±30px, so one period sweeps out to the left card, back across, out to the right card and back: the
   milestone nodes sit at a fixed x, so a wide swing would leave the line
   visibly missing them. One SVG period tiles vertically, so it works at any
   content height without JS measuring anything. */
.story-timeline::before {
	content: '';
	position: absolute;
	top: 0;
	bottom: 0;
	left: -30px;
	width: 76px;
	background-image: url("data:image/svg+xml,%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20width%3D%2276%22%20height%3D%22440%22%20viewBox%3D%220%200%2076%20440%22%20fill%3D%22none%22%3E%3Cpath%20d%3D%22M38%200C38%2055%2068%2055%2068%20110C68%20165%2038%20165%2038%20220C38%20275%208%20275%208%20330C8%20385%2038%20385%2038%20440%22%20stroke%3D%22%23D4AF37%22%20stroke-opacity%3D%220.3%22%20stroke-width%3D%222%22%20stroke-linecap%3D%22round%22%2F%3E%3C%2Fsvg%3E");
	background-repeat: repeat-y;
	background-position: top center;
}

.story-item {
	position: relative;
	padding-bottom: clamp(28px, 4vw, 48px);
}

.story-item:last-child {
	padding-bottom: 0;
}


@keyframes story-card-arrive {
	from {
		opacity: 0;
		transform: translateY(18px);
	}
	to {
		opacity: 1;
		transform: translateY(0);
	}
}

@keyframes story-card-arrive-left {
	from {
		opacity: 0;
		transform: translateX(-28px);
	}
	to {
		opacity: 1;
		transform: translateX(0);
	}
}

@keyframes story-card-arrive-right {
	from {
		opacity: 0;
		transform: translateX(28px);
	}
	to {
		opacity: 1;
		transform: translateX(0);
	}
}

@keyframes story-node-arrive {
	from {
		background: var(--green-950);
		box-shadow: none;
	}
	to {
		background: var(--gold-500);
		box-shadow: 0 0 0 5px rgba(212, 175, 55, 0.18);
	}
}

/* The node where a milestone meets the line. */
.story-marker {
	position: absolute;
	/* The thread is generated from where these sit, so moving the node moves the
	   rope. At the card's top corner, just outside it, on the side the rope runs
	   — the line then points at the top of each card while staying in open
	   space, visible along its whole length. Centring the node instead would put
	   the rope behind the card on a phone, where cards are full width. */
	top: -9px;
	left: -34px;
	transform: none;
	width: 16px;
	height: 16px;
	border-radius: 50%;
	background: var(--green-950);
	border: 2px solid var(--gold-500);
	z-index: 2;
	transition: background var(--transition-base), transform var(--transition-base);
}

.story-marker::after {
	content: '';
	position: absolute;
	inset: 3px;
	border-radius: 50%;
	background: var(--gold-500);
	opacity: 0;
	transition: opacity var(--transition-base);
}

.story-item:hover .story-marker {
	transform: scale(1.15);
}

.story-item:hover .story-marker::after {
	opacity: 1;
}

/* The short connector from the line to the card. */
.story-item::before {
	content: '';
	position: absolute;
	top: 33px;
	left: -19px;
	width: 19px;
	height: 2px;
	background: rgba(212, 175, 55, 0.45);
}

.story-card {
	display: grid;
	grid-template-columns: 1fr;
	background: rgba(255, 255, 255, 0.04);
	border: 1px solid rgba(255, 255, 255, 0.1);
	border-radius: var(--radius-lg);
	overflow: hidden;
	transition: border-color var(--transition-base), background var(--transition-base), transform var(--transition-base);
}

.story-item:hover .story-card {
	transform: translateY(-2px);
	border-color: var(--gold-400);
	background: rgba(255, 255, 255, 0.07);
}

.story-figure {
	margin: 0;
	background: var(--green-900);
	overflow: hidden;
}

.story-figure img {
	width: 100%;
	height: 190px;
	object-fit: cover;
	display: block;
	transition: transform var(--transition-smooth);
}

.story-item:hover .story-figure img {
	transform: scale(1.04);
}

.story-body {
	padding: 18px 20px 22px;
}

.story-year {
	display: inline-block;
	margin-bottom: 8px;
	padding: 4px 12px;
	border-radius: var(--radius-full);
	background: var(--gold-500);
	color: var(--green-950);
	font-family: var(--font-display);
	font-size: var(--text-xs);
	font-weight: 800;
	letter-spacing: 0.06em;
}

.story-title {
	font-family: var(--font-display);
	font-size: var(--text-lg);
	font-weight: 700;
	line-height: 1.3;
	color: #FFFFFF;
	margin-bottom: 8px;
}

.story-text {
	font-size: var(--text-sm);
	line-height: 1.7;
	color: rgba(255, 255, 255, 0.75);
	max-width: 60ch;
}

.story-footnote {
	max-width: 1240px;
	margin: clamp(24px, 4vw, 36px) auto 0;
	padding-left: 34px;
	font-size: var(--text-sm);
	color: rgba(255, 255, 255, 0.6);
}

.story-footnote a:hover {
	transform: translateY(-2px);
	background: rgba(255, 255, 255, 0.14);
	border-color: rgba(255, 255, 255, 0.34);
}

/* From tablet, the photograph sits beside the text. */
@media (min-width: 680px) {
	.story-card {
		grid-template-columns: 260px 1fr;
		align-items: stretch;
		min-height: 236px;
	}

	.story-figure {
		height: 100%;
	}

	/* No max-height. The card grows with its text — longest in Khmer — and a
	   capped image leaves a strip of card showing beneath it instead of filling
	   its half edge to edge. object-fit keeps the crop honest at any height. */
	.story-figure img {
		height: 100%;
		min-height: 186px;
	}

	.story-body {
		padding: 24px 26px;
		align-self: center;
	}

	.story-title {
		font-size: var(--text-xl);
	}

	.story-text {
		font-size: var(--text-base);
	}
}

/* From 1100px the thread runs down the centre and milestones alternate. Order is
   unchanged — only which side of the line each one sits on.

   Not before 1100px: each column is then under 430px, and after the photograph
   that leaves too little for the text. Below this the single-column layout
   already puts the photo beside the words with room to breathe. */
@media (min-width: 1100px) {
	.story-timeline {
		padding-left: 0;
	}

	.story-timeline::before,
	.story-timeline::after {
		left: calc(50% - 38px);
	}

	.story-item {
		width: calc(50% - 42px);
		padding-bottom: clamp(20px, 3vw, 36px);
	}

	/* Odd milestones to the left of the line, even to the right. */
	.story-item:nth-child(odd) {
		margin-right: auto;
	}

	.story-item:nth-child(even) {
		margin-left: auto;
	}

	.story-item:nth-child(odd) .story-marker {
		left: auto;
		right: -8px;
		top: -9px;
	}

	.story-item:nth-child(even) .story-marker {
		left: -8px;
		right: auto;
		top: -9px;
	}

	/* The stub only exists for the no-JS case: it reaches from the card to where
	   the centred fallback rule runs. The thread touches the card itself. */
	.story-item:nth-child(odd)::before {
		left: auto;
		right: -42px;
		width: 42px;
		top: calc(50% - 1px);
	}

	.story-item:nth-child(even)::before {
		left: -42px;
		width: 42px;
		top: calc(50% - 1px);
	}

	.is-threaded .story-item::before {
		display: none;
	}

	/* No JS: a plain centred rule, with the stubs reaching in to meet it. */
	.section-history-timeline:not(.is-threaded) .story-timeline::before {
		display: block;
		left: calc(50% - 1px);
		width: 2px;
		background-image: none;
		background: rgba(212, 175, 55, 0.28);
	}

	/* Interleave the two columns. A percentage pull applied only to even items
	   made the rhythm alternate between -29px and +36px; a uniform negative
	   margin between every pair gives one consistent overlap instead. The cards
	   sit on opposite sides of the line, so overlapping vertically is the point
	   and they can never collide. */
	.story-item {
		padding-bottom: 0;
	}

	.story-item + .story-item {
		margin-top: clamp(-72px, -5vw, -48px);
	}

	/* Milestones arrive from the side they sit on. */
	@media (prefers-reduced-motion: no-preference) {
		.is-threaded .story-item:nth-child(odd) .story-card {
			transform: translateX(-28px);
		}

		.is-threaded .story-item:nth-child(even) .story-card {
			transform: translateX(28px);
		}

		.is-threaded .story-item.is-lit .story-card {
			transform: translateX(0);
		}
	}

	/* Photo beside the text, and on the outer edge of each card — so the words
	   sit nearest the line the reader is following down the page. */
	.story-card {
		grid-template-columns: 200px 1fr;
		min-height: 250px;
	}

	.story-item:nth-child(even) .story-card {
		grid-template-columns: 1fr 200px;
	}

	.story-item:nth-child(even) .story-figure {
		order: 2;
	}

	.story-figure {
		background: transparent;
		height: 100%;
	}

	.story-figure img {
		height: 100%;
		min-height: 188px;
	}

	.story-body {
		padding: 22px 24px;
		align-self: center;
	}

	.story-footnote {
		padding-left: 0;
		text-align: center;
	}
}

@media (min-width: 1320px) {
	.story-item {
		width: calc(50% - 56px);
	}

	.story-card {
		grid-template-columns: 230px 1fr;
		min-height: 268px;
	}

	.story-item:nth-child(even) .story-card {
		grid-template-columns: 1fr 230px;
	}

	.story-figure img {
		min-height: 204px;
	}
}

/* Alternating layout depends on document order, which reversed motion would
   scramble; and the stagger is decorative. */
@media (prefers-reduced-motion: reduce) {
	.story-item:hover .story-figure img,
	.story-item:hover .story-card {
		transform: none;
	}

	.story-item:hover .story-marker {
		transform: none;
	}
}

/* Three Core Pillars */
.pillars-mission-grid {
	display: grid;
	grid-template-columns: repeat(3, 1fr);
	gap: 28px;
	max-width: 1240px;
	margin: 50px auto 0 auto;
	align-items: stretch;
}

@media (max-width: 900px) {
	.pillars-mission-grid {
		grid-template-columns: 1fr;
		gap: 20px;
	}
}

.pillar-mission-card {
	background: rgba(14, 56, 32, 0.65);
	border: 1px solid rgba(212, 175, 55, 0.2);
	border-radius: var(--radius-xl);
	padding: 32px 26px;
	position: relative;
	overflow: hidden;
	transition: transform var(--transition-base), border-color var(--transition-base), box-shadow var(--transition-base);
	display: flex;
	flex-direction: column;
	height: 100%;
	backdrop-filter: blur(12px);
	-webkit-backdrop-filter: blur(12px);
}

.pillar-mission-card:hover {
	transform: translateY(-4px);
	border-color: var(--gold-400);
	box-shadow: 0 16px 32px rgba(0, 0, 0, 0.3);
}

.pillar-letter-tag {
	width: 38px;
	height: 38px;
	border-radius: 50%;
	background: rgba(212, 175, 55, 0.15);
	border: 1px solid var(--gold-500);
	color: var(--gold-400);
	display: flex;
	align-items: center;
	justify-content: center;
	font-weight: 800;
	font-size: 1rem;
	margin-bottom: 20px;
}

.pillar-card-title {
	font-family: var(--font-display);
	font-size: var(--text-xl);
	font-weight: 700;
	color: #FFFFFF;
	margin-bottom: 14px;
	line-height: 1.3;
}

.pillar-card-desc {
	font-size: var(--text-base);
	line-height: 1.65;
	color: var(--slate-300);
}

/* Photo captions sit on a gradient rather than a flat wash, so light parts of
   an image cannot swallow the text. */
.campus-bento-overlay {
  background: linear-gradient(180deg, transparent 0%, rgba(7, 31, 18, 0.15) 45%, rgba(7, 31, 18, 0.88) 100%);
}

.campus-bento-item::after {
  content: '';
  position: absolute;
  inset: 0;
  border: 1px solid rgba(255, 255, 255, 0.1);
  border-radius: inherit;
  pointer-events: none;
}

.program-img-wrapper::after {
  content: '';
  position: absolute;
  inset: 0;
  background: linear-gradient(180deg, transparent 55%, rgba(7, 31, 18, 0.28) 100%);
  pointer-events: none;
}



.hero-btn-group {
	display: flex;
	flex-wrap: wrap;
	gap: 18px;
	justify-content: center;
	margin-bottom: 32px;
}

/* ==========================================================================
   CONTACT US PAGE & MOBILE-FIRST FORM STYLES
   ========================================================================== */
.section-contact-actions {
	padding: var(--section-y) var(--gutter) 0;
	max-width: 1240px;
	margin: 0 auto;
}

.contact-actions-container {
	display: grid;
	grid-template-columns: repeat(4, 1fr);
	gap: 18px;
}

@media (max-width: 1024px) {
	.contact-actions-container {
		grid-template-columns: repeat(2, 1fr);
	}
}

@media (max-width: 600px) {
	.contact-actions-container {
		grid-template-columns: 1fr;
	}
}

.quick-action-card {
	display: flex;
	align-items: center;
	gap: 16px;
	padding: 20px 22px;
	border-radius: var(--radius-xl);
	background: var(--navy-900);
	border: 1px solid rgba(255, 255, 255, 0.08);
	text-decoration: none;
	transition: transform var(--transition-smooth), box-shadow var(--transition-smooth), border-color var(--transition-smooth);
	backdrop-filter: blur(12px);
}

.quick-action-card:hover {
	transform: translateY(-2px);
	border-color: var(--gold-400);
	box-shadow: var(--shadow-lg);
}

.action-card-icon {
	width: 48px;
	height: 48px;
	border-radius: var(--radius-md);
	background: rgba(212, 175, 55, 0.14);
	color: var(--gold-400);
	display: flex;
	align-items: center;
	justify-content: center;
	flex-shrink: 0;
}

.action-card-icon svg {
	width: 26px;
	height: 26px;
}

.action-card-title {
	font-size: var(--text-xs);
	text-transform: uppercase;
	letter-spacing: 0.05em;
	color: var(--slate-400);
	font-weight: 700;
}

.action-card-val {
	font-family: var(--font-display);
	font-size: var(--text-lg);
	font-weight: 700;
	color: #FFFFFF;
	margin: 2px 0;
}

.action-card-hint {
	font-size: var(--text-xs);
	color: var(--gold-400);
}

/* Contact Main Section */
.section-contact-main {
	padding: var(--section-y) var(--gutter);
	max-width: 1280px;
	margin: 0 auto;
}

.contact-main-grid {
	display: grid;
	grid-template-columns: 1fr 1.15fr;
	gap: 48px;
	align-items: flex-start;
}

/* A grid item's default min-width is auto, which lets its intrinsic content
   size override the track and widen the column — exactly what the Turnstile
   widget in the form does: it renders once at its own natural width before its
   own script measures the column and shrinks it to fit, and Grid had already
   sized the track to that first, wider pass. min-width:0 lets the track win. */
.contact-main-grid > * {
	min-width: 0;
}

@media (max-width: 992px) {
	.contact-main-grid {
		grid-template-columns: 1fr;
		gap: 40px;
	}
}

.contact-bento-cards {
	display: flex;
	flex-direction: column;
	gap: 20px;
}

.contact-detail-box {
	background: rgba(7, 31, 18, 0.7);
	border: 1px solid rgba(255, 255, 255, 0.08);
	border-radius: var(--radius-xl);
	padding: 24px;
	display: flex;
	gap: 20px;
	align-items: flex-start;
	backdrop-filter: blur(12px);
	transition: background var(--transition-base), border-color var(--transition-base);
}

.contact-detail-box:hover {
	border-color: var(--gold-400);
	background: rgba(7, 31, 18, 0.8);
}

.contact-box-icon {
	width: 46px;
	height: 46px;
	border-radius: 12px;
	background: rgba(212, 175, 55, 0.12);
	border: 1px solid rgba(212, 175, 55, 0.3);
	color: var(--gold-400);
	display: flex;
	align-items: center;
	justify-content: center;
	flex-shrink: 0;
}

.contact-box-icon svg {
	width: 22px;
	height: 22px;
}

.contact-box-title {
	font-family: var(--font-display);
	font-size: var(--text-lg);
	font-weight: 700;
	color: #FFFFFF;
	margin-bottom: 6px;
}

.contact-box-desc {
	font-size: var(--text-base);
	line-height: 1.6;
	color: var(--slate-300);
	margin-bottom: 8px;
}

.contact-box-link {
	display: inline-flex;
	align-items: center;
	gap: 6px;
	color: var(--gold-400);
	font-size: var(--text-sm);
	font-weight: 700;
	text-decoration: none;
	transition: color 0.2s ease;
}

.contact-box-link:hover {
	color: var(--gold-300);
	text-decoration: underline;
}

.contact-phones-group {
	display: flex;
	flex-direction: column;
	gap: 8px;
}

.phone-dial-link {
	display: inline-flex;
	align-items: center;
	gap: 8px;
	font-size: var(--text-base);
	color: var(--gold-300);
	font-weight: 600;
	text-decoration: none;
}

.phone-dial-link:hover {
	text-decoration: underline;
}

/* Contact Form Card */
.contact-form-card {
	background: var(--green-900);
	border: 1px solid rgba(212, 175, 55, 0.28);
	border-radius: var(--radius-xl);
	padding: clamp(24px, 5vw, 40px) clamp(18px, 4vw, 32px);
	box-shadow: var(--shadow-lg);
}

@media (max-width: 600px) {
	.contact-form-card {
		padding: 28px 18px;
	}
}


.form-main-title {
	font-family: var(--font-display);
	font-size: 1.75rem;
	font-weight: 800;
	color: #FFFFFF;
	margin-bottom: 8px;
}

.form-sub-desc {
	font-size: var(--text-sm);
	color: var(--slate-300);
	margin-bottom: 24px;
	line-height: 1.5;
}

.gtis-mobile-form {
	display: flex;
	flex-direction: column;
	gap: 18px;
}

.form-group {
	display: flex;
	flex-direction: column;
	gap: 6px;
	text-align: left;
}

.form-grid-2 {
	display: grid;
	grid-template-columns: 1fr 1fr;
	gap: 16px;
}

@media (max-width: 600px) {
	.form-grid-2 {
		grid-template-columns: 1fr;
	}
}

.form-label {
	font-size: var(--text-sm);
	font-weight: 600;
	color: var(--slate-200);
}

.form-input,
.form-select,
.form-textarea {
	width: 100%;
	min-height: 50px;
	padding: 12px 16px;
	background: rgba(7, 31, 18, 0.7);
	border: 1px solid rgba(255, 255, 255, 0.15);
	border-radius: var(--radius-md);
	color: #FFFFFF;
	font-size: 1rem;
	font-family: inherit;
	transition: border-color var(--transition-base), box-shadow var(--transition-base), background var(--transition-base);
}

.form-input:focus,
.form-select:focus,
.form-textarea:focus {
	outline: none;
	border-color: var(--gold-500);
	box-shadow: 0 0 0 3px rgba(212, 175, 55, 0.2);
	background: rgba(7, 31, 18, 0.95);
}

.form-textarea {
	min-height: 110px;
	resize: vertical;
}

.form-submit-btn,
.btn--block {
	display: flex;
	width: 100%;
	margin-top: var(--space-sm);
}

/* Map Section */
.section-contact-map {
	padding: 0 var(--gutter) var(--section-y);
	max-width: 1280px;
	margin: 0 auto;
}

.full-map-wrapper {
	border-radius: var(--radius-lg);
	padding: 6px;
	background: linear-gradient(145deg, rgba(212, 175, 55, 0.3), rgba(255, 255, 255, 0.05));
	box-shadow: var(--shadow-lg);
}

/* ==========================================================================
   QUICK-ACTION DOCK (PHONES ONLY)
   Most parents arrive on a phone and want to call or message. These four stay
   within thumb reach; on tablet and up the header CTA takes over.
   ========================================================================== */
.mobile-action-dock {
	display: grid;
	grid-template-columns: repeat(4, 1fr);
	position: fixed;
	bottom: 0;
	left: 0;
	right: 0;
	z-index: 999;
	background: var(--green-950);
	border-top: 1px solid rgba(212, 175, 55, 0.28);
	padding-bottom: env(safe-area-inset-bottom, 0px);
	box-shadow: 0 -2px 12px rgba(7, 31, 18, 0.25);
}

/* Keep the dock from covering the end of the page. */
body {
	padding-bottom: calc(62px + env(safe-area-inset-bottom, 0px));
}

.dock-btn {
	display: flex;
	flex-direction: column;
	align-items: center;
	justify-content: center;
	gap: 3px;
	min-height: 58px;
	padding: 8px 4px;
	color: rgba(255, 255, 255, 0.82);
	font-size: 0.6875rem;
	font-weight: 600;
	line-height: 1.2;
	text-align: center;
	text-decoration: none;
	touch-action: manipulation;
	transition: color var(--transition-fast), background var(--transition-fast);
}

.dock-btn svg {
	width: 20px;
	height: 20px;
	flex-shrink: 0;
}

.dock-btn:active,
.dock-btn:hover {
	color: var(--gold-300);
	background: rgba(255, 255, 255, 0.06);
}

@media (min-width: 768px) {
	.mobile-action-dock {
		display: none;
	}

	body {
		padding-bottom: 0;
	}
}

/* ==========================================================================
   PREMIER INTERNATIONAL SCHOOL FULL-BLEED PANORAMIC HERO
   ========================================================================== */
/* Tall enough to feel like an arrival, short enough that the first section is
   still reachable on a phone without a long scroll. */
.hero-panorama-showcase {
	position: relative;
	min-height: min(78vh, 600px);
	display: flex;
	align-items: center;
	justify-content: center;
	overflow: hidden;
	background: var(--green-950);
	color: #FFFFFF;
	padding: clamp(56px, 12vw, 110px) var(--gutter) clamp(48px, 9vw, 80px);
}

@media (min-width: 1024px) {
	.hero-panorama-showcase {
		min-height: min(84vh, 780px);
	}
}

.hero-panorama-backdrop {
	position: absolute;
	top: 0;
	left: 0;
	right: 0;
	bottom: 0;
	background-size: cover;
	background-position: center 38%;
	background-repeat: no-repeat;
	z-index: 1;
	transform: scale(1.04);
	transform-origin: center 45%;
	will-change: transform;
}

/* A slow drift inwards as the page settles. Hover was the old trigger, which
   meant it never happened on a phone. */
@media (prefers-reduced-motion: no-preference) {
	.hero-panorama-backdrop {
		animation: hero-drift 24s cubic-bezier(0.22, 0.61, 0.36, 1) both;
	}
}

@keyframes hero-drift {
	from { transform: scale(1.04); }
	to   { transform: scale(1.16); }
}

.hero-panorama-overlay {
	position: absolute;
	top: 0;
	left: 0;
	right: 0;
	bottom: 0;
	/* A pool of shade behind the words only, so the headline stays legible while
	   the corners of the photograph stay open.

	   The depth is not a taste choice. The mark is gold (#E5C564, relative
	   luminance 0.575), which tops out at 1.68:1 against white — so wherever the
	   headline crosses a pale rooftop the contrast collapses, and measurement put
	   the worst point at 1.6:1 with a fifth of the line under 4.5:1. Reaching the
	   3:1 that large text requires means holding the backdrop under luminance
	   0.158, which needs roughly 0.86 alpha over a white roof. Hence the centre
	   stop. Every other photograph in the library measured worse here, so this is
	   the picture staying and the shade doing the work. */
	background:
		radial-gradient(ellipse 78% 60% at 50% 44%, rgba(7, 31, 18, 0.80) 0%, rgba(7, 31, 18, 0.70) 38%, rgba(7, 31, 18, 0.34) 68%, rgba(7, 31, 18, 0) 100%),
		linear-gradient(180deg, rgba(7, 31, 18, 0.42) 0%, rgba(7, 31, 18, 0.14) 42%, rgba(7, 31, 18, 0.5) 100%);
	z-index: 2;
}

.hero-panorama-container {
	position: relative;
	z-index: 3;
	max-width: 1200px;
	width: 100%;
	margin: 0 auto;
	display: flex;
	flex-direction: column;
	align-items: center;
	text-align: center;
}

.hero-panorama-editorial {
	max-width: 1240px;
	margin: 0 auto;
	display: flex;
	flex-direction: column;
	align-items: center;
}


/* ==========================================================================
   HERO — THE ACRONYM UNFOLDS
   GTIS is not swapped for the school's name; it grows into it. Each initial
   holds its position while the rest of its word expands out of it:

     GTIS  ->  Glad TIS  ->  Glad Tidings IS  ->  Glad Tidings International S
           ->  Glad Tidings International School

   The four initials never move and never change size. That rules out animating
   font-size, so the whole mark is set at one size — chosen so the finished name
   fits on two lines — and only the width of each suffix animates. The line break
   after "Tidings" is not forced; the text simply outgrows its measure and wraps
   there, which is why the measure is set in ch and scales with the type.

   Everything rests visible, so nothing is hidden if animations never run, and
   the whole sequence is skipped under prefers-reduced-motion.
   ========================================================================== */
.hero-panorama-editorial {
	--hero-title-size: var(--text-4xl);
}

/* The mark is set at 1.5x the motto beneath it. The initials may not resize, so
   that one size has to carry the finished name too — which on a narrow screen
   would run off the edge. min() takes the smaller of the two: exactly 2x where
   there is room for it, and width-bound where there is not.

   The measure is in ch, so it scales with the type: "GTIS" sits on one line, and
   as the words grow out the name wraps a word at a time. */
.hero-eyebrow {
	/* Wider than the text column it sits in. At 2x the motto, "International
	   School" needs about 1250px; the 960px measure below would force a third
	   line. The hero clips its own overflow, so breaking out is safe. */
	width: min(100%, 1240px);
	margin: 0 auto clamp(10px, 1.4vw, 20px);
	font-family: var(--font-display);
	font-size: min(calc(var(--hero-title-size) * 2), 8.1vw);
	font-weight: 800;
	line-height: 1.12;
	letter-spacing: 0.005em;
	text-align: center;
	color: var(--gold-400);
	text-shadow: 0 2px 18px rgba(7, 31, 18, 0.75);
	/* Two lines of height are held from the first frame, though "GTIS" only fills
	   one, so the name can take its second line as it unfolds without pushing the
	   motto, paragraph and buttons down the page. 1.12 is the line-height above. */
	min-height: calc(2 * 1.12em);
	display: flex;
	flex-wrap: wrap;
	justify-content: center;
	align-items: flex-start;
	align-content: flex-start;
}

.mark-word {
	white-space: nowrap;
}

.mark-rest {
	display: inline-block;
	overflow: hidden;
	white-space: nowrap;
	vertical-align: bottom;
	max-width: 0;
	/* Room for the descender on the g in "Tidings" — overflow:hidden clips to
	   the padding box, so without this the tail of the g is cut off. The
	   negative margin keeps the line box unchanged. */
	padding-bottom: 0.24em;
	margin-bottom: -0.24em;
}

@media (prefers-reduced-motion: no-preference) {
	.mark-rest {
		animation: mark-unfold cubic-bezier(0.4, 0, 0.2, 1) both;
	}

	/* "GTIS" is left to stand on its own until 1500ms before the first word opens.
	   --mark-w is the width each word grows into, a little over the text's own
	   width so the last letter is never shaved. */
	.mark-word:nth-child(1) .mark-rest { animation-duration: 420ms; animation-delay: 1500ms; --mark-w: 2.6ch; }
	.mark-word:nth-child(2) .mark-rest { animation-duration: 460ms; animation-delay: 1860ms; --mark-w: 4.8ch; }
	.mark-word:nth-child(3) .mark-rest { animation-duration: 600ms; animation-delay: 2260ms; --mark-w: 9.35ch; }
	.mark-word:nth-child(4) .mark-rest { animation-duration: 420ms; animation-delay: 2800ms; --mark-w: 4.2ch; }

	/* The motto is written on, one word at a time, left to right — the reveal a
	   hand makes rather than a block sliding into place. The inset bleeds past
	   the top and bottom so Caveat's ascenders and tails are never clipped. */
	@keyframes hero-write-on {
		from { clip-path: inset(-0.35em 100% -0.35em -0.1em); }
		to   { clip-path: inset(-0.35em -0.1em -0.35em -0.1em); }
	}

	.hero-title-lead {
		animation: hero-write-on 620ms cubic-bezier(0.33, 0, 0.2, 1) both;
	}

	.hero-motto .hero-title-lead:nth-child(1) { animation-delay: 3350ms; }
	.hero-motto .hero-title-lead:nth-child(2) { animation-delay: 3800ms; }
	.hero-motto .hero-title-lead:nth-child(3) { animation-delay: 4250ms; }

	.hero-cinematic-desc { animation-delay: 4800ms; }

	.hero-cinematic-desc {
		animation: hero-rise-in 600ms ease-out 4050ms both;
	}

	.hero-btn-group {
		animation: hero-rise-in 550ms ease-out 4250ms both;
	}
}

/* max-width caps at the natural width, so a slightly generous target simply
   means the word finishes a touch early rather than being clipped. */
@keyframes mark-unfold {
	from { max-width: 0; }
	to   { max-width: var(--mark-w, 14ch); }
}

@keyframes hero-rise-in {
	from { opacity: 0; transform: translateY(14px); }
	to   { opacity: 1; transform: translateY(0); }
}


.hero-cinematic-title {
	font-family: var(--font-display);
	font-size: var(--hero-title-size);
	font-weight: 800;
	line-height: 1.1;
	color: #FFFFFF;
	letter-spacing: -0.03em;
	margin-bottom: 22px;
}

/* The three motto words wrap onto separate lines on narrow phones and settle
   onto one line as soon as there is room, rather than being forced either way. */
.hero-motto {
	display: flex;
	flex-wrap: wrap;
	justify-content: center;
	gap: 0.1em 0.35em;
}

.hero-title-lead {
	color: #FFFFFF;
	/* Caveat runs small and light against a sans of the same size, so it is set
	   larger and heavier to hold its own beside the mark above it. */
	font-family: var(--font-script);
	font-weight: 700;
	/* Capped against the viewport so the three words stay on one line on the
	   narrowest phone. They wrapped at 320 and 360px otherwise, which broke the
	   line the motto is meant to be read as. */
	font-size: min(1.5em, 13.5vw);
	line-height: 1.05;
	letter-spacing: 0;
	text-shadow: 0 2px 14px rgba(7, 31, 18, 0.8);
}

/* The Khmer motto stays on one line.
   Kantumruy Pro sets much wider than Caveat at the same size, so the three
   words wrapped below 430px. Capping against the viewport width keeps them on
   one line down to the narrowest phone without letting them overflow — a cap,
   not a fixed size, so the motto still scales up with everything else. */
html[lang="km"] .hero-title-lead {
	font-size: min(1.5em, 9.2vw);
}

/* The Chinese motto stays on one line too. Nine full-width characters, each a
   square em, so the cap is tighter than the Khmer one; and the full stop 。
   already carries its own space, so the gap between the words goes. */
html[lang="zh-Hans"] .hero-motto {
	flex-wrap: nowrap;
	gap: 0;
}

html[lang="zh-Hans"] .hero-title-lead {
	font-size: min(1.5em, 9vw);
	white-space: nowrap;
}

/* A script face needs room below the baseline for its tails. */
.hero-motto {
	padding-bottom: 0.12em;
}

.hero-highlight-word {
	color: var(--gold-400);
	font-weight: 800;
	letter-spacing: -0.02em;
	text-shadow: 0 2px 16px rgba(212, 175, 55, 0.35);
}

.hero-cinematic-desc {
	font-size: clamp(1.05rem, 1.6vw, 1.22rem);
	line-height: 1.7;
	color: #E2E8E4;
	max-width: 820px;
	margin: 0 auto 34px auto;
	text-shadow: 0 2px 12px rgba(7, 31, 18, 0.8);
}

/* ==========================================================================
   UNIFIED EDITORIAL CONTENT STYLING FOR ALL SUBPAGES
   ========================================================================== */
/* Editorial content — WordPress-authored pages and posts.
   This block was written for a dark panel but has always been rendered inside a
   white <main>, so body copy computed to roughly 1.2:1 against the page. It is
   now themed for the light surface it actually sits on. */
.entry-content {
	font-family: var(--font-body);
	color: var(--ink-700);
	font-size: var(--text-lg);
	line-height: 1.8;
	max-width: var(--measure);
}

.entry-content > * + * {
	margin-top: 1.2em;
}

.entry-content h1,
.entry-content h2,
.entry-content h3,
.entry-content h4,
.entry-content h5,
.entry-content h6 {
	font-family: var(--font-display);
	color: var(--green-900);
	line-height: 1.25;
	margin-top: 1.8em;
	margin-bottom: 0.5em;
}

.entry-content > :first-child {
	margin-top: 0;
}

.entry-content h2 {
	font-size: var(--text-2xl);
	padding-bottom: 0.35em;
	border-bottom: 1px solid var(--border-soft);
}

.entry-content h3 {
	font-size: var(--text-xl);
	color: var(--green-800);
}

.entry-content h4 {
	font-size: var(--text-lg);
	color: var(--green-800);
}

.entry-content p,
.entry-content ul,
.entry-content ol {
	color: var(--ink-700);
}

.entry-content ul,
.entry-content ol {
	padding-left: 1.4em;
}

.entry-content li {
	margin-bottom: 0.5em;
}

.entry-content li::marker {
	color: var(--gold-600);
}

.entry-content a {
	color: var(--green-700);
	text-decoration: underline;
	text-underline-offset: 3px;
	text-decoration-thickness: 1px;
}

.entry-content a:hover {
	color: var(--green-600);
	text-decoration-thickness: 2px;
}

.entry-content strong {
	color: var(--ink-900);
	font-weight: 700;
}

.entry-content blockquote {
	border-left: 3px solid var(--gold-500);
	background: var(--green-50);
	padding: var(--space-lg);
	margin: 2em 0;
	border-radius: 0 var(--radius-md) var(--radius-md) 0;
	color: var(--ink-800);
	font-size: var(--text-lg);
}

.entry-content blockquote p {
	color: inherit;
}

.entry-content code {
	font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
	font-size: 0.9em;
	background: var(--ink-100);
	color: var(--green-900);
	padding: 0.15em 0.4em;
	border-radius: var(--radius-sm);
}

.entry-content img {
	max-width: 100%;
	height: auto;
	border-radius: var(--radius-lg);
	margin: 2em 0;
	box-shadow: var(--shadow-md);
}

.entry-content figcaption {
	font-size: var(--text-sm);
	color: var(--ink-500);
	margin-top: -1.4em;
	margin-bottom: 2em;
}

.entry-content hr {
	border: 0;
	border-top: 1px solid var(--border-soft);
	margin: 2.5em 0;
}

/* Tables can be wider than the measure, so they scroll rather than push the
   page sideways. */
.entry-content table {
	width: 100%;
	border-collapse: collapse;
	margin: 2em 0;
	background: var(--surface-white);
	border: 1px solid var(--border-soft);
	border-radius: var(--radius-md);
	overflow: hidden;
	font-size: var(--text-base);
}

.entry-content th,
.entry-content td {
	padding: 12px var(--space-md);
	border: 1px solid var(--border-soft);
	text-align: left;
}

.entry-content th {
	background: var(--green-50);
	color: var(--green-900);
	font-weight: 700;
}

/* ==========================================================================
   EMPTY STATE
   Shown when a search or archive returns nothing. Previously white text on the
   white <main>, so it did not appear at all.
   ========================================================================== */
.empty-state {
	max-width: 520px;
	margin: 0 auto;
	padding: clamp(48px, 9vw, 88px) var(--gutter);
	text-align: center;
}

.empty-state-icon {
	display: inline-flex;
	align-items: center;
	justify-content: center;
	width: 64px;
	height: 64px;
	margin-bottom: var(--space-lg);
	border-radius: 50%;
	background: var(--green-50);
	color: var(--green-600);
}

.empty-state-icon svg {
	width: 28px;
	height: 28px;
}

.empty-state-title {
	font-family: var(--font-display);
	font-size: var(--text-2xl);
	font-weight: 700;
	color: var(--green-900);
	margin-bottom: var(--space-sm);
}

.empty-state-text {
	color: var(--ink-600);
	line-height: 1.7;
	margin-bottom: var(--space-lg);
}


/* ==========================================================================
   PAGE CONTAINERS
   The <main> geometry for WordPress-authored pages, previously written inline
   with three different widths. Tokenised at those same widths — narrowing them
   to one measure is a design decision, not a refactor.
   ========================================================================== */
.page-main {
	margin: 0 auto;
	padding: var(--section-y) var(--gutter);
	min-height: 450px;
}

.page-main--wide   { max-width: 1240px; }
.page-main--text   { max-width: 1040px; }
.page-main--narrow { max-width: 900px; }

.pagination-wrap {
	margin-top: var(--space-2xl);
	text-align: center;
}

/* ==========================================================================
   SINGLE POST
   ========================================================================== */

.post-hero-image {
	border-radius: var(--radius-lg);
	overflow: hidden;
	margin-bottom: var(--space-2xl);
	box-shadow: var(--shadow-lg);
}

.post-meta-row {
	display: flex;
	flex-wrap: wrap;
	justify-content: space-between;
	align-items: center;
	gap: var(--space-md);
	margin-top: var(--space-2xl);
	padding-top: var(--space-lg);
	border-top: 1px solid var(--border-soft);
}

.post-meta-author {
	font-size: var(--text-sm);
	color: var(--ink-500);
}

/* The "see all" link that closes a section showing only the first few of
   something. Centred, and clear of the grid above it. */
.section-more {
	display: flex;
	justify-content: center;
	margin-top: var(--space-xl);
}

/* --------------------------------------------------------------------------
   The rest of the photographs from a news post.

   A school event arrives as an album — sports day is 55 pictures, a visiting
   team 160. One becomes the article's lead image and the others belong here,
   below the words rather than interrupting them.

   auto-fill with a minimum rather than a fixed column count: the same rule
   gives one column on a phone and four on a desktop, and it degrades to
   whatever fits in between without a breakpoint for each step.
   -------------------------------------------------------------------------- */

.post-gallery {
	margin-top: var(--space-2xl);
	padding-top: var(--space-lg);
	border-top: 1px solid var(--border-soft);
}

.post-gallery-title {
	font-size: var(--text-lg);
	font-weight: 700;
	color: var(--green-800);
	margin: 0 0 var(--space-md);
}

.post-gallery-grid {
	display: grid;
	grid-template-columns: repeat(auto-fill, minmax(180px, 1fr));
	gap: var(--space-sm);
}

.post-gallery-item {
	margin: 0;
	border-radius: var(--radius-md);
	overflow: hidden;
	background: var(--ink-100);
	box-shadow: var(--shadow-sm);
}

/* Every photograph is a different shape and the school shoots both portrait and
   landscape. A fixed aspect ratio keeps the grid rows level; object-fit stops
   that cropping from squashing anybody. */
.post-gallery-item img {
	display: block;
	width: 100%;
	aspect-ratio: 4 / 3;
	object-fit: cover;
	transition: transform 0.4s ease;
}

.post-gallery-item:hover img {
	transform: scale(1.03);
}

@media (prefers-reduced-motion: reduce) {
	.post-gallery-item img,
	.post-gallery-item:hover img {
		transition: none;
		transform: none;
	}
}

/* A post whose content was a video. The site does not host it, so the article
   carries a way to reach it instead of a gap where the picture would be. */
.post-video-note {
	display: flex;
	justify-content: center;
	margin: var(--space-xl) 0 0;
}

/* --------------------------------------------------------------------------
   The photo viewer.

   Each photograph in a news post is a link to the image file; the viewer
   intercepts the click and shows it full size over the page. Everything here
   describes the overlay — with JavaScript off, none of it is reached and the
   link behaves as a link.
   -------------------------------------------------------------------------- */

.post-gallery-hint {
	margin: -8px 0 var(--space-md);
	font-size: var(--text-sm);
	color: var(--ink-500);
}

/* A photograph that opens is worth signalling as one. */
.photo-view {
	display: block;
	position: relative;
	cursor: zoom-in;
}

.photo-view:focus-visible {
	outline: 3px solid var(--gold-500);
	outline-offset: 3px;
}

.photo-viewer {
	position: fixed;
	inset: 0;
	z-index: 9999;
	display: flex;
	align-items: center;
	justify-content: center;
	padding: clamp(12px, 4vw, 48px);
}

.photo-viewer[hidden] {
	display: none;
}

/* Near-black, warmed towards the brand green rather than a flat grey. */
.photo-viewer-backdrop {
	position: absolute;
	inset: 0;
	background: rgba(7, 31, 18, 0.94);
	cursor: zoom-out;
}

.photo-viewer-stage {
	position: relative;
	margin: 0;
	display: flex;
	flex-direction: column;
	align-items: center;
	gap: var(--space-sm);
	max-width: 100%;
}

/* max-width/height and auto sizing, never a fixed width: the source pictures
   are 640px wide, and stretching one across a 1440px screen makes it worse,
   not bigger. It fills a phone and sits at its own size on a desktop. */
.photo-viewer-image {
	display: block;
	width: auto;
	height: auto;
	max-width: 100%;
	max-height: calc(100vh - 170px);
	border-radius: var(--radius-md);
	background: var(--green-950);
	box-shadow: 0 24px 60px rgba(0, 0, 0, 0.5);
}

.photo-viewer-caption {
	max-width: 62ch;
	text-align: center;
	font-size: var(--text-sm);
	line-height: 1.5;
	color: rgba(255, 255, 255, 0.82);
}

.photo-viewer-caption[hidden] {
	display: none;
}

.photo-viewer-count {
	position: absolute;
	left: 50%;
	bottom: clamp(12px, 3vw, 26px);
	transform: translateX(-50%);
	margin: 0;
	font-size: var(--text-sm);
	font-weight: 600;
	color: rgba(255, 255, 255, 0.66);
	letter-spacing: 0.02em;
}

.photo-viewer-btn {
	position: absolute;
	display: grid;
	place-items: center;
	/* 48px: comfortably past the 44px minimum for a touch target. */
	width: 48px;
	height: 48px;
	padding: 0;
	border: 1px solid rgba(255, 255, 255, 0.22);
	border-radius: var(--radius-full);
	background: rgba(7, 31, 18, 0.72);
	color: #fff;
	cursor: pointer;
	transition: background var(--transition-fast), border-color var(--transition-fast);
}

.photo-viewer-btn svg {
	width: 22px;
	height: 22px;
	fill: none;
	stroke: currentColor;
	stroke-width: 2.2;
	stroke-linecap: round;
	stroke-linejoin: round;
}

.photo-viewer-btn:hover {
	background: rgba(26, 99, 59, 0.9);
	border-color: rgba(255, 255, 255, 0.42);
}

.photo-viewer-btn:focus-visible {
	outline: 3px solid var(--gold-500);
	outline-offset: 2px;
}

.photo-viewer-btn[hidden] {
	display: none;
}

.photo-viewer-close {
	top: clamp(12px, 3vw, 26px);
	right: clamp(12px, 3vw, 26px);
}

.photo-viewer-prev {
	left: clamp(8px, 2.5vw, 26px);
	top: 50%;
	transform: translateY(-50%);
}

.photo-viewer-next {
	right: clamp(8px, 2.5vw, 26px);
	top: 50%;
	transform: translateY(-50%);
}

/* On a phone the arrows would sit over the picture, so they move under it and
   the picture gets the room back. */
@media (max-width: 600px) {
	.photo-viewer-image {
		max-height: calc(100vh - 210px);
	}

	.photo-viewer-prev,
	.photo-viewer-next {
		top: auto;
		bottom: clamp(12px, 3vw, 26px);
		transform: none;
	}

	.photo-viewer-prev {
		left: calc(50% - 84px);
	}

	.photo-viewer-next {
		right: calc(50% - 84px);
	}

	.photo-viewer-count {
		bottom: calc(clamp(12px, 3vw, 26px) + 14px);
	}
}

/* The page behind must not scroll while the viewer is over it. */
html.photo-viewer-open,
html.photo-viewer-open body {
	overflow: hidden;
}

/* Credit back to where the school first published it. */
.post-meta-source {
	display: block;
	margin-top: 4px;
	font-size: var(--text-sm);
	color: var(--ink-500);
}

.post-meta-source a {
	color: var(--green-700);
	text-decoration: underline;
	text-underline-offset: 2px;
}

.post-meta-author strong {
	color: var(--green-800);
	font-weight: 700;
}

/* ==========================================================================
   FOCUS VISIBILITY
   The theme previously had one global ring, 2px solid gold — which is invisible
   on the primary CTA, because that button has a gold gradient background.

   Rather than give every component its own rule, the ring colour is a custom
   property. It inherits, so a dark section overrides it once and every control
   inside picks it up. Using outline (not box-shadow) leaves each component's
   own shadow intact.
   ========================================================================== */
:root {
	--focus-ring: var(--green-800);
}

/* Sections that sit on dark green need a light ring. */
.site-header,
.announce-bar,
.hero-panorama-showcase,
.page-header,
.section-history-timeline,
.section-why-gtis,
.section-cta-banner,
.site-footer,
.mobile-action-dock,
.mobile-panel,
.contact-form-card,
.quick-action-card,
.contact-detail-box {
	--focus-ring: var(--gold-300);
}

/* The header is white, so it wants the dark ring despite being listed above
   for its dark children. Reset it explicitly. */
.site-header {
	--focus-ring: var(--green-800);
}

:focus-visible {
	outline: 3px solid var(--focus-ring);
	outline-offset: 2px;
	border-radius: var(--radius-sm);
}

/* Pill-shaped controls keep their shape when focused. */
.btn-hero-primary:focus-visible,
.btn-hero-secondary:focus-visible,
.btn-visit:focus-visible,
.lang-btn:focus-visible,
.social-icon-btn:focus-visible {
	border-radius: var(--radius-full);
}

/* Cards that carry their own dark background: state the ring colour outright
   rather than relying on the inherited custom property. */
.quick-action-card:focus-visible,
.contact-detail-box:focus-visible,
.campus-bento-item:focus-visible,
.story-card:focus-visible,
.program-bento-card:focus-visible,
.pillar-mission-card:focus-visible {
	outline: 3px solid var(--gold-300);
	outline-offset: 3px;
}

/* Form fields previously set `outline: none` at higher specificity than the
   global rule, so keyboard users got no ring at all. The gold border and glow
   stay; the ring is added back. */
.form-input:focus-visible,
.form-select:focus-visible,
.form-textarea:focus-visible {
	outline: 3px solid var(--focus-ring);
	outline-offset: 2px;
}

/* ==========================================================================
   TAP TARGETS
   Several controls are visually smaller than a comfortable 44px. Growing them
   would push the header down on every page, so the hit area is expanded with an
   absolutely-positioned pseudo-element instead — out of flow, so layout is
   unchanged by construction.
   ========================================================================== */
.lang-btn,
.footer-contact-item a,
.footer-map-link,
.footer-bottom-links a,
.contact-box-link,
.phone-dial-link,
.page-breadcrumb a {
	position: relative;
}

.lang-btn::after,
.footer-contact-item a::after,
.footer-map-link::after,
.footer-bottom-links a::after,
.contact-box-link::after,
.phone-dial-link::after,
.page-breadcrumb a::after {
	content: '';
	position: absolute;
	left: 0;
	right: 0;
	top: 50%;
	transform: translateY(-50%);
	height: var(--tap);
	min-height: 100%;
}

/* Inside the language toggle the two buttons sit 2px apart; an expander wider
   than the button would overlap its neighbour and steal the tap. */
.lang-btn::after {
	left: -1px;
	right: -1px;
}

/* ==========================================================================
   TEMPLATE MODIFIERS
   Extracted from inline style attributes. Appended here so each sits after the
   base class it modifies — they share specificity, so source order decides.
   Values carried across verbatim; this is a refactor, not a redesign.
   ========================================================================== */

.hero-btn-group--spaced-top {
	margin-top: 30px;
}

.section-header--left {
	text-align: left;
	margin-bottom: 28px;
}

.section-main-title--compact {
	font-size: 2.2rem;
}

.full-map-frame {
	border-radius: var(--radius-lg);
}

.contact-form-card--centered {
	max-width: 900px;
	margin: 0 auto;
	text-align: center;
}

.form-main-title--lg {
	font-size: 2.2rem;
}

.form-sub-desc--centered-tight {
	max-width: 680px;
	margin: 0 auto 12px;
}

.form-sub-desc--centered {
	max-width: 680px;
	margin: 0 auto 28px;
}

.pillar-card-lead {
	display: block;
	color: var(--gold-400);
	margin-bottom: var(--space-sm);
}

.pillar-card-lead--motto {
	font-size: 1.15rem;
	letter-spacing: 0.06em;
}

.section-history-timeline--teaser {
	text-align: center;
	padding: 70px var(--space-lg);
}

.history-teaser-inner {
	max-width: 800px;
	margin: 0 auto;
}

.section-subtitle--spaced {
	margin-bottom: 30px;
}

/* ==========================================================================
   SCHOOL HYMN AUDIO (FALLBACK)
   ========================================================================== */
.hymn-audio,
.hymn-audio-element {
	display: none;
	width: 100%;
	margin: var(--space-md) auto 0;
	color-scheme: light;
	accent-color: var(--gold-500);
}

/* ==========================================================================
   PAGE NOT FOUND
   Offer the pages people actually came for rather than leaving them at a
   dead end with an apology.
   ========================================================================== */
.notfound-links {
	display: grid;
	grid-template-columns: 1fr;
	gap: var(--space-md);
	margin: 0 auto;
	max-width: 760px;
}

.notfound-link {
	display: flex;
	flex-direction: column;
	gap: 4px;
	padding: var(--space-lg);
	background: var(--surface-white);
	border: 1px solid var(--border-soft);
	border-radius: var(--radius-lg);
	text-decoration: none;
	transition: transform var(--transition-fast), border-color var(--transition-fast), box-shadow var(--transition-fast);
}

.notfound-link:hover {
	transform: translateY(-2px);
	border-color: var(--gold-400);
	box-shadow: var(--shadow-md);
}

.notfound-link-title {
	font-family: var(--font-display);
	font-size: var(--text-lg);
	font-weight: 700;
	color: var(--green-900);
}

.notfound-link-desc {
	font-size: var(--text-sm);
	color: var(--ink-600);
	line-height: 1.6;
}

.notfound-footnote {
	max-width: 760px;
	margin: var(--space-xl) auto 0;
	text-align: center;
	font-size: var(--text-sm);
	color: var(--ink-500);
}

.notfound-footnote a {
	color: var(--green-700);
	text-decoration: underline;
	text-underline-offset: 3px;
}

@media (min-width: 640px) {
	.notfound-links {
		grid-template-columns: repeat(2, 1fr);
	}
}

/* ==========================================================================
   LOOKING AHEAD
   The one forward-dated item on the site. Photo beside the facts, stacking on
   phones, so the two dates are readable without scrolling past the image.
   ========================================================================== */
.lookahead {
	display: grid;
	grid-template-columns: 1fr;
	gap: clamp(24px, 4vw, 44px);
	align-items: center;
	max-width: var(--container);
	margin: clamp(28px, 4vw, 48px) auto 0;
}

.lookahead-figure {
	margin: 0;
	border-radius: var(--radius-lg);
	overflow: hidden;
	border: 1px solid var(--border-soft);
	box-shadow: var(--shadow-md);
}

.lookahead-figure img {
	width: 100%;
	height: auto;
	display: block;
}

/* The school's own statement of what it is for, set as a statement rather than
   as body copy — wide measure, a little larger, and given room. It sits above
   the mission/vision/motto cards, which take it apart. */
.statement {
	max-width: 62ch;
	margin: clamp(4px, 1vw, 12px) auto clamp(28px, 4vw, 44px);
	text-align: center;
	font-size: var(--text-lg);
	line-height: 1.75;
	color: var(--slate-300);
}

/* The vision spells the school's name — God-centred Thinkers, Intentional
   learners, nation builders and Servant leaders — and the school's own site
   picks those four letters out.

   Weight alone will not do it everywhere: on About Us the whole line is already
   bold gold, so a bolder letter is invisible. The short rule underneath carries
   the emphasis instead, and because it is currentColor it takes the colour of
   whatever line it sits in, gold or white, without a second rule per context. */
.gtis-acrostic {
	font-weight: 800;
	border-bottom: 2px solid currentColor;
	padding-bottom: 1px;
}

/* One photograph closing the visit invitation. Capped and centred: the section
   is an invitation, not a gallery, so the picture supports the words rather than
   competing with the buttons above it. */
/* The KHQR code. A payment code has to be scannable from a phone held in front
   of a screen, so it gets a real minimum size and a white field around it — a QR
   needs its quiet zone, and the card behind it is not always white. */
.khqr {
	margin: clamp(20px, 4vw, 32px) auto;
	max-width: 280px;
	background: #FFFFFF;
	padding: 12px;
	border-radius: var(--radius-lg);
	border: 1px solid var(--slate-200);
	box-shadow: var(--shadow-md);
}

.khqr img {
	width: 100%;
	height: auto;
	display: block;
	border-radius: calc(var(--radius-lg) - 6px);
}

/* KHQR is a proper name and is printed, not translated — it reads the same on
   the Khmer page, which is the point of naming the standard at all. */
.khqr-caption {
	margin-top: 10px;
	text-align: center;
	font-family: var(--font-heading);
	font-size: var(--text-sm);
	font-weight: 800;
	letter-spacing: 0.14em;
	color: var(--slate-600);
}

/* ==========================================================================
   SUPPORTER TIERS & BECOME A SUPPORTER (Inspired by The Forgiveness Project)
   ========================================================================== */
.section-supporters {
	padding: var(--section-y) var(--gutter);
	background: var(--surface-cream);
	position: relative;
}

.supporter-freq-switcher {
	display: flex;
	align-items: center;
	justify-content: center;
	gap: 6px;
	margin: 0 auto clamp(24px, 4vw, 40px);
	background: var(--surface-white);
	padding: 5px;
	border-radius: var(--radius-full);
	border: 1px solid var(--border-soft);
	width: max-content;
	max-width: 100%;
	box-shadow: var(--shadow-sm);
}

.supporter-freq-btn {
	display: inline-flex;
	align-items: center;
	gap: 6px;
	padding: 9px 20px;
	border-radius: var(--radius-full);
	border: none;
	background: transparent;
	font-family: inherit;
	font-size: var(--text-sm);
	font-weight: 700;
	color: var(--ink-700);
	cursor: pointer;
	transition: all var(--transition-fast);
}

.supporter-freq-btn:hover {
	color: var(--green-900);
}

.supporter-freq-btn.is-active {
	background: var(--green-900);
	color: #FFFFFF;
	box-shadow: 0 2px 8px rgba(14, 56, 32, 0.2);
}

.supporter-freq-badge {
	font-size: 0.6875rem;
	padding: 2px 8px;
	border-radius: var(--radius-full);
	background: var(--gold-400);
	color: var(--green-950);
	font-weight: 800;
	text-transform: uppercase;
	letter-spacing: 0.05em;
}

.supporter-tiers-grid {
	display: grid;
	grid-template-columns: 1fr;
	gap: clamp(20px, 3vw, 28px);
	max-width: var(--container);
	margin: 0 auto;
	align-items: stretch;
}

@media (min-width: 960px) {
	.supporter-tiers-grid {
		grid-template-columns: repeat(3, 1fr);
	}
}

.supporter-tier-card {
	position: relative;
	display: flex;
	flex-direction: column;
	background: var(--surface-white);
	border: 1px solid var(--border-soft);
	border-radius: var(--radius-xl);
	padding: clamp(24px, 3.5vw, 36px) clamp(20px, 3vw, 28px);
	box-shadow: var(--shadow-sm);
	transition: transform var(--transition-base), box-shadow var(--transition-base), border-color var(--transition-base);
}

.supporter-tier-card:hover {
	transform: translateY(-4px);
	box-shadow: var(--shadow-lg);
	border-color: var(--green-700);
}

.supporter-tier-card--featured {
	border: 2px solid var(--green-800);
	background: #FFFFFF;
	box-shadow: var(--shadow-md);
}

@media (min-width: 960px) {
	.supporter-tier-card--featured {
		transform: scale(1.03);
		z-index: 2;
	}
	.supporter-tier-card--featured:hover {
		transform: scale(1.03) translateY(-4px);
	}
}

.supporter-card-badge {
	position: absolute;
	top: -14px;
	left: 50%;
	transform: translateX(-50%);
	background: var(--green-800);
	color: var(--gold-300);
	font-size: 0.6875rem;
	font-weight: 800;
	letter-spacing: 0.12em;
	text-transform: uppercase;
	padding: 5px 16px;
	border-radius: var(--radius-full);
	white-space: nowrap;
	box-shadow: 0 4px 12px rgba(14, 56, 32, 0.25);
}

.tier-header {
	margin-bottom: 18px;
	text-align: center;
}

.tier-role {
	display: inline-block;
	font-size: 0.75rem;
	font-weight: 800;
	letter-spacing: 0.12em;
	text-transform: uppercase;
	color: var(--green-800);
	margin-bottom: 8px;
}

.tier-title {
	font-family: var(--font-display);
	font-size: clamp(1.35rem, 2.2vw, 1.65rem);
	font-weight: 800;
	color: var(--green-900);
	line-height: 1.2;
	margin: 0 0 12px;
}

.tier-pricing {
	display: flex;
	align-items: baseline;
	justify-content: center;
	gap: 6px;
	margin-bottom: 4px;
	white-space: nowrap;
}

.tier-currency {
	font-family: var(--font-display);
	font-size: 1.5rem;
	font-weight: 700;
	color: var(--green-900);
}

.tier-code {
	font-size: 0.8125rem;
	font-weight: 700;
	color: var(--ink-600);
	letter-spacing: 0.04em;
	margin-right: 2px;
	white-space: nowrap;
}

.tier-amount {
	font-family: var(--font-display);
	font-size: clamp(2.25rem, 3.5vw, 2.85rem);
	font-weight: 800;
	color: var(--green-900);
	line-height: 1;
}

.tier-period {
	font-size: var(--text-sm);
	font-weight: 600;
	color: var(--ink-500);
	white-space: nowrap;
}

.tier-khr-equiv {
	display: inline-flex;
	align-items: center;
	justify-content: center;
	gap: 4px;
	font-size: 0.8125rem;
	font-weight: 600;
	color: var(--green-800);
	background: var(--green-50);
	padding: 2px 10px;
	border-radius: var(--radius-full);
	border: 1px solid rgba(20, 77, 44, 0.12);
	margin: 0 auto 8px;
	width: max-content;
	white-space: nowrap;
}

.tier-khr-symbol {
	font-family: var(--font-khmer), 'Kantumruy Pro', 'Noto Sans Khmer', sans-serif !important;
	font-weight: 700;
	font-size: 1.05em;
	display: inline-block;
	margin-left: 1px;
	line-height: 1;
}

.tier-subtitle {
	font-size: 0.8125rem;
	font-weight: 600;
	color: var(--ink-500);
	line-height: 1.4;
	margin: 0;
}

.tier-desc {
	font-size: var(--text-sm);
	line-height: 1.6;
	color: var(--ink-700);
	margin-bottom: 20px;
	text-align: center;
}

.tier-divider {
	height: 1px;
	background: var(--border-soft);
	margin: 0 0 20px;
}

.tier-benefits-title {
	font-size: 0.75rem;
	font-weight: 800;
	text-transform: uppercase;
	letter-spacing: 0.08em;
	color: var(--ink-500);
	margin: 0 0 12px;
}

.tier-benefits-list {
	list-style: none;
	padding: 0;
	margin: 0 0 28px;
	display: flex;
	flex-direction: column;
	gap: 12px;
	flex: 1;
}

.tier-benefits-list li {
	display: flex;
	align-items: flex-start;
	gap: 10px;
	font-size: var(--text-sm);
	line-height: 1.5;
	color: var(--ink-800);
}

.tier-benefits-list svg {
	flex-shrink: 0;
	width: 18px;
	height: 18px;
	margin-top: 2px;
	color: var(--green-700);
}

.tier-card-btn {
	margin-top: auto;
	width: 100%;
}

/* Impact stories banner */
.section-impact-story {
	padding: clamp(48px, 8vw, 80px) var(--gutter);
	background: var(--surface-white);
	border-top: 1px solid var(--border-soft);
	border-bottom: 1px solid var(--border-soft);
}

.impact-story-container {
	max-width: var(--container);
	margin: 0 auto;
	display: grid;
	grid-template-columns: 1fr;
	gap: clamp(32px, 5vw, 64px);
	align-items: center;
}

@media (min-width: 900px) {
	.impact-story-container {
		grid-template-columns: 1.15fr 0.85fr;
	}
}

.impact-story-quote {
	font-family: var(--font-display);
	font-size: clamp(1.2rem, 2vw, 1.5rem);
	font-weight: 700;
	line-height: 1.45;
	color: var(--green-950);
	position: relative;
	padding-left: 20px;
	border-left: 4px solid var(--gold-400);
	margin: 0 0 20px;
}

.impact-story-desc {
	font-size: var(--text-md);
	line-height: 1.65;
	color: var(--ink-700);
	margin-bottom: 20px;
}

.impact-story-meta {
	display: flex;
	flex-direction: column;
	gap: 2px;
}

.impact-story-author {
	font-weight: 800;
	font-size: var(--text-md);
	color: var(--green-900);
}

.impact-story-role {
	font-size: var(--text-sm);
	color: var(--ink-500);
}

.impact-metrics-cards {
	display: grid;
	grid-template-columns: repeat(2, 1fr);
	gap: 14px;
}

.impact-metric-box {
	background: var(--green-50);
	border: 1px solid rgba(20, 77, 44, 0.12);
	border-radius: var(--radius-lg);
	padding: 20px 16px;
	text-align: center;
}

.impact-metric-val {
	font-family: var(--font-display);
	font-size: clamp(1.85rem, 3.2vw, 2.5rem);
	font-weight: 800;
	color: var(--green-900);
	line-height: 1.1;
	margin-bottom: 6px;
}

.impact-metric-lbl {
	font-size: 0.75rem;
	font-weight: 700;
	color: var(--green-800);
	text-transform: uppercase;
	letter-spacing: 0.04em;
	line-height: 1.3;
}

/* Honeypot: off screen rather than display:none, which bots skip. Never shown,
   never focusable, and its value being non-empty is what marks a submission as
   automated. */
.form-hp {
	position: absolute;
	left: -9999px;
	width: 1px;
	height: 1px;
	overflow: hidden;
}

/* data-size="flexible" (set in inc/turnstile.php) asks the widget to fill its
   container's width itself, so — unlike a fixed-size embed — it never forces a
   minimum width on the form. It only needs telling how wide that container is;
   width:100% is not the default for a bare div. Most of the time the widget
   passes invisibly and renders nothing at all, so no height is reserved for it
   and the form does not carry a permanent empty gap waiting for a challenge
   that usually never appears. */
.form-captcha .cf-turnstile {
	width: 100%;
}

/* The result of a submission, shown above the form it came from. */
.form-notice {
	margin: 0 0 20px;
	padding: 14px 18px;
	border-radius: var(--radius-md);
	font-size: var(--text-md);
	line-height: 1.6;
	border: 1px solid transparent;
}

.form-notice:focus {
	outline: 2px solid var(--focus-ring, var(--green-700));
	outline-offset: 2px;
}

.form-notice--ok {
	background: rgba(20, 108, 60, 0.08);
	border-color: rgba(20, 108, 60, 0.35);
	color: var(--green-800, #14603A);
}

.form-notice--error {
	background: rgba(158, 40, 30, 0.07);
	border-color: rgba(158, 40, 30, 0.32);
	color: #8A2A1F;
}

.section-contact-main--tight {
	padding-top: 0;
}

/* The Youth Centre has five parts, and neither the two- nor the four-column grid
   divides five evenly — both leave a single card stranded on the last row.
   Three across at desktop gives 3 + 2, which reads as intended. */
.feature-grid {
	max-width: 1180px;
	margin: clamp(28px, 4vw, 44px) auto 0;
	display: grid;
	grid-template-columns: 1fr;
	gap: 20px;
}

@media (min-width: 600px) {
	.feature-grid {
		grid-template-columns: repeat(2, 1fr);
	}
}

@media (min-width: 1024px) {
	.feature-grid {
		grid-template-columns: repeat(3, 1fr);
	}
}

/* The same badge carrying a word instead of a numeral, for the Youth Centre's
   vision and mission — where "1" and "2" would imply an order that isn't there.
   A fixed 36px circle cannot hold a word, least of all the Khmer one, so this
   grows to fit and takes a pill radius. align-self stops it stretching to the
   full width of the card, which is a column flex container. */
.step-number-badge--label {
	width: auto;
	min-width: 36px;
	height: auto;
	min-height: 36px;
	padding: 6px 16px;
	border-radius: var(--radius-full);
	align-self: flex-start;
	text-align: center;
	line-height: 1.3;
}

/* A sub-heading inside a section that already has its own header. */
.subsection-header {
	max-width: 760px;
	margin: clamp(40px, 6vw, 64px) auto 0;
	text-align: center;
}

.subsection-title {
	font-family: var(--font-heading);
	font-size: var(--text-2xl);
	font-weight: 700;
	line-height: 1.25;
	margin-bottom: 10px;
}

/* One wide photograph closing a section, with a line of context beneath it.
   For places where the picture is the point rather than decoration — the motto
   painted on the school wall argues for itself better than another paragraph
   about the motto would. The caption inherits its colour so the block can sit
   on a light or a dark section without a second rule. */
.section-figure {
	max-width: 900px;
	margin: clamp(28px, 4vw, 44px) auto 0;
}

.section-figure img {
	width: 100%;
	height: auto;
	display: block;
	border-radius: var(--radius-lg);
	border: 1px solid rgba(255, 255, 255, 0.14);
	box-shadow: var(--shadow-md);
}

.section-figure figcaption {
	margin-top: 12px;
	text-align: center;
	font-size: var(--text-sm);
	line-height: 1.6;
	color: inherit;
	opacity: 0.72;
}

.lookahead-body {
	display: flex;
	flex-direction: column;
	gap: var(--space-md);
}

.lookahead-dates {
	display: flex;
	flex-wrap: wrap;
	gap: var(--space-sm) var(--space-2xl);
	margin: 0 0 var(--space-sm);
	padding-bottom: var(--space-md);
	border-bottom: 1px solid var(--border-soft);
}

.lookahead-date dt {
	font-size: var(--text-xs);
	font-weight: 700;
	letter-spacing: 0.1em;
	text-transform: uppercase;
	color: var(--gold-600);
	margin-bottom: 2px;
}

.lookahead-date dd {
	margin: 0;
	font-family: var(--font-display);
	font-size: var(--text-xl);
	font-weight: 700;
	color: var(--green-900);
	line-height: 1.2;
}

.lookahead-text {
	font-size: var(--text-lg);
	line-height: 1.75;
	color: var(--ink-700);
	max-width: 58ch;
}

.lookahead-body .btn-hero-primary {
	align-self: flex-start;
	margin-top: var(--space-sm);
}

@media (min-width: 900px) {
	.lookahead {
		grid-template-columns: 1.05fr 0.95fr;
	}
}

/* The line the school leads with. Carries the section, so it sits above the
   explanatory copy at display weight rather than being buried in it. */
.lookahead-lead {
	font-family: var(--font-display);
	font-size: var(--text-xl);
	font-weight: 700;
	line-height: 1.4;
	color: var(--green-800);
	padding-left: var(--space-md);
	border-left: 3px solid var(--gold-500);
	margin-bottom: var(--space-xs);
	text-wrap: balance;
}

/* ==========================================================================
   THE THREAD (WIDE SCREENS)
   From 1100px the milestones alternate, and the generated thread runs between
   the two columns touching each node. The section is the positioning context
   for the SVG, which spans it edge to edge while the list keeps its measure.
   ========================================================================== */
@media (min-width: 1100px) {
	.section-history-timeline {
		position: relative;
		overflow: hidden;
		overflow: clip;
	}

	/* Milestones sit above the thread. Child selectors: without them the commas
	   leave the last two unscoped and applying globally. */
	.section-history-timeline > .section-header,
	.section-history-timeline > .story-timeline,
	.section-history-timeline > .story-footnote {
		position: relative;
		z-index: 1;
	}
}

/* ==========================================================================
   GTIS SCHOOL HYMN EXPERIENCE (ANTHEM & AUDIO PLAYER)
   On the About page only. Refined 2026 glassmorphic presentation
   featuring illuminated poetic stanzas, watermark crest, responsive custom
   audio console, animated equalizer bars, and accessible interactive scrubber.
   ========================================================================== */
.section-school-hymn {
	position: relative;
	overflow: hidden;
}

.hymn-block {
	max-width: 760px;
	margin: 0 auto;
	position: relative;
	z-index: 1;
}

/* 1. The Hymn Card Container */
.hymn-card {
	background: radial-gradient(120% 120% at 50% 0%, rgba(26, 99, 59, 0.4) 0%, rgba(14, 56, 32, 0.85) 45%, rgba(7, 31, 18, 0.96) 100%);
	border: 1px solid rgba(212, 175, 55, 0.3);
	border-radius: var(--radius-xl);
	padding: clamp(32px, 5vw, 52px) clamp(20px, 4.5vw, 48px) clamp(28px, 4vw, 40px);
	position: relative;
	overflow: hidden;
	box-shadow: 0 24px 64px rgba(0, 0, 0, 0.45), inset 0 1px 0 rgba(255, 255, 255, 0.1), 0 0 40px rgba(212, 175, 55, 0.06);
	backdrop-filter: blur(16px);
	-webkit-backdrop-filter: blur(16px);
	transition: border-color var(--transition-base), box-shadow var(--transition-base);
}

.hymn-card:hover {
	border-color: rgba(212, 175, 55, 0.45);
	box-shadow: 0 28px 72px rgba(0, 0, 0, 0.52), inset 0 1px 0 rgba(255, 255, 255, 0.15), 0 0 50px rgba(212, 175, 55, 0.1);
}

/* Glow & Watermark */
.hymn-card-glow {
	position: absolute;
	top: 0;
	left: 50%;
	transform: translateX(-50%);
	width: 80%;
	height: 180px;
	background: radial-gradient(ellipse at top, rgba(212, 175, 55, 0.18) 0%, rgba(212, 175, 55, 0) 70%);
	pointer-events: none;
	z-index: 0;
}

.hymn-card-watermark {
	position: absolute;
	top: 45%;
	left: 50%;
	transform: translate(-50%, -50%);
	opacity: 0.04;
	pointer-events: none;
	user-select: none;
	z-index: 0;
}

.hymn-card-watermark img {
	width: 280px;
	height: auto;
	filter: grayscale(100%) brightness(200%);
}

/* Header Badge & View Switcher */
.hymn-card-header {
	display: flex;
	justify-content: center;
	margin-bottom: clamp(24px, 3.5vw, 32px);
	position: relative;
	z-index: 1;
}

/* The same segmented switcher as the giving frequency on the support page,
   in its dark-band form: a quiet pill, and the chosen option filled in gold
   as the primary buttons are. It replaced a gold-outlined pair with icons
   beside a "School Anthem" badge — a fourth label style on the site, and a
   second name for what the heading above already calls the school hymn. */
.hymn-view-switcher {
	display: inline-flex;
	align-items: center;
	gap: 6px;
	padding: 5px;
	max-width: 100%;
	background: rgba(255, 255, 255, 0.06);
	border: 1px solid rgba(255, 255, 255, 0.14);
	border-radius: var(--radius-full);
}

.hymn-tab-btn {
	display: inline-flex;
	align-items: center;
	min-height: 40px;
	padding: 9px 20px;
	border: none;
	border-radius: var(--radius-full);
	background: transparent;
	color: var(--slate-300);
	font-family: inherit;
	font-size: var(--text-sm);
	font-weight: 700;
	cursor: pointer;
	transition: background var(--transition-fast), color var(--transition-fast);
}

.hymn-tab-btn:hover {
	color: #FFFFFF;
}

.hymn-tab-btn.is-active {
	background: var(--gold-400);
	color: var(--green-950);
	box-shadow: 0 2px 8px rgba(0, 0, 0, 0.25);
}

.hymn-tab-btn:focus-visible {
	outline: 3px solid var(--gold-300);
	outline-offset: 2px;
}

/* 2. Content Panels */
.hymn-panels-container {
	position: relative;
	z-index: 1;
}

.hymn-panel {
	display: none;
}

.hymn-panel.is-active {
	display: block;
	animation: hymnFadeIn 0.3s ease-out;
}

@keyframes hymnFadeIn {
	from {
		opacity: 0;
		transform: translateY(6px);
	}
	to {
		opacity: 1;
		transform: translateY(0);
	}
}

/* 2A. Lyrics Typesetting */
.hymn-lyrics-container {
	text-align: center;
	max-width: 600px;
	margin: 0 auto;
	font-family: var(--font-display);
}

.hymn-stanza {
	margin-bottom: clamp(16px, 2.5vw, 22px);
	display: flex;
	flex-direction: column;
	gap: 4px;
}

.hymn-line {
	margin: 0;
	font-size: clamp(1.0625rem, 0.6vw + 0.95rem, 1.25rem);
	line-height: 1.65;
	color: #FFFFFF;
	font-weight: 400;
	letter-spacing: 0.015em;
	text-shadow: 0 2px 8px rgba(0, 0, 0, 0.4);
}

.hymn-stanza--final .hymn-line--climax {
	color: var(--gold-300);
	font-weight: 700;
	font-size: clamp(1.125rem, 0.8vw + 0.98rem, 1.35rem);
	margin-top: 4px;
	text-shadow: 0 0 20px rgba(212, 175, 55, 0.4), 0 2px 8px rgba(0, 0, 0, 0.5);
	letter-spacing: 0.025em;
}

/* 2B. Hymnal Sheet Music Score */
.hymnal-score-wrapper {
	background: rgba(3, 14, 8, 0.82);
	border: 1px solid rgba(212, 175, 55, 0.22);
	border-radius: var(--radius-lg);
	padding: clamp(16px, 3vw, 24px);
	box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.05), 0 12px 32px rgba(0, 0, 0, 0.4);
	backdrop-filter: blur(12px);
	-webkit-backdrop-filter: blur(12px);
}

.hymnal-score-header {
	display: flex;
	align-items: center;
	justify-content: space-between;
	border-bottom: 1px solid rgba(212, 175, 55, 0.2);
	padding-bottom: 14px;
	margin-bottom: 18px;
	gap: 12px;
}

.hymnal-score-meta-left,
.hymnal-score-meta-right {
	display: flex;
	flex-direction: column;
	gap: 2px;
	font-size: 0.75rem;
	color: var(--slate-400);
	font-family: var(--font-display);
}

.hymnal-score-meta-right {
	text-align: right;
}

.score-meta-tune,
.score-meta-key {
	color: var(--gold-300);
	font-weight: 700;
	text-transform: uppercase;
	letter-spacing: 0.05em;
}

.hymnal-score-title-block {
	text-align: center;
}

.score-hymn-title {
	font-family: var(--font-display);
	font-weight: 700;
	font-size: clamp(0.95rem, 1vw + 0.8rem, 1.15rem);
	color: #FFFFFF;
	text-transform: uppercase;
	letter-spacing: 0.06em;
	margin: 0 0 2px;
}

.score-hymn-subtitle {
	font-family: var(--font-body);
	font-style: italic;
	font-size: 0.8125rem;
	color: var(--gold-400);
	margin: 0;
}

.hymnal-score-display-container,
.hymnal-score-scroll-container {
	width: 100%;
	overflow: visible;
	overflow-x: visible;
	border-radius: 8px;
	padding: 4px 0;
	outline: none;
}

.hymnal-score-display-container:focus-visible,
.hymnal-score-scroll-container:focus-visible {
	outline: 2px solid var(--gold-400);
}

.hymnal-score-svg {
	width: 100%;
	max-width: 100%;
	min-width: 0;
	height: auto;
	display: block;
}

/* SVG Score Elements */
.staff-line {
	stroke: rgba(255, 255, 255, 0.32);
	stroke-width: 1;
}

.bar-line {
	stroke: rgba(255, 255, 255, 0.45);
	stroke-width: 1.2;
}

.bar-line-thick {
	stroke: rgba(255, 255, 255, 0.75);
	stroke-width: 3;
}

.ledger-line {
	stroke: rgba(255, 255, 255, 0.4);
	stroke-width: 1.2;
}

.score-clef,
.score-accidental,
.score-fermata {
	color: var(--gold-400);
}

.score-note {
	color: #FFFFFF;
	transition: color 0.2s ease;
}

.score-dot {
	fill: currentColor;
	color: #FFFFFF;
}

.time-sig {
	fill: #FFFFFF;
	font-family: var(--font-display);
	font-size: 20px;
	font-weight: 700;
	text-anchor: middle;
}

.score-chord {
	fill: var(--gold-400);
	font-family: var(--font-display);
	font-size: 13px;
	font-weight: 700;
	text-anchor: middle;
	letter-spacing: 0.02em;
}

.score-lyric {
	fill: rgba(255, 255, 255, 0.92);
	font-family: var(--font-body);
	font-size: 13.5px;
	font-weight: 500;
	text-anchor: middle;
}

/* Interactive Score System */
.score-system {
	cursor: pointer;
	outline: none;
	transition: transform 0.2s ease;
}

.system-active-highlight {
	transition: fill 0.25s ease, stroke 0.25s ease;
}

.score-system:hover .system-active-highlight {
	fill: rgba(212, 175, 55, 0.08);
	stroke: rgba(212, 175, 55, 0.35);
	stroke-width: 1;
}

.score-system:focus-visible .system-active-highlight {
	stroke: var(--gold-400);
	stroke-width: 1.5;
}

.score-system.is-active-phrase .system-active-highlight {
	fill: rgba(212, 175, 55, 0.16);
	stroke: var(--gold-400);
	stroke-width: 1.5;
	filter: drop-shadow(0 0 10px rgba(212, 175, 55, 0.45));
}

.score-system.is-active-phrase .score-note {
	color: var(--gold-300);
}

.score-system.is-active-phrase .score-lyric {
	fill: #FFFFFF;
	font-weight: 700;
}

.hymnal-score-footer {
	display: flex;
	align-items: center;
	justify-content: center;
	font-size: var(--text-xs);
	color: var(--slate-400);
	padding-top: 12px;
	border-top: 1px solid rgba(255, 255, 255, 0.06);
	margin-top: 8px;
}

.score-copyright-tag {
	color: var(--slate-400);
	font-size: 0.75rem;
}

/* 3. Decorative Card Divider */
.hymn-card-divider {
	display: flex;
	align-items: center;
	justify-content: center;
	gap: 16px;
	margin: clamp(24px, 3.5vw, 32px) 0 clamp(20px, 3vw, 28px);
	position: relative;
	z-index: 1;
}

.hymn-divider-line {
	flex: 1;
	height: 1px;
	background: linear-gradient(90deg, transparent, rgba(212, 175, 55, 0.35), transparent);
}

.hymn-divider-symbol {
	color: var(--gold-400);
	font-size: 14px;
	opacity: 0.85;
	text-shadow: 0 0 10px rgba(212, 175, 55, 0.6);
}

/* 4. The Hymn Player Component */
.hymn-player {
	position: relative;
	z-index: 1;
}

.hymn-audio-element {
	display: none;
}

.hymn-player-ui {
	background: rgba(4, 18, 10, 0.72);
	border: 1px solid rgba(212, 175, 55, 0.25);
	border-radius: var(--radius-lg);
	padding: clamp(16px, 3vw, 22px) clamp(16px, 3.5vw, 24px);
	box-shadow: 0 12px 32px rgba(0, 0, 0, 0.35), inset 0 1px 0 rgba(255, 255, 255, 0.06);
	backdrop-filter: blur(14px);
	-webkit-backdrop-filter: blur(14px);
	transition: border-color var(--transition-base), box-shadow var(--transition-base);
}

.hymn-player.is-playing .hymn-player-ui {
	border-color: rgba(212, 175, 55, 0.45);
	box-shadow: 0 16px 40px rgba(0, 0, 0, 0.45), 0 0 30px rgba(212, 175, 55, 0.12), inset 0 1px 0 rgba(255, 255, 255, 0.1);
}

/* Top Meta Row */
.hymn-player-top {
	display: flex;
	align-items: center;
	justify-content: space-between;
	gap: 12px;
	margin-bottom: clamp(14px, 2.5vw, 18px);
}

.hymn-track-meta {
	display: flex;
	align-items: center;
	gap: 12px;
	min-width: 0;
}

.hymn-track-icon-wrap {
	width: 36px;
	height: 36px;
	border-radius: 10px;
	background: rgba(212, 175, 55, 0.14);
	border: 1px solid rgba(212, 175, 55, 0.3);
	display: flex;
	align-items: center;
	justify-content: center;
	color: var(--gold-400);
	flex-shrink: 0;
	box-shadow: 0 2px 8px rgba(0, 0, 0, 0.2);
}

.hymn-track-titles {
	display: flex;
	flex-direction: column;
	gap: 2px;
	min-width: 0;
}

.hymn-track-label {
	font-weight: 700;
	font-size: var(--text-sm);
	color: #FFFFFF;
	white-space: nowrap;
	overflow: hidden;
	text-overflow: ellipsis;
}

.hymn-track-sub {
	font-size: var(--text-xs);
	color: var(--slate-300);
	white-space: nowrap;
	overflow: hidden;
	text-overflow: ellipsis;
}

/* Status & Equalizer Badge */
.hymn-playback-badge {
	display: inline-flex;
	align-items: center;
	gap: 8px;
	padding: 5px 12px;
	background: rgba(212, 175, 55, 0.08);
	border: 1px solid rgba(212, 175, 55, 0.2);
	border-radius: var(--radius-full);
	flex-shrink: 0;
}

.hymn-status-label {
	font-size: var(--text-xs);
	color: var(--gold-300);
	font-weight: 500;
}

.hymn-equalizer-bars {
	display: flex;
	align-items: flex-end;
	gap: 2px;
	height: 12px;
}

.hymn-eq-bar {
	width: 2px;
	height: 4px;
	background: var(--gold-400);
	border-radius: 1px;
	transition: height 0.2s ease;
}

.hymn-player.is-playing .hymn-eq-bar {
	animation: hymnEqualize 1s ease-in-out infinite alternate;
}

.hymn-player.is-playing .hymn-eq-bar.bar-1 { animation-delay: 0.1s; height: 10px; }
.hymn-player.is-playing .hymn-eq-bar.bar-2 { animation-delay: 0.3s; height: 14px; }
.hymn-player.is-playing .hymn-eq-bar.bar-3 { animation-delay: 0.15s; height: 8px; }
.hymn-player.is-playing .hymn-eq-bar.bar-4 { animation-delay: 0.4s; height: 12px; }

@keyframes hymnEqualize {
	0% { height: 3px; }
	50% { height: 12px; }
	100% { height: 6px; }
}

/* Controls Row */
.hymn-player-controls-row {
	display: flex;
	align-items: center;
	gap: 14px;
}

/* Control Buttons Base */
.hymn-ctrl-btn {
	background: rgba(255, 255, 255, 0.08);
	border: 1px solid rgba(255, 255, 255, 0.14);
	color: var(--slate-200);
	border-radius: 50%;
	display: inline-flex;
	align-items: center;
	justify-content: center;
	cursor: pointer;
	padding: 0;
	transition: transform 0.2s cubic-bezier(0.34, 1.56, 0.64, 1), background-color 0.2s ease, border-color 0.2s ease, color 0.2s ease, box-shadow 0.2s ease;
}

.hymn-ctrl-btn:hover {
	background: rgba(212, 175, 55, 0.2);
	border-color: rgba(212, 175, 55, 0.45);
	color: #FFFFFF;
	transform: scale(1.08);
}

.hymn-ctrl-btn:active {
	transform: scale(0.95);
}

/* Main Play/Pause Button */
.hymn-ctrl-btn--play {
	width: 52px;
	height: 52px;
	background: linear-gradient(135deg, #F3DE8A 0%, #D4AF37 50%, #B08D22 100%);
	border: none;
	color: #071F12;
	flex-shrink: 0;
	box-shadow: 0 4px 16px rgba(212, 175, 55, 0.35);
	position: relative;
}

.hymn-btn-glow {
	position: absolute;
	inset: -4px;
	border-radius: 50%;
	background: radial-gradient(circle, rgba(212, 175, 55, 0.5) 0%, transparent 70%);
	opacity: 0;
	transition: opacity 0.3s ease;
	pointer-events: none;
}

.hymn-player.is-playing .hymn-btn-glow {
	opacity: 1;
	animation: hymnPulseRing 2s cubic-bezier(0.24, 0, 0.38, 1) infinite;
}

@keyframes hymnPulseRing {
	0% { transform: scale(0.95); opacity: 0.7; }
	50% { transform: scale(1.15); opacity: 0.2; }
	100% { transform: scale(0.95); opacity: 0.7; }
}

.hymn-ctrl-btn--play:hover {
	background: linear-gradient(135deg, #FFF0A8 0%, #E5C564 50%, #C49E28 100%);
	color: #071F12;
	box-shadow: 0 6px 24px rgba(212, 175, 55, 0.55);
	transform: scale(1.08);
}

.hymn-ctrl-btn--play .hymn-icon-pause {
	display: none;
}

.hymn-player.is-playing .hymn-ctrl-btn--play .hymn-icon-play {
	display: none;
}

.hymn-player.is-playing .hymn-ctrl-btn--play .hymn-icon-pause {
	display: block;
}

/* Secondary Buttons */
.hymn-ctrl-btn--volume,
.hymn-ctrl-btn--restart {
	width: 38px;
	height: 38px;
	flex-shrink: 0;
}

/* Timeline Container */
.hymn-timeline-container {
	flex: 1;
	display: flex;
	flex-direction: column;
	gap: 6px;
	min-width: 0;
}

.hymn-timeline-track {
	height: 6px;
	background: rgba(255, 255, 255, 0.16);
	border-radius: var(--radius-full);
	position: relative;
	cursor: pointer;
	touch-action: none;
	transition: height 0.15s ease;
}

.hymn-timeline-track:hover,
.hymn-timeline-track:focus-visible {
	height: 8px;
}

.hymn-timeline-track:focus-visible {
	outline: 2px solid var(--gold-400);
	outline-offset: 3px;
}

.hymn-timeline-buffered {
	position: absolute;
	left: 0;
	top: 0;
	height: 100%;
	width: 0%;
	background: rgba(212, 175, 55, 0.2);
	border-radius: var(--radius-full);
	pointer-events: none;
	transition: width 0.2s ease;
}

.hymn-timeline-fill {
	position: absolute;
	left: 0;
	top: 0;
	height: 100%;
	width: 0%;
	background: linear-gradient(90deg, #B08D22 0%, #D4AF37 50%, #F3DE8A 100%);
	border-radius: var(--radius-full);
	pointer-events: none;
	box-shadow: 0 0 10px rgba(212, 175, 55, 0.5);
}

.hymn-timeline-handle {
	position: absolute;
	left: 0%;
	top: 50%;
	width: 14px;
	height: 14px;
	border-radius: 50%;
	background: #FFFFFF;
	border: 2.5px solid var(--gold-500);
	box-shadow: 0 2px 6px rgba(0, 0, 0, 0.4);
	transform: translate(-50%, -50%) scale(0.85);
	transition: transform 0.15s ease;
	pointer-events: none;
	opacity: 0.95;
}

.hymn-timeline-track:hover .hymn-timeline-handle,
.hymn-timeline-track:focus-visible .hymn-timeline-handle {
	transform: translate(-50%, -50%) scale(1.2);
	opacity: 1;
	box-shadow: 0 0 10px rgba(212, 175, 55, 0.8);
}

.hymn-time-display {
	display: flex;
	align-items: center;
	justify-content: space-between;
	font-size: 0.75rem;
	color: var(--slate-300);
	font-variant-numeric: tabular-nums;
	font-feature-settings: "tnum";
	font-family: var(--font-body);
}

.hymn-time-sep {
	display: none;
}

/* Volume Group */
.hymn-volume-group {
	position: relative;
	display: flex;
	align-items: center;
}

.hymn-volume-group .hymn-icon-vol-muted {
	display: none;
}

.hymn-player.is-muted .hymn-volume-group .hymn-icon-vol-high {
	display: none;
}

.hymn-player.is-muted .hymn-volume-group .hymn-icon-vol-muted {
	display: block;
	color: var(--gold-400);
}

.hymn-volume-popover {
	display: flex;
	align-items: center;
	width: 64px;
	margin-left: 6px;
	transition: opacity 0.2s ease, width 0.2s ease;
}

.hymn-volume-range {
	-webkit-appearance: none;
	appearance: none;
	width: 100%;
	height: 4px;
	background: rgba(255, 255, 255, 0.2);
	border-radius: var(--radius-full);
	outline: none;
	cursor: pointer;
}

.hymn-volume-range::-webkit-slider-thumb {
	-webkit-appearance: none;
	appearance: none;
	width: 12px;
	height: 12px;
	border-radius: 50%;
	background: var(--gold-400);
	box-shadow: 0 1px 4px rgba(0, 0, 0, 0.4);
	cursor: pointer;
	transition: transform 0.15s ease;
}

.hymn-volume-range::-webkit-slider-thumb:hover {
	transform: scale(1.25);
	background: #FFFFFF;
}

.hymn-volume-range::-moz-range-thumb {
	width: 12px;
	height: 12px;
	border-radius: 50%;
	background: var(--gold-400);
	border: none;
	box-shadow: 0 1px 4px rgba(0, 0, 0, 0.4);
	cursor: pointer;
}

/* Fallback when JS is disabled */
.no-js .hymn-audio-element {
	display: block;
	width: 100%;
	margin-top: var(--space-md);
	color-scheme: light;
	accent-color: var(--gold-500);
}

.no-js .hymn-player-ui {
	display: none;
}

/* Mobile Responsive Refinements */
@media (max-width: 640px) {
	.hymn-card {
		padding: 28px 16px 20px;
	}

	.hymn-player-ui {
		padding: 16px 14px;
	}

	.hymn-volume-popover {
		display: none;
	}

	.hymn-ctrl-btn--play {
		width: 46px;
		height: 46px;
	}

	.hymn-player-top {
		flex-direction: column;
		align-items: flex-start;
		gap: 10px;
	}

	.hymn-playback-badge {
		align-self: flex-start;
	}
}

/* ==========================================================================
   THE THREAD
   A single generated SVG per timeline, spanning the section while the list of
   milestones keeps its measure. Its path is built in JS from where the nodes
   actually are, so the line touches every one — see assets/js/story-thread.js.
   ========================================================================== */
.story-thread {
	position: absolute;
	inset: 0;
	width: 100%;
	height: 100%;
	overflow: visible;
	pointer-events: none;
	z-index: 0;
}

.story-thread path {
	fill: none;
	stroke-linecap: round;
}

.story-thread__track {
	stroke: rgba(212, 175, 55, 0.28);
	stroke-width: 2;
}

/* A fat translucent duplicate rather than filter: drop-shadow(). A filter on a
   path whose dash offset changes every frame re-rasterises the whole filter
   region, and this element is several thousand pixels tall. */
.story-thread__glow {
	stroke: rgba(229, 197, 100, 0.16);
	stroke-width: 7;
	stroke-dasharray: var(--thread-len, 0);
	stroke-dashoffset: var(--thread-tip, 0);
}

.story-thread__draw {
	stroke: var(--gold-400);
	stroke-width: 2.5;
	stroke-dasharray: var(--thread-len, 0);
	stroke-dashoffset: var(--thread-tip, 0);
}

/* The thread replaces the stylesheet's own rail once JS has drawn it. */
.is-threaded .story-timeline::before {
	display: none;
}

/* Milestones arrive as the thread reaches them. Only ever applied when the
   thread exists, so with JS off every card is simply visible. */
.is-threaded .story-card {
	opacity: 0;
	transition: opacity var(--transition-smooth), transform var(--transition-smooth),
		border-color var(--transition-base), background var(--transition-base);
}

.is-threaded .story-item.is-lit .story-card {
	opacity: 1;
}

.is-threaded .story-marker {
	transition: background var(--transition-base), box-shadow var(--transition-base),
		transform var(--transition-base);
}

.story-item.is-lit .story-marker {
	background: var(--gold-500);
	box-shadow: 0 0 0 5px rgba(212, 175, 55, 0.18);
}

/* Reduced motion: draw the whole thread and light every milestone at once. The
   line carries structure — which milestone follows which — so the answer is to
   stop it moving, not to show less of it. */
@media (prefers-reduced-motion: reduce) {
	.is-threaded .story-card,
	.is-threaded .story-item .story-card {
		opacity: 1;
		transform: none;
		transition: none;
	}

	.is-threaded .story-marker {
		transition: none;
	}
}

@media print {
	.story-thread,
	.site-header,
	.site-footer,
	.mobile-action-dock,
	.hymn-view-switcher,
	.hymn-player,
	.hymn-card-divider,
	.score-tip-badge,
	.section-cta-banner {
		display: none !important;
	}

	.section-school-hymn {
		background: #FFFFFF !important;
		color: #000000 !important;
		padding: 0 !important;
	}

	.hymn-card {
		background: #FFFFFF !important;
		border: none !important;
		box-shadow: none !important;
		padding: 0 !important;
		color: #000000 !important;
	}

	.hymn-panel--sheet {
		display: block !important;
	}

	.hymnal-score-wrapper {
		background: #FFFFFF !important;
		border: 1px solid #CCCCCC !important;
		box-shadow: none !important;
		color: #000000 !important;
	}

	.hymnal-score-header {
		border-bottom: 2px solid #000000 !important;
	}

	.score-hymn-title {
		color: #000000 !important;
	}

	.score-hymn-subtitle {
		color: #555555 !important;
	}

	.score-meta-tune,
	.score-meta-key {
		color: #333333 !important;
	}

	.staff-line,
	.bar-line,
	.ledger-line {
		stroke: #000000 !important;
	}

	.bar-line-thick {
		stroke: #000000 !important;
	}

	.score-clef,
	.score-accidental,
	.score-fermata {
		color: #000000 !important;
		fill: #000000 !important;
	}

	.score-note {
		color: #000000 !important;
		fill: #000000 !important;
	}

	.score-dot {
		fill: #000000 !important;
	}

	.time-sig {
		fill: #000000 !important;
	}

	.score-chord {
		fill: #222222 !important;
	}

	.score-lyric {
		fill: #000000 !important;
		font-weight: 600 !important;
	}

	.system-active-highlight {
		display: none !important;
	}
}

/* ==========================================================================
   THE PAGE SYSTEM
   The rules every page shares, gathered in one place and written last so they
   win on source order. Pages had drifted: a left-aligned header with a tilted
   collage on one, centred banners everywhere else; card grids at 860, 900,
   1180, 1240 and 1320px; three styles of label above a heading; card photos
   at a fixed 250px height, so their shape changed with the card's width.

   The rules, in short:
   - Every inner page opens with .page-header: text on the left, and the
     page's own photograph on the right at 4:3 where it has one.
   - Every section label is .section-eyebrow. Gold on dark, deep gold on light.
   - Every card grid is the width of the page container.
   - Every photograph inside a card is 4:3. Standalone photographs take
     --radius-lg, a hairline border and --shadow-md; the header photograph is
     the one feature photograph and takes --radius-xl and --shadow-xl.
   - Light cards are white with a hairline border, on either background.
   - Dark bands never touch: the closing invitation is a panel on a light
     strip, so it cannot run into a dark section above it or the footer below.
   ========================================================================== */

/* --- Page header ----------------------------------------------------------- */
.page-header {
	--focus-ring: var(--gold-300);
	position: relative;
	padding: clamp(24px, 3.5vw, 40px) var(--gutter) clamp(44px, 6vw, 80px);
	background: radial-gradient(circle at 85% -10%, rgba(212, 175, 55, 0.14), transparent 55%),
	            linear-gradient(180deg, var(--green-950) 0%, var(--green-900) 100%);
	border-bottom: 1px solid rgba(255, 255, 255, 0.08);
	color: #FFFFFF;
}

.page-header-inner {
	max-width: var(--container);
	margin: 0 auto;
	display: grid;
	gap: clamp(28px, 4vw, 64px);
	align-items: center;
}

@media (min-width: 900px) {
	.page-header--with-photo .page-header-inner {
		grid-template-columns: minmax(0, 1.1fr) minmax(0, 0.9fr);
	}
}

.page-header-text {
	max-width: 720px;
}

.page-breadcrumb ol {
	list-style: none;
	margin: 0 0 clamp(24px, 4vw, 48px);
	padding: 0;
	display: flex;
	flex-wrap: wrap;
	align-items: center;
	font-size: var(--text-sm);
	color: rgba(255, 255, 255, 0.72);
}

.page-breadcrumb li {
	display: flex;
	align-items: center;
	min-width: 0;
}

.page-breadcrumb li + li::before {
	content: '/';
	margin: 0 10px;
	color: rgba(255, 255, 255, 0.35);
}

.page-breadcrumb a {
	color: var(--gold-300);
	text-decoration: none;
}

.page-breadcrumb a:hover {
	text-decoration: underline;
	text-underline-offset: 3px;
}

/* A news headline can be a sentence long; the title below already says it in
   full, so the trail gives it one line. */
.page-breadcrumb [aria-current] {
	color: #FFFFFF;
	font-weight: 600;
	max-width: 36ch;
	overflow: hidden;
	text-overflow: ellipsis;
	white-space: nowrap;
}

.page-header-title {
	font-family: var(--font-display);
	font-size: var(--text-4xl);
	font-weight: 800;
	line-height: 1.12;
	letter-spacing: -0.02em;
	color: #FFFFFF;
	margin: 0 0 18px;
	text-wrap: balance;
}

.page-header-lede {
	font-size: var(--text-lg);
	line-height: 1.7;
	color: rgba(255, 255, 255, 0.8);
	max-width: 60ch;
	margin: 0;
}

.page-header-actions {
	display: flex;
	flex-wrap: wrap;
	gap: 12px;
	margin-top: 28px;
}

.page-header-photo {
	margin: 0;
	aspect-ratio: 4 / 3;
	border-radius: var(--radius-xl);
	overflow: hidden;
	border: 1px solid rgba(255, 255, 255, 0.12);
	box-shadow: var(--shadow-xl);
	background: var(--green-800);
}

.page-header-photo img {
	display: block;
	width: 100%;
	height: 100%;
	object-fit: cover;
}

/* --- Page Header Collage (used on Support page) --------------------------- */
.page-header-collage {
	position: relative;
	width: 100%;
	max-width: 520px;
	aspect-ratio: 4 / 3;
	min-height: 380px;
	margin: 0 auto;
	isolation: isolate;
}

.collage-glow {
	position: absolute;
	inset: 10% 12%;
	background: radial-gradient(circle, rgba(212, 175, 55, 0.22) 0%, rgba(20, 77, 44, 0) 70%);
	filter: blur(32px);
	pointer-events: none;
	z-index: 0;
}

.collage-card {
	position: absolute;
	margin: 0;
	border-radius: var(--radius-lg);
	overflow: hidden;
	border: 3px solid rgba(255, 255, 255, 0.95);
	box-shadow: 0 16px 36px rgba(5, 13, 26, 0.35);
	background: var(--green-900);
	transition: transform var(--transition-base), box-shadow var(--transition-base);
}

.collage-card img {
	display: block;
	width: 100%;
	height: 100%;
	object-fit: cover;
}

/* Card 1: Main hero portrait (smiling students) */
.collage-card--1 {
	top: 6%;
	left: 4%;
	width: 60%;
	height: 72%;
	transform: rotate(-2.5deg);
	z-index: 2;
}

/* Card 2: Top-right accent (students on stairs) */
.collage-card--2 {
	top: 2%;
	right: 4%;
	width: 50%;
	height: 52%;
	transform: rotate(3deg);
	z-index: 1;
}

/* Card 3: Bottom-right foreground (classroom teaching) */
.collage-card--3 {
	bottom: 4%;
	right: 8%;
	width: 56%;
	height: 54%;
	transform: rotate(-1.5deg);
	z-index: 3;
	border-color: #FFFFFF;
	box-shadow: 0 20px 42px rgba(5, 13, 26, 0.45);
}

/* Card 4: The Turning Point Youth Centre — a wide building, so a wide print,
   laid across the bottom-left on top of the others. */
.collage-card--4 {
	bottom: 0;
	left: 0;
	width: 52%;
	aspect-ratio: 2 / 1;
	transform: rotate(2deg);
	z-index: 4;
	border-color: #FFFFFF;
	box-shadow: 0 20px 42px rgba(5, 13, 26, 0.45);
}

.collage-card:hover {
	transform: translateY(-4px) scale(1.02);
	z-index: 5;
	box-shadow: 0 22px 48px rgba(5, 13, 26, 0.5);
}

@media (max-width: 640px) {
	.page-header-collage {
		min-height: 290px;
		max-width: 360px;
		margin-top: 16px;
	}
}

/* --- Section labels -------------------------------------------------------- */
/* --gold-500 on white measured 2.1:1, under the 4.5:1 small text needs. */
.section-eyebrow {
	color: var(--gold-700);
	margin: 0 0 12px;
}

.page-header .section-eyebrow,
.section-why-gtis .section-eyebrow,
.section-history-timeline .section-eyebrow,
.cta-banner-container .section-eyebrow,
.contact-form-card .section-eyebrow {
	color: var(--gold-300);
	background: none;
	border: 0;
	padding: 0;
}

/* --- Card grids ------------------------------------------------------------ */
.programs-bento-grid,
.pillars-mission-grid,
.feature-grid,
.roadmap-grid {
	max-width: var(--container);
	margin-left: auto;
	margin-right: auto;
}

/* Two items — a vision and a mission — stay two up at every width above a
   phone; four columns would strand them in the left half. */
@media (min-width: 600px) {
	.roadmap-grid--pair {
		grid-template-columns: repeat(2, 1fr);
	}
}

/* --- Light cards ----------------------------------------------------------- */
.roadmap-step-card {
	background: var(--surface-white);
	padding: 32px 28px;
	box-shadow: var(--shadow-sm);
}

.step-card-title {
	font-size: var(--text-xl);
	line-height: 1.3;
}

.step-card-desc {
	font-size: var(--text-base);
	line-height: 1.6;
}

/* The mission, vision and motto cards are written for the dark band on the
   home page. Where they sit on a light section they take the light card. */
.section-programs .pillar-mission-card {
	background: var(--surface-white);
	border: 1px solid var(--slate-200);
	box-shadow: var(--shadow-sm);
	backdrop-filter: none;
	-webkit-backdrop-filter: none;
}

.section-programs .pillar-mission-card:hover {
	border-color: var(--gold-400);
	box-shadow: var(--shadow-xl);
}

.section-programs .pillar-mission-card:focus-visible {
	outline-color: var(--green-800);
}

.section-programs .pillar-letter-tag {
	background: var(--navy-900);
	border-color: var(--navy-900);
	color: var(--gold-400);
}

.section-programs .pillar-card-title {
	color: var(--navy-900);
}

.section-programs .pillar-card-desc {
	color: var(--slate-600);
}

.section-programs .pillar-card-lead {
	color: var(--green-700);
}

/* --- Photographs ----------------------------------------------------------- */
.program-img-wrapper {
	height: auto;
	aspect-ratio: 4 / 3;
}

.section-programs .section-figure img,
.lookahead-figure,
.post-hero-image {
	border: 1px solid var(--border-soft);
	box-shadow: var(--shadow-md);
}

/* The Youth Centre text runs long beside a wide photograph; centring the photo
   left it floating halfway down the column. */
.lookahead {
	align-items: start;
}

/* --- Contact details ------------------------------------------------------- */
/* These boxes were written for a dark panel and sat on the white page, where
   their translucent green read as a muddy grey. */
.contact-detail-box {
	--focus-ring: var(--green-800);
	background: var(--surface-white);
	border: 1px solid var(--border-soft);
	box-shadow: var(--shadow-sm);
	backdrop-filter: none;
}

.contact-detail-box:hover {
	background: var(--surface-white);
	border-color: var(--gold-400);
}

.contact-detail-box:focus-visible {
	outline-color: var(--green-800);
}

.contact-box-icon {
	background: var(--green-50);
	border-color: var(--green-100);
	color: var(--green-700);
}

.contact-box-title {
	color: var(--navy-900);
}

.contact-box-desc {
	color: var(--slate-600);
}

.contact-box-link,
.contact-box-link:hover,
.phone-dial-link {
	color: var(--green-700);
}

/* --- About: the link through to the history -------------------------------- */
.section-teaser {
	text-align: center;
}

/* --- The closing invitation ------------------------------------------------ */
.section-cta-banner {
	--focus-ring: var(--gold-300);
	background: var(--bg-main);
	padding: var(--section-y) var(--gutter);
	color: inherit;
	overflow: visible;
}

.cta-banner-container {
	max-width: var(--container);
	padding: clamp(44px, 7vw, 88px) clamp(20px, 5vw, 64px);
	border-radius: var(--radius-xl);
	background-color: var(--green-900);
	background-image:
		linear-gradient(180deg, rgba(7, 31, 18, 0.90) 0%, rgba(7, 31, 18, 0.84) 45%, rgba(7, 31, 18, 0.92) 100%),
		url('assets/images/gtis-campus-banner.jpg');
	background-size: auto, cover;
	background-position: center, center;
	background-repeat: no-repeat, no-repeat;
	box-shadow: var(--shadow-lg);
	color: #FFFFFF;
	overflow: hidden;
}

.cta-banner-container > * {
	max-width: 760px;
	margin-left: auto;
	margin-right: auto;
}

.cta-banner-container > .cta-btn-group {
	max-width: none;
}

@media (min-width: 900px) and (prefers-reduced-motion: no-preference) {
	.section-cta-banner {
		background-attachment: scroll;
	}
}

/* --- Arrival landmarks (Contact page) -------------------------------------- */
.arrival-landmarks-grid {
	display: grid;
	grid-template-columns: 1fr;
	gap: clamp(16px, 2.5vw, 28px);
	margin-bottom: clamp(24px, 3.5vw, 36px);
}

@media (min-width: 640px) {
	.arrival-landmarks-grid {
		grid-template-columns: repeat(2, 1fr);
	}
}

.arrival-landmark-card {
	background: var(--surface-white);
	border: 1px solid var(--border-soft);
	border-radius: var(--radius-lg);
	overflow: hidden;
	box-shadow: var(--shadow-sm);
	display: flex;
	flex-direction: column;
	transition: transform 0.2s ease, box-shadow 0.2s ease;
}

.arrival-landmark-card:hover {
	transform: translateY(-2px);
	box-shadow: var(--shadow-md);
}

.arrival-landmark-figure {
	margin: 0;
	aspect-ratio: 16 / 10;
	overflow: hidden;
	background: var(--green-950);
}

.arrival-landmark-figure img {
	width: 100%;
	height: 100%;
	object-fit: cover;
	display: block;
}

.arrival-landmark-caption {
	padding: 16px 20px;
	display: flex;
	flex-direction: column;
	gap: 4px;
	text-align: left;
}

.arrival-landmark-caption strong {
	font-family: var(--font-display);
	font-size: var(--text-base);
	font-weight: 700;
	color: var(--green-900);
}

.arrival-landmark-caption span {
	font-size: var(--text-sm);
	color: var(--charcoal-600);
	line-height: 1.45;
}


/* The campus buildings on the contact page: oldest first, one row of four on a
   desktop, two on a tablet. Each photograph takes the site's 4:3 and carries
   its year in the same chip the programme cards use. */
.arrival-landmark-figure {
	position: relative;
	aspect-ratio: 4 / 3;
}

.arrival-landmark-card {
	margin: 0;
}

.campus-buildings-header {
	margin: 0 auto clamp(20px, 3vw, 32px);
}

@media (min-width: 640px) {
	.arrival-landmarks-grid--four {
		grid-template-columns: repeat(2, 1fr);
	}
}

@media (min-width: 1024px) {
	.arrival-landmarks-grid--four {
		grid-template-columns: repeat(4, 1fr);
	}
}

/* Two white blocks meeting would stack their padding into a double gap. */
.section-contact-main:has(+ .section-cta-banner) {
	padding-bottom: 0;
}

/* --- Chinese ---------------------------------------------------------------
   Noto Sans SC is loaded on Chinese pages only — a CJK face is several hundred
   kilobytes no English or Khmer reader should pay for. It comes after the Latin
   faces in each stack, so "GTIS", figures and English names keep the site's own
   type and only the Chinese characters fall through to it. System CJK faces
   follow, for the moment before the web font arrives. */
html[lang="zh-Hans"] {
	--font-display: 'Plus Jakarta Sans', 'Noto Sans SC', 'PingFang SC', 'Microsoft YaHei', sans-serif;
	--font-heading: 'Plus Jakarta Sans', 'Noto Sans SC', 'PingFang SC', 'Microsoft YaHei', sans-serif;
	--font-body: 'DM Sans', 'Noto Sans SC', 'PingFang SC', 'Microsoft YaHei', sans-serif;
}

/* Chinese headings are set solid; the tight tracking that suits Latin display
   type crowds the characters together. */
html[lang="zh-Hans"] h1,
html[lang="zh-Hans"] h2,
html[lang="zh-Hans"] h3,
html[lang="zh-Hans"] .page-header-title,
html[lang="zh-Hans"] .section-main-title,
html[lang="zh-Hans"] .cta-banner-title {
	letter-spacing: 0;
}

/* The 中文 button on the English and Khmer pages, where the web font is not loaded. */
.lang-btn[lang="zh-Hans"] {
	font-family: 'Noto Sans SC', 'PingFang SC', 'Microsoft YaHei', sans-serif;
}

/* --- Language menu ----------------------------------------------------------
   A globe that opens a short list. Sits where the pills were, so the header's
   own spacing and the collision logic are unchanged. */
.lang-menu {
  position: relative;
}

.lang-menu-button {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  min-height: var(--tap);
  padding: 0 12px;
  border: 1px solid var(--border-soft);
  border-radius: var(--radius-full);
  background: var(--ink-50);
  color: var(--green-800);
  font-size: var(--text-sm);
  font-weight: 700;
  cursor: pointer;
  list-style: none;
  white-space: nowrap;
  transition: border-color var(--transition-fast), background var(--transition-fast);
}

.lang-menu-button::-webkit-details-marker {
  display: none;
}

.lang-menu-button:hover,
.lang-menu[open] .lang-menu-button {
  border-color: var(--green-700);
  background: var(--surface-white);
}

.lang-menu-chevron {
  transition: transform var(--transition-fast);
}

.lang-menu[open] .lang-menu-chevron {
  transform: rotate(180deg);
}

.lang-menu-list {
  position: absolute;
  right: 0;
  top: calc(100% + 8px);
  z-index: 60;
  min-width: 180px;
  margin: 0;
  padding: 6px;
  list-style: none;
  background: var(--surface-white);
  border: 1px solid var(--border-soft);
  border-radius: var(--radius-md);
  box-shadow: var(--shadow-lg);
}

.lang-menu-item {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  min-height: var(--tap);
  padding: 0 12px;
  border-radius: var(--radius-sm);
  color: var(--ink-800);
  font-size: var(--text-md);
  font-weight: 600;
  text-decoration: none;
}

.lang-menu-item:hover {
  background: var(--green-50);
  color: var(--green-800);
}

.lang-menu-item.is-active {
  color: var(--green-800);
}

.lang-menu-item[lang="zh-Hans"],
.lang-menu-current[lang="zh-Hans"] {
  font-family: 'Noto Sans SC', 'PingFang SC', 'Microsoft YaHei', sans-serif;
}

.lang-menu-button:focus-visible {
  border-radius: var(--radius-full);
}

/* Three languages in the menu sheet: three across. */
.lang-toggle--block {
  grid-template-columns: repeat(3, 1fr);
}

/* --- Quick contact: four tiles -------------------------------------------
   The cards sat in one row with the icon beside the text, and a grid column
   will not shrink below its longest unbreakable word — so the email address
   widened its card while the telephone number broke onto four lines next to
   it. They are tiles now: equal columns, icon above the words, two by two
   until there is room for all four across. */
.contact-actions-container {
	grid-template-columns: repeat(2, minmax(0, 1fr));
	gap: clamp(12px, 2vw, 20px);
}

@media (min-width: 1024px) {
	.contact-actions-container {
		grid-template-columns: repeat(4, minmax(0, 1fr));
	}
}

.quick-action-card {
	flex-direction: column;
	align-items: flex-start;
	gap: 14px;
	height: 100%;
	padding: clamp(18px, 2.5vw, 26px);
}

.action-card-text {
	min-width: 0;
	width: 100%;
}

/* A value breaks only at a space or after the @ the markup marks with <wbr>,
   so a narrow tile gives "gtis.cam@ / gmail.com", never "gmail. / com". */
.action-card-val {
	font-size: clamp(0.95rem, 1.6vw, var(--text-lg));
	overflow-wrap: break-word;
	line-height: 1.3;
}

/* Below 360px two tiles leave no room for "@gtiscambodia" whole; one a row. */
@media (max-width: 359px) {
	.contact-actions-container {
		grid-template-columns: minmax(0, 1fr);
	}
}
