/* Base Styles & Typography - Pragyan Institute */
@import url('https://fonts.googleapis.com/css2?family=Outfit:wght@500;600;700;800&family=Plus+Jakarta+Sans:wght@400;500;600;700&display=swap');

*, *::before, *::after {
  box-sizing: border-box;
  margin: 0;
  padding: 0;
}

html {
  font-size: 16px;
  scroll-behavior: smooth;
  scroll-padding-top: calc(var(--nav-height) + 1.5rem);
}

body {
  font-family: var(--font-body);
  background-color: var(--bg-warm-cream);
  color: var(--text-charcoal);
  line-height: 1.65;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  overflow-x: hidden;
}


h1, h2, h3, h4, h5, h6 {
  font-family: var(--font-heading);
  color: var(--text-mahogany);
  line-height: 1.15;
  letter-spacing: -0.015em;
}

p {
  color: var(--text-charcoal);
  font-size: 1rem;
}

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

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

button {
  font-family: var(--font-body);
  border: none;
  outline: none;
  background: none;
  cursor: pointer;
}

/* Container */
.container {
  width: 100%;
  max-width: var(--max-width);
  margin-inline: auto;
  padding-inline: clamp(1.25rem, 4vw, 2.5rem);
}

/* Section Header Shared */
.section-header {
  text-align: center;
  max-width: 680px;
  margin: 0 auto 3.5rem auto;
}

.section-tag {
  display: inline-flex;
  align-items: center;
  gap: 0.5rem;
  padding: 0.35rem 1rem;
  border-radius: var(--radius-full);
  background-color: var(--secondary-sage-light);
  color: var(--secondary-sage);
  font-size: 0.8125rem;
  font-weight: 700;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  margin-bottom: 0.875rem;
  border: 1px solid rgba(111, 127, 95, 0.25);
}

.section-title {
  font-size: clamp(2rem, 3.8vw, 2.75rem);
  font-weight: 800;
  margin-bottom: 1rem;
  color: var(--text-mahogany);
}

.section-subtitle {
  font-size: 1.0625rem;
  color: var(--text-muted);
  line-height: 1.6;
}

/* Buttons */
.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 0.6rem;
  padding: 0.85rem 1.85rem;
  border-radius: var(--radius-full);
  font-weight: 700;
  font-size: 0.95rem;
  letter-spacing: 0.01em;
  transition: all var(--transition-fast);
  cursor: pointer;
  white-space: nowrap;
}

.btn-terracotta {
  background-color: var(--primary-terracotta);
  color: var(--text-on-accent);
  box-shadow: var(--shadow-sm);
}

.btn-terracotta:hover {
  background-color: var(--primary-terracotta-hover);
  transform: translateY(-2px);
  box-shadow: var(--shadow-terracotta-glow);
}

.btn-sage {
  background-color: var(--secondary-sage);
  color: var(--text-on-accent);
  box-shadow: var(--shadow-sm);
}

.btn-sage:hover {
  background-color: var(--secondary-sage-hover);
  transform: translateY(-2px);
  box-shadow: var(--shadow-sage-glow);
}

.btn-outline-terracotta {
  border: 2px solid var(--primary-terracotta);
  color: var(--primary-terracotta);
  background: transparent;
}

.btn-outline-terracotta:hover {
  background-color: var(--primary-terracotta);
  color: var(--text-on-accent);
  transform: translateY(-2px);
}

.btn-outline-sage {
  border: 2px solid var(--secondary-sage);
  color: var(--secondary-sage);
  background: transparent;
}

.btn-outline-sage:hover {
  background-color: var(--secondary-sage);
  color: var(--text-on-accent);
  transform: translateY(-2px);
}

/* Focus Visible High-Contrast Rules */
:focus-visible {
  outline: 3px solid var(--primary-terracotta, #C85A32);
  outline-offset: 3px;
}

/* White outline on terracotta, dark & saturated CTA elements */
.btn-terracotta:focus-visible,
.bg-terracotta:focus-visible,
.btn-emerald:focus-visible,
.btn-primary:focus-visible,
.portal-primary-btn:focus-visible,
.open-portal-trigger:focus-visible,
.hero-slide-nav:focus-visible {
  outline: 3px solid #FFFFFF !important;
  outline-offset: 3px;
  box-shadow: 0 0 0 5px rgba(200, 90, 50, 0.85);
}

/* Terracotta outline on white / light backgrounds and inputs */
input:focus-visible,
textarea:focus-visible,
select:focus-visible,
button:not(.btn-terracotta):not(.btn-emerald):not(.btn-primary):not(.portal-primary-btn):focus-visible,
a:not(.btn-terracotta):not(.btn-emerald):focus-visible,
.tab-btn:focus-visible,
.portal-tab-pill:focus-visible {
  outline: 3px solid var(--primary-terracotta, #C85A32) !important;
  outline-offset: 2px;
}

/* Mobile Responsive Scaling for Clean Information Density */
@media (max-width: 768px) {
  html {
    font-size: 15px;
  }
  .container {
    padding-inline: 1rem;
  }
  .section-header {
    margin-bottom: 2rem;
  }
  .section-title {
    font-size: 1.75rem;
  }
  .section-subtitle {
    font-size: 0.85rem;
  }
  .btn {
    padding: 0.6rem 1.2rem;
    font-size: 0.85rem;
  }
}

@media (max-width: 480px) {
  html {
    font-size: 14px;
  }
  .container {
    padding-inline: 0.85rem;
  }
  .section-header {
    margin-bottom: 1.5rem;
  }
  .section-title {
    font-size: 1.5rem;
  }
  .btn {
    padding: 0.55rem 1.15rem;
    font-size: 0.84rem;
  }
}

/* ==========================================================================
   ENHANCED GRAPHICS & VISUAL DEPTH SUITE (Performance-Optimized)
   ========================================================================== */

/* 1. Dynamic Ambient Aurora Mesh Backdrop (Optimized to 1 Subtle Orb) */
.aurora-ambient-container {
  position: absolute;
  inset: 0;
  overflow: hidden;
  pointer-events: none;
  z-index: 0;
}

.aurora-orb {
  position: absolute;
  border-radius: 50%;
  filter: blur(30px);
  opacity: 0.5;
  pointer-events: none;
  will-change: transform;
}

.aurora-orb-emerald {
  width: 320px;
  height: 320px;
  background: radial-gradient(circle, rgba(181, 84, 58, 0.07) 0%, rgba(181, 84, 58, 0.01) 70%, transparent 100%);
  top: -10%;
  left: 15%;
  animation: auroraDrift1 20s infinite alternate ease-in-out;
}

/* Extra orbs disabled to maintain high FPS and low power usage */
.aurora-orb-gold,
.aurora-orb-cyan {
  display: none !important;
}

@keyframes auroraDrift1 {
  0% { transform: translate3d(0, 0, 0) scale(1); }
  50% { transform: translate3d(60px, 40px, 0) scale(1.08); }
  100% { transform: translate3d(-30px, 50px, 0) scale(0.96); }
}

@media (prefers-reduced-motion: reduce) {
  .aurora-ambient-container,
  .aurora-orb,
  .aurora-orb-emerald,
  .aurora-orb-gold,
  .aurora-orb-cyan {
    animation: none !important;
    display: none !important;
  }
}

/* 2. Gold & Emerald Foil Text Shimmer Sweep */
.shimmer-text-gold {
  background: linear-gradient(135deg, #B45309 0%, #F59E0B 25%, #FFFBEB 50%, #F59E0B 75%, #92400E 100%);
  background-size: 200% auto;
  -webkit-background-clip: text;
  background-clip: text;
  -webkit-text-fill-color: transparent;
  animation: textShimmer 4.5s linear infinite;
  display: inline-block;
}

.shimmer-text-emerald {
  background: linear-gradient(135deg, #064E3B 0%, #059669 25%, #ECFDF5 50%, #059669 75%, #064E3B 100%);
  background-size: 200% auto;
  -webkit-background-clip: text;
  background-clip: text;
  -webkit-text-fill-color: transparent;
  animation: textShimmer 5s linear infinite;
  display: inline-block;
}

@keyframes textShimmer {
  to { background-position: 200% center; }
}

/* 3. Living Breathing Neon LED Status Rings */
.pulse-status-ring {
  position: relative;
  display: inline-flex;
  align-items: center;
  justify-content: center;
}

.pulse-status-ring::after {
  content: '';
  position: absolute;
  inset: -3px;
  border-radius: 99px;
  border: 2px solid currentColor;
  opacity: 0.8;
  animation: pulseRingGlow 2s cubic-bezier(0.24, 0, 0.38, 1) infinite;
  pointer-events: none;
}

@keyframes pulseRingGlow {
  0% { transform: scale(0.95); opacity: 0.85; }
  70% { transform: scale(1.35); opacity: 0; }
  100% { transform: scale(1.4); opacity: 0; }
}

/* 4. Staggered Grid Animations */
.stagger-slide-up {
  animation: staggerSlideUp 0.45s cubic-bezier(0.34, 1.45, 0.64, 1) both;
}

@keyframes staggerSlideUp {
  0% { opacity: 0; transform: translate3d(0, 16px, 0); }
  100% { opacity: 1; transform: translate3d(0, 0, 0); }
}

/* 5. Reduced Motion Respect */
@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: 0.01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.01ms !important;
    /* Delay too, not just duration. Several panels here hide themselves with
       `transition: visibility 0s linear 0.3s` so the fade-out finishes before
       the element leaves the accessibility tree. Zeroing only the duration left
       that delay intact, so with reduced motion on, a dismissed panel snapped
       invisible but stayed focusable for the full delay — the exact tab-order
       trap the visibility toggle exists to prevent. */
    transition-delay: 0s !important;
    animation-delay: 0s !important;
  }
}

/* ==========================================================================
   ACCESSIBILITY & MOBILE LAYOUT CORRECTIONS
   --------------------------------------------------------------------------
   Everything below supports behaviour in js/app.js. Grouped here rather than
   scattered through components.css so the a11y contract is readable in one
   place.
   ========================================================================== */

/* --- Screen-reader-only text (live regions, status announcements) --------- */
.sr-only {
  position: absolute !important;
  width: 1px;
  height: 1px;
  margin: -1px;
  padding: 0;
  overflow: hidden;
  clip: rect(0, 0, 0, 0);
  clip-path: inset(50%);
  white-space: nowrap;
  border: 0;
}

/* --- Skip link: the first tab stop on the page ---------------------------- */
.skip-to-content {
  position: fixed;
  top: 0;
  left: 50%;
  transform: translate(-50%, -120%);
  z-index: 2000;
  padding: 0.75rem 1.5rem;
  background-color: var(--primary-emerald, #064E3B);
  color: #ffffff;
  font-weight: 700;
  text-decoration: none;
  border-radius: 0 0 10px 10px;
  box-shadow: 0 6px 20px rgba(0, 0, 0, 0.25);
  transition: transform 0.18s ease-out;
}

.skip-to-content:focus,
.skip-to-content:focus-visible {
  transform: translate(-50%, 0);
  outline: 3px solid var(--primary-terracotta, #C2410C);
  outline-offset: 2px;
}

/* Skip targets are sections, which get tabindex="-1" to receive focus. They
   should not then draw a focus ring around the whole viewport. */
section[tabindex="-1"]:focus {
  outline: none;
}

/* --- Reference-counted scroll lock (drawer / lightbox / portal modal) -----
   Set on <html> by window.PragyanUI.lockScroll(). Locking <html> as well as
   <body> is what actually holds iOS Safari still. */
html.scroll-locked,
html.scroll-locked body {
  overflow: hidden;
}

/* --- Batch filtering ------------------------------------------------------
   A class instead of an inline style, so filtering never overwrites the card's
   own display mode. */
.batch-card.is-filtered-out {
  display: none !important;
}

/* --- Form validation messaging ------------------------------------------- */
.form-hint {
  margin: 0.35rem 0 0;
  font-size: 0.8rem;
  color: var(--text-muted, #6B7280);
}

.form-error-text {
  margin: 0.35rem 0 0;
  font-size: 0.82rem;
  font-weight: 700;
  color: #B42318;
  display: flex;
  align-items: flex-start;
  gap: 0.35rem;
}

.form-error-text[hidden] {
  display: none;
}

.form-input[aria-invalid="true"],
.form-select[aria-invalid="true"],
.form-textarea[aria-invalid="true"] {
  border-color: #B42318;
  box-shadow: 0 0 0 3px rgba(180, 35, 24, 0.12);
}

/* --- Toast ---------------------------------------------------------------
   Centred at the bottom and lifted clear of the floating call/WhatsApp
   buttons on small screens, which the old fixed `bottom: 6rem` overlapped. */
.site-toast {
  position: fixed;
  left: 50%;
  bottom: 1.25rem;
  z-index: 1100;
  transform: translate(-50%, 160%);
  max-width: min(430px, calc(100vw - 2rem));
  padding: 0.9rem 1.35rem;
  border-radius: 12px;
  background-color: var(--primary-emerald, #064E3B);
  color: #ffffff;
  font-size: 0.92rem;
  font-weight: 600;
  line-height: 1.45;
  text-align: center;
  box-shadow: 0 12px 32px rgba(0, 0, 0, 0.28);
  opacity: 0;
  pointer-events: none;
  transition: transform 0.32s cubic-bezier(0.16, 1, 0.3, 1), opacity 0.32s ease;
}

.site-toast.is-visible {
  transform: translate(-50%, 0);
  opacity: 1;
}

.site-toast.is-error {
  background-color: #7F1D1D;
}

/* --- FAQ accordion -------------------------------------------------------
   The headers are now <button>s. UA chrome reset lives with the full
   .faq-header style in components.css (single source; this file previously
   carried a duplicate that drifted). */
.faq-wrap .faq-item.open .faq-body {
  max-height: 2400px;
}

/* --- Slideshow controls -------------------------------------------------- */
.slide-play-pause {
  position: absolute;
  bottom: 0.85rem;
  left: 1.25rem;
  z-index: 5;
  width: 34px;
  height: 34px;
  border: 0;
  border-radius: 50%;
  background-color: rgba(240, 230, 216, 0.85);
  color: var(--text-mahogany, #4A2C2A);
  font-size: 0.8rem;
  display: flex;
  align-items: center;
  justify-content: center;
  cursor: pointer;
  box-shadow: 0 3px 10px rgba(0, 0, 0, 0.22);
  transition: background-color var(--transition-fast, 0.2s ease), color var(--transition-fast, 0.2s ease);
}

.slide-play-pause:hover {
  background-color: var(--primary-terracotta, #C2410C);
  color: #ffffff;
}

/* The dots are real <button>s now; strip UA chrome and give them a hit area
   larger than the 9px visual (WCAG 2.5.8). */
.hero-slide-dots .dot {
  position: relative;
  padding: 0;
  border: 0;
  appearance: none;
  -webkit-appearance: none;
}

.hero-slide-dots .dot::after {
  content: "";
  position: absolute;
  inset: -7px -3px;
}

/* --- Tab strip -----------------------------------------------------------
   Six filters no longer fit one mobile row; wrapping produced a three-line
   block that pushed the grid below the fold. */
.tab-btn {
  min-height: 44px;
}

@media (max-width: 768px) {
  .tabs-container {
    display: grid;
    grid-template-columns: repeat(2, 1fr);
    gap: 0.55rem;
    width: 100%;
    max-width: 520px;
    margin: 0 auto 1.5rem auto;
    padding: 0;
    overflow-x: visible;
  }

  .tabs-container::-webkit-scrollbar {
    display: none;
  }

  .tabs-container .tab-btn {
    width: 100%;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    text-align: center;
  }

  .tabs-container .tab-btn[data-class="all"] {
    grid-column: 1 / -1;
  }
}

/* --- Coarse pointers ----------------------------------------------------- */
@media (hover: none), (pointer: coarse) {
  .hero-slide-dots {
    gap: 0.8rem;
  }

  .hero-slide-dots .dot::after {
    inset: -9px -6px;
  }

  .slide-play-pause {
    width: 44px;
    height: 44px;
    font-size: 0.9rem;
    opacity: 1;
  }

  /* Hover-only reveals never fire on touch, so the arrows stayed at 0.6 opacity. */
  .hero-slideshow-container .slide-nav-btn {
    opacity: 0.9;
  }
}

@media (max-width: 576px) {
  .site-toast {
    /* Clear of the two 48px floating action buttons. */
    bottom: calc(1.25rem + 108px);
  }
}

/* --- Keyboard focus for the gallery thumbnails (now role="button") ------- */
.gallery-card:focus-visible {
  outline: 3px solid var(--primary-terracotta, #C2410C);
  outline-offset: 3px;
}


/* ==========================================================================
   TOUCH-DEVICE FORM CONTROL FLOOR — iOS auto-zoom
   --------------------------------------------------------------------------
   Mobile Safari zooms the whole viewport whenever a focused input, select or
   textarea has a computed font-size below 16px, and it does not zoom back out
   when the field is blurred. Every form control in this app was under that
   threshold — .form-input 15.2px, .portal-input 14.72px, .search-input-field
   14px, .filter-select-mobile 13.12px — so on a phone, tapping the student
   search box, a fee filter or a payment amount zoomed the dashboard and left it
   scrolled sideways with the action buttons off-screen. The admin then had to
   pinch back out after every single field.

   Scoped to `pointer: coarse` so desktop density is untouched, and one rule
   rather than a dozen edits so a new control cannot reintroduce the bug.
   !important is deliberate: several of the declarations this has to beat live
   inside their own narrower media queries and are themselves !important.

   Checkbox, radio and range are excluded — font-size does not affect their
   rendering and they are not text-entry targets.
   ========================================================================== */
@media (pointer: coarse) {
  input:not([type="checkbox"]):not([type="radio"]):not([type="range"]):not([type="hidden"]),
  select,
  textarea {
    font-size: 16px !important;
  }
}

/* --- Minimum touch target -------------------------------------------------
   WCAG 2.5.8 (AA) asks for 24x24 CSS px; 44px is Apple's and Google's
   comfortable minimum. Small icon-only controls — modal close crosses, table
   row actions, filter chips — were rendering between 24px and 30px, which is
   inside the error rate where a thumb hits the neighbouring row instead. Only
   applied on coarse pointers, and only as a floor, so nothing shrinks. */
@media (pointer: coarse) {
  button,
  [role="button"],
  [role="tab"],
  .btn-icon,
  .modal-close-btn,
  .close-modal-btn,
  /* Anchors styled as buttons. 31 of them across the site — the primary CTAs,
     the WhatsApp and call floats, the UPI pay button — and none was covered by
     the `button` selector above. They all carry an inline-flex display from .btn
     and friends, which is what makes min-height apply to them at all. */
  a.btn,
  a.app-btn,
  a.action-btn,
  a.float-btn,
  a.upi-btn-main,
  /* Form controls are tap targets too. The admin request queue and the fee and
     audit filter bars set `height: 36px` / `height: 38px` inline on their
     selects, which the font-size floor above does nothing about: a 36px select
     is a 36px target. min-height is the right property rather than height —
     min-height clamps the used height, so it beats the inline declaration
     without !important and without stopping a taller control from being taller. */
  select,
  input:not([type="checkbox"]):not([type="radio"]):not([type="range"]):not([type="hidden"]),
  textarea,
  /* Not interactive, but it shares a flex row with the approve/decline buttons
     and carries the same inline height: 38px. Without this it stays 38px while
     they grow to 44px, leaving the row visibly ragged on a phone. */
  .req-verifier-chip {
    min-height: 44px;
  }

  /* Icon-only controls need the width too, or they stay a thin vertical strip. */
  button.btn-icon,
  button.modal-close-btn,
  button.close-modal-btn,
  .icon-only-btn {
    min-width: 44px;
  }
}
