/* =========================================================
   Saraye Danesh — Professional design system
   Navy + cream/ice canvas + dominant orange accent
   ========================================================= */

:root {
  /* ---- Brand palette ---- */
  --orange: #EE6334;        /* dominant brand accent — unchanged role, refined value */
  --orange-hover: #D14211;
  --amber: #F1825C;         /* warm tint of orange, used only in orange gradients */
  --navy: #1F2C43;          /* primary ink / dark surfaces */
  --navy-light: #273754;    /* hover / lighter navy surfaces */
  --ice: #E0E6ED;           /* cool soft section background */
  --cream: #F6F1E6;         /* warm soft section background */
  --slate: #64748B;         /* secondary / muted text */
  --purple: #7c3aed;
  --purple-hover: #6d28d9;
  --purple-light: #a78bfa;
  --emerald: #059669;
  --emerald-dark: #065f46;
  --emerald-light: #10b981;
  --emerald-glow: rgba(5, 150, 105, 0.16);
  --text: var(--navy);
  --muted: var(--slate);
  --line: #E4E8EE;
  --card: #ffffff;
  --bg: #FAFBFC;            /* near-white canvas with a cool cast */
  --bg-soft: var(--cream);
  --bg-ice: var(--ice);
  --radius: 20px;
  --radius-sm: 14px;
  --radius-xs: 10px;
  --shadow: 0 1px 2px rgba(31,44,67,0.05), 0 8px 24px rgba(31,44,67,0.05);
  --shadow-lg: 0 4px 12px rgba(31,44,67,0.07), 0 20px 40px rgba(238,99,52,0.08);
  --font: 'Vazirmatn', 'Outfit', system-ui, -apple-system, sans-serif;
  --ease: cubic-bezier(0.22, 1, 0.36, 1);
  --space: 1.25rem;
  /* aliases for older templates */
  --brand-orange: var(--orange);
  --brand-orange-hover: var(--orange-hover);
  --brand-amber: var(--amber);
  --brand-navy: var(--navy);
  --brand-dark: var(--text);
  --brand-card: var(--card);
  --brand-border: var(--line);
  --brand-bg: var(--bg);
  --brand-bg-accent: var(--bg-soft);
  --brand-muted: var(--muted);
}

[data-theme='dark'] {
  --text: #F3F5F8;
  --muted: #97A3B4;
  --line: #2A3548;
  --card: #212B3D;
  --bg: #141B28;
  --bg-soft: #1B2536;
  --bg-ice: #1B2536;
  --navy-light: #33456A;
  --shadow: 0 1px 3px rgba(0,0,0,0.4);
  --shadow-lg: 0 12px 40px rgba(0,0,0,0.5);
}

*, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; }
html { scroll-behavior: smooth; }
body {
  font-family: var(--font);
  background: var(--bg);
  color: var(--text);
  min-height: 100vh;
  line-height: 1.7;
  -webkit-font-smoothing: antialiased;
}
img { max-width: 100%; display: block; }
a { color: inherit; text-decoration: none; transition: color 0.2s var(--ease); }
button, input, select, textarea { font-family: inherit; }
ul { list-style: none; }
.container { width: min(1120px, calc(100% - 2.5rem)); margin-inline: auto; }
/* Header gets a wider row than the 1120px content container: with 13 nav
   items + logo + actions, the standard container is too narrow and was
   forcing the navbar to wrap/overflow on every screen size. */
.container-header { width: min(1440px, calc(100% - 2rem)); margin-inline: auto; }
.clay-bg { display: none; }

/* ---------- Typography ---------- */
h1, h2, h3, h4 { line-height: 1.25; font-weight: 700; letter-spacing: -0.02em; }
h1 { font-size: clamp(1.65rem, 3.5vw, 2.4rem); }
h2 { font-size: clamp(1.3rem, 2.5vw, 1.75rem); }
h3 { font-size: 1.1rem; }
.kicker {
  display: inline-block;
  font-size: 0.78rem;
  font-weight: 700;
  color: var(--orange);
  letter-spacing: 0.04em;
  text-transform: uppercase;
  margin-bottom: 0.35rem;
}
.lede, .muted { color: var(--muted); }
.lede { font-size: 1.05rem; max-width: 48ch; margin-top: 0.5rem; }

/* ---------- Cards / blocks (rounded squares) ---------- */
.glass, .glass-strong, .md-card, .panel-card, .form-card,
.book-card, .course-card, .teacher-card, .sample-card,
.service-card, .branch-card, .stat-card, .result-card, .slide {
  background: var(--card);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  box-shadow: var(--shadow);
  transition: transform 0.35s var(--ease), box-shadow 0.35s var(--ease), border-color 0.25s var(--ease);
}
.service-card:hover, .course-card:hover, .teacher-card:hover,
.sample-card:hover, .book-card:hover, .branch-card:hover {
  transform: translateY(-4px);
  box-shadow: var(--shadow-lg);
  border-color: rgba(238, 99, 52, 0.2);
}
.md-card, .panel-card, .form-card { padding: 1.5rem 1.4rem; }
.md-card-soft { background: var(--bg-soft); }
.md-card-accent {
  border-color: rgba(238, 99, 52, 0.22);
  background: linear-gradient(180deg, #fff 0%, #fff7ed 100%);
}
[data-theme='dark'] .md-card-accent { background: var(--card); }

/* Bookstore order-confirmation "bank card" box (requests.php) — a plastic
   card look-alike carrying the payment card number an admin sets from the
   panel, the amount to pay, and who to make it out to. */
.sd-bank-card {
  border-radius: 18px;
  padding: 1.35rem 1.5rem;
  background: linear-gradient(135deg, var(--purple, #7c3aed) 0%, #4c1d95 100%);
  color: #fff;
  text-align: start;
  box-shadow: 0 18px 40px -18px rgba(76, 29, 149, 0.55);
  position: relative;
  overflow: hidden;
}
.sd-bank-card::before {
  content: '';
  position: absolute;
  inset: 0;
  background: radial-gradient(circle at 90% -10%, rgba(255,255,255,0.18), transparent 55%);
  pointer-events: none;
}
.sd-bank-card-top {
  display: flex;
  align-items: center;
  gap: 0.5rem;
  font-weight: 700;
  font-size: 0.92rem;
  opacity: 0.92;
  margin-bottom: 1.1rem;
}
.sd-bank-card-number {
  font-size: 1.25rem;
  font-weight: 700;
  letter-spacing: 0.08em;
  font-variant-numeric: tabular-nums;
  direction: ltr;
  text-align: start;
  margin-bottom: 0.9rem;
}
.sd-bank-card-row {
  font-size: 0.85rem;
  opacity: 0.9;
  margin-bottom: 0.6rem;
}
.sd-bank-card-amount {
  font-size: 0.88rem;
  opacity: 0.95;
  border-top: 1px solid rgba(255,255,255,0.2);
  padding-top: 0.6rem;
}
.sd-bank-card-amount strong {
  display: block;
  font-size: 1.1rem;
  margin-top: 0.2rem;
}

/* ---------- Grids with real gaps ---------- */
.grid-2 {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(260px, 1fr));
  gap: 1.25rem;
}
.grid-3 {
  display: grid !important;
  grid-template-columns: repeat(3, 1fr);
  gap: 1.5rem !important;
}
@media (max-width: 900px) {
  .grid-3 { grid-template-columns: repeat(2, 1fr); }
}
@media (max-width: 560px) {
  .grid-3 { grid-template-columns: 1fr; }
}
.split {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 2rem;
  align-items: start;
}
@media (max-width: 768px) {
  .split { grid-template-columns: 1fr; gap: 1.25rem; }
}

/* ---------- Layout sections ---------- */
.page-wrap { padding: 2.75rem 0 4rem; }
.section { padding: 3rem 0; }
.section-band-ice { background: var(--bg-ice); }
.section-band-cream { background: var(--bg-soft); }

/* Divider between "Why Saraye Danesh" (ice) and "Our Services" (cream)
   bands — gives a clear visual break plus a brand-color accent so the
   two sections read as distinct, not a single continuous block. */
.section-split-divider {
  position: relative;
  height: 1px;
  background: var(--line);
}
.section-split-divider span {
  position: absolute;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
  width: 96px;
  height: 4px;
  border-radius: 999px;
  background: linear-gradient(90deg, var(--orange), var(--amber));
  box-shadow: 0 2px 10px rgba(238, 99, 52, 0.35);
}
.section-head { margin-bottom: 1.75rem; }
.section-head h2 { margin-top: 0.25rem; }

/* ---------- Header ---------- */
.announcement-bar {
  /* FIXED (per request): keep this a single short line ("ثبت نام ترم
     پاییز شروع شد.") and make the bar itself as thin as a banner can be. */
  text-align: center;
  padding: 0.18rem 1rem;
  background: linear-gradient(135deg, var(--purple), var(--purple-hover));
  color: #faf5ff;
  font-size: 0.68rem;
  line-height: 1.3;
  font-weight: 500;
}
/* Yellow "heads up" variant — used for the site-wide maintenance/update
   notice instead of the usual purple promo styling. */
.announcement-bar--notice {
  background: linear-gradient(135deg, #facc15, #eab308);
  color: #4a3400;
  font-weight: 700;
}
.announcement-bar--notice i { margin-inline-end: 0.35rem; }
.site-header {
  position: sticky;
  top: 0;
  z-index: 50;
  transition: box-shadow 0.35s var(--ease), background 0.45s var(--ease),
    backdrop-filter 0.45s var(--ease), border-color 0.45s var(--ease);
}
.site-header.scrolled { box-shadow: var(--shadow); }
.navbar {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 1rem;
  min-height: 62px;
  flex-wrap: nowrap;
  padding-block: 0.45rem;
}
/* Brand-group: logo + LIMS button side by side */
.brand-group {
  display: flex;
  align-items: center;
  gap: 0.65rem;
  flex-shrink: 0;
}
.brand-logo { display: flex; align-items: center; gap: 0.6rem; }
.logo-mark {
  width: 46px; height: 46px;
  border-radius: 12px;
  overflow: hidden;
  flex-shrink: 0;
  background: transparent;
  position: relative;
  transition: transform 0.4s var(--ease), border-radius 0.4s var(--ease);
}
.brand-logo:hover .logo-mark { transform: scale(1.08) rotate(-4deg); border-radius: 30%; }
.logo-img { width: 100%; height: 100%; object-fit: contain; transition: transform 0.4s var(--ease); }
/* Per request: a subtle, ambient "shine" sweep across the header logo,
   on its own — not only on hover — so it reads as a little alive rather
   than a static image. A diagonal highlight band sweeps across every few
   seconds; disabled entirely for anyone who has asked for less motion. */
.header-logo-shine .logo-mark::after {
  content: "";
  position: absolute;
  inset: 0;
  background: linear-gradient(115deg, transparent 40%, rgba(255,255,255,0.75) 50%, transparent 60%);
  transform: translateX(-120%);
  animation: sd-logo-shine 5s ease-in-out infinite;
  pointer-events: none;
}
@keyframes sd-logo-shine {
  0%, 35% { transform: translateX(-120%); }
  55%, 100% { transform: translateX(120%); }
}
@media (prefers-reduced-motion: reduce) {
  .header-logo-shine .logo-mark::after { animation: none; display: none; }
}
.logo-text strong { display: block; font-size: 0.95rem; font-weight: 700; }
.logo-text small { display: block; font-size: 0.7rem; color: var(--muted); line-height: 1.2; }

.nav-links {
  display: flex;
  flex-wrap: nowrap;
  gap: 0.2rem;
  align-items: center;
  justify-content: center;
  overflow-x: auto;
  scrollbar-width: none;
  -ms-overflow-style: none;
}
.nav-links::-webkit-scrollbar { display: none; }
.nav-link {
  padding: 0.3rem 0.65rem;
  border-radius: 999px;
  font-size: 0.76rem;
  font-weight: 500;
  color: var(--muted);
  white-space: nowrap;
  /* FIXED (per request): a longer label like "کتاب‌فروشی" could end up
     visually poking out past its own pill's rounded corners once the
     nav bar got tight — flex-shrink:0 plus a touch more side padding
     keeps every label's pill sized to fit its own text instead of being
     squeezed by its neighbors. */
  flex-shrink: 0;
  display: inline-flex;
  align-items: center;
  transition: background 0.2s var(--ease), color 0.2s var(--ease);
}
@media (min-width: 1301px) and (max-width: 1400px) {
  .nav-link { font-size: 0.72rem; padding: 0.28rem 0.42rem; }
  .nav-links { gap: 0.05rem; }
}
.nav-link:hover, .nav-link.active {
  background: rgba(238, 99, 52, 0.1);
  color: var(--orange);
}
/* Bookstore — light purple pill with black text */
.nav-link-bookstore {
  background: rgba(167, 139, 250, 0.22) !important;
  color: #1F2C43 !important;
  border: 1px solid rgba(124, 58, 237, 0.25);
  font-weight: 600;
}
.nav-link-bookstore:hover, .nav-link-bookstore.active {
  background: rgba(124, 58, 237, 0.18) !important;
  color: #1F2C43 !important;
  border-color: rgba(124, 58, 237, 0.4);
}
/* Mobile-menu-only login/exit row (see includes/header.php) — always
   reachable the moment the dropdown is open, independent of whatever
   happens to the icon-only login/logout button in .nav-actions. */
.nav-links-mobile-auth { margin-top: 0.35rem; padding-top: 0.5rem; border-top: 1px dashed var(--line); }
.nav-link-logout, .nav-link-login {
  font-weight: 700 !important;
  color: var(--orange) !important;
  background: rgba(238, 99, 52, 0.08) !important;
}
[data-theme='dark'] .nav-link-bookstore { color: #f5f3ff !important; }
[data-theme='dark'] .nav-link-bookstore:hover { color: #f5f3ff !important; }
.header-actions { display: flex; align-items: center; gap: 0.45rem; }

/* ---------- Buttons ---------- */
.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 0.4rem;
  padding: 0.7rem 1.25rem;
  border-radius: 999px;
  border: 1px solid transparent;
  font-weight: 600;
  font-size: 0.92rem;
  cursor: pointer;
  transition: transform 0.25s var(--ease), box-shadow 0.25s var(--ease), background 0.2s var(--ease);
}
.btn:hover { transform: translateY(-1px); }
.btn:active { transform: translateY(0); }
.btn-primary {
  background: var(--orange);
  color: #fff;
  box-shadow: 0 4px 14px rgba(238, 99, 52, 0.35);
}
.btn-primary:hover { background: var(--orange-hover); box-shadow: 0 6px 20px rgba(238, 99, 52, 0.4); }
.btn-outline {
  border-color: var(--line);
  background: var(--card);
  color: var(--text);
}
.btn-outline:hover { border-color: var(--orange); color: var(--orange); }
.btn-sm { padding: 0.45rem 0.9rem; font-size: 0.84rem; }
.icon-btn {
  width: 40px; height: 40px;
  border-radius: 50%;
  border: 1px solid var(--line);
  background: var(--card);
  display: inline-flex;
  align-items: center;
  justify-content: center;
  cursor: pointer;
  transition: background 0.2s var(--ease), border-color 0.2s var(--ease), transform 0.25s var(--ease), color 0.2s var(--ease);
}
.icon-btn:hover { border-color: var(--orange); color: var(--orange); }

/* ---------- Hero ---------- */
.hero-slider { padding: 2.5rem 0 1rem; }
/* FIXED (stage 6 – slider size): the slide box only had a min-height, so
   its real height tracked whatever the active slide's text/photo needed —
   switching slides visibly grew/shrank the whole hero (and shoved every
   section below it up/down). A fixed height + clamped title/text means
   every slide renders at the exact same size no matter what it contains. */
.hero-slider .slide {
  display: grid;
  grid-template-columns: 1.15fr 0.85fr;
  gap: 2.5rem;
  align-items: center;
  padding: 2.25rem 2rem;
  /* FIXED (per request): the old fixed height() + overflow:hidden clipped
     the CTA buttons off the bottom of the slide whenever a slide's copy
     ran a bit long (mostly on mobile), making them appear to fall behind
     the slide/pagination dots. min-height keeps every slide the same
     size in the common case (avoiding the layout-shift this was meant to
     prevent) without ever cutting content off when it runs longer. */
  min-height: 560px;
}
.hero-slider .slide:not(.active) { display: none; }
.hero-copy h1 {
  margin: 0.35rem 0 0.75rem;
  display: -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
  overflow: hidden;
}
.hero-copy p {
  color: var(--muted);
  max-width: 38ch;
  display: -webkit-box;
  -webkit-line-clamp: 4;
  -webkit-box-orient: vertical;
  overflow: hidden;
}
.hero-note {
  display: inline-flex;
  align-items: center;
  gap: 0.5rem;
  margin-top: 0.85rem;
  padding: 0.5rem 0.9rem;
  background: var(--bg-ice);
  border: 1px solid rgba(31, 44, 67, 0.1);
  border-radius: 999px;
  font-size: 0.82rem;
  font-weight: 600;
  color: var(--navy);
  /* FIXED (per request): now a link to class-formats.php instead of a
     plain, non-interactive line of text. */
  text-decoration: none;
  transition: transform 0.2s var(--ease), border-color 0.2s var(--ease);
}
.hero-note:hover { transform: translateY(-1px); border-color: var(--orange); }
.hero-note i { color: var(--slate); font-size: 0.8rem; }
[data-theme='dark'] .hero-note { background: rgba(255,255,255,0.06); border-color: rgba(255,255,255,0.1); color: var(--text); }
.hero-actions {
  display: flex;
  flex-wrap: wrap;
  gap: 0.75rem;
  margin-top: 1.5rem;
}

/* ---------- Visual frame: the reusable "photo square" ----------
   One consistent, upload-ready image slot used by the hero and the
   about section (and reused later for teacher/gallery photos).
   Fixed aspect-ratio + object-fit:cover means any photo the admin
   uploads — portrait, landscape, whatever size — fills the frame
   cleanly without stretching or leaving gaps. */
.visual-frame {
  position: relative;
  border-radius: var(--radius);
  overflow: hidden;
  aspect-ratio: 4 / 5;
  box-shadow: var(--shadow-lg);
  isolation: isolate;
}
.visual-frame img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  transition: transform 1s var(--ease);
}
.visual-frame:hover img,
.visual-frame.parallax-active img { transform: scale(1.06); }
.hero-visual .visual-frame { aspect-ratio: 5 / 4; }
@media (max-width: 768px) {
  .visual-frame { aspect-ratio: 4 / 3; }
}

/* Floating stat/quote badge that overlaps the corner of a visual-frame */
.visual-badge {
  position: absolute;
  bottom: 1rem;
  inset-inline-start: 1rem;
  z-index: 2;
  display: flex;
  align-items: center;
  gap: 0.65rem;
  background: rgba(255, 255, 255, 0.92);
  backdrop-filter: blur(10px);
  -webkit-backdrop-filter: blur(10px);
  border: 1px solid rgba(255, 255, 255, 0.6);
  border-radius: 999px;
  padding: 0.55rem 1rem 0.55rem 0.55rem;
  box-shadow: var(--shadow-lg);
  transform: translateY(14px) scale(0.92);
  opacity: 0;
  transition: transform 0.6s var(--ease) 0.35s, opacity 0.6s var(--ease) 0.35s;
}
[dir='rtl'] .visual-badge { padding: 0.55rem 0.55rem 0.55rem 1rem; }
.visual-frame.is-visible .visual-badge,
[data-reveal].is-visible .visual-frame .visual-badge { transform: translateY(0) scale(1); opacity: 1; }
.visual-badge-num {
  width: 44px; height: 44px;
  border-radius: 50%;
  background: linear-gradient(135deg, var(--amber), var(--orange));
  color: #fff;
  display: flex;
  align-items: center;
  justify-content: center;
  font-weight: 800;
  font-size: 0.95rem;
  flex-shrink: 0;
}
.visual-badge-text { display: flex; flex-direction: column; line-height: 1.25; }
.visual-badge-text strong { font-size: 0.85rem; }
.visual-badge-text span { font-size: 0.72rem; color: var(--muted); }
[data-theme='dark'] .visual-badge { background: rgba(28, 25, 23, 0.85); border-color: rgba(255,255,255,0.08); }
.slider-nav {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 0.5rem;
  margin-top: 1.25rem;
}
.slider-dot {
  width: 8px; height: 8px;
  border-radius: 50%;
  border: none;
  background: var(--line);
  cursor: pointer;
  transition: background 0.2s, transform 0.2s;
}
.slider-dot.active { background: var(--orange); transform: scale(1.25); }
/* Small pause/play control for the autoplaying hero slider — sits in the
   bottom corner of the nav row rather than on top of the slide photo/text,
   so it never overlaps the content it controls. */
.slider-nav { position: relative; }
.slider-nav-controls { display: flex; align-items: center; gap: 0.5rem; }
.slider-pause-btn {
  position: absolute;
  inset-inline-end: 0;
  top: 50%;
  transform: translateY(-50%);
  width: 30px;
  height: 30px;
  font-size: 0.72rem;
}
@media (max-width: 768px) {
  .hero-slider .slide {
    grid-template-columns: 1fr;
    text-align: center;
    padding: 1.5rem 1.25rem;
    gap: 1.25rem;
    min-height: 620px;
  }
  .hero-copy p { margin-inline: auto; }
  .hero-actions { justify-content: center; }
  .hero-visual { order: -1; }
  .slider-pause-btn { position: static; transform: none; margin-inline-start: 0.5rem; }
}

/* ---------- Trust / stats ---------- */
.trust-bar { padding-top: 0.5rem; }
.trust-label { text-align: center; margin-bottom: 1.25rem; font-size: 0.9rem; }
.stats {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: 1.15rem;
}
.stat-card {
  text-align: center;
  padding: 1.5rem 1rem;
}
.stat-icon {
  display: block;
  font-size: 1.3rem;
  color: var(--orange);
  margin-bottom: 0.6rem;
  opacity: 0.85;
}
.stat-card strong {
  display: block;
  font-size: 1.85rem;
  font-weight: 800;
  color: var(--orange);
  line-height: 1.15;
  margin-bottom: 0.35rem;
}
@media (max-width: 700px) {
  .stats { grid-template-columns: repeat(2, 1fr); gap: 0.85rem; }
}

/* ---------- Service / program cards ---------- */
.service-card, .course-card {
  padding: 1.5rem 1.35rem;
  display: flex;
  flex-direction: column;
  gap: 0.5rem;
}
.service-icon {
  width: 48px; height: 48px;
  border-radius: 14px;
  background: rgba(238, 99, 52, 0.1);
  color: var(--orange);
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 1.2rem;
  margin-bottom: 0.25rem;
}
.badge {
  align-self: flex-start;
  font-size: 0.72rem;
  font-weight: 700;
  padding: 0.2rem 0.55rem;
  border-radius: 999px;
  background: rgba(238, 99, 52, 0.1);
  color: var(--orange);
}
.meta { font-size: 0.85rem; color: var(--muted); }

/* ---------- Teachers ---------- */
.teacher-card {
  text-align: center;
  padding: 1.75rem 1.35rem;
}
.teacher-photo-wrap {
  width: 96px; height: 96px;
  margin: 0 auto 0.9rem;
  border-radius: 50%;
  overflow: hidden;
  border: 3px solid rgba(238, 99, 52, 0.2);
  background: linear-gradient(135deg, #fed7aa, #fdba74);
  transition: border-color 0.3s var(--ease), box-shadow 0.3s var(--ease);
}
.teacher-card:hover .teacher-photo-wrap {
  border-color: var(--orange);
  box-shadow: 0 0 0 6px rgba(238, 99, 52, 0.1);
}
.teacher-photo {
  width: 100%; height: 100%;
  object-fit: cover;
}
.teacher-role {
  font-size: 0.9rem;
  font-weight: 600;
  color: var(--orange);
  margin: 0.25rem 0 0.5rem;
}

/* ---------- Gallery: the main "squares to upload images" grid ----------
   Fixed 1:1 slots, each backed by data/content.json → gallery[].image.
   Empty image falls back to a dashed "upload from admin panel" placeholder
   (see includes below) so empty slots read as intentional, not broken. */
.gallery-grid {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: 1rem;
}
@media (max-width: 900px) { .gallery-grid { grid-template-columns: repeat(3, 1fr); } }
@media (max-width: 600px) { .gallery-grid { grid-template-columns: repeat(2, 1fr); gap: 0.6rem; } }
.gallery-item {
  position: relative;
  aspect-ratio: 1 / 1;
  border-radius: var(--radius-sm);
  overflow: hidden;
  box-shadow: var(--shadow);
  transition: box-shadow 0.3s var(--ease);
}
.gallery-item:hover { box-shadow: var(--shadow-lg); }
.gallery-item img {
  width: 100%; height: 100%;
  object-fit: cover;
  transition: transform 0.6s var(--ease);
}
.gallery-item:hover img { transform: scale(1.08); }
.gallery-caption {
  position: absolute;
  inset-inline: 0;
  bottom: 0;
  padding: 1.6rem 0.85rem 0.65rem;
  background: linear-gradient(0deg, rgba(12,10,9,0.78), transparent);
  color: #fff;
  font-size: 0.8rem;
  font-weight: 600;
  transform: translateY(100%);
  transition: transform 0.35s var(--ease);
}
.gallery-item:hover .gallery-caption { transform: translateY(0); }

/* ---------- Testimonials ---------- */
.testimonial-card {
  padding: 1.6rem 1.4rem;
  display: flex;
  flex-direction: column;
  gap: 0.75rem;
}
.testimonial-stars { color: var(--amber); font-size: 0.85rem; letter-spacing: 0.15em; }
.testimonial-text { color: var(--text); font-size: 0.95rem; line-height: 1.8; flex-grow: 1; }
.testimonial-person { display: flex; align-items: center; gap: 0.7rem; }
.testimonial-avatar {
  width: 44px; height: 44px;
  border-radius: 50%;
  overflow: hidden;
  flex-shrink: 0;
  background: linear-gradient(135deg, #fed7aa, #fdba74);
}
.testimonial-avatar img { width: 100%; height: 100%; object-fit: cover; }
.testimonial-person strong { display: block; font-size: 0.9rem; }
.testimonial-person span { font-size: 0.78rem; color: var(--muted); }

/* ---------- Forms ---------- */
.stack-form { display: flex; flex-direction: column; gap: 0.9rem; }
.stack-form label {
  display: flex;
  flex-direction: column;
  gap: 0.35rem;
  font-weight: 600;
  font-size: 0.9rem;
}
.field, .stack-form input, .stack-form select, .stack-form textarea,
input.field, select.field, textarea.field,
.newsletter-form input {
  width: 100%;
  padding: 0.75rem 1rem;
  border: 1px solid var(--line);
  border-radius: var(--radius-sm);
  background: var(--bg-soft);
  color: var(--text);
  font-size: 0.95rem;
  transition: border-color 0.2s var(--ease), box-shadow 0.2s var(--ease), background 0.2s;
}
.field:focus, .stack-form input:focus, .stack-form select:focus,
.stack-form textarea:focus, .newsletter-form input:focus {
  outline: none;
  border-color: var(--orange);
  box-shadow: 0 0 0 4px rgba(238, 99, 52, 0.12);
  background: var(--card);
}

/* ---------- Footer ---------- */
.site-footer {
  margin-top: 3rem;
  border-top: 1px solid var(--line);
  background: var(--card);
}
.footer-newsletter {
  padding: 2rem 0;
  border-bottom: 1px solid var(--line);
  border-radius: 0 !important;
  box-shadow: none !important;
  border-left: none !important;
  border-right: none !important;
}
.newsletter-grid {
  display: grid;
  grid-template-columns: 1fr auto;
  gap: 1.5rem;
  align-items: center;
}
.newsletter-form {
  display: flex;
  gap: 0.5rem;
  flex-wrap: wrap;
}
.newsletter-form input { min-width: 0; width: 100%; flex: 1 1 220px; }
.footer-main { padding: 2.5rem 0 1.25rem; }
.footer-grid {
  display: grid;
  grid-template-columns: 1.4fr 1fr 1fr;
  gap: 1.25rem;
  align-items: stretch;
}
/* Footer cards: give each column its own defined, elevated block instead
   of loose columns floating on the glass footer background. */
.footer-card {
  background: var(--card);
  border: 1px solid var(--line);
  border-radius: var(--radius-sm);
  box-shadow: var(--shadow);
  padding: 1.35rem 1.4rem;
  transition: box-shadow 0.3s var(--ease), border-color 0.3s var(--ease), transform 0.3s var(--ease);
}
.footer-card:hover {
  box-shadow: var(--shadow-lg);
  border-color: rgba(238, 99, 52, 0.18);
  transform: translateY(-2px);
}
.footer-card-brand { display: flex; flex-direction: column; gap: 0.85rem; }
.footer-card .footer-brand { margin: 0; }
.footer-card p.muted { margin: 0; font-size: 0.9rem; }
.footer-grid h4 {
  font-size: 0.95rem;
  margin: 0 0 0.9rem;
  padding-bottom: 0.6rem;
  border-bottom: 1px solid var(--line);
  color: var(--text);
}
.footer-grid ul {
  display: grid;
  gap: 0.5rem;
}
.footer-grid ul a {
  color: var(--muted);
  font-size: 0.92rem;
  transition: color 0.2s, transform 0.2s var(--ease);
  display: inline-flex;
}
.footer-grid ul a:hover { color: var(--orange); transform: translateX(-2px); }
[dir="rtl"] .footer-grid ul a:hover { transform: translateX(2px); }
.footer-contact {
  display: grid;
  gap: 0.6rem;
  margin: 0 0 1.1rem;
}
.footer-contact li {
  display: flex;
  align-items: center;
  gap: 0.55rem;
  color: var(--muted);
  font-size: 0.92rem;
}
.footer-contact i {
  color: var(--orange);
  width: 1.9rem;
  height: 1.9rem;
  flex-shrink: 0;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  background: rgba(238, 99, 52, 0.08);
  border-radius: 8px;
  font-size: 0.85rem;
}
.footer-bottom {
  margin-top: 1.5rem;
  padding: 1rem 1.4rem;
  border-top: none;
  background: var(--bg-soft);
  border: 1px solid var(--line);
  border-radius: var(--radius-sm);
  display: flex;
  flex-wrap: wrap;
  gap: 0.75rem;
  justify-content: space-between;
  align-items: center;
  font-size: 0.85rem;
  color: var(--muted);
}
.footer-copy { margin: 0; }
.footer-bottom-links {
  display: flex;
  gap: 1.25rem;
}
.footer-bottom-links a { color: var(--muted); transition: color 0.2s; }
.footer-bottom-links a:hover { color: var(--orange); }
.social-links {
  display: flex;
  flex-wrap: wrap;
  gap: 0.5rem;
  margin-top: 1rem;
}
.social-btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 40px; height: 40px;
  border-radius: 12px;
  background: rgba(238, 99, 52, 0.08);
  color: var(--orange);
  font-size: 1.05rem;
  transition: all 0.25s var(--ease);
}
.social-btn:hover {
  background: var(--orange);
  color: #fff;
  transform: translateY(-2px);
  box-shadow: 0 6px 16px rgba(238, 99, 52, 0.3);
}
.design-v {
  text-align: center;
  font-size: 0.72rem;
  color: var(--muted);
  opacity: 0.75;
  margin: 0.9rem 0 0;
  padding-top: 0.9rem;
}
@media (max-width: 800px) {
  .footer-grid { grid-template-columns: 1fr; gap: 1rem; }
  .newsletter-grid { grid-template-columns: 1fr; }
  .footer-bottom { flex-direction: column; align-items: flex-start; text-align: start; }
}

/* ---------- Flash / misc ---------- */
.flash {
  padding: 0.9rem 1.15rem;
  border-radius: var(--radius-sm);
  font-weight: 500;
}
.flash-ok, .flash-success { background: #ecfdf5; color: #047857; border: 1px solid #a7f3d0; }
/* "Changes were made" footer toast — per request, shown after any save
   anywhere on the site/dashboard, always green, always at the bottom,
   auto-dismissing. See assets/js/app.js (public pages) and
   sd_flash_toast_script() in includes/functions.php (standalone admin
   panels) for what applies this class. */
.flash-toast {
  position: fixed;
  bottom: 1.25rem;
  inset-inline-start: 50%;
  transform: translateX(-50%);
  z-index: 10000;
  width: max-content;
  max-width: min(420px, calc(100vw - 2rem));
  box-shadow: 0 12px 30px -8px rgba(4, 120, 87, 0.35);
  animation: sd-toast-in 0.3s var(--ease, ease);
}
[dir='rtl'] .flash-toast { transform: translateX(50%); }
.flash-toast-hide { opacity: 0; transform: translateX(-50%) translateY(8px); transition: opacity 0.55s ease, transform 0.55s ease; }
[dir='rtl'] .flash-toast-hide { transform: translateX(50%) translateY(8px); }
@keyframes sd-toast-in {
  from { opacity: 0; transform: translateX(-50%) translateY(12px); }
  to { opacity: 1; transform: translateX(-50%) translateY(0); }
}
[data-theme='dark'] .flash-toast { box-shadow: 0 12px 30px -8px rgba(0,0,0,0.55); }
.flash-error { background: #fef2f2; color: #b91c1c; border: 1px solid #fecaca; }
.flash-info { background: #eff6ff; color: #1d4ed8; border: 1px solid #bfdbfe; }
.flash-warn { background: #fffbeb; color: #b45309; border: 1px solid #fde68a; }
[data-theme='dark'] .flash-info { background: #1e3a8a; color: #bfdbfe; }
[data-theme='dark'] .flash-ok { background: #064e3b; color: #a7f3d0; }
[data-theme='dark'] .flash-error { background: #7f1d1d; color: #fecaca; }
[data-theme='dark'] .flash-warn { background: #78350f; color: #fde68a; }

/* Data-accuracy notice — verification.php + login.php (per request: tell
   people to contact us if their certificate/account data isn't showing
   up right, so we can fix it on our end). Built on the same warm-warn
   palette as .flash-warn but styled as a standalone callout card. */
.notice-box {
  display: flex;
  align-items: flex-start;
  gap: 0.75rem;
  padding: 1rem 1.15rem;
  border-radius: var(--radius-sm);
  background: #fffbeb;
  border: 1px solid #fde68a;
  color: #92400e;
  font-size: 0.9rem;
  line-height: 1.6;
  margin: 1.25rem 0;
}
.notice-box i {
  font-size: 1.1rem;
  margin-top: 0.15rem;
  flex-shrink: 0;
  color: #b45309;
}
.notice-box a {
  color: #92400e;
  font-weight: 700;
  text-decoration: underline;
}
[data-theme='dark'] .notice-box {
  background: #78350f;
  border-color: #92400e;
  color: #fde68a;
}
[data-theme='dark'] .notice-box i,
[data-theme='dark'] .notice-box a { color: #fde68a; }

.skip-link {
  position: absolute;
  top: -100px;
  inset-inline-start: 1rem;
  background: var(--orange);
  color: #fff;
  padding: 0.5rem 1rem;
  border-radius: 8px;
  z-index: 10000;
  transition: top 0.2s;
}
.skip-link:focus { top: 1rem; }
:focus-visible {
  outline: 2px solid var(--orange);
  outline-offset: 3px;
}
@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: 0.01ms !important;
    transition-duration: 0.01ms !important;
  }
}

/* =========================================================
   Motion engine — scroll reveals, Apple-style text reveals,
   hover response, page-load fade. Everything here is additive:
   base styles stay untouched, elements just opt in via
   data-attributes or utility classes.
   ========================================================= */

/* ---------- Page-load fade ---------- */
body { opacity: 0; }
body.is-ready { opacity: 1; transition: opacity 0.5s var(--ease); }

/* ---------- Scroll reveal ---------- */
[data-reveal] {
  opacity: 0;
  transform: translateY(28px);
  transition: opacity 0.7s var(--ease), transform 0.7s var(--ease);
  transition-delay: var(--reveal-delay, 0s);
  will-change: opacity, transform;
}
[data-reveal="fade"] { transform: none; }
[data-reveal="left"] { transform: translateX(var(--reveal-x, -28px)); }
[data-reveal="right"] { transform: translateX(var(--reveal-x, 28px)); }
[data-reveal="scale"] { transform: scale(0.94); }
[data-reveal].is-visible {
  opacity: 1;
  transform: none;
}

/* ---------- Apple-style headline reveal (word by word) ---------- */
.reveal-text { display: block; overflow: hidden; }
.reveal-text .word-wrap { display: inline-block; overflow: hidden; vertical-align: top; }
.reveal-text .word {
  display: inline-block;
  transform: translateY(115%);
  opacity: 0;
  transition: transform 0.85s var(--ease), opacity 0.85s var(--ease);
  transition-delay: calc(var(--w, 0) * 55ms);
}
.reveal-text.is-visible .word { transform: translateY(0); opacity: 1; }

/* ---------- Typing effect (kicker / tagline) ----------
   .type-content grows via JS (substring reveal) so Persian/Arabic
   letter joining renders correctly — no per-character DOM splitting. */
.type-text { position: relative; white-space: normal; }
.type-content { display: inline; }
.type-cursor {
  display: inline-block;
  width: 2px;
  height: 1em;
  background: var(--orange);
  margin-inline-start: 2px;
  vertical-align: -0.15em;
  animation: sd-blink 0.9s steps(1) infinite;
}
.type-cursor.done { animation: none; opacity: 0; }
@keyframes sd-blink { 50% { opacity: 0; } }

/* ---------- Count-up numbers ---------- */
[data-count] { font-variant-numeric: tabular-nums; }

/* ---------- Hover response: tilt + glow ---------- */
[data-tilt] {
  transform-style: preserve-3d;
  transition: transform 0.25s var(--ease), box-shadow 0.25s var(--ease);
}
[data-tilt]::after {
  content: '';
  position: absolute;
  inset: 0;
  border-radius: inherit;
  background: radial-gradient(320px circle at var(--mx, 50%) var(--my, 50%),
    rgba(238, 99, 52, 0.14), transparent 60%);
  opacity: 0;
  transition: opacity 0.3s var(--ease);
  pointer-events: none;
}
[data-tilt]:hover::after,
[data-tilt].tilt-active::after { opacity: 1; }
[data-tilt] { position: relative; overflow: hidden; }

/* ---------- Magnetic buttons ---------- */
.btn { transition: transform 0.25s var(--ease), box-shadow 0.25s var(--ease), background 0.25s var(--ease), color 0.25s var(--ease); }
.btn-primary:hover, .btn-outline:hover { box-shadow: 0 10px 26px rgba(238, 99, 52, 0.28); }

/* ---------- Image hover zoom (for gallery / cards with photos) ---------- */
.img-zoom { overflow: hidden; border-radius: inherit; }
.img-zoom img { transition: transform 0.6s var(--ease); }
.img-zoom:hover img { transform: scale(1.06); }

/* ---------- Nav link hover: pill scale + icon-btn lift ---------- */
.nav-link {
  transition: background 0.25s var(--ease), color 0.25s var(--ease), transform 0.25s var(--ease);
}
.nav-link:hover { transform: translateY(-1px); }
.icon-btn:hover { transform: translateY(-2px) rotate(-6deg); }

/* ---------- Sticky mobile CTA ---------- */
.sticky-enroll {
  display: none;
  position: fixed;
  bottom: 1.25rem;
  left: 50%;
  transform: translateX(-50%);
  z-index: 900;
  padding: 0 1rem;
}
.sticky-enroll-btn {
  box-shadow: 0 10px 30px rgba(238, 99, 52, 0.45);
  padding: 0.75rem 1.5rem;
  border-radius: 999px;
}
@media (max-width: 768px) {
  .sticky-enroll { display: block; }
  #sd-chatbot { bottom: 5.5rem; }
}

/* ---------- Chatbot ---------- */
#sd-chatbot {
  position: fixed;
  bottom: 1.5rem;
  inset-inline-end: 1.5rem;
  z-index: 9999;
}
.sd-chat-toggle {
  width: 56px; height: 56px;
  border-radius: 50%;
  border: none;
  background: linear-gradient(135deg, #F1825C, #EE6334);
  color: #fff;
  font-size: 1.35rem;
  cursor: pointer;
  box-shadow: 0 8px 24px rgba(238, 99, 52, 0.4);
  transition: transform 0.25s var(--ease);
}
.sd-chat-toggle:hover { transform: scale(1.06); }
.sd-chat-panel {
  position: absolute;
  bottom: 70px;
  inset-inline-end: 0;
  width: min(340px, calc(100vw - 2rem));
  /* FIXED (per request): 420px wasn't enough room for header + messages
     (min-height 200px) + the pre-chat name/phone form's own title, two
     inputs and "Start chat" button — that button was the first thing to
     get clipped by overflow:hidden below. This is worse now that live
     chat (and its pre-chat gate) is the default mode every new visitor
     sees. min(…, 100vh - 90px) keeps it from overflowing very short
     mobile viewports too. */
  max-height: min(520px, calc(100vh - 90px));
  display: flex;
  flex-direction: column;
  border-radius: 20px;
  overflow: hidden;
  box-shadow: var(--shadow-lg);
  background: var(--card);
  border: 1px solid var(--line);
}
.sd-chat-panel[hidden] { display: none !important; }
.sd-chat-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 0.85rem 1rem;
  background: linear-gradient(135deg, #F1825C, #EE6334);
  color: #fff;
  font-weight: 600;
}
.sd-chat-header-title {
  display: flex;
  flex-direction: column;
  gap: 0.2rem;
  min-width: 0;
}
.sd-chat-header-title strong {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
/* Reception online/offline presence dot — green while a secretary/manager/
   super_admin has the live-chat tab open (see sd_chat_is_online()), yellow
   otherwise. Shown only once live mode is active. */
.sd-chat-status {
  display: inline-flex;
  align-items: center;
  gap: 0.35rem;
  font-size: 0.7rem;
  font-weight: 600;
  opacity: 0.92;
}
.sd-chat-status[hidden] { display: none !important; }
.sd-chat-status-dot {
  width: 8px;
  height: 8px;
  border-radius: 50%;
  background: #facc15;
  box-shadow: 0 0 0 2px rgba(255, 255, 255, 0.35);
}
.sd-chat-status-dot.is-online { background: #22c55e; }
.sd-chat-status-dot.is-offline { background: #facc15; }
.sd-chat-header-actions {
  display: flex;
  align-items: center;
  gap: 0.5rem;
}
.sd-chat-mode-btn {
  background: rgba(255, 255, 255, 0.18);
  border: none;
  color: #fff;
  width: 30px;
  height: 30px;
  border-radius: 50%;
  cursor: pointer;
  font-size: 0.9rem;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  transition: background 0.2s var(--ease);
}
.sd-chat-mode-btn:hover { background: rgba(255, 255, 255, 0.3); }
.sd-chat-close {
  background: transparent;
  border: none;
  color: #fff;
  font-size: 1.4rem;
  cursor: pointer;
  line-height: 1;
}
.sd-chat-messages {
  flex: 1;
  overflow-y: auto;
  padding: 0.85rem;
  display: flex;
  flex-direction: column;
  gap: 0.55rem;
  /* Trimmed from 200px — that floor left no room for the pre-chat
     name/phone form underneath (see .sd-chat-panel's max-height note). */
  min-height: 140px;
  max-height: 260px;
}
.sd-msg {
  max-width: 85%;
  padding: 0.55rem 0.8rem;
  border-radius: 14px;
  font-size: 0.9rem;
  line-height: 1.45;
}
.sd-msg-bot { align-self: flex-start; background: rgba(238, 99, 52, 0.1); }
.sd-msg-user { align-self: flex-end; background: var(--orange); color: #fff; }
.sd-msg-secretary { align-self: flex-start; background: rgba(124, 58, 237, 0.12); color: #6d28d9; }
.sd-chat-form,
.sd-chat-precontact {
  display: flex;
  flex-shrink: 0;
  gap: 0.4rem;
  padding: 0.65rem;
  border-top: 1px solid var(--line);
}
.sd-chat-form[hidden],
.sd-chat-precontact[hidden] { display: none !important; }
.sd-chat-form input,
.sd-chat-precontact input {
  flex: 1;
  border: 1px solid var(--line);
  border-radius: 12px;
  padding: 0.45rem 0.7rem;
  background: var(--bg-soft);
  color: var(--text);
}
/* Pre-chat name+phone gate — collected once, before a guest's first live
   message, so reception always has a way to call them back. */
.sd-chat-precontact {
  flex-wrap: wrap;
  flex-direction: column;
}
.sd-chat-precontact-title {
  margin: 0 0 0.15rem;
  font-size: 0.82rem;
  font-weight: 700;
  color: var(--text);
}
/* "Seen" tick under the visitor's own last message, once reception has
   actually opened/read the conversation (secretary_read_at from the
   server >= this message's timestamp). */
.sd-msg-seen {
  display: block;
  margin-top: 0.25rem;
  font-size: 0.68rem;
  font-weight: 700;
  opacity: 0.85;
  text-align: end;
}

/* ---------- Course / sample extras ---------- */
.course-card .cover {
  width: 100%;
  height: 140px;
  object-fit: cover;
  border-radius: var(--radius-sm);
  background: linear-gradient(135deg, #fed7aa, #fdba74);
}
/* Generic cover fallback: .book-cover and blog .cover had NO sizing rule
   anywhere before this — book covers and blog thumbnails were rendering at
   native image size with no object-fit, breaking card grid alignment. */
.cover {
  width: 100%;
  object-fit: cover;
  border-radius: var(--radius-sm);
  background: var(--bg-soft);
}
/* Book card: cover bleeds to full width, content has padding */
article.book-card {
  overflow: hidden;
  padding: 0;
  display: flex;
  flex-direction: column;
}
article.book-card .book-cover,
article.book-card .book-cover-placeholder {
  width: 100%;
  border-radius: 0;          /* cover fills top edge of card, no rounded corners */
  border-top-left-radius: var(--radius);
  border-top-right-radius: var(--radius);
  flex-shrink: 0;
}
/* Book text area gets proper inset padding */
article.book-card h3,
article.book-card p,
article.book-card .book-meta,
article.book-card .book-actions {
  padding-inline: 1.1rem;
}
article.book-card h3 { padding-top: 0.9rem; }
article.book-card .book-actions { padding-bottom: 1rem; }
.book-cover, .book-cover-placeholder {
  height: 200px;
}
/* Discount "bubble" pinned to the book cover's corner (admin/bookstore.php
   sets discount_percent per book) — and the struck-through original price
   next to the discounted one. */
.book-cover-wrap {
  position: relative;
  flex-shrink: 0;
}
.book-cover-wrap .book-cover,
.book-cover-wrap .book-cover-placeholder {
  margin: 0;
}
.book-discount-bubble {
  position: absolute;
  top: 0.6rem;
  inset-inline-end: 0.6rem;
  background: linear-gradient(135deg, #ef4444, #dc2626);
  color: #fff;
  font-size: 0.72rem;
  font-weight: 700;
  padding: 0.3rem 0.6rem;
  border-radius: 999px;
  box-shadow: 0 6px 16px -6px rgba(220, 38, 38, 0.6);
}
.price-original {
  text-decoration: line-through;
  color: var(--muted);
  font-size: 0.85rem;
  font-weight: 500;
  margin-inline-end: 0.4rem;
}
.price-discounted {
  color: #dc2626;
}

.post-card .cover {
  height: 170px;
  margin-bottom: 0.75rem;
}
.course-meta {
  display: flex;
  flex-wrap: wrap;
  gap: 0.75rem;
  font-size: 0.85rem;
  color: var(--muted);
}
.course-meta i { color: var(--orange); margin-inline-end: 0.25rem; }
.course-card .price {
  font-size: 1.15rem;
  font-weight: 700;
  color: var(--orange);
}
.sample-card { padding: 1.35rem 1.25rem; display: flex; flex-direction: column; gap: 0.45rem; }
.sample-card .badge {
  background: rgba(34, 197, 94, 0.12);
  color: #16a34a;
}

/* ---------- About ---------- */
.about-section h2 {
  font-size: 1.15rem;
  margin-bottom: 0.65rem;
  display: flex;
  align-items: center;
  gap: 0.45rem;
}
.about-section h2 i { color: var(--orange); }
.about-section p { margin-top: 0.65rem; line-height: 1.85; }
.md-list {
  padding-inline-start: 1.25rem;
  color: var(--muted);
  line-height: 1.85;
  list-style: disc;
}

/* ---------- Level test ---------- */
.level-q {
  border: 1px solid var(--line);
  border-radius: var(--radius-sm);
  padding: 1rem 1.15rem;
  margin-bottom: 0.85rem;
}
.level-q legend {
  font-weight: 600;
  padding: 0 0.35rem;
  color: var(--orange);
}
.level-q label {
  display: block;
  padding: 0.4rem 0;
  cursor: pointer;
  font-weight: 500;
}
.level-q input { margin-inline-end: 0.45rem; }

/* ---------- Auth / admin simple ---------- */
.auth-wrap {
  min-height: 70vh;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 2rem 0;
}
.auth-card { width: min(400px, 100%); }

/* Mobile nav collapse hint */
@media (max-width: 960px) {
  .nav-links { max-width: 100%; }
  .navbar { gap: 0.5rem; }
}



/* =========================================================
   Apple iOS Liquid Glass (iOS 26 Style)
   High-grade frosted refraction, specular sheen, dynamic
   cursor spotlight, chromatic lens edge, and ambient depth.
   Brand orange & amber preserved; minimal & ultra-clean.
   ========================================================= */

:root {
  --lg-bg: rgba(255, 255, 255, 0.58);
  --lg-bg-strong: rgba(255, 255, 255, 0.78);
  --lg-border: rgba(255, 255, 255, 0.75);
  --lg-border-subtle: rgba(255, 255, 255, 0.35);
  --lg-border-outer: rgba(31, 44, 67, 0.08);
  --lg-shadow: 0 10px 30px -6px rgba(31, 44, 67, 0.06), 0 2px 6px -1px rgba(31, 44, 67, 0.04);
  --lg-shadow-hover: 0 20px 45px -8px rgba(31, 44, 67, 0.11), 0 8px 18px -2px rgba(238, 99, 52, 0.08);
  --lg-blur: blur(24px) saturate(180%) brightness(106%);
  --lg-blur-subtle: blur(14px) saturate(150%);
  --lg-radius: 22px;
  /* More opaque than --lg-bg-strong, used only for the mobile slide-down
     nav panel — that panel sits over page content/photos, so it needs
     to read as a solid menu, not a see-through sheet. Pushed close to
     fully solid (was 0.97) and paired with a lighter, non-brightening
     blur so the page content behind it no longer shows through. */
  --nav-menu-bg: rgba(255, 255, 255, 0.99);
  --nav-menu-blur: blur(20px) saturate(120%);
}

[data-theme='dark'] {
  --lg-bg: rgba(24, 21, 20, 0.62);
  --lg-bg-strong: rgba(30, 27, 25, 0.82);
  --nav-menu-bg: rgba(20, 17, 16, 0.99);
  --lg-border: rgba(255, 255, 255, 0.16);
  --lg-border-subtle: rgba(255, 255, 255, 0.08);
  --lg-border-outer: rgba(255, 255, 255, 0.07);
  --lg-shadow: 0 14px 40px -8px rgba(0, 0, 0, 0.52), 0 2px 8px rgba(0, 0, 0, 0.3);
  --lg-shadow-hover: 0 24px 55px -10px rgba(0, 0, 0, 0.7), 0 8px 24px -2px rgba(238, 99, 52, 0.2);
  --lg-blur: blur(26px) saturate(180%) brightness(110%);
}

/* ---- PERF (per request — "the phone heats up and gets slow, the site
   should be smooth; reduce animations as much as reasonable"): a handful
   of sitewide decorative effects were fine on a desktop GPU but kept the
   mobile compositor permanently busy — continuous CSS animation forces a
   repaint every single frame for as long as the tab stays open, and a
   few of these run on EVERY page, forever, whether or not anyone is
   even looking at them. That sustained, never-idle GPU work is exactly
   what shows up as a phone getting hot and sluggish. None of this
   touches desktop/mouse users, and reduced-motion users already get an
   even stronger version of this via the prefers-reduced-motion rules
   already in place elsewhere in this file. ---- */
@media (pointer: coarse), (max-width: 782px) {
  /* By far the single biggest cost: 4 full-viewport, heavily blurred
     (75-90px) background orbs with mix-blend-mode, continuously
     transform-animated on every page for as long as it stays open.
     Freezing the animation keeps the exact same look (a soft blurred
     color wash behind the page) with none of the ongoing per-frame
     compositor cost. Also trimming the blur radius itself: a fixed-
     position, blend-mode layer this large can force a full repaint (not
     just a cheap re-composite) on scroll on some Android GPUs, and a
     smaller blur is noticeably lighter to paint while still reading as
     a soft color wash. */
  .liquid-orb { animation: none !important; filter: blur(40px); }
  [data-theme='dark'] .liquid-orb { filter: blur(50px); }

  /* Backdrop blur ("glass") is one of the most GPU-expensive effects on
     a phone, especially repeated across many cards on one screen and
     recomposited on every scroll frame. Nearly every glass surface
     site-wide reads its blur from these shared custom properties, so
     lowering them here quietly lightens all of them at once instead of
     hunting down every individual rule. */
  :root {
    --lg-blur: blur(10px) saturate(140%);
    --lg-blur-subtle: blur(8px) saturate(130%);
    --nav-menu-blur: blur(10px) saturate(110%);
    --header-blur: 14px;
  }

  /* Small always-on flashing/pulsing/sweeping touches, sitewide —
     individually cheap, but each is one more layer the compositor can
     never let go idle, and none of them carry real information (pure
     decoration). Everything still renders normally, just still. */
  .kicker::before,
  .floater,
  .header-logo-shine .logo-mark::after,
  .network-lines path,
  .network-pulse-ring {
    animation: none !important;
  }

  /* The homepage hero banner auto-rotates every few seconds (see app.js)
     — every rotation recomposites its 30px backdrop blur across the
     full-width slide, on the very first screen every visitor lands on.
     A lighter blur here keeps the frosted-glass look with a much
     cheaper repaint each time it advances. */
  .hero-slider .slide {
    backdrop-filter: blur(12px) saturate(150%) !important;
    -webkit-backdrop-filter: blur(12px) saturate(150%) !important;
  }
}

/* ---- Ultra-lightweight Top Page Loader (Zero CPU overhead) ---- */
.sd-top-loader {
  position: fixed;
  top: 0;
  left: 0;
  right: 0;
  height: 3.5px;
  z-index: 9999;
  pointer-events: none;
  overflow: hidden;
  background: transparent;
}
.sd-loader-bar {
  width: 0%;
  height: 100%;
  background: linear-gradient(90deg, #EE6334 0%, #F1825C 45%, #10b981 100%);
  box-shadow: 0 0 12px rgba(16, 185, 129, 0.8), 0 0 6px rgba(238, 99, 52, 0.6);
  transition: width 0.3s cubic-bezier(0.1, 0.9, 0.2, 1), opacity 0.4s ease;
  animation: initialLoadPulse 1.2s ease-out forwards;
}
@keyframes initialLoadPulse {
  0% { width: 0%; opacity: 1; }
  35% { width: 60%; opacity: 1; }
  75% { width: 85%; opacity: 1; }
  100% { width: 92%; opacity: 1; }
}
body.is-ready .sd-loader-bar {
  width: 100% !important;
  opacity: 0;
  transition: width 0.2s ease, opacity 0.4s ease 0.25s;
}

/* Floating Ambient Light Mesh Background */
.liquid-ambient-mesh {
  position: fixed;
  inset: 0;
  pointer-events: none;
  z-index: -1;
  overflow: hidden;
  opacity: 0.85;
  transform: translate3d(0, 0, 0);
}

.liquid-orb {
  position: absolute;
  border-radius: 50%;
  filter: blur(75px);
  opacity: 0.55;
  mix-blend-mode: multiply;
  pointer-events: none;
  animation: floatOrb 22s cubic-bezier(0.4, 0, 0.2, 1) infinite alternate;
  transform: translate3d(0, 0, 0);
  will-change: transform;
}

[data-theme='dark'] .liquid-orb {
  mix-blend-mode: screen;
  opacity: 0.28;
  filter: blur(90px);
}

.orb-1 {
  top: -120px;
  inset-inline-start: -80px;
  width: 520px;
  height: 520px;
  background: radial-gradient(circle, rgba(251, 191, 36, 0.35) 0%, rgba(245, 158, 11, 0.15) 55%, transparent 70%);
  animation-duration: 24s;
}

.orb-2 {
  top: 15%;
  inset-inline-end: -100px;
  width: 580px;
  height: 580px;
  background: radial-gradient(circle, rgba(238, 99, 52, 0.22) 0%, rgba(251, 146, 60, 0.1) 60%, transparent 75%);
  animation-duration: 28s;
  animation-delay: -7s;
}

.orb-3 {
  bottom: 5%;
  inset-inline-start: 25%;
  width: 480px;
  height: 480px;
  background: radial-gradient(circle, rgba(253, 186, 116, 0.3) 0%, rgba(238, 99, 52, 0.12) 55%, transparent 70%);
  animation-duration: 32s;
  animation-delay: -14s;
}

.orb-emerald {
  bottom: 22%;
  inset-inline-end: -60px;
  width: 460px;
  height: 460px;
  background: radial-gradient(circle, rgba(5, 150, 105, 0.24) 0%, rgba(6, 95, 70, 0.08) 55%, transparent 70%);
  animation-duration: 26s;
  animation-delay: -10s;
}

@keyframes floatOrb {
  0% { transform: translate3d(0, 0, 0) scale(1); }
  50% { transform: translate3d(35px, 45px, 0) scale(1.08); }
  100% { transform: translate3d(-30px, 60px, 0) scale(0.95); }
}

@media (prefers-reduced-motion: reduce) {
  .liquid-orb { animation: none !important; }
}

body {
  background-color: var(--bg, #fafaf9);
  background-attachment: fixed;
}

/* Core liquid glass surface */
.glass, .glass-strong, .md-card, .panel-card, .form-card,
.book-card, .course-card, .teacher-card, .sample-card,
.service-card, .branch-card, .stat-card, .result-card, .slide,
.admin-side, .auth-card {
  background: var(--lg-bg);
  border: 1px solid var(--lg-border-outer);
  border-radius: var(--lg-radius);
  box-shadow:
    var(--lg-shadow),
    inset 0 1px 1px 0 var(--lg-border),
    inset 0 0 0 1px var(--lg-border-subtle),
    inset 0 -1px 2px 0 rgba(238, 99, 52, 0.04);
  backdrop-filter: var(--lg-blur);
  -webkit-backdrop-filter: var(--lg-blur);
  transition:
    transform 0.4s cubic-bezier(0.22, 1, 0.36, 1),
    box-shadow 0.4s cubic-bezier(0.22, 1, 0.36, 1),
    background 0.3s ease,
    border-color 0.3s ease;
}

.glass-strong, .slide, .form-card, .panel-card {
  background: var(--lg-bg-strong);
}

/* Apple-style Liquid Glass refraction & depth for hero slider */
.hero-slider {
  position: relative;
  isolation: isolate;
}
.hero-slider::before {
  content: "";
  position: absolute;
  inset: -20px;
  background: radial-gradient(circle at 30% 30%, rgba(251, 191, 36, 0.28), transparent 50%),
              radial-gradient(circle at 80% 70%, rgba(238, 99, 52, 0.2), transparent 55%);
  z-index: 0;
  pointer-events: none;
  filter: blur(40px);
  opacity: 0.85;
}
.hero-slider .slide {
  background: linear-gradient(135deg, rgba(255, 255, 255, 0.82) 0%, rgba(255, 255, 255, 0.52) 100%);
  backdrop-filter: blur(30px) saturate(180%) brightness(108%);
  -webkit-backdrop-filter: blur(30px) saturate(180%) brightness(108%);
  border: 1px solid rgba(255, 255, 255, 0.9);
  box-shadow: 
    0 24px 60px -12px rgba(31, 44, 67, 0.12),
    inset 0 1.5px 1.5px 0 rgba(255, 255, 255, 0.95),
    inset 0 0 0 1px rgba(255, 255, 255, 0.4),
    inset 0 -1px 3px 0 rgba(238, 99, 52, 0.08);
  border-radius: 28px;
  position: relative;
  overflow: hidden;
  transition: transform 0.5s cubic-bezier(0.22, 1, 0.36, 1), box-shadow 0.5s cubic-bezier(0.22, 1, 0.36, 1);
}
.hero-slider .slide::after {
  content: "";
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
  height: 52%;
  background: linear-gradient(180deg, rgba(255, 255, 255, 0.5) 0%, rgba(255, 255, 255, 0) 100%);
  pointer-events: none;
  border-top-left-radius: 28px;
  border-top-right-radius: 28px;
}
[data-theme='dark'] .hero-slider .slide {
  background: linear-gradient(135deg, rgba(38, 33, 30, 0.82) 0%, rgba(24, 21, 20, 0.6) 100%);
  border: 1px solid rgba(255, 255, 255, 0.16);
  box-shadow: 
    0 24px 60px -12px rgba(0, 0, 0, 0.6),
    inset 0 1.5px 1.5px 0 rgba(255, 255, 255, 0.25),
    inset 0 0 0 1px rgba(255, 255, 255, 0.08),
    inset 0 -1px 3px 0 rgba(238, 99, 52, 0.18);
}
[data-theme='dark'] .hero-slider .slide::after {
  background: linear-gradient(180deg, rgba(255, 255, 255, 0.1) 0%, rgba(255, 255, 255, 0) 100%);
}

.service-card:hover, .course-card:hover, .teacher-card:hover,
.sample-card:hover, .book-card:hover, .branch-card:hover, .md-card:hover {
  transform: translateY(-5px) scale(1.01);
  box-shadow: var(--lg-shadow-hover), inset 0 1px 1.5px 0 var(--lg-border);
  border-color: rgba(238, 99, 52, 0.22);
}
/* Light theme: a near-opaque white hover tint reads fine because the page
   background is also light. */
[data-theme='light'] .service-card:hover,
[data-theme='light'] .course-card:hover,
[data-theme='light'] .teacher-card:hover,
[data-theme='light'] .sample-card:hover,
[data-theme='light'] .book-card:hover,
[data-theme='light'] .branch-card:hover,
[data-theme='light'] .md-card:hover {
  background: rgba(255, 255, 255, 0.84);
}
/* FIXED (dark-mode hover contrast): the rule above used to apply
   everywhere with no theme scoping, so in dark mode EVERY one of these
   cards flashed to an almost-white background on hover, and this override
   only listed 3 of the 7 affected classes (teacher/sample/book/branch were
   missing) — those four stayed washed-out and unreadable. Every card type
   now gets the same dark, low-opacity tint on hover instead of white. */
[data-theme='dark'] .service-card:hover,
[data-theme='dark'] .course-card:hover,
[data-theme='dark'] .teacher-card:hover,
[data-theme='dark'] .sample-card:hover,
[data-theme='dark'] .book-card:hover,
[data-theme='dark'] .branch-card:hover,
[data-theme='dark'] .md-card:hover {
  background: rgba(44, 39, 36, 0.88);
}

/* Header — liquid floating bar */
.site-header {
  background: rgba(250, 250, 249, var(--header-alpha, 0.92)) !important;
  backdrop-filter: blur(var(--header-blur, 24px)) saturate(1.8) brightness(1.05) !important;
  -webkit-backdrop-filter: blur(var(--header-blur, 24px)) saturate(1.8) brightness(1.05) !important;
  border-bottom: 1px solid rgba(31, 44, 67, var(--header-border-alpha, 0.06)) !important;
  box-shadow: 0 1px 0 rgba(255, 255, 255, 0.75) inset, 0 8px 24px -6px rgba(31, 44, 67, 0.04);
}
[data-theme='dark'] .site-header {
  background: rgba(14, 12, 11, var(--header-alpha, 0.92)) !important;
  border-bottom-color: rgba(255, 255, 255, var(--header-border-alpha-dark, 0.08)) !important;
  box-shadow: 0 1px 0 rgba(255, 255, 255, 0.12) inset, 0 8px 24px -6px rgba(0, 0, 0, 0.4);
}
.site-header.scrolled {
  --header-alpha: 0.98;
  --header-blur: 28px;
  --header-border-alpha: 0.08;
  --header-border-alpha-dark: 0.12;
}

/* Nav pills */
.nav-link {
  border-radius: 999px;
  position: relative;
  transition: background 0.25s ease, color 0.25s ease, box-shadow 0.25s ease, transform 0.2s ease;
}
.nav-link:hover, .nav-link.active {
  background: rgba(238, 99, 52, 0.12);
  color: var(--orange, #EE6334);
  box-shadow: inset 0 1px 1px rgba(255, 255, 255, 0.6), inset 0 0 0 1px rgba(238, 99, 52, 0.15);
}
[data-theme='dark'] .nav-link:hover,
[data-theme='dark'] .nav-link.active {
  box-shadow: inset 0 1px 1px rgba(255, 255, 255, 0.15), inset 0 0 0 1px rgba(238, 99, 52, 0.25);
}

/* Header brand buttons — LIMS / Sign-up / Bookstore.
   FIXED (per explicit request): all three now share one fixed shape and
   size and a short, constant label each — the same on phones and on
   desktop, with no responsive shrinking or label-swapping. This
   supersedes the old .btn-lims-liquid/.btn-signup-liquid setup, which
   had two DIFFERENT "shrink the label" breakpoints (520px vs 900px)
   that didn't line up — that mismatch was the root cause of a header
   overflow bug found in QA (between 520–900px wide, LIMS had shrunk but
   sign-up hadn't, so the combined row no longer fit and pushed the
   theme/EN/login controls off-screen). Removing responsive text entirely
   removes that whole bug class. .brand-buttons (the wrapper) is the
   safety net now: on narrow screens the trio simply wraps onto its own
   row instead of any button changing size or text. */
.brand-buttons {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0.5rem;
}
.btn-header-pill {
  display: inline-flex;
  align-items: center;
  gap: 0.4rem;
  font-weight: 700 !important;
  font-size: 0.8rem !important;
  padding: 0.38rem 0.85rem !important;
  border-radius: 999px !important;
  border: 1px solid rgba(255, 255, 255, 0.45) !important;
  color: #ffffff !important;
  backdrop-filter: blur(12px);
  -webkit-backdrop-filter: blur(12px);
  white-space: nowrap;
  transition: transform 0.25s var(--ease), box-shadow 0.25s var(--ease), background 0.25s ease !important;
}
.btn-header-pill:hover {
  transform: translateY(-2px) scale(1.03) !important;
}

/* Compact variant used only inside .mobile-header-bar (see below) — the
   same three buttons, small enough to sit next to the login/theme/lang
   icons on one line without overflowing a phone-width container. */
.btn-header-pill--xs {
  gap: 0.25rem;
  font-size: 0.68rem !important;
  padding: 0.3rem 0.55rem !important;
}
.btn-header-pill--xs i { font-size: 0.72rem; }

/* LIMS — purple */
.btn-lims-liquid {
  background: linear-gradient(135deg, rgba(109, 40, 217, 0.92) 0%, rgba(124, 58, 237, 0.95) 100%) !important;
  box-shadow: 0 4px 14px rgba(109, 40, 217, 0.35), inset 0 1px 1.5px rgba(255, 255, 255, 0.65), inset 0 0 0 1px rgba(167, 139, 250, 0.3) !important;
}
.btn-lims-liquid:hover {
  background: linear-gradient(135deg, rgba(124, 58, 237, 0.98) 0%, rgba(139, 92, 246, 1) 100%) !important;
  box-shadow: 0 6px 20px rgba(109, 40, 217, 0.48), inset 0 1px 2px rgba(255, 255, 255, 0.85) !important;
}

/* Sign-up — green */
.btn-signup-liquid {
  background: linear-gradient(135deg, rgba(5, 150, 105, 0.92) 0%, rgba(16, 185, 129, 0.95) 100%) !important;
  box-shadow: 0 4px 14px rgba(5, 150, 105, 0.35), inset 0 1px 1.5px rgba(255, 255, 255, 0.65), inset 0 0 0 1px rgba(110, 231, 183, 0.3) !important;
}
.btn-signup-liquid:hover {
  background: linear-gradient(135deg, rgba(4, 120, 87, 0.98) 0%, rgba(5, 150, 105, 1) 100%) !important;
  box-shadow: 0 6px 20px rgba(5, 150, 105, 0.48), inset 0 1px 2px rgba(255, 255, 255, 0.85) !important;
}

/* Bookstore — light orange leaning to yellow (amber/gold), the new third
   button per request ("نارنجی روشن مایل به زرد") */
.btn-bookstore-liquid {
  background: linear-gradient(135deg, rgba(245, 158, 11, 0.92) 0%, rgba(251, 191, 36, 0.95) 100%) !important;
  box-shadow: 0 4px 14px rgba(245, 158, 11, 0.35), inset 0 1px 1.5px rgba(255, 255, 255, 0.65), inset 0 0 0 1px rgba(253, 224, 71, 0.35) !important;
}
.btn-bookstore-liquid:hover {
  background: linear-gradient(135deg, rgba(217, 119, 6, 0.98) 0%, rgba(245, 158, 11, 1) 100%) !important;
  box-shadow: 0 6px 20px rgba(245, 158, 11, 0.48), inset 0 1px 2px rgba(255, 255, 255, 0.85) !important;
}

/* ---------- Nav "More" dropdown (About / Requests / Rules) ---------- */
.nav-dropdown { position: relative; }
.nav-dropdown-toggle {
  display: inline-flex;
  align-items: center;
  gap: 0.3rem;
  background: none;
  border: none;
  cursor: pointer;
  font-family: inherit;
}
.nav-dropdown-caret {
  font-size: 0.6rem;
  transition: transform 0.25s var(--ease);
}
.nav-dropdown.open .nav-dropdown-caret { transform: rotate(180deg); }
.nav-dropdown-menu {
  position: absolute;
  top: calc(100% + 0.5rem);
  inset-inline-start: 0;
  min-width: 170px;
  background: var(--card);
  border: 1px solid var(--line);
  border-radius: var(--radius-sm);
  box-shadow: var(--shadow-lg);
  padding: 0.4rem;
  display: none;
  flex-direction: column;
  gap: 0.1rem;
  z-index: 20;
}
.nav-dropdown.open .nav-dropdown-menu { display: flex; }
.nav-dropdown-menu li { width: 100%; }
.nav-dropdown-menu .nav-link { display: block; width: 100%; text-align: start; }
@media (max-width: 1300px) {
  /* Inside the mobile slide-down nav, the submenu should expand inline
     rather than float — there's no room for a floating popover there. */
  .nav-dropdown-menu {
    position: static;
    box-shadow: none;
    border: none;
    background: transparent;
    padding-inline-start: 0.75rem;
    margin-top: 0.15rem;
  }
  .nav-dropdown-toggle { width: 100%; justify-content: space-between; }
}


/* Buttons — soft liquid */
.btn-primary {
  background: linear-gradient(180deg, #f97316 0%, #EE6334 100%);
  border: 1px solid rgba(255, 255, 255, 0.35);
  box-shadow:
    0 4px 16px rgba(238, 99, 52, 0.35),
    inset 0 1px 1px rgba(255, 255, 255, 0.5),
    inset 0 -1px 2px rgba(0, 0, 0, 0.15);
}
.btn-primary:hover {
  background: linear-gradient(180deg, #fb923c 0%, #D14211 100%);
  box-shadow:
    0 8px 24px rgba(238, 99, 52, 0.42),
    inset 0 1px 1.5px rgba(255, 255, 255, 0.6);
}
.btn-outline {
  background: rgba(255, 255, 255, 0.52);
  backdrop-filter: var(--lg-blur-subtle);
  -webkit-backdrop-filter: var(--lg-blur-subtle);
  border: 1px solid rgba(31, 44, 67, 0.1);
  box-shadow:
    inset 0 1px 1px rgba(255, 255, 255, 0.7),
    inset 0 0 0 1px rgba(255, 255, 255, 0.25),
    0 2px 6px rgba(31, 44, 67, 0.03);
}
.btn-outline:hover {
  border-color: rgba(31, 44, 67, 0.35);
  color: var(--navy, #1F2C43);
  background: rgba(255, 255, 255, 0.8);
  box-shadow:
    inset 0 1px 1.5px rgba(255, 255, 255, 0.8),
    0 6px 18px rgba(31, 44, 67, 0.14);
}
[data-theme='dark'] .btn-outline {
  background: rgba(36, 32, 30, 0.65);
  border-color: rgba(255, 255, 255, 0.12);
  box-shadow: inset 0 1px 1px rgba(255, 255, 255, 0.15);
}
[data-theme='dark'] .btn-outline:hover {
  background: rgba(48, 42, 40, 0.8);
}

/* Icon button tactile glass */
.icon-btn.glass {
  background: rgba(255, 255, 255, 0.55);
  backdrop-filter: var(--lg-blur-subtle);
  -webkit-backdrop-filter: var(--lg-blur-subtle);
  border: 1px solid rgba(31, 44, 67, 0.08);
  box-shadow: inset 0 1px 1px rgba(255, 255, 255, 0.75), 0 2px 8px rgba(31, 44, 67, 0.04);
}
.icon-btn.glass:hover {
  background: rgba(255, 255, 255, 0.85);
  border-color: rgba(238, 99, 52, 0.35);
  transform: translateY(-2px) scale(1.05);
  box-shadow: 0 6px 16px rgba(238, 99, 52, 0.12), inset 0 1px 1px rgba(255, 255, 255, 0.9);
}
[data-theme='dark'] .icon-btn.glass {
  background: rgba(36, 32, 30, 0.65);
  border-color: rgba(255, 255, 255, 0.12);
  box-shadow: inset 0 1px 1px rgba(255, 255, 255, 0.15);
}
[data-theme='dark'] .icon-btn.glass:hover {
  background: rgba(48, 42, 40, 0.85);
}

/* Inputs on glass */
.field, .stack-form input, .stack-form select, .stack-form textarea,
.newsletter-form input {
  background: rgba(255, 255, 255, 0.55);
  border: 1px solid rgba(31, 44, 67, 0.1);
  box-shadow: inset 0 1px 2px rgba(31, 44, 67, 0.04), inset 0 1px 0 rgba(255, 255, 255, 0.6);
  backdrop-filter: var(--lg-blur-subtle);
  -webkit-backdrop-filter: var(--lg-blur-subtle);
}
.field:focus, .stack-form input:focus, .stack-form select:focus,
.stack-form textarea:focus, .newsletter-form input:focus {
  border-color: rgba(238, 99, 52, 0.5);
  box-shadow: 0 0 0 4px rgba(238, 99, 52, 0.14), inset 0 1px 2px rgba(31, 44, 67, 0.04), inset 0 1px 0 rgba(255, 255, 255, 0.8);
  background: rgba(255, 255, 255, 0.88);
}
[data-theme='dark'] .field,
[data-theme='dark'] .stack-form input,
[data-theme='dark'] .stack-form select,
[data-theme='dark'] .stack-form textarea,
[data-theme='dark'] .newsletter-form input {
  background: rgba(30, 27, 25, 0.65);
  border-color: rgba(255, 255, 255, 0.12);
  box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.3);
}
[data-theme='dark'] .field:focus,
[data-theme='dark'] .stack-form input:focus,
[data-theme='dark'] .stack-form select:focus,
[data-theme='dark'] .stack-form textarea:focus,
[data-theme='dark'] .newsletter-form input:focus {
  background: rgba(38, 34, 32, 0.9);
  border-color: rgba(238, 99, 52, 0.6);
}

/* Restore brand orange accents (undo blue) */
.kicker { color: var(--orange, #EE6334) !important; }
.service-icon {
  background: rgba(238, 99, 52, 0.12) !important;
  color: var(--orange, #EE6334) !important;
  border: 1px solid rgba(255, 255, 255, 0.5);
  box-shadow: inset 0 1px 1px rgba(255, 255, 255, 0.6), 0 4px 12px rgba(238, 99, 52, 0.08);
}
.badge {
  background: rgba(238, 99, 52, 0.12) !important;
  color: #D14211 !important;
  border: 1px solid rgba(238, 99, 52, 0.2);
}
.stat-card strong { color: var(--orange, #EE6334) !important; }

/* Footer — the site's closing "general info" band (contact, links, legal).
   FIXED: recolored from the solid navy band to the requested cool "ice"
   tone (#E0E6ED — same value as the --ice brand variable already used for
   soft section backgrounds elsewhere), in both light and dark mode, so
   this band reads the same everywhere. The --text/--muted/--line/--card
   custom properties below are scoped to .site-footer, so every element
   inside it (footer cards, headings, links, contact list) automatically
   switches from "light text on navy" to "dark text on ice" with them. */
.site-footer {
  --text: var(--navy);
  --muted: var(--slate);
  --line: rgba(31, 44, 67, 0.12);
  --card: #ffffff;
  --bg-soft: rgba(31, 44, 67, 0.04);
  background: var(--ice);
  backdrop-filter: none;
  -webkit-backdrop-filter: none;
  border-top: none;
  color: var(--text);
}
[data-theme='dark'] .site-footer {
  background: var(--ice);
}
.footer-newsletter {
  background: rgba(31, 44, 67, 0.03) !important;
  border-bottom: 1px solid rgba(31, 44, 67, 0.1) !important;
}
[data-theme='dark'] .footer-newsletter {
  border-bottom-color: rgba(31, 44, 67, 0.08) !important;
}
.site-footer .footer-contact i { background: rgba(238, 99, 52, 0.18); }
.site-footer .social-btn { background: rgba(238, 99, 52, 0.16); }
.site-footer .footer-card:hover { border-color: rgba(238, 99, 52, 0.3); }
/* The newsletter <input> above normally gets dark-theme colors (dark,
   near-opaque background) from the generic `.field`/`.newsletter-form
   input` dark-theme rule earlier in this file. Since the footer is now
   always the light "ice" tone regardless of theme, force that one field
   back to light styling here too, so its text stays readable instead of
   dark navy on a near-black box. */
[data-theme='dark'] .site-footer .newsletter-form input {
  background: rgba(255, 255, 255, 0.65) !important;
  border-color: rgba(31, 44, 67, 0.12) !important;
  box-shadow: inset 0 1px 2px rgba(31, 44, 67, 0.04) !important;
}
[data-theme='dark'] .site-footer .newsletter-form input:focus {
  background: rgba(255, 255, 255, 0.92) !important;
  border-color: rgba(238, 99, 52, 0.5) !important;
}

/* Chat + sticky stay consistent */
/* FIXED (per request): the chat panel used the same translucent
   --lg-bg-strong (0.78 alpha) as decorative cards — fine for a card that's
   just ambiance, but here the page content behind it (footer newsletter
   field, sticky-enroll button, etc.) showed through enough that the
   pre-chat name/phone inputs looked like they were "behind a layer" —
   hard to tell the widget's own fields apart from the page ghosting
   through. A form people actually type into needs a near-opaque backing,
   not a light frost, so this overrides the shared glass background with a
   much more solid one specifically for the chat panel. */
.sd-chat-panel {
  background: var(--sd-chat-panel-bg, rgba(255, 255, 255, 0.97)) !important;
  backdrop-filter: blur(20px) saturate(160%) !important;
  -webkit-backdrop-filter: blur(20px) saturate(160%) !important;
  border: 1px solid var(--lg-border-outer) !important;
  box-shadow: var(--lg-shadow-hover) !important;
  isolation: isolate;
}
[data-theme='dark'] .sd-chat-panel {
  --sd-chat-panel-bg: rgba(27, 33, 48, 0.97);
}
/* Belt-and-braces: give every section of the panel its own solid
   background too, so nothing behind the panel can bleed through the
   messages list or the pre-chat/chat forms even if the blur above is
   ever changed. */
.sd-chat-messages, .sd-chat-form, .sd-chat-precontact {
  background: var(--card);
  position: relative;
  z-index: 1;
}
.sd-chat-form input, .sd-chat-precontact input {
  background: var(--card) !important;
  position: relative;
  z-index: 2;
}
.social-btn {
  background: rgba(255, 255, 255, 0.52);
  backdrop-filter: blur(12px);
  border: 1px solid rgba(31, 44, 67, 0.08);
  box-shadow: inset 0 1px 1px rgba(255, 255, 255, 0.6);
}
.social-btn:hover {
  background: var(--orange, #EE6334);
  color: #fff;
  border-color: transparent;
  transform: translateY(-2px);
}

/* Admin liquid */
.admin-side a:hover, .admin-side a.active {
  background: rgba(238, 99, 52, 0.12);
  color: var(--orange, #EE6334);
}

/* =========================================================
   Task 1 — Front-end bug fixes + Liquid Glass enhancement
   ========================================================= */

/* ---- Global overflow / long-text safety net ----
   IMPORTANT: this must NOT be `overflow-x: hidden`. Setting overflow-x to
   anything other than `visible` forces the *other* axis (overflow-y) to
   compute as `auto` too (that's spec behaviour, not a typo) — which turns
   <body>/<html> into their own scroll container and silently breaks
   `position: sticky` on the header everywhere in the site (confirmed with
   an automated scroll test: the header scrolled off-screen with the page
   instead of sticking). `overflow-x: clip` gives the same "never scroll
   sideways" guarantee without claiming the y-axis, so the sticky header
   keeps working. */
html, body { max-width: 100%; overflow-x: clip; }
h1, h2, h3, h4, p, a, span, li, label, .btn, .badge, .kicker {
  overflow-wrap: break-word;
  word-break: break-word;
}
.container { max-width: 100%; }
pre, code { white-space: pre-wrap; word-break: break-word; }
table { max-width: 100%; }
.table-scroll { width: 100%; overflow-x: auto; -webkit-overflow-scrolling: touch; }

/* ==========================================================================
   Header layout — .nav-actions / .nav-menu / .hamburger
   ==========================================================================
   .navbar is one flex row: [brand-group] [sep] [nav-menu] [sep] [nav-actions]
   [hamburger]. .nav-menu is the "separated space" bounded by the two
   .header-sep dividers — it holds the 5-item pill row on desktop. Below the
   collapse breakpoint the pills fade out, .nav-menu turns into an
   off-flow slide-down panel, and .hamburger — a normal in-flow flex item —
   grows to fill exactly the space .nav-menu vacated and centers its
   "منو" label + icon inside it. Because that's plain flexbox (not
   position:absolute + math against the whole header), the trigger can
   physically never render outside that divider-to-divider slot.
   ========================================================================== */

/* ---------- Class rules (base / desktop state) ---------- */

.nav-actions {
  display: flex;
  align-items: center;
  gap: 0.45rem;
  flex-shrink: 0;
  position: relative;
  z-index: 2;
}

/* Phone-only combined bar (login/theme/lang + the three brand buttons) —
   hidden by default; only shown below the @media (max-width: 600px)
   phone breakpoint, where it replaces .nav-actions. See there for the
   full rule set and the reasoning. */
.mobile-header-bar { display: none; }

/* Signed-in role indicator, shown in the header corner next to the
   dashboard/logout icons (per request: "indicate it is site admin in the
   corner" / "for bookstore it should show bookstore account"). Sits in
   .nav-actions, which — being the last flex child in this RTL layout —
   is already the left-most group in the header, so the logout button
   right after it lands "in the left" as requested. */
.header-role-chip {
  display: inline-flex;
  align-items: center;
  gap: 0.35rem;
  padding: 0.35rem 0.7rem;
  border-radius: 999px;
  font-size: 0.78rem;
  font-weight: 600;
  white-space: nowrap;
  color: var(--brand-orange);
  background: rgba(238, 99, 52, 0.1);
  border: 1px solid rgba(238, 99, 52, 0.25);
}
.header-role-chip i { font-size: 0.85em; }

.header-logout-btn:hover {
  border-color: #dc2626;
  color: #dc2626;
}

@media (max-width: 720px) {
  .header-role-chip span,
  .header-role-chip { font-size: 0.7rem; padding: 0.3rem 0.55rem; }
}

.nav-menu {
  display: flex;
  min-width: 0;
  flex: 1 1 auto;
}

/* Two separate nav-link lists live inside .nav-menu: a 5-item "essentials"
   row for PC browsers (with a "بیشتر" dropdown holding everything else),
   and a flat, full list for the mobile/tablet slide-down panel. Only one
   is shown at a time — see the collapse breakpoint below. */
.nav-links--mobile { display: none; }

/* The base .nav-links has overflow-x: auto for horizontal scrolling when
   space is tight, but per spec that silently forces overflow-y to "auto"
   too — which clips the absolutely-positioned "بیشتر" dropdown panel.
   The desktop row only ever holds 5 items + the dropdown trigger, so it
   never needs to scroll; let its dropdown escape the row instead. */
.nav-links--desktop { overflow: visible; }

/* Vertical dividers between the header's four groups: logo — LIMS/register —
   menu links — action buttons (theme/lang/login/hamburger). Each is a plain
   flex sibling so existing row `gap` already spaces it from its neighbours;
   align-self: stretch makes it span the row's own height automatically. */
.header-sep {
  width: 1px;
  align-self: stretch;
  margin-block: 0.4rem;
  background: var(--line);
  flex-shrink: 0;
}
[data-theme='dark'] .header-sep { background: rgba(255, 255, 255, 0.14); }

.lang-btn { font-weight: 700; font-size: 0.8rem; }
.btn-ghost {
  background: transparent;
  border: 1px solid transparent;
  color: var(--muted);
}
.btn-ghost:hover { background: rgba(238, 99, 52, 0.08); color: var(--orange); border-color: transparent; }

/* Hamburger / pulldown trigger — hidden entirely on desktop. Row layout:
   "منو" label beside a small stacked-line icon, the pair centered as a
   unit once the button is allowed to grow (see media query). */
.hamburger {
  display: none;
  align-items: center;
  justify-content: center;
  gap: 0.5rem;
  min-width: 0;
  padding: 0.45rem 0.9rem;
  border: 1px solid var(--lg-border-outer, var(--line));
  border-radius: 999px;
  background: var(--lg-bg, var(--card));
  backdrop-filter: var(--lg-blur, none);
  -webkit-backdrop-filter: var(--lg-blur, none);
  cursor: pointer;
  transition: background 0.2s var(--ease), border-color 0.2s var(--ease);
}
.hamburger:hover { border-color: rgba(238, 99, 52, 0.35); }

.hamburger-label {
  font-size: 0.8rem;
  font-weight: 600;
  color: var(--text);
  white-space: nowrap;
}

.hamburger-icon {
  display: flex;
  flex-direction: column;
  justify-content: center;
  align-items: center;
  gap: 4px;
  width: 18px;
  height: 14px;
  flex-shrink: 0;
}
.hamburger-icon span {
  display: block;
  width: 18px;
  height: 2px;
  border-radius: 2px;
  background: var(--text);
  transition: transform 0.28s var(--ease), opacity 0.2s var(--ease);
}
.hamburger.active .hamburger-icon span:nth-child(1) { transform: translateY(6px) rotate(45deg); }
.hamburger.active .hamburger-icon span:nth-child(2) { opacity: 0; }
.hamburger.active .hamburger-icon span:nth-child(3) { transform: translateY(-6px) rotate(-45deg); }

@keyframes hamburgerFadeIn {
  from { opacity: 0; transform: scale(0.92); }
  to   { opacity: 1; transform: scale(1); }
}

/* ---------- Media-query fallback (collapsed / narrow state) ---------- */

@media (max-width: 1300px) {
  .navbar { flex-wrap: nowrap; }

  /* Below this width the menu links collapse into a dropdown under the
     header, so the line right before .nav-actions would otherwise sit
     directly next to the logo/menu divider. Keep just that one. */
  .header-sep--menu-actions { display: none; }

  .nav-links--desktop { display: none; }
  .nav-links--mobile { display: flex; }

  /* .nav-menu leaves normal flow to become the full-width slide-down
     panel — this is what frees up its slot for .hamburger to fill. */
  .nav-menu {
    position: absolute;
    inset-inline: 0;
    top: 100%;
    display: block;
    max-height: 0;
    overflow: hidden;
    background: var(--nav-menu-bg, var(--lg-bg-strong, var(--card)));
    backdrop-filter: var(--nav-menu-blur, var(--lg-blur, none));
    -webkit-backdrop-filter: var(--nav-menu-blur, var(--lg-blur, none));
    border-bottom: 1px solid var(--lg-border-outer, var(--line));
    box-shadow: var(--lg-shadow, var(--shadow));
    transition: max-height 0.35s var(--ease);
    /* Sits above .nav-actions and the hamburger so the open dropdown's
       links are never painted underneath those buttons. */
    z-index: 5;
  }
  .nav-menu.active { max-height: 70vh; overflow-y: auto; }

  /* Bottom fade — only shown (via JS toggling .has-more-below) when the
     flat item list is actually taller than the panel, so short lists never
     get an inexplicable fade at the last item. */
  .nav-menu.active.has-more-below {
    -webkit-mask-image: linear-gradient(to bottom, #000 calc(100% - 28px), transparent 100%);
    mask-image: linear-gradient(to bottom, #000 calc(100% - 28px), transparent 100%);
  }

  /* Prevents the page behind the open slide-down panel from scrolling —
     set/cleared by app.js alongside .active so the two always match. */
  body.nav-open-lock { overflow: hidden; }

  /* Fills exactly the space .nav-menu vacated (it's the only remaining
     flex: 1 1 auto item between the two dividers), then centers its own
     label + icon inside that grown box — never outside it. */
  .hamburger {
    display: flex;
    flex: 1 1 auto;
    min-width: 0;
    animation: hamburgerFadeIn 0.3s var(--ease);
  }

  .nav-links {
    flex-direction: column;
    align-items: stretch;
    gap: 0.15rem;
    padding: 0.75rem 1.25rem 1.25rem;
  }
  .nav-link { display: block; padding: 0.65rem 0.85rem; }

  /* Buttons row stays on its own lower layer and keeps its normal size —
     the navbar height/min-height is untouched, only the stacking order
     changes so the dropdown menu below it is fully visible and clickable.
     order: 2 also places it after the hamburger visually, flush at the
     end of the row once the hamburger has grown to fill the middle. */
  .nav-actions { order: 2; z-index: 1; }

  /* FIXED (per request): the logged-out "ورود" (login) button used its
     normal full-size .btn.btn-primary.btn-sm styling here, which made it
     visibly larger than the round icon-btn language/theme buttons right
     next to it on phones — desktop was never affected since this whole
     block only applies below the nav collapse breakpoint. Matching it to
     the icon-btn footprint keeps all three controls the same size. */
  .nav-actions > a.btn.btn-primary.btn-sm {
    padding: 0 0.85rem !important;
    height: 40px;
    display: inline-flex;
    align-items: center;
    font-size: 0.8rem !important;
  }

  /* Staggered slide-in for mobile menu items (opt-in via JS index var --i) */
  .nav-menu .nav-links li {
    opacity: 0;
    transform: translateY(-8px);
    transition: opacity 0.35s var(--ease), transform 0.35s var(--ease);
    transition-delay: 0s;
  }
  .nav-menu.active .nav-links li {
    opacity: 1;
    transform: translateY(0);
    transition-delay: calc(var(--i, 0) * 45ms);
  }
}
/* Tablet: the LIMS/sign-up/bookstore trio now has a fixed size and label
   at every width (see .btn-header-pill above), so this breakpoint only
   still trims the small logo subtitle. */
@media (max-width: 900px) {
  .logo-text small { display: none; }
}
@media (max-width: 420px) {
  .logo-text small { display: none; }
  .header-actions, .nav-actions { gap: 0.3rem; }
  .icon-btn, .lang-btn { width: 34px; height: 34px; }
  .nav-actions > a.btn.btn-primary.btn-sm { height: 34px; padding: 0 0.65rem !important; }
  .logo-mark { width: 38px; height: 38px; }
  .navbar { gap: 0.5rem; }
}

/* ---- Header overflow fix (phones in portrait, e.g. Galaxy S24 FE) ----
   Bug: brand-group + the hamburger trigger + nav-actions (theme / EN-FA /
   login-logout) are all flex-shrink:0-ish fixed-width groups fighting for
   the same row. On a narrow phone their combined minimum width can exceed
   the viewport; since the row was flex-wrap:nowrap, the hamburger (the one
   item allowed to shrink) got crushed toward zero width instead — its
   icon+label no longer fit their own button and visibly overlapped — and
   whatever didn't fit (often nav-actions, i.e. the EN/FA switch and the
   login/logout button) was pushed off-screen, only reachable by scrolling
   the page sideways.
   Fix: nothing is hidden or removed — every control (theme, language,
   login/logout) stays exactly where it is functionally. Below this width
   the navbar is simply allowed to WRAP: brand-group + the hamburger share
   the first row (comfortably — with the sign-up button gone and the LIMS
   label already hidden well above this width, that first row is small),
   and nav-actions drops to its own full-width second row, centered, so
   every icon in it renders at full, untouched size with nothing clipped
   and no horizontal scroll needed to reach any of them. */
@media (max-width: 600px) {
  .navbar { flex-wrap: wrap; row-gap: 0.5rem; }
  .header-sep--menu-actions { display: none; }
  .hamburger { order: 1; }
  .nav-menu { order: 2; }

  /* FIXED (per request): at this width the logo + all three brand
     buttons (LIMS/sign-up/bookstore) no longer fit on one line, and
     whichever one didn't fit — usually bookstore — silently wrapped out
     of view. Hiding .brand-buttons here (its desktop/tablet instance,
     still nested in .brand-group) frees up enough room for the bare
     logo and the hamburger to comfortably share the first row, and
     .mobile-header-bar below takes over as the one place all three
     buttons — plus login/theme/language — live on phones. */
  .brand-buttons { display: none; }
  .nav-actions { display: none; }

  /* Replaces .nav-actions in this row's slot: login (icon-only), dark
     mode, language, a divider, then the three brand buttons at a
     smaller size — everything that used to be spread across two
     separate rows (one of them overflowing) now fits on one. */
  .mobile-header-bar {
    display: flex;
    order: 3;
    flex: 1 1 100%;
    align-items: center;
    justify-content: center;
    flex-wrap: wrap;
    gap: 0.5rem;
    padding-top: 0.5rem;
    border-top: 1px solid var(--line);
  }
  [data-theme='dark'] .mobile-header-bar { border-top-color: rgba(255, 255, 255, 0.14); }
  .mobile-header-controls {
    display: flex;
    align-items: center;
    gap: 0.45rem;
  }
  .mobile-header-divider {
    width: 1px;
    height: 22px;
    background: var(--line);
    flex-shrink: 0;
  }
  [data-theme='dark'] .mobile-header-divider { background: rgba(255, 255, 255, 0.14); }
  .mobile-header-buttons {
    display: flex;
    align-items: center;
    gap: 0.4rem;
    flex-wrap: wrap;
    justify-content: center;
  }
}


/* ---- Liquid glass depth: dynamic specular sheen & refraction hotspot ---- */
.glass, .glass-strong, .md-card, .panel-card, .form-card,
.book-card, .course-card, .teacher-card, .sample-card,
.service-card, .branch-card, .stat-card, .result-card, .slide,
.admin-side, .auth-card {
  position: relative;
  isolation: isolate;
  overflow: hidden;
}
.glass::before, .glass-strong::before, .md-card::before, .panel-card::before,
.form-card::before, .book-card::before, .course-card::before, .teacher-card::before,
.sample-card::before, .service-card::before, .branch-card::before, .stat-card::before,
.result-card::before, .slide::before, .admin-side::before, .auth-card::before {
  content: "";
  position: absolute;
  inset: 0;
  z-index: -1;
  border-radius: inherit;
  background:
    radial-gradient(circle 380px at var(--mx, 30%) var(--my, 20%), rgba(255, 255, 255, 0.45) 0%, rgba(255, 255, 255, 0.05) 45%, transparent 75%),
    linear-gradient(125deg, rgba(255, 255, 255, 0.65) 0%, rgba(255, 255, 255, 0) 32%);
  pointer-events: none;
  transition: opacity 0.4s ease;
}
/* FIXED (per request — dashboard screenshots): every ".admin-repeat-item"
   (hero slides, features, gallery, branches, teachers, samples — every
   repeater in the admin) carries the shared ".glass" class above, which
   sets "overflow: hidden" for its rounded-corner shine effect. That clips
   the floating "#N" / ID badge (.admin-repeat-index), which is deliberately
   positioned to poke out above the card's own top edge (top: -12px) — so
   the badge's top half was being cut off by its own card instead of
   floating cleanly on the border, reading as if it sat "underneath" the
   card below it. The shine pseudo-element just above now clips itself to
   the same rounded corners via "border-radius: inherit", so relaxing
   overflow here for repeat-item cards only doesn't let that pseudo-element
   spill out with square corners. */
.admin-repeat-item.glass { overflow: visible; }
[data-theme='dark'] .glass::before, [data-theme='dark'] .glass-strong::before,
[data-theme='dark'] .md-card::before, [data-theme='dark'] .panel-card::before,
[data-theme='dark'] .form-card::before, [data-theme='dark'] .book-card::before,
[data-theme='dark'] .course-card::before, [data-theme='dark'] .teacher-card::before,
[data-theme='dark'] .sample-card::before, [data-theme='dark'] .service-card::before,
[data-theme='dark'] .branch-card::before, [data-theme='dark'] .stat-card::before,
[data-theme='dark'] .result-card::before, [data-theme='dark'] .slide::before,
[data-theme='dark'] .admin-side::before, [data-theme='dark'] .auth-card::before {
  background:
    radial-gradient(circle 380px at var(--mx, 30%) var(--my, 20%), rgba(255, 255, 255, 0.16) 0%, rgba(255, 255, 255, 0.02) 45%, transparent 75%),
    linear-gradient(125deg, rgba(255, 255, 255, 0.16) 0%, rgba(255, 255, 255, 0) 32%);
}

/* Glossy sweep on buttons (liquid highlight) */
.btn-primary, .btn-outline {
  position: relative;
  overflow: hidden;
  isolation: isolate;
}
.btn-primary::after, .btn-outline::after {
  content: "";
  position: absolute;
  inset: 0;
  background: linear-gradient(115deg, rgba(255,255,255,0.55) 0%, rgba(255,255,255,0) 35%);
  pointer-events: none;
}

/* Visual frame liquid badge */
.visual-badge {
  background: rgba(255, 255, 255, 0.82) !important;
  backdrop-filter: var(--lg-blur) !important;
  -webkit-backdrop-filter: var(--lg-blur) !important;
  border: 1px solid rgba(255, 255, 255, 0.85) !important;
  box-shadow: 0 12px 32px -4px rgba(0, 0, 0, 0.12), inset 0 1px 1px 0 rgba(255, 255, 255, 0.9) !important;
}
[data-theme='dark'] .visual-badge {
  background: rgba(28, 25, 23, 0.82) !important;
  border: 1px solid rgba(255, 255, 255, 0.15) !important;
  box-shadow: 0 12px 32px -4px rgba(0, 0, 0, 0.6), inset 0 1px 1px 0 rgba(255, 255, 255, 0.2) !important;
}

/* Smoother glass edge on the header hairline */
.site-header { isolation: isolate; }

/* The shared .glass "sheen" utility (used by cards everywhere) sets
   position: relative + overflow: hidden. Since <header> also carries
   .glass, that was silently cancelling the header's sticky positioning
   and — critically — clipping the mobile nav dropdown, which needs to
   extend below the header via position:absolute/top:100%. That clipping
   is exactly why the "other pages" links were unreachable, hidden behind
   the theme/lang/login/hamburger row. Restore both, scoped to the header
   only, without touching the sheen effect anywhere else. */
.site-header.glass {
  position: sticky;
  top: 0;
  overflow: visible;
  /* The shared .glass card style rounds all four corners, but a
     full-width sticky header should never look rounded on one side
     only (it read as a stray rounded corner on the end edge). Keep
     the header perfectly square. */
  border-radius: 0 !important;
}

/* ---- Small-screen container breathing room ---- */
@media (max-width: 480px) {
  .container { width: min(1120px, calc(100% - 1.5rem)); }
  h1 { font-size: clamp(1.4rem, 7vw, 2rem); }
  .btn { padding: 0.65rem 1rem; font-size: 0.88rem; }
}

/* ---- Announcement bar: keep on one readable line, wrap gracefully ---- */
.announcement-bar p { max-width: 100%; }

/* ---- Stats / grids: guard against 1-column squeeze on very small phones ---- */
@media (max-width: 380px) {
  .stats { grid-template-columns: 1fr 1fr; }
}

/* =========================================================
   Task 2 — Admin Panel: professional CMS design system
   Inspired by EF Education First / Oxford UP / Pearson-style
   back-office dashboards: structured sidebar, data-dense but
   calm tables, clear typographic hierarchy, brand accent kept.
   ========================================================= */

:root {
  --admin-ink: #1F2C43;
  --admin-ink-soft: #52607A;
  --admin-line: rgba(31, 44, 67, 0.08);
  --admin-side-bg: linear-gradient(185deg, #141B28 0%, #1F2C43 55%, #2C3C58 100%);
  --admin-side-line: rgba(255, 255, 255, 0.08);
  --admin-side-text: rgba(255, 255, 255, 0.68);
  --admin-side-text-strong: #ffffff;
  --admin-surface: #ffffff;
  --admin-surface-soft: #F5F7FA;
  --admin-radius: 16px;
  --admin-side-accent: var(--orange);
}

/* ---------- Role-distinct sidebar palettes ----------
   Task: every admin dashboard used the exact same navy sidebar, so it was
   impossible to tell at a glance which panel you were in (site CMS vs
   manager/boss vs secretary vs bookstore vs accounting). Each portal's
   admin-shell now carries data-role="…" (set once, per file, in the PHP)
   and gets its own gradient + accent — same structure, unmistakable color. */
.admin-shell[data-role="manager"] .admin-side {
  --admin-side-bg: linear-gradient(185deg, #241505 0%, #6b3f10 55%, #a8641b 100%);
  --admin-side-line: rgba(255, 214, 156, 0.16);
  --admin-side-accent: #d97706;
}
.admin-shell[data-role="accounting"] .admin-side {
  --admin-side-bg: linear-gradient(185deg, #1E1B08 0%, #5A4A0F 55%, #8A7115 100%);
  --admin-side-line: rgba(250, 230, 150, 0.16);
  --admin-side-accent: #d97706;
}
.admin-shell[data-role="secretary"] .admin-side {
  --admin-side-bg: linear-gradient(185deg, #1B1533 0%, #3B2478 55%, #5B36B0 100%);
  --admin-side-line: rgba(216, 190, 255, 0.16);
  --admin-side-accent: #7c3aed;
}
.admin-shell[data-role="bookstore"] .admin-side {
  /* FIXED (per request): was green — now yellow, to match Khatte Sefid's
     own brand color instead of a generic "success" green. */
  --admin-side-bg: linear-gradient(185deg, #2B2205 0%, #7A5F0B 55%, #B8930F 100%);
  --admin-side-line: rgba(253, 230, 138, 0.18);
  --admin-side-accent: #eab308;
}
.admin-shell[data-role="supervisor"] .admin-side {
  --admin-side-bg: linear-gradient(185deg, #1A0F2E 0%, #4C1D95 55%, #7E22CE 100%);
  --admin-side-line: rgba(233, 213, 255, 0.16);
  --admin-side-accent: #a855f7;
}
[data-theme='dark'] {
  --admin-ink: #F3F5F8;
  --admin-ink-soft: #A7B1C2;
  --admin-line: rgba(255, 255, 255, 0.08);
  --admin-surface: #212B3D;
  --admin-surface-soft: #1B2536;
}

body:has(.admin-shell) { background: var(--admin-surface-soft); }

.admin-shell {
  display: grid;
  grid-template-columns: 264px 1fr;
  align-items: start;
  min-height: 100vh;
}

/* ---------- Sidebar ---------- */
.admin-side {
  position: sticky;
  top: 0;
  height: 100vh;
  overflow-y: auto;
  display: flex;
  flex-direction: column;
  gap: 0.15rem;
  padding: 1.5rem 1rem 2rem;
  background: var(--admin-side-bg) !important;
  border: none;
  border-inline-end: 1px solid var(--admin-side-line);
  border-radius: 0;
  color: var(--admin-side-text);
  backdrop-filter: none !important;
  -webkit-backdrop-filter: none !important;
  box-shadow: none;
}
.admin-side::before { display: none; }
.admin-brand {
  display: flex;
  align-items: center;
  gap: 0.65rem;
  padding: 0.4rem 0.6rem 1.25rem;
  margin-bottom: 0.5rem;
  border-bottom: 1px solid var(--admin-side-line);
  /* FIXED (per request): .admin-brand is now an <a> (links home) instead
     of a plain <div> — reset the anchor defaults so it still looks like
     a static logo block, with just a subtle hint on hover/focus that it's
     clickable. */
  text-decoration: none;
  cursor: pointer;
  transition: opacity 0.2s ease;
}
.admin-brand:hover, .admin-brand:focus-visible { opacity: 0.82; }
.admin-brand .logo-mark { width: 34px; height: 34px; border-radius: 10px; }
.admin-brand strong { display: block; font-size: 0.92rem; color: var(--admin-side-text-strong); }
.admin-brand small { display: block; font-size: 0.72rem; color: var(--admin-side-text); opacity: 0.7; }

.admin-side p.side-eyebrow,
.admin-side .side-group-label {
  font-size: 0.68rem;
  font-weight: 700;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: rgba(255, 255, 255, 0.4);
  padding: 1rem 0.75rem 0.35rem;
}
.admin-side > p:first-of-type { padding: 0 0.6rem 0.75rem; }
.admin-side a {
  display: flex;
  align-items: center;
  gap: 0.65rem;
  padding: 0.62rem 0.75rem;
  border-radius: 11px;
  font-size: 0.88rem;
  font-weight: 500;
  color: var(--admin-side-text);
  border-inline-start: 2px solid transparent;
  transition: background 0.18s ease, color 0.18s ease, border-color 0.18s ease;
}
.admin-side a i { width: 1.1rem; text-align: center; opacity: 0.85; font-size: 0.85rem; }
/* FIXED (per request): color-code each nav icon by its group (Content &
   Front / Academic / Blog / Inbox & Files / System) — set as an inline
   custom property per link in admin/panel.php's nav loop. Kept as its own
   rule (not baked into the base ".admin-side a i" above) so a tab with no
   group color (nothing set) just falls back to the original muted color,
   and so hover/active states below can't accidentally strip it. */
.admin-side a[style*="--nav-icon-color"] i { color: var(--nav-icon-color); opacity: 1; }
.admin-side a:hover {
  background: rgba(255, 255, 255, 0.06);
  color: #fff;
}
.admin-side a.active {
  background: rgba(255, 255, 255, 0.14);
  color: #fff;
  border-inline-start-color: var(--admin-side-accent, var(--orange));
}
.admin-side a.admin-exit { margin-top: auto; }
/* Maintenance-on pill, shown in the site-CMS sidebar (admin/panel.php)
   whenever maintenance mode is active, so it's never invisible/forgotten
   once turned on. Yellow — matches the toggle switch and the public
   splash's accent, our design language's "heads up" color. */
.admin-maint-pill {
  display: flex;
  align-items: center;
  gap: 0.5rem;
  margin-bottom: 0.75rem;
  padding: 0.55rem 0.75rem;
  border-radius: 12px;
  background: rgba(250, 204, 21, 0.16);
  border: 1px solid rgba(250, 204, 21, 0.4);
  color: #fde68a;
  font-size: 0.78rem;
  font-weight: 700;
}
.admin-maint-pill i { color: #facc15; }
/* FIXED (per request): Live Support Chat, then Unanswered Requests too,
   moved to the top of the sidebar — both get the same "pill" treatment as
   the maintenance banner above them (so they read as priority items, not
   just another nav link), in the site's own accent color rather than the
   maintenance warning's yellow. Shared class since both links get the
   identical top-of-sidebar treatment. */
.admin-side-priority-link {
  margin-bottom: 0.75rem;
  padding: 0.55rem 0.75rem;
  border-radius: 12px;
  background: rgba(238, 99, 52, 0.14);
  border: 1px solid rgba(238, 99, 52, 0.4);
  font-weight: 700;
}
.admin-side-priority-link i { color: var(--orange); }
.admin-side hr.side-sep {
  border: none;
  border-top: 1px solid var(--admin-side-line);
  margin: 0.85rem 0.6rem;
}

/* ---------- Main column ---------- */
.admin-main {
  padding: 1.75rem 2.25rem 4rem;
  max-width: 1180px;
  min-width: 0;
}
.admin-topbar {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 1rem;
  flex-wrap: wrap;
  margin-bottom: 1.5rem;
  padding-bottom: 1.1rem;
  border-bottom: 1px solid var(--admin-line);
}
.admin-topbar h1 { font-size: 1.35rem; margin: 0; }

/* FIXED (per request): "a very thin layer underneath header" showing
   live visitors (green), unanswered requests (yellow) and chats waiting
   to be answered (blue), each flashing gently so it reads as "live" —
   replaces having to check three separate stat cards. Rendered by
   sd_admin_status_strip() in includes/functions.php, right above
   .admin-topbar in every standalone admin panel. Kept sticky so it's
   always visible while scrolling, centered, with vertical dividers
   between the three pills. On the two panels that have a counterpart to
   switch to (institute <-> bookstore), a second centered row underneath
   carries the switch button plus the signed-in account's name — see
   .admin-status-whoami below. */
.admin-status-strip {
  position: sticky;
  top: 0;
  z-index: 30;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 0.5rem;
  margin: -0.25rem 0 1.25rem;
  padding: 0.7rem 1rem;
  border-radius: 14px;
  background: var(--admin-surface-soft);
  border: 1px solid var(--admin-side-line);
  backdrop-filter: blur(6px);
}
.admin-status-pills {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  align-items: center;
  gap: 0;
}
.admin-status-pill {
  display: inline-flex;
  align-items: center;
  gap: 0.45rem;
  padding: 0.35rem 1rem;
  font-size: 0.76rem;
  font-weight: 600;
  color: var(--admin-ink-soft);
  border-inline-end: 1px solid var(--admin-side-line);
}
.admin-status-pill:last-child { border-inline-end: none; }
.admin-status-pill strong { color: var(--admin-ink); font-size: 0.92em; }
.admin-status-dot {
  width: 8px;
  height: 8px;
  border-radius: 50%;
  flex-shrink: 0;
  animation: adminStatusFlash 1.6s ease-in-out infinite;
}
.admin-status-online .admin-status-dot { background: #22c55e; box-shadow: 0 0 0 0 rgba(34, 197, 94, 0.5); }
.admin-status-requests .admin-status-dot { background: #eab308; box-shadow: 0 0 0 0 rgba(234, 179, 8, 0.5); animation-delay: 0.3s; }
.admin-status-bookstore .admin-status-dot { background: #a855f7; box-shadow: 0 0 0 0 rgba(168, 85, 247, 0.5); animation-delay: 0.45s; }
.admin-status-chats .admin-status-dot { background: #3b82f6; box-shadow: 0 0 0 0 rgba(59, 130, 246, 0.5); animation-delay: 0.6s; }
@keyframes adminStatusFlash {
  0%, 100% { opacity: 1; transform: scale(1); }
  50% { opacity: 0.45; transform: scale(0.82); }
}
@media (prefers-reduced-motion: reduce) {
  .admin-status-dot { animation: none; }
}
/* Switch-panel + account-name row — centered, sits right below the
   pills inside the same sticky strip. */
.admin-status-whoami {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  align-items: center;
  gap: 0.6rem;
  padding-top: 0.5rem;
  border-top: 1px solid var(--admin-side-line);
  width: 100%;
}
.admin-status-name {
  font-weight: 700;
  font-size: 0.95rem;
  color: var(--admin-ink);
  text-align: center;
}
.admin-status-switch {
  display: inline-flex;
  align-items: center;
  gap: 0.45rem;
  padding: 0.4rem 0.85rem;
  border-radius: 10px;
  background: rgba(14, 165, 233, 0.12);
  color: #0284c7;
  border: 1px solid rgba(14, 165, 233, 0.25);
  font-size: 0.8rem;
  font-weight: 600;
  text-decoration: none;
  transition: background 0.2s ease;
}
.admin-status-switch:hover { background: rgba(14, 165, 233, 0.2); }
[data-theme='dark'] .admin-status-switch { color: #38bdf8; }

/* ---- Status as cards (dashboard.php landing page) ------------------------
   sd_admin_status_strip([], 'auto', 'cards'): the same four live numbers
   as the thin admin strip, but as a compact column of small cards that
   sits beside the profile card (see .dash-hero-row in dashboard.php),
   each with a little spotlight that flickers to life and glows every
   few seconds — a "studio light" cue that the numbers are live, not a
   static readout. The light pulses while there is something to look at
   and goes calm/dim at 0. */
.admin-status-strip.admin-status-cards {
  position: static;
  display: block;
  margin: 0;
  padding: 0;
  background: none;
  border: 0;
  border-radius: 0;
  backdrop-filter: none;
}
.admin-status-heading {
  display: flex;
  align-items: center;
  gap: 0.5rem;
  margin: 0 0 0.75rem;
  font-size: 0.82rem;
  font-weight: 800;
  letter-spacing: 0.03em;
  color: var(--text);
}
/* Small "on air" bulb next to the heading — its own gentle, irregular
   flicker so the whole section reads as live the moment you see it,
   before your eye even reaches the numbers. */
.admin-status-onair {
  flex: 0 0 auto;
  width: 8px;
  height: 8px;
  border-radius: 50%;
  background: #ef4444;
  box-shadow: 0 0 5px 1px rgba(239, 68, 68, 0.65);
  animation: adminOnAirFlicker 3.2s ease-in-out infinite;
}
@keyframes adminOnAirFlicker {
  0%, 42%, 100% { opacity: 1; }
  44% { opacity: 0.25; }
  46% { opacity: 1; }
  48% { opacity: 0.35; }
  51% { opacity: 1; }
}
.admin-status-cards .admin-status-pills {
  display: grid;
  grid-template-columns: repeat(2, 1fr);
  gap: 0.65rem;
  align-items: stretch;
  justify-content: stretch;
}
.admin-status-card {
  display: flex;
  align-items: center;
  gap: 0.7rem;
  min-height: 76px;
  margin: 0;
  padding: 0.75rem 0.85rem;
}
.admin-status-cards .admin-status-online   { --asc: #22c55e; --asc-soft: rgba(34, 197, 94, 0.14);  --asc-glow: rgba(34, 197, 94, 0.55); }
.admin-status-cards .admin-status-requests { --asc: #eab308; --asc-soft: rgba(234, 179, 8, 0.16);  --asc-glow: rgba(234, 179, 8, 0.55); }
.admin-status-cards .admin-status-bookstore{ --asc: #a855f7; --asc-soft: rgba(168, 85, 247, 0.14); --asc-glow: rgba(168, 85, 247, 0.55); }
.admin-status-cards .admin-status-chats    { --asc: #3b82f6; --asc-soft: rgba(59, 130, 246, 0.14); --asc-glow: rgba(59, 130, 246, 0.55); }
/* Stagger each color's periodic glow so the four lights don't flash in
   unison — reads as a lively little control panel instead of a strobe. */
.admin-status-cards .admin-status-online   .admin-status-light::before { animation-delay: 0s; }
.admin-status-cards .admin-status-requests .admin-status-light::before { animation-delay: 1.1s; }
.admin-status-cards .admin-status-bookstore  .admin-status-light::before { animation-delay: 2.2s; }
.admin-status-cards .admin-status-chats    .admin-status-light::before { animation-delay: 3.3s; }
.admin-status-light {
  position: relative;
  flex: 0 0 auto;
  display: grid;
  place-items: center;
  width: 38px;
  height: 38px;
  border-radius: 50%;
  background: var(--asc-soft);
}
/* The "spotlight": a soft halo behind the bulb that sits almost invisible
   most of the time, then blooms into a bright glow for a moment — like a
   spot lamp being switched on — before fading back down. Repeats on a
   ~4.6s loop, offset per card above. */
.admin-status-light::before {
  content: "";
  position: absolute;
  inset: -45%;
  border-radius: 50%;
  background: radial-gradient(circle, var(--asc-glow) 0%, transparent 72%);
  opacity: 0;
  filter: blur(1px);
  animation: adminBulbGlow 4.6s ease-in-out infinite;
  pointer-events: none;
}
.admin-status-card.is-idle .admin-status-light::before { animation: none; opacity: 0; }
@keyframes adminBulbGlow {
  0%, 76%, 100% { opacity: 0; transform: scale(0.8); }
  82% { opacity: 1; transform: scale(1.25); }
  88% { opacity: 0.3; transform: scale(1); }
  92% { opacity: 0.85; transform: scale(1.15); }
  97% { opacity: 0; transform: scale(0.9); }
}
.admin-status-cards .admin-status-dot {
  position: relative;
  width: 16px;
  height: 16px;
  background: var(--asc);
  box-shadow: 0 0 0 3px var(--asc-soft), 0 0 12px 2px var(--asc-glow);
  animation: none;
  transition: opacity 0.3s ease, box-shadow 0.3s ease;
}
.admin-status-cards .admin-status-dot::after {
  content: "";
  position: absolute;
  inset: -3px;
  border-radius: 50%;
  border: 2px solid var(--asc);
  opacity: 0;
  animation: adminStatusRing 1.9s ease-out infinite;
}
@keyframes adminStatusRing {
  0%   { transform: scale(0.7); opacity: 0.7; }
  100% { transform: scale(2);   opacity: 0; }
}
/* count is 0: calm, dimmed light, no pulse */
.admin-status-card.is-idle .admin-status-dot { opacity: 0.5; box-shadow: 0 0 0 3px var(--asc-soft); }
.admin-status-card.is-idle .admin-status-dot::after { animation: none; }
.admin-status-body { display: flex; flex-direction: column; gap: 0.2rem; min-width: 0; }
.admin-status-num {
  font-size: 1.35rem;
  font-weight: 800;
  line-height: 1;
  letter-spacing: -0.01em;
  font-variant-numeric: tabular-nums;
  color: var(--text);
}
.admin-status-label {
  font-size: 0.72rem;
  font-weight: 700;
  line-height: 1.35;
  letter-spacing: 0.01em;
  color: var(--muted);
}
@media (prefers-reduced-motion: reduce) {
  .admin-status-cards .admin-status-dot::after,
  .admin-status-light::before,
  .admin-status-onair { animation: none; }
}
html[data-motion="off"]:not([data-allow~="loops"]) .admin-status-cards .admin-status-dot::after,
html[data-motion="off"]:not([data-allow~="loops"]) .admin-status-light::before,
html[data-motion="off"]:not([data-allow~="loops"]) .admin-status-onair { animation: none !important; }

/* ---- Dashboard hero row: profile card + the compact live-status column
   side by side (status column sits to the inline-start side — the left
   in RTL — of the profile card), instead of the old full-width stack. ---- */
.dash-hero-row {
  display: flex;
  align-items: flex-start;
  flex-wrap: wrap;
  gap: 1.5rem;
  margin-top: 1.5rem;
}
.dash-profile-card {
  flex: 1 1 380px;
  max-width: 420px;
  margin: 0;
}
.dash-hero-row .admin-status-strip.admin-status-cards {
  flex: 1 1 280px;
  max-width: 340px;
}
@media (max-width: 640px) {
  .dash-profile-card,
  .dash-hero-row .admin-status-strip.admin-status-cards {
    max-width: none;
    flex-basis: 100%;
  }
}
.admin-topbar .admin-breadcrumb {
  font-size: 0.78rem;
  color: var(--admin-ink-soft);
  text-transform: uppercase;
  letter-spacing: 0.05em;
  font-weight: 700;
  margin-bottom: 0.2rem;
}
.admin-whoami {
  display: flex;
  align-items: center;
  gap: 0.6rem;
  font-size: 0.85rem;
  color: var(--admin-ink-soft);
  background: var(--admin-surface);
  border: 1px solid var(--admin-line);
  padding: 0.4rem 0.7rem 0.4rem 0.4rem;
  border-radius: 999px;
}
.admin-whoami .avatar {
  width: 28px; height: 28px;
  border-radius: 50%;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  background: linear-gradient(135deg, var(--amber), var(--orange));
  color: #fff;
  font-weight: 700;
  font-size: 0.75rem;
}

.admin-main h1 { margin-bottom: 0.3rem; }
.admin-section-intro {
  color: var(--admin-ink-soft);
  font-size: 0.92rem;
  max-width: 62ch;
  margin-bottom: 1.5rem;
}

/* ---------- Forms inside admin ---------- */
.admin-main .form-card, .admin-main .panel-card, .admin-main .md-card {
  background: var(--admin-surface);
  border: 1px solid var(--admin-line);
  backdrop-filter: none;
  -webkit-backdrop-filter: none;
}
.admin-main .form-card::before, .admin-main .panel-card::before, .admin-main .md-card::before { display: none; }
.admin-fieldset {
  padding: 1.5rem;
  margin-bottom: 1.25rem;
}
.admin-fieldset h3 {
  font-size: 0.95rem;
  display: flex;
  align-items: center;
  gap: 0.5rem;
  margin-bottom: 1rem;
  color: var(--admin-ink);
}
.admin-fieldset h3 i { color: var(--orange); }

/* FIXED (per request): the repetitive site/about/contact/etc. edit forms
   used to all sit open on the page at once, in one long scroll. Each
   .admin-fieldset that has its own <h3> title is now a native <details>
   disclosure ("admin-accordion") instead — a small pull-down per
   category, marked with a pencil "edit" icon, so the admin sees a
   wrapped, organized list of sections and only opens the one they came
   to change. <summary> replaces the old <h3> 1:1 (same icon + title),
   so nothing about what each section is called or contains changed —
   only whether it's expanded by default. */
.admin-accordion { padding: 0; }
.admin-accordion > summary {
  list-style: none;
  cursor: pointer;
  display: flex;
  align-items: center;
  gap: 0.5rem;
  font-size: 0.95rem;
  font-weight: 600;
  color: var(--admin-ink);
  padding: 1.1rem 1.5rem;
  user-select: none;
}
.admin-accordion > summary::-webkit-details-marker { display: none; }
.admin-accordion > summary > i:first-child { color: var(--orange); }
.admin-accordion-caret {
  margin-inline-start: auto;
  font-size: 0.8em;
  color: var(--admin-ink-soft);
  opacity: 0.6;
  transition: transform 0.2s var(--ease);
}
.admin-accordion[open] > summary .admin-accordion-caret { transform: rotate(180deg); }
.admin-accordion-edit-icon {
  /* Removed per feedback: the edit-pencil mark in front of every
     accordion section header was cluttering the dashboards. Icon kept
     in markup (harmless) but hidden everywhere. */
  display: none;
}
.admin-accordion > summary:hover .admin-accordion-caret { opacity: 1; }
.admin-accordion > summary:hover { background: rgba(238, 99, 52, 0.06); }
.admin-accordion > summary:focus-visible { outline: 2px solid var(--orange); outline-offset: -2px; }
/* Direct children after <summary> are the section's actual body (the
   .admin-grid-fields grid, a nested <form>, etc.) — pad them the same
   way the old plain .admin-fieldset content was padded. */
.admin-accordion > *:not(summary) { padding: 0 1.5rem 1.5rem; }
.admin-accordion:not([open]) > *:not(summary) { display: none; }
/* FIXED (per request): a little more visual care on an opened section —
   the header picks up a soft tint + bottom divider, and the revealed
   body gently fades/slides in instead of just popping into place. */
.admin-accordion[open] > summary {
  background: rgba(238, 99, 52, 0.05);
  border-bottom: 1px solid var(--admin-side-line);
}
.admin-accordion[open] > *:not(summary) {
  animation: adminAccordionReveal 0.25s ease;
}
@keyframes adminAccordionReveal {
  from { opacity: 0; transform: translateY(-6px); }
  to { opacity: 1; transform: translateY(0); }
}
@media (prefers-reduced-motion: reduce) {
  .admin-accordion[open] > *:not(summary) { animation: none; }
}
.admin-grid-fields {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(220px, 1fr));
  gap: 0.9rem 1.1rem;
}
.admin-main label {
  display: flex;
  flex-direction: column;
  gap: 0.32rem;
  font-size: 0.82rem;
  font-weight: 600;
  color: var(--admin-ink-soft);
}
.admin-main label.full { grid-column: 1 / -1; }
.admin-main input, .admin-main select, .admin-main textarea {
  width: 100%;
  padding: 0.6rem 0.8rem;
  border: 1px solid var(--admin-line);
  border-radius: 10px;
  background: var(--admin-surface-soft);
  color: var(--admin-ink);
  font-size: 0.88rem;
  font-weight: 400;
  font-family: inherit;
}
.admin-main input:focus, .admin-main select:focus, .admin-main textarea:focus {
  outline: none;
  border-color: var(--orange);
  box-shadow: 0 0 0 3px rgba(238, 99, 52, 0.14);
  background: var(--admin-surface);
}
/* FIXED (per request): "in some dashboard sections the Apply-changes area
   sits outside the box, not included in that section" — a bare
   .admin-toolbar used to be just a flex row with no background/border, so
   whenever it sat after a <details> box (or after a list of repeat-item
   cards) rather than inside one, the Save/Apply button visually floated in
   empty space below the section instead of reading as part of it. Giving
   the toolbar itself a contained "box" treatment (same background/border/
   radius language as .glass) fixes every one of those spots at once,
   including the ones already inside an accordion (which just get a subtle
   nested action-bar card — a common, intentional pattern, not a bug). */
.admin-toolbar {
  display: flex;
  gap: 0.6rem;
  align-items: center;
  justify-content: flex-end;
  margin-top: 0.75rem;
  padding: 0.85rem 1rem;
  background: var(--card);
  border: 1px solid var(--line);
  border-radius: var(--radius-sm, 14px);
  box-shadow: var(--shadow);
}
/* Toolbars used purely as inline filter/search bars (not a trailing
   "apply changes" action row) opt back out of the boxed look via their own
   inline style overrides already present in the markup — this default
   only affects the plain, unstyled `.admin-toolbar` usage. */

/* ---------- Maintenance mode card + toggle switch (yellow, design-language
   consistent) — deliberately the first thing on the Security tab, not
   buried under other settings. ---------- */
.admin-maint-card {
  margin-bottom: 1.5rem;
  padding: 1.35rem 1.5rem;
  border-radius: var(--admin-radius);
  border: 1px solid rgba(217, 119, 6, 0.25);
  background: linear-gradient(180deg, rgba(250, 204, 21, 0.09), rgba(250, 204, 21, 0.03));
}
.admin-maint-card.is-on {
  border-color: rgba(217, 119, 6, 0.55);
  background: linear-gradient(180deg, rgba(250, 204, 21, 0.18), rgba(250, 204, 21, 0.06));
}
.admin-maint-card-head {
  display: flex;
  align-items: flex-start;
  gap: 0.85rem;
  margin-bottom: 0.9rem;
}
.admin-maint-card-head h3 { margin: 0; font-size: 1rem; }
.admin-maint-icon {
  width: 40px; height: 40px;
  flex-shrink: 0;
  border-radius: 12px;
  display: flex;
  align-items: center;
  justify-content: center;
  background: #facc15;
  color: #4a3400;
  font-size: 1.05rem;
}
.admin-maint-live-note {
  display: flex;
  align-items: center;
  gap: 0.5rem;
  color: #92400e;
  font-weight: 700;
  font-size: 0.85rem;
  margin: 0 0 1rem;
}
[data-theme='dark'] .admin-maint-live-note { color: #fde68a; }
.admin-maint-switch {
  display: inline-flex;
  align-items: center;
  gap: 0.75rem;
  border: none;
  background: transparent;
  cursor: pointer;
  padding: 0;
  font-family: inherit;
}
.admin-maint-switch-track {
  width: 52px; height: 28px;
  border-radius: 999px;
  background: rgba(31, 44, 67, 0.18);
  position: relative;
  transition: background 0.25s var(--ease);
  flex-shrink: 0;
}
.admin-maint-switch[aria-pressed="true"] .admin-maint-switch-track {
  background: #facc15;
}
.admin-maint-switch-knob {
  position: absolute;
  top: 3px;
  inset-inline-start: 3px;
  width: 22px; height: 22px;
  border-radius: 50%;
  background: #fff;
  box-shadow: 0 2px 6px rgba(0,0,0,0.25);
  transition: inset-inline-start 0.25s var(--ease);
}
.admin-maint-switch[aria-pressed="true"] .admin-maint-switch-knob {
  inset-inline-start: 27px;
}
.admin-maint-switch-label {
  font-weight: 700;
  font-size: 0.86rem;
  color: var(--admin-ink);
}
/* Book-order "fulfilled" toggle (admin/bookstore.php orders table) — same
   switch control, but green when ON (order done) instead of maintenance's
   warning yellow. */
.admin-maint-switch--done[aria-pressed="true"] .admin-maint-switch-track {
  background: #10b981;
}

/* Homepage sections on/off list (admin/panel.php, Site tab) — one row
   per toggleable section, each its own tiny independent form using the
   same .admin-maint-switch control as maintenance mode. */
.admin-section-toggles {
  display: flex;
  flex-direction: column;
  gap: 0.25rem;
}
.admin-section-toggle-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 1rem;
  padding: 0.7rem 0.25rem;
  border-bottom: 1px solid var(--admin-side-line);
}
.admin-section-toggle-row:last-child { border-bottom: none; }
.admin-section-toggle-label {
  font-size: 0.88rem;
  font-weight: 600;
  color: var(--admin-ink);
}
/* Generic admin <details> expander — per-teacher "Classes" (admin/panel.php
   Teachers tab, mirrored read-only on admin/accounting.php) and the
   per-student consolidated profile (Users tab, and the read-only student
   lookup on admin/manager.php + admin/secretary.php). Plain <details>, no
   JS needed anywhere it's used. */
.admin-teacher-classes,
.admin-detail-expander {
  border: 1px solid var(--admin-line);
  border-radius: var(--admin-radius);
  padding: 0.75rem 1rem;
  margin-top: 0.75rem;
}
.admin-teacher-classes summary,
.admin-detail-expander summary {
  cursor: pointer;
  display: flex;
  align-items: center;
  gap: 0.6rem;
  font-size: 0.92rem;
  list-style: none;
}
.admin-teacher-classes summary::-webkit-details-marker,
.admin-detail-expander summary::-webkit-details-marker { display: none; }
.admin-teacher-classes summary::before,
.admin-detail-expander summary::before {
  content: "\f105";
  font-family: "Font Awesome 6 Free";
  font-weight: 900;
  transition: transform 0.2s ease;
  color: var(--muted);
}
.admin-teacher-classes[open] summary::before,
.admin-detail-expander[open] summary::before { transform: rotate(90deg); }
.admin-detail-expander dl.profile-mini-dl {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(160px, 1fr));
  gap: 0.5rem 1rem;
  margin: 0.75rem 0;
}
.admin-detail-expander dl.profile-mini-dl dt { font-size: 0.75rem; color: var(--muted); margin-bottom: 0.15rem; }
.admin-detail-expander dl.profile-mini-dl dd { margin: 0; font-weight: 600; }

.admin-repeat-item {
  border: 1px solid var(--admin-line);
  border-radius: var(--admin-radius);
  /* FIXED (per request — screenshot): the floating "#N" index badge sits
     on the card's top edge via negative margin, but the card's own
     top padding left almost no breathing room below it, so the badge
     visually crowded/overlapped the delete button and first field right
     underneath it. More top padding here is the actual fix — the badge's
     position is unchanged, it just now has room to float clear of the
     content instead of nearly touching it. */
  padding: 1.85rem 1.25rem 1.1rem;
  margin-top: 0.65rem;
  margin-bottom: 0.9rem;
  background: var(--admin-surface);
  position: relative;
}
.admin-repeat-item .admin-repeat-index {
  position: absolute;
  top: -12px;
  inset-inline-start: 1rem;
  background: var(--orange);
  color: #fff;
  font-size: 0.68rem;
  font-weight: 700;
  padding: 0.15rem 0.55rem;
  border-radius: 999px;
  z-index: 1;
  box-shadow: 0 2px 6px rgba(0,0,0,0.15);
}

/* FIXED (per request): sections that repeat an item with BOTH an image and
   several text fields (Hero Slides, Courses) used to show every field of
   every item expanded at once — with a handful of items that's a wall of
   inputs to scroll past. Each item is now its own native <details>, closed
   by default: a compact one-line header (thumbnail + title + delete), the
   full field grid only appears once that one item is opened. Kept as a
   separate class from .admin-repeat-item/.admin-accordion (used elsewhere,
   always-expanded) so this doesn't fight either of their CSS. */
.admin-repeat-collapsible {
  border: 1px solid var(--admin-line);
  border-radius: var(--admin-radius);
  background: var(--admin-surface);
  margin-bottom: 1.1rem;
  overflow: hidden;
}
.admin-repeat-collapsible > summary {
  list-style: none;
  cursor: pointer;
  display: flex;
  align-items: center;
  gap: 0.7rem;
  padding: 0.85rem 1.1rem;
  font-size: 0.9rem;
  font-weight: 600;
  color: var(--admin-ink);
  user-select: none;
}
.admin-repeat-collapsible > summary::-webkit-details-marker { display: none; }
.admin-repeat-collapsible > summary:hover { background: rgba(238, 99, 52, 0.06); }
.admin-repeat-collapsible[open] > summary {
  background: rgba(238, 99, 52, 0.05);
  border-bottom: 1px solid var(--admin-line);
}
.admin-repeat-collapsible-thumb {
  width: 42px;
  height: 42px;
  border-radius: 10px;
  overflow: hidden;
  flex-shrink: 0;
  background: var(--admin-surface-soft);
  display: flex;
  align-items: center;
  justify-content: center;
  color: var(--admin-ink-soft);
  font-size: 1rem;
}
.admin-repeat-collapsible-thumb img { width: 100%; height: 100%; object-fit: cover; }
.admin-repeat-collapsible-title {
  flex: 1;
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.admin-repeat-collapsible > summary .admin-accordion-caret {
  font-size: 0.8em;
  color: var(--admin-ink-soft);
  opacity: 0.6;
  flex-shrink: 0;
  transition: transform 0.2s var(--ease);
}
.admin-repeat-collapsible[open] > summary .admin-accordion-caret { transform: rotate(180deg); }
.admin-repeat-collapsible > *:not(summary) { padding: 1.1rem 1.25rem 1.4rem; }
.admin-repeat-collapsible:not([open]) > *:not(summary) { display: none; }
.admin-repeat-collapsible[open] > *:not(summary) { animation: adminAccordionReveal 0.25s ease; }
@media (prefers-reduced-motion: reduce) {
  .admin-repeat-collapsible[open] > *:not(summary) { animation: none; }
}

/* ---------- Tables ---------- */
.admin-table-wrap {
  width: 100%;
  overflow-x: auto;
  border: 1px solid var(--admin-line);
  border-radius: var(--admin-radius);
  background: var(--admin-surface);
}
.admin-table {
  width: 100%;
  min-width: 560px;
  border-collapse: collapse;
  font-size: 0.86rem;
}
.admin-table th {
  position: sticky;
  top: 0;
  background: var(--admin-surface-soft);
  text-align: start;
  font-size: 0.72rem;
  text-transform: uppercase;
  letter-spacing: 0.04em;
  color: var(--admin-ink-soft);
  font-weight: 700;
  padding: 0.75rem 0.9rem;
  border-bottom: 1px solid var(--admin-line);
}
.admin-table td {
  padding: 0.7rem 0.9rem;
  border-bottom: 1px solid var(--admin-line);
  vertical-align: middle;
  color: var(--admin-ink);
}
.admin-table td input, .admin-table td select, .admin-table td textarea {
  min-width: 130px;
}
.admin-table tbody tr:hover { background: rgba(238, 99, 52, 0.04); }
.admin-table tbody tr:last-child td { border-bottom: none; }

/* Role / status chips */
.chip {
  display: inline-flex;
  align-items: center;
  gap: 0.3rem;
  font-size: 0.72rem;
  font-weight: 700;
  padding: 0.22rem 0.6rem;
  border-radius: 999px;
  white-space: nowrap;
}
.chip-role-super_admin { background: rgba(238, 99, 52, 0.14); color: #D14211; }
.chip-role-editor { background: rgba(37, 99, 235, 0.12); color: #1d4ed8; }
.chip-role-bookstore_staff { background: rgba(22, 163, 74, 0.12); color: #15803d; }
.chip-role-secretary { background: rgba(124, 58, 237, 0.12); color: #7c3aed; }
.chip-role-manager { background: rgba(217, 119, 6, 0.14); color: #b45309; }
.chip-role-supervisor { background: rgba(168, 85, 247, 0.14); color: #7e22ce; }
.chip-role-teacher { background: rgba(8, 145, 178, 0.12); color: #0e7490; }
.chip-role-student { background: rgba(100, 116, 139, 0.14); color: #475569; }
.chip-status-valid, .chip-status-active { background: rgba(22, 163, 74, 0.12); color: #15803d; }
.chip-status-invalid, .chip-status-inactive { background: rgba(220, 38, 38, 0.12); color: #b91c1c; }
/* Blue "Seen" / "Pending" request-status chip — both are still-open states,
   as opposed to the green "Reviewed / Completed" one above. */
.chip-status-info { background: rgba(37, 99, 235, 0.12); color: #1d4ed8; }
.chip-stock-in_stock { background: rgba(22, 163, 74, 0.12); color: #15803d; }
.chip-stock-low_stock { background: rgba(217, 119, 6, 0.14); color: #b45309; }
.chip-stock-out_of_stock { background: rgba(220, 38, 38, 0.12); color: #b91c1c; }
.chip-stock-preorder { background: rgba(37, 99, 235, 0.12); color: #1d4ed8; }

/* Shared stock-status badge — used on the public bookstore page AND the
   member dashboard's certificate list; previously only defined locally in
   bookstore.php's <style> block, so it rendered unstyled on the dashboard. */
.stock-badge {
    font-size: 0.75rem;
    padding: 0.2rem 0.55rem;
    border-radius: 999px;
    background: rgba(238, 99, 52, 0.12);
    color: var(--brand-orange);
    white-space: nowrap;
    display: inline-block;
}
.stock-out_of_stock { background: rgba(239, 68, 68, 0.12); color: #dc2626; }
.stock-low_stock { background: rgba(245, 158, 11, 0.15); color: #d97706; }
.stock-preorder { background: rgba(59, 130, 246, 0.12); color: #2563eb; }
/* FIXED: .stock-in_stock had no rule of its own, so the "completed" /
   "fulfilled" badge on the dashboard silently fell back to the default
   orange .stock-badge color instead of green. */
.stock-in_stock { background: rgba(22, 163, 74, 0.12); color: #15803d; }

/* Completed toggle switch — admin/secretary.php requests inbox. Flips a
   request's status to/from 'completed' (green, on the requester's panel
   too), independent of the existing seen/pending mark. */
.toggle-switch { position: relative; display: inline-flex; width: 38px; height: 22px; flex: none; vertical-align: middle; }
.toggle-switch input { position: absolute; opacity: 0; width: 100%; height: 100%; margin: 0; cursor: pointer; }
.toggle-switch .toggle-track { position: absolute; inset: 0; background: #cbd5e1; border-radius: 999px; transition: background 0.18s var(--ease); pointer-events: none; }
.toggle-switch .toggle-track::before { content: ""; position: absolute; height: 16px; width: 16px; left: 3px; top: 3px; background: #fff; border-radius: 50%; transition: transform 0.18s var(--ease); box-shadow: 0 1px 2px rgba(0,0,0,0.25); }
.toggle-switch input:checked + .toggle-track { background: #16a34a; }
.toggle-switch input:checked + .toggle-track::before { transform: translateX(16px); }
.toggle-switch input:focus-visible + .toggle-track { outline: 2px solid var(--orange); outline-offset: 2px; }
.toggle-switch input:disabled { cursor: not-allowed; }
.toggle-switch input:disabled + .toggle-track { opacity: 0.5; }
.toggle-row { display: inline-flex; align-items: center; gap: 0.4rem; font-size: 0.7rem; color: var(--muted); white-space: nowrap; }

/* Small icon action buttons in tables */
.row-actions { display: flex; gap: 0.4rem; flex-wrap: wrap; }
.row-actions form { display: inline-flex; }
.btn-icon-sm {
  width: 32px; height: 32px;
  border-radius: 9px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  border: 1px solid var(--admin-line);
  background: var(--admin-surface-soft);
  color: var(--admin-ink-soft);
  cursor: pointer;
  font-size: 0.8rem;
}
.btn-icon-sm:hover { border-color: var(--orange); color: var(--orange); }
.btn-icon-sm.danger:hover { border-color: #dc2626; color: #dc2626; }

/* Empty state */
.admin-empty {
  text-align: center;
  padding: 2.5rem 1rem;
  color: var(--admin-ink-soft);
  font-size: 0.9rem;
}
.admin-empty i { font-size: 1.5rem; color: var(--orange); margin-bottom: 0.5rem; display: block; }

/* KPI / stat strip at top of dashboard-style tabs */
.admin-kpis {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(160px, 1fr));
  gap: 0.9rem;
  margin-bottom: 1.5rem;
}
.admin-kpi {
  background: var(--admin-surface);
  border: 1px solid var(--admin-line);
  border-radius: var(--admin-radius);
  padding: 1.1rem 1.25rem;
}
.admin-kpi span { display: block; font-size: 0.75rem; color: var(--admin-ink-soft); font-weight: 600; margin-bottom: 0.3rem; }
.admin-kpi strong { font-size: 1.5rem; color: var(--admin-ink); }

/* ---------- Mobile ---------- */
@media (max-width: 980px) {
  /* FIXED (per request — Galaxy S24 FE screenshot): grid/flex items default
     to min-width:auto, so any unshrinkable content in .admin-main (a wide
     table, a KPI row, a nowrap button) refused to shrink below its own
     content width — which forced the WHOLE .admin-shell grid (sidebar
     included) wider than the phone's screen, and the sidebar rendered as a
     tall, near-illegible sliver with its title text wrapping one syllable
     per line. min-width: 0 on both grid tracks is what actually lets them
     shrink to the viewport; everything below just keeps each piece of
     content (brand text, nav labels, the bookstore-switch pill) from
     wrapping mid-word once the bar is a normal-height horizontal strip. */
  .admin-shell { grid-template-columns: 1fr; }
  .admin-side, .admin-main { min-width: 0; }
  .admin-side {
    /* FIXED (per request): the sidebar now stays pinned to the top of the
       screen while scrolling on mobile, same idea as the site header. */
    position: sticky;
    top: 0;
    z-index: 40;
    height: auto;
    flex-direction: row;
    flex-wrap: nowrap;
    overflow-x: auto;
    -webkit-overflow-scrolling: touch;
    padding: 0.85rem;
    border-inline-end: none;
    border-bottom: 1px solid var(--admin-side-line);
  }
  .admin-brand {
    border-bottom: none;
    padding: 0 0.75rem 0 0.25rem;
    margin-bottom: 0;
    border-inline-end: 1px solid var(--admin-side-line);
    flex-shrink: 0;
  }
  .admin-brand strong, .admin-brand small { white-space: nowrap; }
  .admin-side .side-group-label { display: none; }
  .admin-side hr.side-sep { display: none; }
  .admin-side a { white-space: nowrap; flex-shrink: 0; }
  .admin-side a.admin-exit { margin-top: 0; }
  .admin-maint-pill { margin-bottom: 0; white-space: nowrap; flex-shrink: 0; }
  .admin-main { padding: 1.5rem 1.1rem 3rem; }
  .admin-grid-fields { grid-template-columns: 1fr; }
  .admin-kpis { grid-template-columns: 1fr 1fr; }
  .admin-topbar { flex-direction: column; align-items: stretch; }
  .admin-whoami { justify-content: space-between; }

  /* FIXED (per request): the mobile admin bar collapses to a minimal strip
     — brand + a menu toggle + only the CURRENTLY SELECTED item — instead
     of dumping every nav link into one crowded horizontal row. Tapping the
     toggle expands the full list (it wraps onto its own lines); choosing
     any item is a normal page navigation, so the next page loads back in
     this same minimal, "just show what's selected" state automatically. */
  .admin-side-toggle {
    display: inline-flex;
    align-items: center;
    gap: 0.4rem;
    flex-shrink: 0;
    background: rgba(255, 255, 255, 0.12);
    color: var(--admin-side-text-strong);
    border: 1px solid var(--admin-side-line);
    border-radius: 10px;
    padding: 0.5rem 0.75rem;
    font-size: 0.78rem;
    font-weight: 600;
    font-family: inherit;
    cursor: pointer;
    white-space: nowrap;
  }
  .admin-side-toggle:hover { background: rgba(255, 255, 255, 0.2); }
  /* FIXED (per request): the collapsed bar was still forcing the wide
     "switch panel" pill AND the current page's own link to stay visible
     alongside the brand + toggle — on a narrow phone that's four
     competing pieces of content fighting for one row, which is exactly
     the cramped/cut-off look reported. Collapsed now shows only the
     brand and the toggle; the page's own <h1> in .admin-topbar already
     says where you are, so the duplicate active-link pill is redundant
     here. Tap "منو" to reach the switch-panel link and every other item. */
  .admin-side:not(.is-expanded) a { display: none; }
  .admin-side:not(.is-expanded) .admin-maint-pill { display: none; }
  .admin-side.is-expanded {
    flex-wrap: wrap;
    overflow-x: visible;
    max-height: 75vh;
    overflow-y: auto;
  }
  /* FIXED (per request): expanded nav items had no flex-basis, so they
     packed inline next to each other (and next to full-width group
     labels) in whatever order they happened to wrap — which is what made
     things like the "پشتیبانی" group label look like it had landed in a
     random spot. Every link now takes its own full-width row, same as
     the group labels and separators already did, so the expanded menu
     reads as a normal, neatly stacked list. */
  .admin-side.is-expanded a { flex-basis: 100%; }
  .admin-side.is-expanded .side-group-label { display: block; flex-basis: 100%; }
  .admin-side.is-expanded hr.side-sep { display: block; flex-basis: 100%; border: none; }
}
@media (min-width: 981px) {
  .admin-side-toggle { display: none; }

  /* UPDATED (v1.1, per request — "two scrollbars on the right side, keep only
     one"): the sidebar is a full-height sticky column with its own
     overflow-y, and the page itself scrolls too, so two scrollbars sat
     side by side at the right edge. Fix: the sidebar keeps scrolling
     (mouse wheel / trackpad / keyboard / touch all still work — hover over
     the menu and scroll to reach the lower items, and once it hits its end
     the wheel carries on to the page) but its scrollbar is now invisible
     (see the .admin-side scrollbar rules in the v1.1 block at the end of
     this file), leaving the window's own scrollbar as the only one.
     This replaces the earlier scaleX(-1) mirror trick, which existed only
     to shove the sidebar's scrollbar to the opposite edge; with no visible
     scrollbar there is nothing left to move, so the sidebar renders
     normally again. */
}

/* ---------- Professional split login (EF / Pearson style) ---------- */
.auth-wrap { min-height: 82vh; align-items: center; padding: 2.5rem 1rem; }
.auth-shell {
  width: min(860px, 100%);
  margin-inline: auto;
  display: grid;
  grid-template-columns: 1fr 1.1fr;
  border-radius: 24px;
  overflow: hidden;
  box-shadow: 0 8px 40px rgba(0,0,0,0.14);
  border: 1px solid var(--lg-border-outer, var(--line));
}
.auth-brand-panel {
  position: relative;
  overflow: hidden;
  isolation: isolate;
  padding: 2.5rem 2rem;
  color: #fff;
  background: linear-gradient(135deg, #7c3aed, #EE6334);
  display: flex;
  flex-direction: column;
  justify-content: space-between;
  gap: 1.5rem;
}
/* Readability overlay, painted above the full-bleed logo image and below
   the text content — keeps the heading/paragraph/stats legible over any
   part of the artwork. */
.auth-brand-panel::before {
  content: "";
  position: absolute;
  inset: 0;
  background: linear-gradient(155deg, rgba(10,8,6,0.72), rgba(10,8,6,0.42));
  z-index: 1;
  pointer-events: none;
}
.auth-brand-panel .logo-mark {
  width: 64px; height: 64px;
  border-radius: 16px;
  background: rgba(255,255,255,0.15);
  backdrop-filter: blur(8px);
}
.auth-brand-panel .logo-img { object-fit: contain; }
/* The logo now fills the entire brand-panel canvas edge-to-edge, instead
   of sitting inside a small centered rounded box. */
.auth-logo-hero {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  margin: 0;
  border-radius: 0;
  background: none;
  backdrop-filter: none;
  border: none;
  box-shadow: none;
  z-index: 0;
}
.auth-logo-img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
}
.auth-brand-text {
  position: relative;
  z-index: 2;
}
.auth-brand-panel h2 { color: #fff; font-size: 1.25rem; margin-top: 0.85rem; }
.auth-brand-panel p { color: rgba(255,255,255,0.82); font-size: 0.9rem; max-width: 30ch; line-height: 1.6; }
.auth-brand-stats { display: flex; gap: 1.5rem; flex-wrap: wrap; }
.auth-brand-stats div strong { display: block; font-size: 1.3rem; }
.auth-brand-stats div span { font-size: 0.72rem; color: rgba(255,255,255,0.75); text-transform: uppercase; letter-spacing: 0.04em; }
.auth-form-panel {
  background: var(--card);
  padding: 2.5rem 2rem;
  display: flex;
  flex-direction: column;
  justify-content: center;
  gap: 0;
}
.auth-form-panel .auth-card { box-shadow: none; border: none; background: transparent; padding: 0; }
.auth-form-panel .auth-card::before { display: none; }
/* Better field inputs on login */
.auth-form-panel input[type="text"],
.auth-form-panel input[type="password"],
.auth-form-panel input:not([type="hidden"]):not([type="submit"]) {
  display: block;
  width: 100%;
  padding: 0.7rem 1rem;
  border: 1.5px solid var(--line);
  border-radius: 12px;
  background: var(--bg-soft);
  color: var(--text);
  font-size: 0.95rem;
  font-family: var(--font);
  transition: border-color 0.2s, box-shadow 0.2s, background 0.2s;
  outline: none;
}
.auth-form-panel input:focus {
  border-color: #7c3aed;
  box-shadow: 0 0 0 3px rgba(124, 58, 237, 0.14);
  background: var(--card);
}
.auth-form-panel .btn-primary {
  width: 100%;
  padding: 0.75rem 1.25rem;
  font-size: 1rem;
  margin-top: 0.5rem;
}
@media (max-width: 680px) {
  .auth-shell { grid-template-columns: 1fr; border-radius: 20px; }
  .auth-brand-panel { padding: 1.75rem 1.5rem; min-height: 140px; justify-content: flex-start; }
  .auth-brand-panel p { display: none; }
  .auth-form-panel { padding: 2rem 1.5rem; }
}


/* ---------- Branches: directions button + bookstore card (added) ---------- */
.branch-card {
  padding: 1.5rem 1.4rem;
  display: flex;
  flex-direction: column;
  gap: 0.35rem;
}
.branch-card .branch-directions,
.branch-actions {
  margin-top: 0.75rem;
}
.branch-actions {
  display: flex;
  flex-wrap: wrap;
  gap: 0.5rem;
}
.branch-directions {
  align-self: flex-start;
  display: inline-flex;
  align-items: center;
  gap: 0.4rem;
}
.branch-card-bookstore {
  border-color: rgba(238, 99, 52, 0.3);
  background: linear-gradient(180deg, rgba(255,255,255,0.9) 0%, rgba(255,247,237,0.9) 100%);
}
[data-theme='dark'] .branch-card-bookstore {
  background: rgba(238, 99, 52, 0.08);
}
.branch-bookstore-badge {
  align-self: flex-start;
  display: inline-flex;
  align-items: center;
  gap: 0.35rem;
  margin-bottom: 0.35rem;
}
.contact-bookstore {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: 1.25rem;
}
.contact-bookstore .btn { flex-shrink: 0; }
@media (max-width: 560px) {
  .contact-bookstore { flex-direction: column; align-items: stretch; text-align: center; }
}

/* =========================================================
   Network / Org map — "how we're connected" diagram
   Hub -> cluster heads -> leaf nodes. Connector lines are
   drawn into #networkLines by app.js (see network map engine).
   ========================================================= */
.network-map-section { overflow: visible; }
.network-map {
  position: relative;
  padding: 1rem 0 0.5rem;
}
.network-lines {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  overflow: visible;
  pointer-events: none;
  z-index: 0;
}
.network-lines path {
  fill: none;
  stroke: var(--orange);
  stroke-width: 1.6;
  opacity: 0.55;
  stroke-linecap: round;
  stroke-dasharray: 6 7;
  animation: sd-line-flow 1.6s linear infinite;
}
[data-theme='dark'] .network-lines path { opacity: 0.6; }
@keyframes sd-line-flow { to { stroke-dashoffset: -52; } }
.network-lines circle.network-pulse-dot {
  fill: var(--amber);
}
.network-lines marker path {
  fill: var(--orange);
  opacity: 0.75;
}

.network-hub {
  position: relative;
  z-index: 1;
  display: flex;
  align-items: center;
  gap: 0.85rem;
  width: fit-content;
  max-width: 100%;
  margin: 0 auto 3rem;
  padding: 1rem 1.5rem;
  background: var(--card);
  border: 1px solid var(--line);
  border-radius: 999px;
  box-shadow: var(--shadow-lg);
}
.network-hub-icon {
  flex-shrink: 0;
  width: 52px; height: 52px;
  border-radius: 14px;
  display: flex; align-items: center; justify-content: center;
  font-size: 1.3rem;
  color: #fff;
  background: linear-gradient(135deg, var(--orange), var(--amber));
}
.network-hub-text { display: flex; flex-direction: column; line-height: 1.35; }
.network-hub-text strong { font-size: 1.05rem; }
.network-hub-text .muted { font-size: 0.82rem; }
.network-pulse-ring {
  position: absolute;
  inset: -1px;
  border-radius: 999px;
  border: 2px solid var(--orange);
  opacity: 0;
  animation: sd-pulse-ring 2.6s var(--ease) infinite;
  pointer-events: none;
}
@keyframes sd-pulse-ring {
  0% { transform: scale(1); opacity: 0.5; }
  100% { transform: scale(1.18); opacity: 0; }
}

.network-clusters {
  position: relative;
  z-index: 1;
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: 1.5rem;
}
@media (max-width: 900px) {
  .network-clusters { grid-template-columns: repeat(2, 1fr); }
}
@media (max-width: 560px) {
  .network-clusters { grid-template-columns: 1fr; }
  .network-hub { margin-bottom: 2.5rem; }
}

@keyframes sd-dot-flash {
  0%, 100% { box-shadow: 0 0 0 0 rgba(245, 158, 11, 0.55); }
  50% { box-shadow: 0 0 0 6px rgba(245, 158, 11, 0); }
}

/* ---------- Network cards (org-chart style) ---------- */
.network-card {
  position: relative;
  display: flex;
  flex-direction: column;
  gap: 0.9rem;
  padding: 1.1rem 1.15rem 1.25rem;
  background: var(--card);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  box-shadow: var(--shadow);
  transition: transform 0.3s var(--ease), box-shadow 0.3s var(--ease), border-color 0.25s var(--ease);
}
.network-card:hover {
  transform: translateY(-4px);
  box-shadow: var(--shadow-lg);
  border-color: rgba(238, 99, 52, 0.25);
}
.network-card-head {
  display: flex;
  align-items: center;
  gap: 0.65rem;
  padding-bottom: 0.85rem;
  border-bottom: 1px solid var(--line);
}
.network-card-back {
  flex-shrink: 0;
  width: 30px; height: 30px;
  border-radius: 50%;
  display: flex; align-items: center; justify-content: center;
  background: var(--bg-ice);
  color: var(--slate);
  font-size: 0.72rem;
}
.network-card-title {
  flex: 1;
  font-weight: 700;
  font-size: 0.94rem;
  color: var(--text);
}
.network-card-icon {
  flex-shrink: 0;
  width: 38px; height: 38px;
  border-radius: 11px;
  display: flex; align-items: center; justify-content: center;
  background: var(--bg-ice);
  color: var(--navy);
  font-size: 1rem;
}
.network-card-icon-accent {
  background: linear-gradient(135deg, var(--orange), var(--amber));
  color: #fff;
}
.network-list { display: flex; flex-direction: column; gap: 0.55rem; }
.network-list li {
  position: relative;
  padding-inline-start: 1.1rem;
  font-size: 0.86rem;
  color: var(--muted);
}
[dir='rtl'] .network-list li { padding-inline-start: 1.1rem; padding-inline-end: 0; }
.network-list li::before {
  content: '';
  position: absolute;
  inset-inline-start: 0;
  top: 0.5em;
  width: 6px; height: 6px;
  border-radius: 2px;
  background: var(--orange);
}

@media (prefers-reduced-motion: reduce) {
  .network-lines path { animation: none; }
  .network-pulse-ring { animation: none; opacity: 0; }
}

/* =========================================================
   Color accents — small flashing dots + nudging arrows
   Lightweight, reusable, on-brand touches for a livelier feel.
   ========================================================= */

/* Small flashing dot before every kicker label, site-wide */
.kicker::before {
  content: '';
  display: inline-block;
  width: 6px; height: 6px;
  margin-inline-end: 6px;
  vertical-align: middle;
  border-radius: 50%;
  background: var(--amber);
  animation: sd-dot-flash 1.8s ease-in-out infinite;
}

/* Ambient floating color circles — decorative, non-interactive */
.floaters {
  position: absolute;
  inset: 0;
  overflow: hidden;
  pointer-events: none;
  z-index: 0;
}
.hero-slider { position: relative; }
.hero-slider .container.slider { position: relative; z-index: 1; }
.panel-card-accent { position: relative; overflow: hidden; }
.panel-card-accent > *:not(.floaters) { position: relative; z-index: 1; }

.floater {
  position: absolute;
  border-radius: 50%;
  filter: blur(0.5px);
  opacity: 0.3;
  animation: sd-float 7s ease-in-out infinite;
}
.floater-1 { width: 14px; height: 14px; background: var(--orange); top: 14%; inset-inline-start: 6%; animation-duration: 6.5s; }
.floater-2 { width: 9px;  height: 9px;  background: var(--amber);  top: 72%; inset-inline-start: 16%; animation-duration: 8s; animation-delay: 1.1s; }
.floater-3 { width: 18px; height: 18px; background: var(--amber);  top: 20%; inset-inline-end: 10%; animation-duration: 9s; animation-delay: 0.5s; }
.floater-4 { width: 10px; height: 10px; background: var(--orange); top: 76%; inset-inline-end: 18%; animation-duration: 7s; animation-delay: 2s; }
@keyframes sd-float {
  0%, 100% { transform: translateY(0) scale(1); opacity: 0.25; }
  50% { transform: translateY(-18px) scale(1.2); opacity: 0.55; }
}

/* FIXED (per request): the little nudging arrow on hero/CTA buttons
   ("تعیین سطح رایگان" and friends) didn't look good — replaced with a
   plain periodic flash/highlight sweep across the button itself instead,
   no arrow glyph at all. Kept the .btn-nudge class name so every existing
   caller (hero CTAs, about button, 404 page, level-test-remote's call
   button) picks up the new effect automatically. */
.btn-nudge {
  position: relative;
  overflow: hidden;
  isolation: isolate;
}
.btn-nudge::after {
  content: '';
  position: absolute;
  inset: 0;
  background: rgba(255, 255, 255, 0.4);
  opacity: 0;
  pointer-events: none;
  animation: sd-btn-flash 4s ease-in-out infinite;
}

@keyframes sd-btn-flash {
  0%, 88%, 100% { opacity: 0; }
  92% { opacity: 1; }
}

@media (prefers-reduced-motion: reduce) {
  .kicker::before { animation: none; }
  .floater { animation: none; opacity: 0.25; }
  .btn-nudge::after { animation: none; }
}

/* KPI stat cards — shared by admin/panel.php, admin/secretary.php,
   admin/manager.php and admin/accounting.php dashboards. */
.acct-kpi-row { display: grid; grid-template-columns: repeat(auto-fit, minmax(200px, 1fr)); gap: 1rem; }
.acct-kpi-card { background: var(--card); border: 1px solid var(--line); border-radius: var(--radius-sm); padding: 1rem 1.15rem; display: flex; flex-direction: column; gap: 0.35rem; }
.acct-kpi-label { font-size: 0.8rem; color: var(--muted); }
.acct-kpi-value { font-size: 1.4rem; }
.acct-kpi-pending .acct-kpi-value { color: #b45309; }

/* FIXED (per request): the single consolidated "who you are + what's
   waiting for you" card that replaced the old 4-card KPI grid on
   admin/panel.php and admin/secretary.php — name, role, a welcome line,
   and the one number that actually needs action (unanswered requests). */
.admin-profile-card {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 1rem;
  flex-wrap: wrap;
  padding: 1.1rem 1.4rem;
  text-align: center;
  /* FIXED (per request): "orange got used too much — maybe just use it
     as a subtle accent, e.g. around the name card" — a thin tinted
     border here instead of another solid orange fill. */
  border: 1px solid rgba(238, 99, 52, 0.25);
}
.admin-profile-avatar { width: 44px; height: 44px; font-size: 1.05rem; flex-shrink: 0; }
.admin-profile-info { display: flex; flex-direction: column; align-items: center; gap: 0.4rem; }
.admin-profile-info strong { font-size: 1.15rem; font-weight: 700; }
.admin-profile-req {
  display: inline-flex;
  align-items: center;
  gap: 0.5rem;
  padding: 0.55rem 1rem;
  border-radius: 12px;
  background: var(--admin-surface-soft);
  border: 1px solid var(--admin-side-line);
  color: var(--admin-ink-soft);
  font-size: 0.85rem;
  font-weight: 600;
  text-decoration: none;
  transition: background 0.2s ease, border-color 0.2s ease;
}
.admin-profile-req strong { color: var(--admin-ink); font-size: 1.05rem; }
.admin-profile-req:hover { background: rgba(238, 99, 52, 0.1); border-color: rgba(238, 99, 52, 0.3); }
.admin-profile-req.has-pending { background: rgba(234, 179, 8, 0.12); border-color: rgba(234, 179, 8, 0.35); color: #92400e; }
.admin-profile-req.has-pending strong { color: #92400e; }
[data-theme='dark'] .admin-profile-req.has-pending { color: #fcd34d; }
[data-theme='dark'] .admin-profile-req.has-pending strong { color: #fcd34d; }

/* Quick-access maintenance-mode indicator on the account card — grey/off
   by default, amber/on when maintenance is active. Links straight to the
   Security tab's full toggle card. */
.admin-profile-maint {
  display: inline-flex;
  align-items: center;
  gap: 0.5rem;
  padding: 0.55rem 1rem;
  border-radius: 12px;
  background: var(--admin-surface-soft);
  border: 1px solid var(--admin-side-line);
  color: var(--admin-ink-soft);
  font-size: 0.85rem;
  font-weight: 600;
  text-decoration: none;
  transition: background 0.2s ease, border-color 0.2s ease;
}
.admin-profile-maint:hover { background: rgba(234, 179, 8, 0.1); border-color: rgba(234, 179, 8, 0.3); }
.admin-profile-maint.is-on { background: rgba(234, 179, 8, 0.14); border-color: rgba(234, 179, 8, 0.4); color: #92400e; }
.admin-profile-maint.is-on i { color: #eab308; }
[data-theme='dark'] .admin-profile-maint.is-on { color: #fcd34d; }
@media (max-width: 600px) {
  .admin-profile-maint { width: 100%; justify-content: center; }
}
@media (max-width: 600px) {
  .admin-profile-req { margin-inline-start: 0; width: 100%; justify-content: center; }
}

/* Student dashboard — LIMS-encouragement banner ("just requests and certs
   are here; everything else lives in LIMS"). */
.lims-banner {
  display: flex;
  align-items: center;
  gap: 1rem;
  padding: 1rem 1.25rem;
  border-radius: var(--radius-sm);
  margin: 1rem 0 1.5rem;
  border: 1px solid rgba(14, 165, 233, 0.25);
  background: rgba(14, 165, 233, 0.08);
}
.lims-banner > i { font-size: 1.6rem; color: #0284c7; flex-shrink: 0; }
.lims-banner > div { flex: 1; min-width: 200px; }
.lims-banner > div strong { display: block; margin-bottom: 0.2rem; }
.lims-banner > div p { margin: 0; font-size: 0.85rem; color: var(--muted); }
.lims-banner > a { flex-shrink: 0; white-space: nowrap; }
@media (max-width: 640px) {
  .lims-banner { flex-direction: column; align-items: flex-start; }
}


/* =========================================================
   2026-09 front upgrade
   — stats row that flows on from the hero (rise-in reveal)
   — typing effect on the small orange kicker tags
   — five standardised course tracks (homepage)
   — four standardised location cards (homepage)
   — "student path" 4-step section above the footer
   — footer v2: intro + slogan, one 3-part panel, social, bottom bar
   Everything is scoped to NEW class names (.trust-bar--flow,
   .track-*, .branches-grid, .journey-*, .sf-*), so no existing
   page — including every admin panel — is affected.
   ========================================================= */

/* ---------- Shared bits ---------- */
.sr-only {
  position: absolute;
  width: 1px; height: 1px;
  padding: 0; margin: -1px;
  overflow: hidden;
  clip: rect(0, 0, 0, 0);
  white-space: nowrap;
  border: 0;
}
/* Kicker waiting for its turn to type: keep the space, hide the text
   (set/cleared by assets/js/app.js). */
[data-type-pending] { visibility: hidden; }
/* Anchor jumps (footer → #track-…, #branches, #journey) land below the
   sticky header instead of underneath it. */
[id^="track-"], #programs, #branches, #journey { scroll-margin-top: 6rem; }

/* ---------- Stats row directly under the hero ---------- */
.trust-bar--flow {
  background: transparent;
  padding: 0.5rem 0 1.25rem;
  position: relative;
}
.trust-bar--flow .stats { position: relative; z-index: 1; }
.trust-bar--flow .stat-card { box-shadow: var(--shadow-lg); }
/* 'rise' reveal: a longer, softer lift than the default fade so the cards
   seem to slide up out of the banner as you scroll. */
[data-reveal="rise"] {
  transform: translateY(54px) scale(0.965);
  transition-duration: 0.95s;
}

/* ---------- Course tracks ---------- */
.tracks-grid { align-items: stretch; }
.track-card { gap: 0.55rem; }
.track-card h3 { margin: 0.1rem 0 0; }
.track-card > .muted { margin: 0; font-size: 0.92rem; line-height: 1.75; }
.track-points {
  list-style: none;
  margin: 0.3rem 0 0;
  padding: 0;
  display: grid;
  gap: 0.4rem;
}
.track-points li {
  display: flex;
  align-items: flex-start;
  gap: 0.55rem;
  font-size: 0.9rem;
  line-height: 1.6;
  color: var(--text);
}
.track-points i {
  flex-shrink: 0;
  margin-top: 0.42em;
  font-size: 0.7rem;
  color: var(--orange);
}
.track-meta {
  margin: auto 0 0;
  padding-top: 0.7rem;
  border-top: 1px dashed var(--line);
  display: flex;
  align-items: center;
  gap: 0.45rem;
  font-weight: 600;
}
.track-meta i { color: var(--orange); }
.track-points + .track-meta,
.track-card > .muted + .track-meta { margin-top: auto; }
.track-card-cta {
  justify-content: center;
  border-color: rgba(238, 99, 52, 0.3);
  background: linear-gradient(180deg, rgba(255, 255, 255, 0.9) 0%, rgba(255, 247, 237, 0.9) 100%);
}
[data-theme='dark'] .track-card-cta { background: rgba(238, 99, 52, 0.08); }
.track-card-cta .branch-directions { margin-top: 0.6rem; }
.track-extras {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0.6rem;
  margin-top: 1.6rem;
}
.track-extras-label { font-size: 0.85rem; font-weight: 700; color: var(--muted); }
.track-extra {
  display: inline-flex;
  align-items: center;
  gap: 0.45rem;
  padding: 0.4rem 0.9rem;
  border-radius: 999px;
  border: 1px solid var(--line);
  background: var(--card);
  color: var(--text);
  font-size: 0.88rem;
  font-weight: 600;
  transition: border-color 0.2s, color 0.2s, transform 0.25s var(--ease), box-shadow 0.25s var(--ease);
}
.track-extra i { color: var(--orange); font-size: 0.85rem; }
.track-extra:hover {
  border-color: var(--orange);
  color: var(--orange);
  transform: translateY(-1px);
  box-shadow: 0 6px 16px rgba(238, 99, 52, 0.15);
}

/* ---------- Location cards: Central Office / Moradi / Payambar / Bookstore ---------- */
.branches-grid {
  display: grid;
  grid-template-columns: repeat(4, minmax(0, 1fr));
  gap: 1.25rem;
  align-items: stretch;
}
@media (max-width: 1080px) { .branches-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
@media (max-width: 560px)  { .branches-grid { grid-template-columns: 1fr; } }
.branches-grid .branch-card { gap: 0.45rem; }
.branches-grid .branch-icon { margin-bottom: 0.2rem; }
.branches-grid .branch-card h3 { margin: 0; }
.branch-address { margin: 0; font-size: 0.92rem; line-height: 1.75; }
.branch-phone,
.branch-hours {
  margin: 0;
  display: flex;
  align-items: flex-start;
  gap: 0.5rem;
  font-size: 0.88rem;
  line-height: 1.6;
}
.branch-phone i,
.branch-hours i {
  flex-shrink: 0;
  margin-top: 0.3em;
  color: var(--orange);
}
.branches-grid .branch-directions { margin-top: auto; }
.branches-grid .branch-hours { margin-bottom: 0.85rem; }

/* ---------- Student path ---------- */
.journey-steps {
  list-style: none;
  margin: 0;
  padding: 0;
  display: grid;
  grid-template-columns: repeat(4, minmax(0, 1fr));
  gap: 1.5rem;
}
.journey-step { position: relative; display: flex; }
/* dashed connector living in the gap between two cards */
.journey-step:not(:last-child)::after {
  content: '';
  position: absolute;
  top: 44px;
  inset-inline-end: -1.5rem;
  width: 1.5rem;
  border-top: 2px dashed rgba(238, 99, 52, 0.55);
}
.journey-card {
  width: 100%;
  padding: 1.4rem 1.25rem 1.25rem;
  display: flex;
  flex-direction: column;
  gap: 0.5rem;
}
.journey-top {
  display: flex;
  align-items: center;
  justify-content: space-between;
  margin-bottom: 0.35rem;
}
.journey-num {
  width: 44px; height: 44px;
  border-radius: 50%;
  display: grid;
  place-items: center;
  font-size: 1.1rem;
  font-weight: 800;
  color: #fff;
  background: linear-gradient(180deg, #f97316 0%, #EE6334 100%);
  box-shadow: 0 6px 16px rgba(238, 99, 52, 0.35), inset 0 1px 1px rgba(255, 255, 255, 0.5);
}
.journey-icon {
  width: 44px; height: 44px;
  border-radius: 14px;
  display: grid;
  place-items: center;
  font-size: 1.1rem;
  color: var(--orange);
  background: rgba(238, 99, 52, 0.1);
}
.journey-card h3 { margin: 0; }
.journey-card p { margin: 0; font-size: 0.92rem; line-height: 1.75; }
.journey-link {
  margin-top: auto;
  padding-top: 0.6rem;
  display: inline-flex;
  align-items: center;
  gap: 0.45rem;
  font-size: 0.88rem;
  font-weight: 700;
  color: var(--orange);
}
.journey-link i { font-size: 0.78rem; transition: transform 0.25s var(--ease); }
.journey-link:hover i { transform: translateX(3px); }
[dir="rtl"] .journey-link:hover i { transform: translateX(-3px); }
.journey-cta {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: 0.75rem;
  margin-top: 2rem;
}
@media (max-width: 960px) {
  .journey-steps { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .journey-step::after { display: none; }
}
@media (max-width: 560px) {
  .journey-steps { grid-template-columns: 1fr; gap: 1rem; }
}

/* ---------- Footer v2 ---------- */
.site-footer--v2 {
  position: relative;
  margin-top: 3rem;
}
/* thin glowing line along the top edge */
.site-footer--v2::before {
  content: '';
  position: absolute;
  top: 0;
  left: 50%;
  transform: translateX(-50%);
  width: min(560px, 80%);
  height: 2px;
  border-radius: 999px;
  background: linear-gradient(90deg, transparent, var(--orange), transparent);
  opacity: 0.75;
}
.sf-wrap { padding: 2.75rem 0 1rem; }

.sf-top {
  max-width: 720px;
  margin: 0 auto 2rem;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 0.85rem;
  text-align: center;
}
.sf-brand { margin: 0; }
.sf-intro {
  margin: 0;
  font-size: 0.95rem;
  line-height: 1.95;
  color: var(--muted);
}
.sf-slogan {
  margin: 0.3rem 0 0;
  font-size: clamp(1.55rem, 3.8vw, 2.4rem);
  font-weight: 800;
  line-height: 1.35;
  letter-spacing: 0;
  background: linear-gradient(90deg, var(--orange), var(--amber));
  -webkit-background-clip: text;
  background-clip: text;
  color: transparent;
}

/* one card, three parts, thin lines between them */
.sf-panel {
  display: grid;
  grid-template-columns: 1fr 1.15fr 1.35fr;
  background: var(--card);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  box-shadow: var(--shadow);
  overflow: hidden;
}
.sf-col { padding: 1.6rem 1.75rem; min-width: 0; }
.sf-col + .sf-col { border-inline-start: 1px solid var(--line); }
.sf-col h4 {
  display: flex;
  align-items: center;
  gap: 0.5rem;
  margin: 0 0 1.05rem;
  font-size: 0.98rem;
  color: var(--text);
}
.sf-col h4::before {
  content: '';
  width: 6px; height: 6px;
  border-radius: 50%;
  background: var(--orange);
}
.sf-links,
.sf-contact,
.sf-branches {
  list-style: none;
  margin: 0;
  padding: 0;
  display: grid;
  gap: 0.6rem;
}
.sf-links a {
  display: inline-flex;
  color: var(--muted);
  font-size: 0.92rem;
  transition: color 0.2s, transform 0.2s var(--ease);
}
.sf-links a:hover { color: var(--orange); transform: translateX(-3px); }
[dir="rtl"] .sf-links a:hover { transform: translateX(3px); }
.sf-contact li {
  display: flex;
  align-items: flex-start;
  gap: 0.55rem;
  color: var(--muted);
  font-size: 0.9rem;
  line-height: 1.6;
}
.sf-contact i {
  flex-shrink: 0;
  width: 1.9rem; height: 1.9rem;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  border-radius: 8px;
  font-size: 0.85rem;
  color: var(--orange);
  background: rgba(238, 99, 52, 0.12);
}
.sf-contact li > span { padding-top: 0.25rem; }
.sf-branches {
  margin-top: 1.1rem;
  padding-top: 1rem;
  border-top: 1px dashed var(--line);
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 0.5rem 0.75rem;
}
.sf-branches a {
  display: flex;
  align-items: center;
  gap: 0.45rem;
  color: var(--muted);
  font-size: 0.86rem;
  transition: color 0.2s;
}
.sf-branches a i { color: var(--orange); font-size: 0.8rem; width: 1rem; text-align: center; }
.sf-branches a:hover { color: var(--orange); }

/* social: handles + follow links */
.sf-social {
  margin-top: 1.25rem;
  padding: 0.95rem 1.25rem;
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: 0.9rem;
  border: 1px solid var(--line);
  border-radius: var(--radius-sm);
  background: rgba(255, 255, 255, 0.55);
}
.sf-social-label { font-size: 0.92rem; font-weight: 700; color: var(--text); }
.sf-social-links { display: flex; flex-wrap: wrap; align-items: center; gap: 0.6rem; }
.sf-social-pill {
  display: inline-flex;
  align-items: center;
  gap: 0.7rem;
  padding: 0.5rem 1rem;
  border-radius: 14px;
  border: 1px solid var(--line);
  background: var(--card);
  color: var(--text);
  transition: border-color 0.2s, box-shadow 0.25s var(--ease), transform 0.25s var(--ease);
}
.sf-social-pill > i { font-size: 1.4rem; color: var(--orange); }
.sf-social-text { display: flex; flex-direction: column; line-height: 1.3; }
.sf-social-text small { font-size: 0.72rem; color: var(--muted); }
.sf-social-text strong { font-size: 0.9rem; font-weight: 700; }
.sf-social-pill:hover {
  border-color: var(--orange);
  transform: translateY(-2px);
  box-shadow: 0 8px 20px rgba(238, 99, 52, 0.18);
}
.sf-bottom { margin-top: 1.25rem; }

@media (max-width: 900px) {
  .sf-panel { grid-template-columns: 1fr; }
  .sf-col + .sf-col { border-inline-start: 0; border-top: 1px solid var(--line); }
}
@media (max-width: 560px) {
  .sf-col { padding: 1.35rem 1.25rem; }
  .sf-branches { grid-template-columns: 1fr; }
  .sf-social { flex-direction: column; align-items: flex-start; }
  .sf-social-pill { width: 100%; }
}

/* one phone number per line so a number never wraps in the middle */
.branch-phone-list { display: flex; flex-direction: column; align-items: flex-start; gap: 0.1rem; }
.branch-phone-list > span { white-space: nowrap; }


/* =========================================================
   Platform v1.1 — admin panel upgrades
   ========================================================= */

/* ---- 1) Only ONE scrollbar in the dashboard ------------------------------
   The sidebar stays scrollable but never draws its own scrollbar (Firefox:
   scrollbar-width; old Edge/IE: -ms-overflow-style; Chrome/Safari/new Edge:
   the ::-webkit-scrollbar rule). Applies to every admin panel's sidebar
   (site admin, bookstore, secretary, manager, supervisor, accounting, SMS).
   overscroll-behavior stays at its default (auto) on purpose, so that when
   the menu reaches its end the mouse wheel continues scrolling the page. */
.admin-side {
  scrollbar-width: none;
  -ms-overflow-style: none;
}
.admin-side::-webkit-scrollbar {
  width: 0;
  height: 0;
  display: none;
}

/* ---- 2) "Apply changes" bar always visible at the bottom ------------------
   The save bar (.admin-toolbar) that closes each admin form is now sticky:
   while the form is on screen the bar is pinned to the bottom of the
   viewport, and when you scroll to the end of the form it simply rests in
   its normal place right below the last field. Only the toolbar that is the
   LAST child of a form is affected, so filter/search bars and CSV rows
   (which are not form footers) keep behaving as before. */
.admin-main form > .admin-toolbar:last-child {
  position: sticky;
  bottom: 1rem;
  z-index: 25;
  background: var(--admin-surface);
  border-color: rgba(238, 99, 52, 0.3);
  box-shadow:
    0 -10px 26px -12px rgba(0, 0, 0, 0.35),
    0 12px 30px -12px rgba(0, 0, 0, 0.4);
}
/* position: sticky stops working inside an `overflow: hidden` ancestor (it
   would stick to that box instead of the screen). The glass accordions /
   fieldsets that wrap some forms use overflow: hidden for their rounded
   corners, so in the admin they use `overflow: clip` instead: it clips the
   same way but does not create a scroll container, so the bar can still
   stick to the screen. Repeat-item cards already use overflow: visible. */
.admin-main :is(.admin-fieldset, .admin-accordion).glass:not(.admin-repeat-item) {
  overflow: clip;
}

/* ---- 3) Homepage sections: order arrows ---------------------------------- */
.admin-section-toggle-row {
  border-radius: 10px;
  scroll-margin-top: 9rem;
  scroll-margin-bottom: 2rem;
}
.admin-section-toggle-label { flex: 1 1 auto; min-width: 0; }
.admin-section-order {
  display: inline-flex;
  align-items: center;
  gap: 0.35rem;
  flex-shrink: 0;
}
.admin-section-pos {
  min-width: 1.75rem;
  height: 1.75rem;
  padding: 0 0.3rem;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  border-radius: 8px;
  font-size: 0.75rem;
  font-weight: 700;
  color: var(--admin-ink-soft);
  background: var(--admin-surface-soft);
  border: 1px solid var(--admin-line);
}
.admin-section-move {
  width: 30px;
  height: 30px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  padding: 0;
  border-radius: 9px;
  border: 1px solid var(--admin-line);
  background: var(--admin-surface-soft);
  color: var(--admin-ink);
  font-size: 0.72rem;
  cursor: pointer;
  transition: background 0.18s ease, color 0.18s ease, border-color 0.18s ease, transform 0.18s ease;
}
.admin-section-move:hover:not(:disabled) {
  background: var(--orange);
  border-color: var(--orange);
  color: #fff;
  transform: translateY(-1px);
}
.admin-section-move:active:not(:disabled) { transform: translateY(0); }
.admin-section-move:focus-visible {
  outline: 2px solid var(--orange);
  outline-offset: 2px;
}
.admin-section-move:disabled {
  opacity: 0.32;
  cursor: not-allowed;
}
.admin-section-toggle-row.is-moved { animation: sdSectionMoved 0.9s ease; }
@keyframes sdSectionMoved {
  0%   { background: rgba(238, 99, 52, 0.24); }
  100% { background: transparent; }
}
.admin-section-reset {
  display: flex;
  justify-content: flex-end;
  margin-top: 0.6rem;
  padding-top: 0.9rem;
  border-top: 1px solid var(--admin-side-line);
}
@media (prefers-reduced-motion: reduce) {
  .admin-section-toggle-row.is-moved { animation: none; }
  .admin-section-move { transition: none; }
}

/* ---- 4) "Platform version" page ------------------------------------------ */
.sd-version-list {
  display: flex;
  flex-direction: column;
  gap: 1.5rem;
}
.sd-version-card { padding: 1.5rem 1.6rem; }
.sd-version-card.is-current {
  border-color: rgba(34, 197, 94, 0.45);
  box-shadow: 0 0 0 1px rgba(34, 197, 94, 0.16), var(--shadow);
}
.sd-version-head {
  display: flex;
  align-items: center;
  gap: 1rem;
  flex-wrap: wrap;
  margin-bottom: 1.2rem;
  padding-bottom: 1.1rem;
  border-bottom: 1px solid var(--admin-line);
}
.sd-version-badge {
  padding: 0.45rem 0.95rem;
  border-radius: 12px;
  font-size: 0.95rem;
  font-weight: 800;
  color: #fff;
  background: linear-gradient(180deg, #f97316 0%, #ee6334 100%);
  box-shadow: 0 8px 18px -8px rgba(238, 99, 52, 0.7);
  white-space: nowrap;
}
.sd-version-title { flex: 1 1 200px; min-width: 0; }
.sd-version-title h2 {
  margin: 0;
  font-size: 1.15rem;
  color: var(--admin-ink);
}
.sd-version-title small {
  display: block;
  margin-top: 0.15rem;
  color: var(--admin-ink-soft);
}
.sd-version-pill {
  display: inline-flex;
  align-items: center;
  gap: 0.4rem;
  padding: 0.35rem 0.8rem;
  border-radius: 999px;
  font-size: 0.78rem;
  font-weight: 700;
  color: #15803d;
  background: rgba(34, 197, 94, 0.14);
  border: 1px solid rgba(34, 197, 94, 0.38);
}
[data-theme='dark'] .sd-version-pill { color: #4ade80; }

/* NEW (v1.3): each version's changes now split into two headed groups —
   "New features" and "Bug fixes" — instead of one flat list. */
.sd-version-group + .sd-version-group { margin-top: 1.25rem; }
.sd-version-group-label {
  display: flex;
  align-items: center;
  gap: 0.5rem;
  margin: 0 0 0.75rem;
  font-size: 0.82rem;
  font-weight: 700;
  letter-spacing: 0.01em;
  color: var(--admin-ink-soft);
  text-transform: uppercase;
}
.sd-version-group-label i { color: #F1825C; }
.sd-version-group-bugfixes .sd-version-group-label i { color: #f59e0b; }
.sd-version-group-bugfixes .sd-version-check {
  background: #f59e0b;
  box-shadow: 0 5px 12px -4px rgba(245, 158, 11, 0.6);
}
.sd-version-items {
  list-style: none;
  margin: 0;
  padding: 0;
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 1rem 1.75rem;
}
.sd-version-item {
  display: flex;
  align-items: flex-start;
  gap: 0.75rem;
}
.sd-version-check {
  flex: 0 0 auto;
  width: 26px;
  height: 26px;
  margin-top: 0.1rem;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  border-radius: 50%;
  font-size: 0.72rem;
  color: #fff;
  background: #22c55e;
  box-shadow: 0 5px 12px -4px rgba(34, 197, 94, 0.6);
}
.sd-version-item strong {
  display: block;
  font-size: 0.92rem;
  color: var(--admin-ink);
}
.sd-version-item p {
  margin: 0.2rem 0 0;
  font-size: 0.82rem;
  line-height: 1.7;
  color: var(--admin-ink-soft);
}
@media (max-width: 860px) {
  .sd-version-items { grid-template-columns: 1fr; }
  .sd-version-card { padding: 1.2rem 1.1rem; }
}

/* ---------- Request / receipt numbers (REQ-…, RCPT-…) ---------- */
.req-no {
  display: inline-block;
  font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
  font-size: 0.74rem;
  font-weight: 600;
  letter-spacing: 0.02em;
  line-height: 1.5;
  padding: 0.12rem 0.5rem;
  border-radius: 999px;
  background: rgba(238, 99, 52, 0.11);
  color: #c2410c;
  border: 1px solid rgba(238, 99, 52, 0.25);
  white-space: nowrap;
  direction: ltr;
  unicode-bidi: isolate;
}
[data-theme='dark'] .req-no { color: #fdba74; background: rgba(238, 99, 52, 0.16); }
.req-no--lg { font-size: 0.95rem; padding: 0.2rem 0.8rem; }

/* =========================================================
   SITE MOTION SWITCH -- Admin panel -> System -> "Speed & animations".
   includes/header.php adds data-motion="off" to <html> while the super
   admin has animations turned off (lightweight mode), plus
   data-allow="bg reveal text hover slider loops general" listing the
   animation TYPES the admin chose to keep running anyway. Every rule
   below is inert unless data-motion="off" is present, so the default
   look is untouched; each type's rules apply only while that type is
   NOT in data-allow. (assets/js/app.js reads the same two attributes
   for the JS-driven types: reveal, text, hover, slider, loops.)
   Content that starts hidden and waits for JS to reveal it is forced
   visible whenever its type is off, so nothing can stay invisible.
   ========================================================= */

/* general: hover/menu/toast transitions, one-shot keyframes, smooth scroll */
html[data-motion="off"]:not([data-allow~="general"]),
html[data-motion="off"]:not([data-allow~="general"]) body { scroll-behavior: auto !important; }
html[data-motion="off"]:not([data-allow~="general"]) *:not([data-reveal]):not(.word),
html[data-motion="off"]:not([data-allow~="general"]) *:not([data-reveal]):not(.word)::before,
html[data-motion="off"]:not([data-allow~="general"]) *:not([data-reveal]):not(.word)::after {
  transition-duration: 0.001ms !important;
  transition-delay: 0s !important;
  will-change: auto !important;
}
html[data-motion="off"]:not([data-allow~="general"]) .flash-toast,
html[data-motion="off"]:not([data-allow~="general"]) .hamburger,
html[data-motion="off"]:not([data-allow~="general"]) .admin-accordion[open] > *:not(summary),
html[data-motion="off"]:not([data-allow~="general"]) .admin-repeat-collapsible[open] > *:not(summary),
html[data-motion="off"]:not([data-allow~="general"]) .admin-section-toggle-row.is-moved { animation: none !important; }
html[data-motion="off"]:not([data-allow~="general"]) body { opacity: 1 !important; }

/* bg: the fixed, heavily blurred, continuously moving "liquid orbs" */
html[data-motion="off"]:not([data-allow~="bg"]) .liquid-ambient-mesh,
html[data-motion="off"]:not([data-allow~="bg"]) .liquid-orb { display: none !important; }

/* reveal: scroll-in effects and the word-by-word headlines */
html[data-motion="off"]:not([data-allow~="reveal"]) [data-reveal] { opacity: 1 !important; transform: none !important; transition: none !important; }
html[data-motion="off"]:not([data-allow~="reveal"]) .reveal-text .word { opacity: 1 !important; transform: none !important; transition: none !important; }

/* text: typing kickers + count-up numbers (JS only; this is the safety net) */
html[data-motion="off"]:not([data-allow~="text"]) [data-type-pending] { visibility: visible !important; }

/* hover: mouse-follow tilt / glow (JS only; this is the safety net) */
html[data-motion="off"]:not([data-allow~="hover"]) [data-tilt] { transform: none !important; }

/* loops: endlessly repeating decorative keyframes */
html[data-motion="off"]:not([data-allow~="loops"]) .kicker::before,
html[data-motion="off"]:not([data-allow~="loops"]) .btn-nudge::after,
html[data-motion="off"]:not([data-allow~="loops"]) .floater,
html[data-motion="off"]:not([data-allow~="loops"]) .network-lines path,
html[data-motion="off"]:not([data-allow~="loops"]) .network-pulse-ring,
html[data-motion="off"]:not([data-allow~="loops"]) .admin-status-dot { animation: none !important; }
html[data-motion="off"]:not([data-allow~="loops"]) .header-logo-shine .logo-mark::after { display: none !important; }
