/*
 * site.css — KOTA MAS Public Design System v2
 *
 * Theme: Batik Luxe Editorial — light cream ground, deep navy, muted gold, warm teal
 * Fonts: Playfair Display (headings) + Lora (body) + DM Sans (UI)
 *
 * Table of contents:
 *  1. Variables
 *  2. Reset & base
 *  3. Typography helpers
 *  4. Layout
 *  5. Navigation
 *  6. Page hero (inner pages)
 *  7. Batik decorative elements
 *  8. Section bands & panels
 *  9. Cards & tiles
 * 10. Forms
 * 11. Hero slider (homepage)
 * 12. Announcement popup
 * 13. Footer
 * 14. Animations & scroll reveal
 * 15. Responsive
 * 16. Language toggle & view transitions
 */

/* ── 1. Variables ─────────────────────────────────────────────────────────── */

:root {
  /* Palette */
  --cream:        #F8F6F3;
  --cream-mid:    #FDFBF8;
  --cream-deep:   #F5F3F0;
  /* Page background. Eleven places across the templates and stylesheets already
     said var(--bg) but nothing ever defined it on public pages, so they all
     resolved to transparent and only *looked* right by inheriting body's cream.
     Named explicitly so it stops being an accident. (auth.css overrides it with
     its own dark value for the login screen.) */
  --bg:           #F8F6F3;
  --navy:         #0F4C75;
  --navy-mid:     #1B3B6F;
  --navy-light:   rgba(15, 76, 117, 0.07);
  --gold:         #FBBF24;   /* bright — for dark/navy backgrounds only */
  --gold-light:   rgba(251, 191, 36, 0.15);
  /* Hover partner for --gold-ink. Every use is a link hover on a light
     surface, so it has to clear 4.5:1 too — #D97706 only managed 3.19:1. */
  --gold-hover:   #A8480A;   /* 5.84:1 on white */
  /* Readable gold for text, icons, thin borders sitting on light/white
     surfaces. #B45309 ≈ 5:1 on white (WCAG AA normal text). Same amber hue
     as --gold so it stays on-brand. Use --gold only on dark backgrounds. */
  --gold-ink:        #B45309;
  --gold-ink-border: rgba(180, 83, 9, 0.45);
  /* Vibrant accent gold for LARGE decorative symbols only (the stat "K"/"+"/"."
     accents). This is the brand gold #FBBF24 at its exact hue (43deg), just
     darkened to 3.11:1 on white — the closest-to-original colour that still
     clears WCAG AA for large text (>=24px; these are 35px). The original at
     full brightness is only 1.67:1. Large-decorative use only — normal text
     uses --gold-ink. */
  --gold-accent:     #BD8903;
  /* --teal is the same value as --navy-mid and is kept deliberately: its
     partner --teal-light is NOT the same as --navy-light (0.12 vs 0.07 alpha,
     different hue), so collapsing --teal would orphan it. Two names, one
     concept, on purpose. --copper was a third name for --gold with no such
     excuse and has been removed. */
  --teal:         #1B3B6F;
  --teal-light:   rgba(27, 59, 111, 0.12);

  /* Cyan accent.
     --cyan is the brand cyan and is fine as a fill or on navy, but at 3.11:1
     on white it fails AA as a text colour. --cyan-ink is the text-safe pair,
     same hue family. */
  --cyan:         #0E9FC1;
  --cyan-ink:     #0A7A96;   /* 4.96:1 on white */
  --cyan-dim:     rgba(14, 159, 193, 0.1);

  /* home.css aliases */
  --gold-dim:     rgba(251, 191, 36, 0.12);
  --foreground:   #1a1a1a;
  --muted-text:   #595959;
  --font-serif:   'Playfair Display', Georgia, serif;

  /* Accent Colors */
  --primary-dark: #052E47;

  /* Text */
  --fg:           #1a1a1a;
  --fg-mid:       #3d3d3d;
  --fg-muted:     #595959;
  /* #767676 cleared 4.5:1 on pure white but only reached 4.40:1 against the
     warm card surface (--cream-mid #FDFBF8) it is most often used on, which is
     where it actually appears. #6E6E6E passes on every surface in the palette. */
  --fg-subtle:    #6E6E6E;

  /* Surfaces */
  --surface:      #ffffff;
  --surface-warm: #fdfbf7;
  --border:       rgba(15, 76, 117, 0.09);
  --border-mid:   rgba(15, 76, 117, 0.16);

  /* Typography
     Two families, not three. Playfair carries the brand voice in headings;
     DM Sans does everything else. Lora was a third render-blocking download
     doing the same job as DM Sans, and a serif at 16 px is the harder read
     for the 30+ membership this site is built for.
     To restore Lora: put it back on --font-body/--font-serif and re-add the
     family to the Google Fonts <link> in layouts/main.latte. */
  --font-display: 'Playfair Display', Georgia, serif;
  --font-body:    'DM Sans', system-ui, -apple-system, 'Segoe UI', sans-serif;
  --font-ui:      'DM Sans', system-ui, -apple-system, 'Segoe UI', sans-serif;

  /* Spacing */
  --nav-height:   68px;

  /* One width for the whole site: .container, .nav__inner and .pb-container all
     read this, so the nav bar and the page content always share an edge.
     Floor is set by the nav bar itself — logo + links + language + portal
     button measure ~1154px, so anything under ~1224px total clips the portal
     button off-screen. Change this and check --nav-desktop-min below. */
  --container-max: 1280px;

  /* Radius */
  --r-sm:   6px;
  --r-md:   12px;
  --r-lg:   20px;
  --r-xl:   32px;
}

/* ── 2. Reset & base ─────────────────────────────────────────────────────── */

*, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; }

/* Base font raised for the 30+ cooperative audience — all rem values scale from
   this, not 16px. Expressed as a percentage, not 20px: a flat px value silently
   overrides whatever default text size the visitor set in their own browser.
   125% of the 16px default is the same 20px, but a visitor who asked for 24px
   now gets 30px instead of being ignored. */
html { scroll-behavior: smooth; -webkit-font-smoothing: antialiased; font-size: 125%; overflow-x: clip; }

body {
  font-family:  var(--font-body);
  background:   var(--cream);
  color:        var(--fg);
  min-height:   100vh;
  overflow-x:   clip;
  line-height:  1.7;
}

/* height:auto is not optional: an <img> with width/height attributes gets them
   as presentational hints, and a fixed height makes the browser ignore any CSS
   aspect-ratio — the image then renders at its literal pixel height. Class
   rules that want height:100% (card/hero images) still win on specificity. */
img { display: block; max-width: 100%; height: auto; }
a   { color: inherit; text-decoration: none; }

/* ── 3. Typography helpers ───────────────────────────────────────────────── */

.label-tag {
  display:        inline-block;
  font-family:    var(--font-ui);
  font-size:      0.85rem;
  font-weight:    600;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color:          var(--gold-ink);
  padding:        0.25rem 0.75rem;
  border:         1px solid var(--gold-ink-border);
  border-radius:  20px;
  background:     var(--gold-light);
}

.section-label {
  font-family:    var(--font-ui);
  font-size:      0.85rem;
  font-weight:    600;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color:          var(--gold-ink);
  margin-bottom:  0.9rem;
  display:        block;
}

.section-heading {
  font-family:  var(--font-display);
  font-size:    clamp(1.6rem, 3vw, 2.4rem);
  font-weight:  600;
  color:        var(--primary-dark);
  line-height:  1.25;
  margin-bottom: 1rem;
}

.section-sub {
  font-family:  var(--font-body);
  font-size:    1rem;
  color:        var(--fg-muted);
  line-height:  1.8;
  max-width:    65ch;
}

/* ── 4. Layout ───────────────────────────────────────────────────────────── */

.container {
  max-width: var(--container-max);
  margin:    0 auto;
  padding:   0 1.75rem;
}

.page-main { position: relative; }

/* Band = full-width section strip */
.band {
  padding: 5rem 0;
}
.band--cream    { background: var(--cream); }
.band--warm     { background: var(--cream-mid); }
.band--surface  { background: var(--surface); }
.band--navy     { background: var(--navy); color: #fff; }

.band + .band {
  border-top: 1px solid var(--border);
}

/* Two-column layout helpers */
.col-layout {
  display: grid;
  gap: 3rem;
  align-items: start;
}

@media (min-width: 900px) {
  .col-layout--6040 { grid-template-columns: 1.5fr 1fr; }
  .col-layout--half { grid-template-columns: 1fr 1fr; }
  .col-layout--third { grid-template-columns: repeat(3, 1fr); }
  .col-layout--quarter { grid-template-columns: repeat(4, 1fr); }
}

/* Vertically centre the two columns. Use on intro rows where the right column
   is a supporting panel/card-stack shorter than the left: without this it pins
   to the top and lines up with the eyebrow label instead of the body, leaving
   dead space below. One shared rule so every such row behaves the same. */
.col-layout--center { align-items: center; }

/* Generic card grid */
.card-grid {
  display: grid;
  gap: 1.5rem;
}

@media (min-width: 700px)  { .card-grid--2 { grid-template-columns: repeat(2, 1fr); } }
@media (min-width: 900px)  { .card-grid--3 { grid-template-columns: repeat(3, 1fr); } }
@media (min-width: 1100px) { .card-grid--4 { grid-template-columns: repeat(4, 1fr); } }

.page-section {
  padding: 4.5rem 0 5rem;
}

/* ── 5. Navigation ───────────────────────────────────────────────────────── */

.nav {
  position:   fixed;
  top:        0;
  left:       0;
  right:      0;
  z-index:    100;
  height:     var(--nav-height);
  display:    flex;
  align-items: center;
  background: transparent;
  transition: background 0.35s, box-shadow 0.35s;
}

.nav.is-scrolled {
  background: rgba(250, 248, 244, 0.96);
  box-shadow: 0 1px 0 var(--border), 0 4px 20px rgba(27,43,75,0.06);
  backdrop-filter: blur(16px);
}

.nav__inner {
  max-width:      var(--container-max);
  margin:         0 auto;
  padding:        0 1.75rem;
  width:          100%;
  display:        flex;
  align-items:    center;
  justify-content: space-between;
  gap:            1rem;
}

.nav__logo {
  display:     flex;
  align-items: center;
  gap:         0.8rem;
  flex-shrink: 0;
}

.nav__logo-img {
  height: 40px;
  width: auto;
  max-width: 180px;
}

/* Decorative mark: two overlapping diamond shapes */
.nav__logo-mark {
  position:         relative;
  width:            38px;
  height:           38px;
  display:          flex;
  align-items:      center;
  justify-content:  center;
  flex-shrink:      0;
}

.nav__logo-mark::before,
.nav__logo-mark::after {
  content:      '';
  position:     absolute;
  width:        20px;
  height:       20px;
  border:       1.5px solid var(--gold);
  transform:    rotate(45deg);
}

.nav__logo-mark::before {
  top:  4px;
  left: 4px;
  background: var(--gold-light);
}

.nav__logo-mark::after {
  bottom: 4px;
  right:  4px;
  background: transparent;
  opacity: 0.4;
}

.nav__logo-initials {
  position:   relative;
  z-index:    1;
  font-family: var(--font-display);
  font-size:  0.85rem;
  font-weight: 700;
  color:      var(--gold);
  letter-spacing: 0.03em;
}

/* Over the dark hero the nav is transparent and bright gold reads well; once
   scrolled the bar turns cream, where bright gold loses contrast — darken it. */
.nav.is-scrolled .nav__logo-initials      { color: var(--gold-ink); }
.nav.is-scrolled .nav__logo-mark::before  { border-color: var(--gold-ink); }
.nav.is-scrolled .nav__logo-mark::after   { border-color: var(--gold-ink); }

.nav__logo-text {
  display:        flex;
  flex-direction: column;
  line-height:    1.2;
}

.nav__logo-name {
  font-family:    var(--font-display);
  font-size:      0.9rem;
  font-weight:    700;
  color:          var(--navy);
  letter-spacing: 0.04em;
}

.nav__logo-tagline {
  font-family:    var(--font-ui);
  font-size:      0.68rem;
  color:          var(--fg-muted);
  letter-spacing: 0.12em;
  text-transform: uppercase;
}

.nav__links {
  display:    flex;
  align-items: center;
  gap:        0.1rem;
  list-style: none;
}

/* Only exists for the mobile menu — the desktop bar has its own .nav__portal. */
.nav__portal-mobile { display: none; }

/* The dropdown trigger is a <button> so it can be opened from the keyboard;
   these two selectors keep it pixel-identical to the plain <a> siblings. */
.nav__links > li > a,
.nav__links > li > .nav__dropdown-trigger {
  display:        block;
  padding:        0.4rem 0.7rem;
  font-family:    var(--font-ui);
  font-size:      0.85rem;
  font-weight:    500;
  color:          var(--fg-mid);
  border-radius:  var(--r-sm);
  transition:     color 0.2s, background 0.2s;
  white-space:    nowrap;

  /* button reset — appearance:none is the important one: without it the
     <button> keeps its native chrome (a box border) on mobile even with
     border:0, which is why the dropdown items rendered as outlined boxes
     next to the plain <a> links. */
  appearance:         none;
  -webkit-appearance: none;
  background:     none;
  border:         0;
  cursor:         pointer;
  font:           inherit;
  font-size:      0.85rem;
  font-weight:    500;
  line-height:    inherit;
  text-align:     left;
}

.nav__links > li > a:hover,
.nav__links > li > .nav__dropdown-trigger:hover {
  color:      var(--navy);
  background: var(--navy-light);
}

.nav__links > li > a.is-active,
.nav__links > li > .nav__dropdown-trigger.is-active {
  color:   var(--gold-ink);
  font-weight: 600;
}

/* The caret used to be a literal ▾ in the markup, which renders differently
   per platform font. Drawn in CSS instead so it matches everywhere. */
.nav__dropdown-trigger::after {
  content:       '';
  display:       inline-block;
  width:         0.34em;
  height:        0.34em;
  margin-left:   0.45em;
  vertical-align: 0.16em;
  border-right:  1.5px solid currentColor;
  border-bottom: 1.5px solid currentColor;
  transform:     rotate(45deg);
  transition:    transform 0.2s;
}

.nav__dropdown-trigger[aria-expanded="true"]::after {
  transform: rotate(-135deg);
}

/* Visible to screen readers only — for labels that would be redundant on
   screen but are required for the control to have an accessible name. */
.sr-only {
  position:    absolute;
  width:       1px;
  height:      1px;
  padding:     0;
  margin:      -1px;
  overflow:    hidden;
  clip:        rect(0 0 0 0);
  clip-path:   inset(50%);
  white-space: nowrap;
  border:      0;
}

/* ── Skip link (WCAG 2.4.1) ──────────────────────────────────────────────
   Off-screen until focused, then pinned top-left above the sticky nav. */
.skip-link {
  position:      absolute;
  top:           0;
  left:          0;
  z-index:       1000;
  padding:       0.75rem 1.25rem;
  background:    var(--navy);
  color:         #fff;
  font-family:   var(--font-ui);
  font-size:     0.9rem;
  font-weight:   600;
  border-radius: 0 0 var(--r-sm) 0;
  transform:     translateY(-110%);
  transition:    transform 0.15s ease;
}

.skip-link:focus {
  transform: translateY(0);
}

/* ── Focus ring ──────────────────────────────────────────────────────────
   One token for the whole site. The gold reads against both the cream nav
   and the navy footer, where a default blue-black ring disappears. Applied
   via :focus-visible so mouse users never see it. */
:root {
  --focus-ring: 0 0 0 3px rgba(15, 76, 117, 0.25), 0 0 0 1.5px var(--navy);
}

*:focus-visible {
  outline:        2px solid var(--navy);
  outline-offset: 2px;
  border-radius:  var(--r-sm);
}

/* Navy on navy is invisible — flip to gold inside dark surfaces. */
.footer *:focus-visible,
.nav__portal:focus-visible,
.back-to-top:focus-visible {
  outline: 2px solid var(--gold);
}

/* Dropdown */
.nav__dropdown { position: relative; }

.nav__dropdown-menu {
  display:        none;
  position:       absolute;
  top:            calc(100% + 4px);
  left:           50%;
  transform:      translateX(-50%);
  /* max-content so "Jawatankuasa Audit Dalaman" and "Pencapaian & Anugerah"
     stay on one line; the max-width keeps a stray long label from running off
     the viewport edge. */
  min-width:      230px;
  width:          max-content;
  max-width:      min(20rem, calc(100vw - 2rem));
  background:     var(--surface);
  border:         1px solid var(--border-mid);
  border-radius:  var(--r-md);
  /* invisible bridge: extended padding and negative margin to catch cursor movement from trigger to menu */
  padding:        calc(0.6rem + 8px) 0.6rem 0.6rem;
  margin-top:     -8px;
  box-shadow:     0 12px 40px rgba(27,43,75,0.14);
  z-index:        100;
  pointer-events: none; /* disabled by default to prevent hover interference */
}

.nav__dropdown:nth-child(3) .nav__dropdown-menu {
  margin-top: -12px;  /* Increase gap for taller menu */
}

/* JS sets [data-open] — no CSS :hover, so the delay works properly */
.nav__dropdown-menu[data-open] {
  display: block;
  pointer-events: auto; /* enable pointer events when open */
  animation: dropIn 0.18s ease;
}

@keyframes dropIn {
  from { opacity: 0; transform: translateX(-50%) translateY(-6px); }
  to   { opacity: 1; transform: translateX(-50%) translateY(0); }
}

.nav__dropdown > a.is-active {
  border-bottom: 2px solid transparent;
  background: linear-gradient(var(--surface), var(--surface)) padding-box,
              linear-gradient(90deg, var(--gold), var(--teal)) border-box;
  padding-bottom: 3px;
}
.nav__dropdown-menu a {
  display:       block;
  padding:       0.5rem 0.85rem;
  font-family:   var(--font-ui);
  font-size:     0.85rem;
  font-weight:   400;
  color:         var(--fg-muted);
  border-radius: var(--r-sm);
  transition:    color 0.15s, background 0.15s;
}

.nav__dropdown-menu a:hover {
  color:      var(--navy);
  background: var(--navy-light);
}

.nav__portal {
  display:       flex;
  align-items:   center;
  gap:           0.4rem;
  padding:       0.5rem 1.1rem;
  font-family:   var(--font-ui);
  font-size:     0.85rem;
  font-weight:   600;
  color:         var(--navy);
  background:    var(--gold-light);
  border:        1.5px solid rgba(184,147,90,0.45);
  border-radius: var(--r-sm);
  transition:    background 0.2s, border-color 0.2s, color 0.2s;
  white-space:   nowrap;
  letter-spacing: 0.02em;
}

.nav__portal:hover {
  background:   var(--gold);
  border-color: var(--gold);
  color:        #fff;
}

.nav__hamburger {
  display:    none;
  background: none;
  border:     none;
  cursor:     pointer;
  padding:    0.5rem;
  color:      var(--navy);
}

/* Language switcher — both options visible, active one marked (desktop). */
.nav__lang {
  display:       flex;
  flex-shrink:   0;
  align-items:   center;
  gap:           0.15rem;
  padding:       0.2rem 0.3rem;
  border:        1.5px solid var(--border-mid);
  border-radius: var(--r-sm);
  background:    var(--surface);
}

/* Compact single-language chip — mobile only (the pair is too wide there). */
.nav__lang-compact {
  display:         none;   /* shown at <=768px, pair hidden */
  align-items:     center;
  justify-content: center;
  flex-shrink:     0;
  min-width:       40px;
  min-height:      40px;
  padding:         0.35rem 0.6rem;
  font-family:     var(--font-ui);
  font-size:       0.8rem;
  font-weight:     700;
  letter-spacing:  0.03em;
  color:           #fff;
  background:      var(--navy);
  border:          1.5px solid var(--navy);
  border-radius:   var(--r-sm);
  text-decoration: none;
}
.nav__lang-compact:hover { background: var(--navy-mid); border-color: var(--navy-mid); }

.nav__lang__opt {
  display:         flex;
  align-items:     center;
  justify-content: center;
  min-width:       34px;
  min-height:      32px;
  padding:         0.2rem 0.45rem;
  font-family:     var(--font-ui);
  font-size:       0.8rem;
  font-weight:     600;
  letter-spacing:  0.03em;
  color:           var(--fg-muted);
  border-radius:   calc(var(--r-sm) - 2px);
  text-decoration: none;
  transition:      background 0.2s, color 0.2s;
}

/* Link half only — the active half is a <span> and must not look pressable. */
a.nav__lang__opt:hover {
  color:      var(--navy);
  background: var(--navy-light);
}

.nav__lang__opt.is-active {
  color:      #fff;
  background: var(--navy);
  cursor:     default;
}

.nav__lang__sep {
  color:       var(--border-mid);
  font-size:   0.8rem;
  user-select: none;
}

/* ── 6. Page hero (inner pages) ──────────────────────────────────────────── */

.page-hero {
  position:   relative;
  min-height: 46vh;
  display:    grid;
  align-items: center;
  padding:    7rem 0 5rem;
  overflow:   hidden;
  background: var(--cream-mid);
}

/* Batik geometric overlay on the hero */
.page-hero::before {
  content:    '';
  position:   absolute;
  inset:      0;
  background-image:
    radial-gradient(circle at 80% 30%, rgba(184,147,90,0.13) 0%, transparent 55%),
    radial-gradient(circle at 15% 75%, rgba(42,125,140,0.10) 0%, transparent 50%);
  pointer-events: none;
}

/* SVG batik corner motif (injected via ::after on container) */
.page-hero__inner {
  position: relative;
  z-index:  1;
  width:    100%;
}

.page-hero .section-label { margin-bottom: 0.7rem; }

.page-hero .section-heading {
  font-size:  clamp(2rem, 4.5vw, 3.2rem);
  max-width:  18ch;
  margin-bottom: 1.2rem;
}

.page-hero .section-sub {
  font-size:  1.05rem;
  max-width:  55ch;
}

/* Gold rule under hero heading */
.page-hero__rule {
  width:      3.5rem;
  height:     2px;
  background: linear-gradient(90deg, var(--gold), var(--teal));
  border-radius: 2px;
  margin:     1.2rem 0;
}

/* Decorative batik-diamond motif top-right */
.page-hero__motif {
  position:       absolute;
  top:            -40px;
  right:          -60px;
  width:          360px;
  height:         360px;
  opacity:        0.06;
  pointer-events: none;
  z-index:        0;
}

/* ── 7. Batik decorative elements ────────────────────────────────────────── */

/* Full-width gradient rule */
.batik-rule {
  height:    2px;
  background: linear-gradient(90deg, transparent, var(--gold) 25%, var(--teal) 75%, transparent);
  opacity:   0.6;
  border:    none;
  margin:    0;
}

/* Small diamond separator */
.diamond-sep {
  display:   flex;
  align-items: center;
  gap:       0.75rem;
  margin:    2rem 0;
}

.diamond-sep::before,
.diamond-sep::after {
  content:    '';
  flex:       1;
  height:     1px;
  background: linear-gradient(90deg, transparent, var(--border-mid));
}

.diamond-sep::after {
  background: linear-gradient(90deg, var(--border-mid), transparent);
}

.diamond-sep__gem {
  width:      8px;
  height:     8px;
  background: var(--gold);
  transform:  rotate(45deg);
  flex-shrink: 0;
}

/* Section intro block */
.section-intro {
  max-width: 640px;
  margin-bottom: 3rem;
}

/* ── 8. Section bands & panels ───────────────────────────────────────────── */

/* Content panel — replaces the plain div boxes */
.content-panel {
  background:    var(--surface);
  border:        1px solid var(--border);
  border-radius: var(--r-lg);
  padding:       2.5rem 3rem;
  box-shadow:    0 2px 12px rgba(27,43,75,0.04), 0 8px 32px rgba(27,43,75,0.03);
  position:      relative;
  overflow:      hidden;
}

/* Gold left accent bar */
.content-panel--accented::before {
  content:    '';
  position:   absolute;
  top:        0;
  left:       0;
  width:      3px;
  height:     100%;
  background: linear-gradient(180deg, var(--gold), var(--teal));
  border-radius: 3px 0 0 3px;
}

/* Warm panel variant */
.content-panel--warm {
  background: var(--cream-mid);
  border-color: var(--cream-deep);
}

.content-panel h2.section-heading {
  font-size: 1.35rem;
  margin-bottom: 1.2rem;
}

.content-panel p { margin-bottom: 1rem; color: var(--fg-mid); }
.content-panel p:last-child { margin-bottom: 0; }

.content-panel ul {
  list-style: none;
  padding:    0;
  display:    flex;
  flex-direction: column;
  gap:        0.7rem;
}

.content-panel ul li {
  padding-left: 1.4rem;
  position:     relative;
  color:        var(--fg-mid);
  font-size:    0.95rem;
  line-height:  1.6;
}

.content-panel ul li::before {
  content:    '';
  position:   absolute;
  left:       0;
  top:        0.55em;
  width:      7px;
  height:     7px;
  background: var(--gold);
  transform:  rotate(45deg);
}

/* ── 9. Cards & tiles ────────────────────────────────────────────────────── */

/* Feature card — service overview, stat, etc. */
.feat-card {
  background:    var(--surface);
  border:        1px solid var(--border);
  border-radius: var(--r-md);
  padding:       2rem 1.75rem;
  transition:    transform 0.25s, box-shadow 0.25s, border-color 0.25s;
  position:      relative;
  overflow:      hidden;
}

.feat-card::after {
  content:    '';
  position:   absolute;
  bottom:     0;
  left:       0;
  right:      0;
  height:     2px;
  background: linear-gradient(90deg, var(--gold), var(--teal));
  transform:  scaleX(0);
  transform-origin: left;
  transition: transform 0.3s ease;
}

.feat-card:hover {
  transform:    translateY(-4px);
  box-shadow:   0 12px 36px rgba(27,43,75,0.10);
  border-color: rgba(184,147,90,0.3);
}

.feat-card:hover::after {
  transform: scaleX(1);
}

.feat-card__icon {
  width:         44px;
  height:        44px;
  border-radius: var(--r-sm);
  background:    var(--gold-light);
  border:        1px solid rgba(184,147,90,0.3);
  display:       flex;
  align-items:   center;
  justify-content: center;
  margin-bottom: 1.2rem;
  color:         var(--gold-ink);
}

.feat-card__title {
  font-family:   var(--font-display);
  font-size:     1.05rem;
  font-weight:   600;
  color:         var(--primary-dark);
  margin-bottom: 0.5rem;
}

.feat-card__body {
  font-size:  0.9rem;
  color:      var(--fg-muted);
  line-height: 1.7;
}

/* Timeline entry */
.timeline-item {
  display:  grid;
  grid-template-columns: auto 1fr;
  gap:      0 1.75rem;
  position: relative;
}

.timeline-item + .timeline-item {
  margin-top: 2rem;
}

.timeline-dot {
  display:        flex;
  flex-direction: column;
  align-items:    center;
  gap:            0;
}

.timeline-dot__gem {
  width:         14px;
  height:        14px;
  background:    var(--gold);
  transform:     rotate(45deg);
  flex-shrink:   0;
  border:        2px solid var(--surface);
  box-shadow:    0 0 0 2px var(--gold);
}

.timeline-dot__line {
  flex:       1;
  width:      1px;
  background: linear-gradient(180deg, var(--gold), transparent);
  min-height: 2rem;
  margin-top: 4px;
}

.timeline-content {
  padding-top: 0;
  padding-bottom: 2rem;
}

.timeline-content__year {
  font-family:  var(--font-ui);
  font-size:    0.85rem;
  font-weight:  600;
  color:        var(--gold);
  letter-spacing: 0.12em;
  text-transform: uppercase;
  margin-bottom: 0.35rem;
}

.timeline-content__title {
  font-family:   var(--font-display);
  font-size:     1.05rem;
  font-weight:   600;
  color:         var(--primary-dark);
  margin-bottom: 0.4rem;
}

.timeline-content__body {
  font-size:  0.9rem;
  color:      var(--fg-muted);
  line-height: 1.7;
}

/* Award card */
.award-card {
  background:    var(--surface);
  border:        1px solid var(--border);
  border-radius: var(--r-md);
  padding:       1.75rem;
  display:       flex;
  gap:           1.25rem;
  align-items:   flex-start;
  transition:    border-color 0.25s, box-shadow 0.25s;
}

.award-card:hover {
  border-color: rgba(184,147,90,0.35);
  box-shadow:   0 6px 24px rgba(27,43,75,0.07);
}

.award-card__medal {
  width:         48px;
  height:        48px;
  border-radius: 50%;
  background:    linear-gradient(135deg, var(--gold-light), rgba(184,147,90,0.3));
  border:        1px solid rgba(184,147,90,0.4);
  display:       flex;
  align-items:   center;
  justify-content: center;
  font-family:   var(--font-display);
  font-size:     1.2rem;
  flex-shrink:   0;
  color:         var(--gold);
}

.award-card__title {
  font-family:   var(--font-display);
  font-size:     1rem;
  font-weight:   600;
  color:         var(--primary-dark);
  margin-bottom: 0.35rem;
}

.award-card__body {
  font-size:  0.88rem;
  color:      var(--fg-muted);
  line-height: 1.6;
}

/* Pekeliling / announcement card */
.pekeliling-card {
  display:        flex;
  flex-direction: column;
  background:     var(--surface);
  border:         1px solid var(--border);
  border-radius:  var(--r-md);
  overflow:       hidden;
  transition:     transform 0.25s, border-color 0.25s, box-shadow 0.25s;
}

.pekeliling-card:hover {
  transform:    translateY(-4px);
  border-color: rgba(184,147,90,0.3);
  box-shadow:   0 10px 32px rgba(27,43,75,0.09);
}

.pekeliling-card__img {
  display:      block;
  width:        100%;
  aspect-ratio: 16/9;
  object-fit:   cover;
}

.pekeliling-card__body {
  padding:        1.4rem;
  display:        flex;
  flex-direction: column;
  flex:           1;
}

.pekeliling-card__meta {
  font-family:  var(--font-ui);
  font-size:    0.85rem;
  color:        var(--teal);
  font-weight:  600;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  margin-bottom: 0.5rem;
}

.pekeliling-card__title {
  font-family:  var(--font-display);
  font-size:    0.95rem;
  font-weight:  600;
  color:        var(--navy);
  line-height:  1.45;
  margin-bottom: 0.6rem;
  flex:         1;
}

.pekeliling-card__link {
  font-family:  var(--font-ui);
  font-size:    0.85rem;
  font-weight:  600;
  color:        var(--gold);
  letter-spacing: 0.04em;
  transition:   color 0.2s;
}

.pekeliling-card__link:hover { color: var(--gold-hover); }

/* Officer portraits (Carta Organisasi, Perutusan Khas). The sources are
   background-removed cutouts exported at a matching 2:3 with the subject
   centred off its alpha bbox and bottom-anchored, so nothing here crops or
   nudges them, and no border either — a frame round a cutout outlines empty
   space. --photo-w is all that varies: by rank, or 100% to fill a column. */
.person-photo {
  width:        var(--photo-w, 170px);
  aspect-ratio: 2 / 3;
  object-fit:   contain;
  margin:       0 auto 1rem;
}

/* Jawatankuasa Audit Dalaman — one row per member, accented by role.
   These live here rather than in an inline style because Latte escapes a
   variable dropped into a style attribute as CSS, turning var(--gold) into
   var\(--gold\) — valid escaping, silently dead declaration. */
.audit-member {
  display:       flex;
  gap:           1.25rem;
  align-items:   center;
  padding:       1.5rem 1.75rem;
  background:    var(--surface);
  border:        1px solid var(--border);
  border-left:   3px solid var(--navy-mid);
  border-radius: var(--r-md);
}
.audit-member--chair {
  background:  var(--cream-mid);
  border:      1.5px solid rgba(184,147,90,0.3);
  border-left: 3px solid var(--gold);
}
.audit-member--sec { border-left-color: var(--teal); }

.audit-member__role {
  font-family:    var(--font-ui);
  font-size:      0.65rem;
  font-weight:    700;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color:          var(--fg-muted);
  margin-bottom:  0.3rem;
}
.audit-member--chair .audit-member__role { color: var(--gold-ink); }
.audit-member--sec   .audit-member__role { color: var(--teal); }

.audit-member__name {
  font-family: var(--font-display);
  font-size:   1.1rem;
  font-weight: 600;
  color:       var(--navy);
}

.audit-member__photo {
  --photo-w:   120px;
  flex-shrink: 0;
  margin:      0;
}

/* At 120px the portrait eats a third of a narrow screen and wraps the name onto
   three lines — give the text back its room. */
@media (max-width: 480px) {
  .audit-member { padding: 1.15rem 1.25rem; gap: 1rem; }
  .audit-member__photo       { --photo-w: 88px; }
  .audit-member__placeholder { width: 88px; }
}

/* Fallback frame for a member whose portrait has not been supplied yet.
   Matches the photo's rendered box so the row height does not jump. */
.audit-member__placeholder {
  width:         120px;
  flex-shrink:   0;
  aspect-ratio:  2 / 3;
  background:    linear-gradient(160deg, #f0ede8 0%, var(--cream-mid) 100%);
  border:        1.5px solid rgba(184,147,90,0.35);
  border-radius: var(--r-md);
  display:       flex;
  align-items:   center;
  justify-content: center;
}

/* ── 10. Forms ───────────────────────────────────────────────────────────── */

.form-surface {
  background:    var(--surface);
  border:        1px solid var(--border);
  border-radius: var(--r-lg);
  padding:       2.5rem;
  box-shadow:    0 4px 20px rgba(27,43,75,0.06);
}

.field-group {
  margin-bottom: 1.25rem;
}

.field-label {
  display:        block;
  font-family:    var(--font-ui);
  font-size:      0.85rem;
  font-weight:    600;
  color:          var(--fg-mid);
  margin-bottom:  0.4rem;
  letter-spacing: 0.03em;
}

.field-input,
.field-select,
.field-textarea {
  width:         100%;
  background:    var(--cream);
  border:        1.5px solid var(--border-mid);
  border-radius: var(--r-sm);
  padding:       0.75rem 1rem;
  font-family:   var(--font-body);
  font-size:     0.9rem;
  color:         var(--fg);
  transition:    border-color 0.2s, box-shadow 0.2s;
  outline:       none;
  appearance:    none;
}

.field-input:focus,
.field-select:focus,
.field-textarea:focus {
  border-color: var(--gold);
  box-shadow:   0 0 0 3px rgba(184,147,90,0.12);
}

.field-input::placeholder,
.field-textarea::placeholder {
  color: var(--fg-subtle);
}

.field-textarea { resize: vertical; min-height: 100px; }

.field-grid {
  display: grid;
  grid-template-columns: repeat(2, 1fr);
  gap: 1rem;
}

@media (max-width: 640px) {
  .field-grid { grid-template-columns: 1fr; }
}

.field-error {
  font-family:  var(--font-ui);
  font-size:    0.85rem;
  color:        #c0392b;
  margin-top:   0.3rem;
}

.alert {
  border-radius: var(--r-sm);
  padding:       0.9rem 1.25rem;
  margin-bottom: 1.5rem;
  font-family:   var(--font-ui);
  font-size:     0.85rem;
}

.alert--success {
  background: rgba(39,174,96,0.1);
  border:     1px solid rgba(39,174,96,0.25);
  color:      #1a6b39;
}

.alert--error {
  background: rgba(192,57,43,0.08);
  border:     1px solid rgba(192,57,43,0.25);
  color:      #8b1a0f;
}

/* CTA Button */
.btn-cta {
  display:        inline-flex;
  align-items:    center;
  gap:            0.5rem;
  padding:        0.8rem 1.75rem;
  font-family:    var(--font-ui);
  font-size:      0.85rem;
  font-weight:    600;
  letter-spacing: 0.04em;
  background:     var(--primary-dark);
  color:          #fff;
  border:         none;
  border-radius:  var(--r-sm);
  cursor:         pointer;
  transition:     background 0.2s, transform 0.15s;
  text-decoration: none;
}

.btn-cta:hover {
  background: #031F2E;
  transform:  translateY(-1px);
}

.btn-cta--gold {
  background: var(--gold);
  color:      var(--primary-dark);   /* dark text on bright gold — white failed contrast */
}

.btn-cta--gold:hover { background: var(--gold-hover); }

.btn-cta:disabled {
  opacity: 0.45;
  cursor: not-allowed;
  transform: none;
}

.btn-ghost {
  display:        inline-flex;
  align-items:    center;
  gap:            0.5rem;
  padding:        0.75rem 1.5rem;
  font-family:    var(--font-ui);
  font-size:      0.85rem;
  font-weight:    600;
  color:          var(--gold-ink);
  border:         1.5px solid var(--gold-ink-border);
  border-radius:  var(--r-sm);
  background:     transparent;
  transition:     background 0.2s, border-color 0.2s, color 0.2s;
  text-decoration: none;
  cursor:         pointer;
  letter-spacing: 0.03em;
}

.btn-ghost:hover {
  background:    var(--gold-light);
  border-color:  var(--gold-ink);
}

/* ── Download links (forms / PDFs — shared by service pages) ─────────────── */
/* Multi-column so a long list (e.g. 10 claim forms) flows into rows instead of
   one tall column — which is what left the old two-column split badly unbalanced. */
.dl-list {
  display: grid;
  /* min() so the 300px track collapses instead of overflowing in a narrow
     container (e.g. the membership sidebar), where it used to get clipped. */
  grid-template-columns: repeat(auto-fill, minmax(min(300px, 100%), 1fr));
  gap: 0.75rem;
  align-items: start;
}
.dl-item {
  display: flex;
  align-items: center;
  gap: 0.9rem;
  padding: 0.9rem 1.1rem;
  background: var(--surface);
  border: 1px solid var(--border);
  border-left: 3px solid var(--gold-ink);
  border-radius: var(--r-md);
  text-decoration: none;
  transition: border-color 0.2s, box-shadow 0.2s, transform 0.15s;
}
.dl-item:hover, .dl-item:focus-visible {
  border-color: var(--border-mid);
  box-shadow: 0 6px 20px rgba(15,76,117,0.08);
  transform: translateY(-1px);
}
.dl-item__icon {
  flex-shrink: 0;
  width: 38px; height: 38px;
  display: flex; align-items: center; justify-content: center;
  background: var(--gold-light);
  color: var(--gold-ink);
  border-radius: var(--r-sm);
}
.dl-item__body { flex: 1; min-width: 0; display: flex; flex-direction: column; }
.dl-item__title {
  font-family: var(--font-ui);
  font-size: 0.9rem;
  font-weight: 600;
  color: var(--navy);
  line-height: 1.3;
}
.dl-item__meta {
  font-family: var(--font-ui);
  font-size: 0.72rem;
  color: var(--fg-subtle);
  margin-top: 0.1rem;
}
.dl-item__arrow { flex-shrink: 0; color: var(--gold-ink); }

/* Back link on service sub-pages */
.subpage-back {
  display: inline-flex;
  align-items: center;
  gap: 0.4rem;
  font-family: var(--font-ui);
  font-size: 0.8rem;
  font-weight: 600;
  color: var(--teal);
  text-decoration: none;
  margin-bottom: 1.75rem;
  transition: gap 0.2s;
}
.subpage-back:hover { gap: 0.7rem; }

/* ── Listing search bar (shared: pekeliling + aktiviti pages) ────────────── */

.listing-search {
  display:     flex;
  align-items: center;
  gap:         0.5rem;
  padding:     0.75rem 0;
}

.listing-search__wrap {
  position:  relative;
  display:   flex;
  flex:      1;
  max-width: 400px;
}

.listing-search__icon {
  position:       absolute;
  left:           0.75rem;
  top:            50%;
  transform:      translateY(-50%);
  color:          var(--fg-subtle);
  pointer-events: none;
}

.listing-search__input {
  width:         100%;
  padding:       0.55rem 1rem 0.55rem 2.4rem;
  font-family:   var(--font-ui);
  font-size:     0.9rem;
  background:    var(--cream);
  border:        1.5px solid var(--border-mid);
  border-radius: var(--r-sm);
  color:         var(--fg);
  outline:       none;
  transition:    border-color 0.2s, box-shadow 0.2s;
  appearance:    none;
}

.listing-search__input:focus {
  border-color: var(--gold);
  box-shadow:   0 0 0 3px rgba(184,147,90,0.12);
}

.listing-search__input::placeholder { color: var(--fg-subtle); }

.listing-search__btn {
  padding:       0.55rem 1.1rem;
  font-family:   var(--font-ui);
  font-size:     0.85rem;
  font-weight:   600;
  background:    var(--navy);
  color:         #fff;
  border:        none;
  border-radius: var(--r-sm);
  cursor:        pointer;
  flex-shrink:   0;
  transition:    background 0.2s;
}

.listing-search__btn:hover { background: var(--primary-dark); }

/* Search row: the form fills the width, the record count sits on the right so
   it stops taking a line of its own. Wraps below the form on narrow screens. */
.pek-search-row {
  display:     flex;
  align-items: center;
  gap:         0.75rem 1.5rem;
  flex-wrap:   wrap;
}
.pek-search-row .listing-search { flex: 1 1 22rem; margin: 0; }
.pek-search-row .pek-count-badge { flex-shrink: 0; margin: 0; white-space: nowrap; }

/* Year filter — sits inside the search form so both submit together.
   appearance:none + a drawn caret so the arrow has real padding from the right
   edge (the native arrow sat flush against the border). */
.listing-search__year {
  padding:       0.55rem 2.4rem 0.55rem 0.9rem;
  min-height:    44px;
  font-family:   var(--font-ui);
  font-size:     0.85rem;
  font-weight:   500;
  color:         var(--fg);
  background:    var(--surface);
  border:        1px solid var(--border-mid);
  border-radius: var(--r-sm);
  cursor:        pointer;
  flex-shrink:   0;
  appearance:         none;
  -webkit-appearance: none;
  background-image:    url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='12' viewBox='0 0 24 24' fill='none' stroke='%230F4C75' stroke-width='2.5'%3E%3Cpolyline points='6 9 12 15 18 9'/%3E%3C/svg%3E");
  background-repeat:   no-repeat;
  background-position: right 0.85rem center;
}

.listing-search__clear {
  font-family:     var(--font-ui);
  font-size:       0.85rem;
  color:           var(--fg-muted);
  text-decoration: none;
  padding:         0.3rem 0.4rem;
  border-radius:   var(--r-sm);
  white-space:     nowrap;
  transition:      color 0.2s;
}

.listing-search__clear:hover { color: var(--fg); }

/* ── 11. Hero slider (homepage) ──────────────────────────────────────────── */

/* A fixed height in vh made the hero's SHAPE depend on the visitor's window:
   60vh was ~3.3:1 on a 1080p laptop, ~3.6:1 on a 768px one and ~4:1 on an
   ultrawide, so no single crop could ever suit them all. Fixing the ratio and
   only clamping the extremes holds it at ~2.8–3.5:1 instead, which is why
   images now behave predictably. Keep this in sync with HERO_RATIOS in
   public/js/admin-focal.js — that is what the editor previews. */
.hero {
  position:     relative;
  width:        100%;
  aspect-ratio: 3 / 1;
  min-height:   360px;
  max-height:   70vh;
  overflow:     clip;   /* clip (not hidden) so abs children don't contribute to scroll width */
  background:   #c8c0b4;
}

.hero__img {
  position:   absolute;
  inset:      0;
  width:      100%;
  height:     100%;
  object-fit: cover;   /* framing comes from object-position, set per slide by hero.js */
  transition: opacity 0.9s cubic-bezier(0.4, 0, 0.2, 1);
}

/* Hidden until hero.js has applied the crop transform, so no uncropped frame
   flashes first. Guarded by .js-reveal: with no JS there is nothing to wait
   for, and an uncropped hero beats an empty grey box. object-fit: cover above
   already gives a sane framing in that case. */
.js-reveal .hero__img { opacity: 0; }

.hero__img.is-active { opacity: 1; }

.hero__overlay {
  position:   absolute;
  inset:      0;
  background: linear-gradient(
    to bottom,
    rgba(27, 43, 75, 0.4) 0%,
    rgba(27, 43, 75, 0.15) 40%,
    rgba(27, 43, 75, 0.6) 100%
  );
  z-index: 2;
}

.hero__ring {
  position:      absolute;
  border-radius: 50%;
  border:        1px solid rgba(184,147,90,0.15);
  z-index:       3;
  pointer-events: none;
}

.hero__ring--tl { width: 600px; height: 600px; top: -200px; left: -200px; }
.hero__ring--br { width: 400px; height: 400px; bottom: -150px; right: -100px; }

.hero__brand {
  position:        absolute;
  inset:           0;
  z-index:         4;
  display:         flex;
  align-items:     center;
  justify-content: center;
  flex-direction:  column;
  text-align:      center;
  padding:         2rem;
}

.hero__brand-name {
  font-family:    var(--font-display);
  font-size:      clamp(1.4rem, 4vw, 2.5rem);
  font-weight:    600;
  color:          #fff;
  text-shadow:    0 2px 20px rgba(0,0,0,0.5);
  letter-spacing: 0.02em;
  background:     linear-gradient(90deg, #fff 30%, var(--gold) 50%, #fff 70%);
  background-size: 200% auto;
  -webkit-background-clip: text;
  -webkit-text-fill-color: transparent;
  background-clip: text;
  animation:      shimmer 4s linear infinite;
}

.hero__brand-divider {
  width:      60px;
  height:     2px;
  background: var(--gold);
  margin:     0.9rem auto;
  opacity:    0.8;
}

.hero__brand-tagline {
  font-family:    var(--font-ui);
  font-size:      0.85rem;
  color:          rgba(255,255,255,0.72);
  letter-spacing: 0.28em;
  text-transform: uppercase;
}

.hero__controls {
  position:       absolute;
  bottom:         1.5rem;
  left:           50%;
  transform:      translateX(-50%);
  z-index:        5;
  display:        flex;
  flex-direction: column;
  align-items:    center;
  gap:            0.75rem;
}

.hero__dots { display: flex; gap: 0.5rem; align-items: center; }

.hero__dot {
  width:  8px;
  height: 8px;
  border-radius: 50%;
  background: rgba(255,255,255,0.35);
  border:     none;
  cursor:     pointer;
  transition: background 0.25s, transform 0.25s;
  padding:    0;
}

.hero__dot.is-active { background: var(--gold); transform: scale(1.3); }

.hero__progress {
  width:  120px;
  height: 2px;
  background: rgba(255,255,255,0.2);
  border-radius: 1px;
  overflow: hidden;
}

.hero__progress-bar {
  height:     100%;
  background: var(--gold);
  width:      0%;
}

.hero__arrow {
  position:    absolute;
  top:         50%;
  transform:   translateY(-50%);
  z-index:     5;
  background:  rgba(27,43,75,0.35);
  border:      1px solid rgba(255,255,255,0.15);
  color:       #fff;
  width:       42px;
  height:      42px;
  border-radius: 50%;
  display:     flex;
  align-items: center;
  justify-content: center;
  cursor:      pointer;
  transition:  background 0.2s, border-color 0.2s;
}

.hero__arrow:hover { background: rgba(27,43,75,0.7); border-color: var(--gold); }
.hero__arrow--prev { left:  1rem; }
.hero__arrow--next { right: 1rem; }

.hero__placeholder {
  position:        absolute;
  inset:           0;
  display:         flex;
  flex-direction:  column;
  align-items:     center;
  justify-content: center;
  gap:             0.75rem;
  color:           rgba(255,255,255,0.5);
  font-size:       0.85rem;
  letter-spacing:  0.05em;
  background:      #1a2a3a;
}

.hero__scroll {
  position:   absolute;
  bottom:     4.5rem;
  right:      1.5rem;
  z-index:    5;
  display:    flex;
  flex-direction: column;
  align-items: center;
  gap:        0.4rem;
  color:      rgba(255,255,255,0.4);
  font-family: var(--font-ui);
  font-size:  0.72rem;
  letter-spacing: 0.15em;
  text-transform: uppercase;
}

.hero__scroll-icon { animation: scrollBounce 1.8s infinite; }

/* ── 12. Announcement popup ──────────────────────────────────────────────── */

.popup-overlay {
  position:        fixed;
  inset:           0;
  z-index:         200;
  background:      rgba(27,43,75,0.72);
  backdrop-filter: blur(6px);
  display:         flex;
  align-items:     center;
  justify-content: center;
  padding:         2rem 1rem;
  opacity:         0;
  pointer-events:  none;
  transition:      opacity 0.3s;
}

.popup-overlay.is-open {
  opacity:        1;
  pointer-events: all;
}

.popup {
  position:      relative;
  width:         100%;
  /* Width is capped by the height budget so the 3:4 poster never gets cropped:
     4rem overlay padding + ~3.5rem footer/progress, ×0.75 back to a width. */
  max-width:     min(440px, calc((100dvh - 7.5rem) * 0.75));
  max-height:    calc(100dvh - 4rem);
  display:       flex;
  flex-direction: column;
  background:    var(--surface);
  border:        1px solid var(--border-mid);
  border-radius: var(--r-lg);
  overflow:      hidden;
  box-shadow:    0 24px 80px rgba(27,43,75,0.35);
  transform:     translateY(14px);
  transition:    transform 0.35s cubic-bezier(0.22, 1, 0.36, 1);
}

.popup-overlay.is-open .popup { transform: translateY(0); }

.popup__close {
  position:    absolute;
  top:         0.75rem;
  right:       0.75rem;
  z-index:     10;
  background:  rgba(27,43,75,0.5);
  border:      1px solid rgba(255,255,255,0.15);
  color:       #fff;
  width:       32px;
  height:      32px;
  border-radius: 50%;
  display:     flex;
  align-items: center;
  justify-content: center;
  cursor:      pointer;
  transition:  background 0.2s;
}

.popup__close:hover { background: rgba(27,43,75,0.8); }

.popup__counter {
  position:      absolute;
  top:           0.75rem;
  left:          0.75rem;
  z-index:       10;
  font-family:   var(--font-ui);
  font-size:     0.72rem;
  font-weight:   600;
  letter-spacing: 0.08em;
  background:    rgba(27,43,75,0.5);
  color:         rgba(255,255,255,0.8);
  padding:       0.2rem 0.6rem;
  border-radius: 20px;
}

.popup__img-wrap {
  position:     relative;
  width:        100%;
  flex:         0 0 auto;   /* aspect-ratio wins; never stretch or squash the poster */
  aspect-ratio: 3 / 4;
  overflow:     hidden;
  background:   var(--cream-mid);
  cursor:       pointer;
}

.popup__img {
  position:   absolute;
  inset:      0;
  width:      100%;
  height:     100%;
  object-fit: cover;   /* framing comes from object-position, set per slide by popup.js */
  opacity:    0;
}

.popup__placeholder {
  position:        absolute;
  inset:           0;
  display:         flex;
  align-items:     center;
  justify-content: center;
  color:           var(--fg-subtle);
}

.popup__arrow {
  position:    absolute;
  top:         50%;
  transform:   translateY(-50%);
  z-index:     5;
  background:  rgba(27,43,75,0.4);
  border:      1px solid rgba(255,255,255,0.15);
  color:       #fff;
  width:       32px;
  height:      32px;
  border-radius: 50%;
  display:     flex;
  align-items: center;
  justify-content: center;
  cursor:      pointer;
  transition:  background 0.2s;
}

.popup__arrow:hover { background: rgba(27,43,75,0.7); }
.popup__arrow--prev { left:  0.6rem; }
.popup__arrow--next { right: 0.6rem; }

.popup__footer {
  display:         flex;
  align-items:     center;
  justify-content: space-between;
  padding:         0.85rem 1.1rem 0.65rem;
}

.popup__label {
  font-family:    var(--font-ui);
  font-size:      0.72rem;
  font-weight:    700;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color:          var(--gold-ink);
}

.popup__dots { display: flex; gap: 0.4rem; align-items: center; }

.popup__dot {
  width:  7px;
  height: 7px;
  border-radius: 50%;
  background: var(--border-mid);
  border:     none;
  cursor:     pointer;
  transition: background 0.25s, transform 0.25s;
  padding:    0;
}

.popup__dot.is-active { background: var(--gold); transform: scale(1.3); }

.popup__progress { height: 3px; background: var(--cream-mid); }

.popup__progress-bar {
  height:     100%;
  background: linear-gradient(90deg, var(--gold), var(--teal));
  width:      0%;
}

/* ── Back-to-top button ──────────────────────────────────────────────────── */

.back-to-top {
  position:        fixed;
  bottom:          1.75rem;
  right:           1.75rem;
  z-index:         90;
  width:           44px;
  height:          44px;
  border-radius:   50%;
  background:      var(--gold);
  color:           var(--navy);
  border:          none;
  cursor:          pointer;
  display:         flex;
  align-items:     center;
  justify-content: center;
  box-shadow:      0 4px 16px rgba(27,43,75,0.28);
  opacity:         0;
  transform:       translateY(12px);
  transition:      opacity 0.25s, transform 0.25s, background 0.2s;
  pointer-events:  none;
}

.back-to-top.is-visible {
  opacity:        1;
  transform:      translateY(0);
  pointer-events: auto;
}

.back-to-top:hover { background: #a07a28; }

/* ── 13. Footer ──────────────────────────────────────────────────────────── */

.footer {
  background:  var(--navy);
  color:       rgba(255,255,255,0.75);
  padding:     4rem 0 2.5rem;
  position:    relative;
  overflow:    hidden;
}

/* Batik texture overlay */
.footer::before {
  content:    '';
  position:   absolute;
  inset:      0;
  background-image:
    radial-gradient(circle at 90% 10%, rgba(184,147,90,0.08) 0%, transparent 50%),
    radial-gradient(circle at 10% 90%, rgba(42,125,140,0.06) 0%, transparent 50%);
  pointer-events: none;
}

.footer__inner { position: relative; z-index: 1; }

.footer__grid {
  display:               grid;
  grid-template-columns: 2.2fr 1fr 1fr 1fr;
  gap:                   3rem;
  margin-bottom:         3rem;
}

.footer__brand-name {
  font-family:   var(--font-display);
  font-size:     1.1rem;
  font-weight:   600;
  color:         #fff;
  margin-bottom: 0.6rem;
}

.footer__address {
  font-family:  var(--font-ui);
  font-size:    0.85rem;
  color:        rgba(255,255,255,0.85);
  line-height:  1.8;
}

.footer__contact {
  margin-top:   0.85rem;
  font-family:  var(--font-ui);
  font-size:    0.85rem;
  color:        rgba(255,255,255,0.85);
  line-height:  1.9;
}

.footer__contact a { color: rgba(255,255,255,0.85); transition: color 0.2s; }
.footer__contact a:hover { color: rgba(255,255,255,1); }

.footer__heading {
  font-family:    var(--font-ui);
  font-size:      0.75rem;
  font-weight:    700;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color:          var(--gold);
  margin-bottom:  1rem;
}

.footer__links {
  list-style: none;
  display:    flex;
  flex-direction: column;
  gap:        0.15rem;
}

.footer__links a {
  font-family:  var(--font-ui);
  font-size:    0.85rem;
  color:        rgba(255,255,255,0.85);
  transition:   color 0.2s;
  display:      inline-block;
  padding-block: 0.25rem;
  min-height:   24px;
}

.footer__links a:hover { color: rgba(255,255,255,1); }

.footer__bottom {
  display:         flex;
  align-items:     center;
  justify-content: space-between;
  padding-top:     2rem;
  border-top:      1px solid rgba(255,255,255,0.08);
  flex-wrap:       wrap;
  gap:             1rem;
}

.footer__copy {
  font-family:  var(--font-ui);
  font-size:    0.85rem;
  color:        rgba(255,255,255,0.85);
}

.footer__socials { display: flex; gap: 0.75rem; align-items: center; }

.footer__social-link {
  color:         rgba(255,255,255,0.85);
  transition:    color 0.2s;
  display:       flex;
  align-items:   center;
}

.footer__social-link:hover { color: var(--gold); }

/* ── 14. Animations & scroll reveal ──────────────────────────────────────── */

/* Every hidden start state below is scoped to .js-reveal, a class that
   layouts/main.latte sets on <html> from an inline script. No JS, blocked JS or
   a thrown error anywhere in nav.js all mean the class is absent and the page
   renders as plain, fully visible content — the animation is the enhancement,
   never the thing standing between a member and the page. */

.js-reveal .fade-in {
  opacity:    0;
  transform:  translateY(22px);
  transition: opacity 0.7s ease, transform 0.7s ease;
}

.js-reveal .fade-in.is-visible {
  opacity:   1;
  transform: translateY(0);
}

.js-reveal .slide-in-left {
  opacity:   0;
  transform: translateX(-30px);
  transition: opacity 0.65s ease, transform 0.65s ease;
}

.js-reveal .slide-in-left.is-visible { opacity: 1; transform: translateX(0); }

.js-reveal .slide-in-right {
  opacity:   0;
  transform: translateX(30px);
  transition: opacity 0.65s ease, transform 0.65s ease;
}

.js-reveal .slide-in-right.is-visible { opacity: 1; transform: translateX(0); }

.js-reveal .scale-in {
  opacity:   0;
  transform: scale(0.94);
  transition: opacity 0.6s ease, transform 0.6s ease;
}

.js-reveal .scale-in.is-visible { opacity: 1; transform: scale(1); }

.stagger-children > *:nth-child(1) { transition-delay: 0.04s; }
.stagger-children > *:nth-child(2) { transition-delay: 0.11s; }
.stagger-children > *:nth-child(3) { transition-delay: 0.18s; }
.stagger-children > *:nth-child(4) { transition-delay: 0.25s; }
.stagger-children > *:nth-child(5) { transition-delay: 0.32s; }
.stagger-children > *:nth-child(n+6) { transition-delay: 0.38s; }

@keyframes shimmer {
  0%   { background-position: -200% center; }
  100% { background-position:  200% center; }
}

@keyframes scrollBounce {
  0%, 100% { transform: translateY(0);  opacity: 0.5; }
  50%       { transform: translateY(5px); opacity: 1; }
}

/* Richer scroll-reveal variants — used sparingly for visual variety so the
   whole site doesn't share one identical fade. Observed by nav.js. */
.js-reveal .reveal-blur {
  opacity: 0;
  transform: translateY(24px);
  filter: blur(8px);
  transition: opacity 0.75s ease, transform 0.75s ease, filter 0.75s ease;
}
.js-reveal .reveal-blur.is-visible { opacity: 1; transform: translateY(0); filter: blur(0); }

.js-reveal .reveal-rotate {
  opacity: 0;
  transform: perspective(900px) rotateX(14deg) translateY(28px);
  transform-origin: bottom center;
  transition: opacity 0.7s ease, transform 0.7s cubic-bezier(0.16, 1, 0.3, 1);
}
.js-reveal .reveal-rotate.is-visible { opacity: 1; transform: perspective(900px) rotateX(0) translateY(0); }

/* reveal-clip was retired: clip-path: inset(0 0 100% 0) makes the element
   report zero intersection to IntersectionObserver, so it never received
   is-visible and its content stayed permanently hidden. It was only ever used
   on two content-critical blocks (the Port Dickson gallery and the 36-illness
   grid), both now on the reliable .fade-in. Do not reintroduce a clip-path
   reveal without confirming IO still fires. */

/* 3D flip-up — cards tilt into place from the top edge (great for grids) */
.js-reveal .reveal-flip {
  opacity: 0;
  transform: perspective(1000px) rotateX(-24deg) translateY(30px);
  transform-origin: center top;
  transition: opacity 0.6s ease, transform 0.75s cubic-bezier(0.16, 1, 0.3, 1);
}
.js-reveal .reveal-flip.is-visible { opacity: 1; transform: perspective(1000px) rotateX(0) translateY(0); }

/* Word-by-word text reveal ("texting" effect). JS (home-animations.js) wraps
   each word in .tr-word; words rise + fade in sequence when scrolled into view.
   No .js-reveal guard needed — .tr-word only exists once that script has run. */
.text-reveal .tr-word {
  display: inline-block;
  opacity: 0;
  transform: translateY(0.55em);
  transition: opacity 0.5s ease, transform 0.5s cubic-bezier(0.16, 1, 0.3, 1);
  will-change: opacity, transform;
}
.text-reveal.is-revealed .tr-word { opacity: 1; transform: translateY(0); }

/* Honour prefers-reduced-motion for every scroll reveal (fixes a pre-existing
   gap where reveals still animated) — content appears instantly, no motion. */
@media (prefers-reduced-motion: reduce) {
  .fade-in, .slide-in-left, .slide-in-right, .scale-in,
  .reveal-blur, .reveal-rotate, .reveal-flip {
    transition: none !important;
    opacity: 1 !important;
    transform: none !important;
    filter: none !important;
  }
  .text-reveal .tr-word {
    transition: none !important;
    opacity: 1 !important;
    transform: none !important;
  }
}

/* ── Image lightbox (click/tap to enlarge) ──────────────────────────────── */
.zoomable { cursor: zoom-in; }
.lightbox-overlay {
  position: fixed;
  inset: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 4vh 4vw;
  background: rgba(9, 20, 32, 0.9);
  z-index: 2000;
  opacity: 0;
  /* The overlay is built once and reused, so a closed one is still a
     full-viewport fixed layer. Without these it stays invisible but keeps
     swallowing every click on the page and keeps its close button in the tab
     order — which is why closing it looked like it had done nothing. The
     visibility delay lets the fade-out finish before it is pulled. */
  visibility: hidden;
  pointer-events: none;
  transition: opacity 0.25s ease, visibility 0s linear 0.25s;
  -webkit-tap-highlight-color: transparent;
}
.lightbox-overlay.is-open {
  opacity: 1;
  visibility: visible;
  pointer-events: auto;
  transition: opacity 0.25s ease, visibility 0s;
}
.lightbox-overlay img {
  max-width: 100%;
  max-height: 92vh;
  object-fit: contain;
  border-radius: 8px;
  box-shadow: 0 24px 70px rgba(0, 0, 0, 0.55);
  transform: scale(0.95);
  transition: transform 0.25s cubic-bezier(0.16, 1, 0.3, 1);
  cursor: zoom-out;
}
.lightbox-overlay.is-open img { transform: scale(1); }
.lightbox-close {
  position: absolute;
  top: 1rem;
  right: 1.25rem;
  width: 44px;
  height: 44px;
  border: none;
  border-radius: 50%;
  background: rgba(255, 255, 255, 0.14);
  color: #fff;
  font-size: 1.7rem;
  line-height: 1;
  cursor: pointer;
  display: flex;
  align-items: center;
  justify-content: center;
  transition: background 0.2s;
}
.lightbox-close:hover { background: rgba(255, 255, 255, 0.26); }
@media (prefers-reduced-motion: reduce) {
  .lightbox-overlay, .lightbox-overlay img { transition: none; }
}

/* ── 14b. Skeleton shimmer ───────────────────────────────────────────────── */

.skel {
  background: linear-gradient(
    90deg,
    #eae6e1 25%,
    #f5f2ed 50%,
    #eae6e1 75%
  );
  background-size: 200% 100%;
  animation: shimmer 1.6s ease-in-out infinite;
  border-radius: 4px;
  color: transparent !important;
  pointer-events: none;
  user-select: none;
}

.hero__placeholder {
  background: linear-gradient(
    90deg,
    #1a2a3a 25%,
    #253850 50%,
    #1a2a3a 75%
  );
  background-size: 200% 100%;
  animation: shimmer 2s ease-in-out infinite;
}

/* ── 15. Responsive ──────────────────────────────────────────────────────── */

@media (max-width: 1024px) {
  .footer__grid { grid-template-columns: 1fr 1fr; gap: 2rem; }
}

/* The desktop nav bar is not responsive — logo + 5 links + language + portal
   button measure a fixed ~1154px. Below ~1224px of viewport that no longer fits
   the container, and because the row is justify-content:space-between the
   overflow lands entirely on the last item: the Portal Anggota button was being
   pushed past the right edge and clipped away by html{overflow-x:clip}. This
   used to collapse at 768px, which left every 769–1223px viewport with the
   site's primary CTA invisible. Collapse to the hamburger instead — it carries
   the portal link as .nav__portal-mobile. */
@media (max-width: 1279px) {
  /* .nav__portal is the desktop bar button. It hides here and the same link
     reappears as the last item inside the open menu (.nav__portal-mobile),
     because otherwise the member portal — the highest-intent action on the
     site — has no entry point at all. */
  .nav__links, .nav__portal { display: none; }
  .nav__hamburger            { display: flex; }
  .nav__portal-mobile        { display: block; }

  /* Swap the BM|EN pair for the single compact chip to save width. */
  .nav__lang         { display: none; }
  .nav__lang-compact { display: flex; margin-left: auto; }

  /* With nav__links/nav__portal hidden, only logo + lang-toggle + hamburger remain in the
     flex row — space-between then splits the gap evenly and strands the lang button in the
     middle. Push it (and the hamburger, which follows it) to the right edge as a group. */

  .nav__links.is-open {
    display:         flex;
    flex-direction:  column;
    align-items:     stretch;   /* override desktop align-items:center so items fill full width */
    position:        absolute;
    top:             var(--nav-height);
    left:            0;
    right:           0;
    /* Opaque, not 0.97 — page content showing faintly through a nav panel
       reads as a rendering fault, and the blur cost nothing but GPU. */
    background:      var(--bg);
    padding:         1rem 1rem 1.25rem;
    border-top:      1px solid var(--border);
    box-shadow:      0 8px 24px rgba(27,43,75,0.10);
    max-height:      calc(100vh - var(--nav-height));
    overflow-y:      auto;
  }

  /* Portal CTA at the foot of the menu — styled as the one filled action so it
     reads as the primary target rather than a sixth nav link. */
  .nav__portal-mobile {
    margin-top:  0.75rem;
    padding-top: 0.9rem;
    border-top:  1px solid var(--border);
  }

  /* Two classes deep on purpose: `.nav__links > li > a` sets background:none at
     (0,1,2) and would otherwise win over a single-class selector here. */
  .nav__links .nav__portal-mobile > a {
    display:         flex;
    align-items:     center;
    justify-content: center;
    gap:             0.5rem;
    padding:         0.8rem 1rem;
    min-height:      48px;
    background:      var(--navy);
    color:           #fff;
    font-family:     var(--font-ui);
    font-size:       0.95rem;
    font-weight:     600;
    border-radius:   var(--r-sm);
  }

  .nav__dropdown-trigger { width: 100%; }

  .nav__links.is-open .nav__dropdown-menu {
    position:  static;
    transform: none;
    box-shadow: none;
    border:    none;
    background: transparent;
    padding:   0 0 0 1rem;
    /* Desktop's -8px/-12px margin-top is an invisible hover-bridge for the floating
       menu — in this static accordion layout it just pulls the first child up into
       the trigger. Reset it so the first child gets the same spacing as the rest. */
    margin-top: 0;
  }

  /* Kill the desktop-centric dropIn animation on mobile — it uses translateX(-50%)
     which causes the menu to visibly jerk left before snapping back */
  .nav__links.is-open .nav__dropdown-menu[data-open] {
    animation: none;
  }

  /* Suppress the desktop gradient-underline active state on mobile — it adds
     padding-bottom + border-bottom which visually shifts the parent link */
  .nav__links.is-open .nav__dropdown > a.is-active {
    padding-bottom: 0;
    border-bottom:  none;
    background:     none;
  }
}

@media (max-width: 768px) {
  /* Portrait, and bounded for the same reason as the desktop hero above. */
  .hero {
    aspect-ratio: 4 / 5;
    min-height:   340px;
    max-height:   70vh;
  }

  .footer__grid { grid-template-columns: 1fr; gap: 1.75rem; }
  .col-layout--6040,
  .col-layout--half,
  .col-layout--third,
  .col-layout--quarter { grid-template-columns: 1fr; }

  .content-panel { padding: 1.75rem; }
  .form-surface   { padding: 1.75rem; }
}

/* ── 16. Print ───────────────────────────────────────────────────────────── */

@media print {
  @page { margin: 1.5cm; }

  /* Kill animations, shadows, transitions */
  *, *::before, *::after {
    animation:  none !important;
    transition: none !important;
    box-shadow: none !important;
    text-shadow: none !important;
  }

  body {
    background: #fff !important;
    color: #000 !important;
    font-size: 11pt;
    line-height: 1.55;
  }

  /* ── Hide chrome ── */
  .nav,
  .back-to-top,
  .popup-overlay,
  .hero,
  .footer,
  .hero__scroll,
  .hero__ring,
  .listing-search,
  .pek-filter-bar,
  .akt-filter-bar,
  .akt-tabs-bar,
  .pek-pagination,
  .akt-pagination { display: none !important; }

  /* Remove top offset caused by hidden nav */
  .page-main { margin-top: 0 !important; }

  /* ── Detail page hero: drop the photo, keep the title ── */
  .hero-header {
    background: none !important;
    min-height: 0 !important;
    padding: 0 0 1rem !important;
  }
  .hero-header img,
  .hero-header::before { display: none !important; }
  .hero-header__content {
    color: #000 !important;
    padding: 0 !important;
    text-align: left !important;
  }
  .hero-header h1      { font-size: 18pt !important; color: #000 !important; }
  .hero-header .hero-badge { color: #444 !important; }

  /* ── Content ── */
  .ann-body        { color: #000 !important; }
  .ann-body a      { color: #000 !important; text-decoration: underline; }

  /* Gallery: images print, shimmer background stripped */
  .ann-gallery__item {
    background: none !important;
    border: 1px solid #ccc !important;
    break-inside: avoid;
    page-break-inside: avoid;
  }
  .ann-gallery__item img { display: block; max-width: 100%; }

  /* Heading page-break rules */
  h1, h2, h3 { break-after: avoid; page-break-after: avoid; }
  img         { break-inside: avoid; page-break-inside: avoid; }
}

/* ── 16. Language toggle & view transitions ─────────────────────────────── */

/* Native cross-document View Transitions: smooths every same-origin
   navigation (including the language toggle) into a crossfade instead of
   a hard reload flash. No-op in browsers that don't support it yet. */
@view-transition {
  navigation: auto;
}

@media (prefers-reduced-motion: reduce) {
  ::view-transition-group(*),
  ::view-transition-old(*),
  ::view-transition-new(*) {
    animation: none !important;
  }
}

/* ── Corner ribbon (e.g. "Coming Soon" teaser on a card) ──────────────────── */
.pb-ribbon-card { position: relative; overflow: hidden; }
.pb-ribbon {
  position: absolute;
  top: 20px;
  right: -44px;
  width: 160px;              /* fixed width + centered text = band centered on the corner */
  text-align: center;
  transform: rotate(45deg);
  background: var(--gold);
  color: var(--navy);
  font-family: var(--font-ui);
  font-size: 0.58rem;
  font-weight: 700;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  padding: 0.28rem 0;
  box-shadow: 0 1px 3px rgba(0,0,0,0.15);
  pointer-events: none;
}

/* ── Tabs + filter pills — one system, reused across listing pages ─────────── */
/* Tabs: underline indicator, for the primary content switch. */
.tabs {
  display: flex;
  align-items: flex-end;
  flex-wrap: wrap;
  gap: 0;
  margin-bottom: -2px;   /* overlap a 2px bottom border on the bar */
}
.tab {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 0.4rem;
  min-height: 44px;
  padding: 0.85rem 1.3rem;
  font-family: var(--font-ui);
  font-size: 0.85rem;
  font-weight: 600;
  color: var(--fg-muted);
  text-decoration: none;
  white-space: nowrap;
  border-bottom: 2px solid transparent;
  transition: color 0.2s, border-color 0.2s;
}
.tab:hover { color: var(--fg); }
.tab.is-active { color: var(--primary-dark); border-bottom-color: var(--gold); }

/* Pills: rounded, filled-when-active, for secondary category filters. */
.filter-pill {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-height: 36px;
  padding: 0.4rem 0.9rem;
  font-family: var(--font-ui);
  font-size: 0.85rem;
  font-weight: 600;
  color: var(--fg-muted);
  background: transparent;
  text-decoration: none;
  white-space: nowrap;
  border: 1.5px solid var(--border-mid);
  border-radius: 99px;
  transition: background 0.2s, border-color 0.2s, color 0.2s;
}
.filter-pill:hover { border-color: rgba(184,147,90,0.4); color: var(--fg); background: var(--gold-light); }
.filter-pill.is-active { background: var(--navy); border-color: var(--navy); color: #fff; }

/* Mobile: tabs go full-width equal columns so they sit under the thumb. */
@media (max-width: 560px) {
  .tabs { width: 100%; }
  .tab { flex: 1 1 0; padding: 0.85rem 0.4rem; }
  .filter-pill { min-height: 40px; }
}

/* ── Global reduced-motion safety net ─────────────────────────────────────── */
/* Belt-and-suspenders: on top of the per-component guards above, neutralise all
   transition/animation timing for users who ask for reduced motion. Durations
   only — visibility/reveal states are handled by the component rules. */
@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;
  }
}
