@import url('https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;600;700;800;900&family=Libre+Baskerville:ital,wght@0,400;0,700;1,400&family=JetBrains+Mono:wght@400;500;600;700&display=swap');

/* Basic fonts and Tailwind base layer rules are loaded from CDN in Jaspr */
/* Neutral ScholarFee defaults — replaced at runtime with the active
   school's primary (--brand-*) and secondary (--brand-2-*) colors by
   lib/theme/brand_theme.dart. */
:root {
  --brand-rgb: 10 10 10;
  --brand-light: #F4F4F4;
  --brand-dark: #1A1A1A;
  --brand-contrast: #FFFFFF;
  --brand-2-rgb: 64 64 64;
  --brand-2-light: #F0F0F0;
  --brand-2-dark: #303030;
  --brand-2-contrast: #FFFFFF;
}

body {
  font-family: "Inter", ui-sans-serif, system-ui, sans-serif;
}

/* ═══════════════════════════════════════════════════════════
   Mobile-first foundation
   ═══════════════════════════════════════════════════════════ */

html {
  -webkit-tap-highlight-color: transparent;
  -webkit-text-size-adjust: 100%;
}

/* Momentum scrolling + contained overscroll for scroll regions.
   Contain only the axis each region actually scrolls: a blanket
   `overscroll-behavior: contain` on x-scrollers (tables) also swallows
   vertical wheel/trackpad input, freezing page scroll over any table. */
.overflow-x-auto,
.overflow-y-auto {
  -webkit-overflow-scrolling: touch;
}
.overflow-x-auto {
  overscroll-behavior-x: contain;
}
.overflow-y-auto {
  overscroll-behavior-y: contain;
}

/* iOS Safari zooms the page when a focused control's font-size is below
   16px. Force 16px on touch-sized screens so focus never triggers zoom. */
@media (max-width: 1023px) {
  input:not([type='checkbox']):not([type='radio']),
  select,
  textarea {
    font-size: 16px !important;
  }
}

/* Comfortable touch targets on coarse-pointer (touch) devices.
   Applied via .tap-target so tiny decorative controls (e.g. the theme
   toggle) keep their compact size. */
@media (pointer: coarse) {
  .tap-target {
    min-height: 44px;
    min-width: 44px;
  }
  button:not(.no-tap),
  a[href],
  select,
  input:not([type='checkbox']):not([type='radio']) {
    min-height: 44px;
  }
  input[type='checkbox'],
  input[type='radio'] {
    min-width: 20px;
    min-height: 20px;
  }
}

/* Safe-area helpers for notched phones */
.pb-safe {
  padding-bottom: env(safe-area-inset-bottom, 0px);
}
.bottom-nav-safe {
  padding-bottom: calc(env(safe-area-inset-bottom, 0px) + 0.25rem);
}

/* When a modal/bottom-sheet (.sf-modal) is open, hide the mobile app chrome
   (bottom tab bar + sticky header). Those are position:fixed at the root, and
   on mobile browsers a modal rendered inside the scrolling <main> can paint
   *beneath* them — so the bottom nav ends up covering the modal's action
   button. Hiding the chrome while a modal is open removes the overlap. */
body:has(.sf-modal) .app-mobile-chrome {
  display: none !important;
}

/* ═══════════════════════════════════════════════════════════
   Phone density (see lib/pages/layout.dart — the .sf-app <main>)
   ═══════════════════════════════════════════════════════════

   The pages are written at desktop density: `space-y-8` between blocks,
   `p-6`/`p-8` cards, and `py-4` form controls. On a ~700px phone screen that
   spends most of the first screenful on padding — the Activity log's table and
   the staff list both started below the fold.

   Tightening it here rather than in each page keeps one source of truth and
   leaves the desktop layout untouched: everything below applies only under
   768px, and only inside the signed-in app. Touch targets are unaffected —
   the `pointer: coarse` rules above still hold every control at 44px.

   Deliberately NOT touched: font sizes (16px on controls stops iOS zooming),
   gap utilities inside cards, and anything outside .sf-app. */
@media (max-width: 767px) {
  /* Vertical rhythm between page blocks: 2rem -> 1.25rem */
  .sf-app .space-y-8 > :not([hidden]) ~ :not([hidden]) {
    margin-top: 1.25rem;
  }
  .sf-app .space-y-6 > :not([hidden]) ~ :not([hidden]) {
    margin-top: 1rem;
  }

  /* Card padding. p-8 is a desktop flourish; p-6 is the common card. */
  .sf-app .p-8 {
    padding: 1rem;
  }
  .sf-app .p-6 {
    padding: 1rem;
  }
  .sf-app .sm\:p-8 {
    padding: 1rem;
  }

  /* Form controls: the tallest repeated element on filter-heavy pages
     (Activity log, Report Cards). Height is still governed by the 44px
     touch-target minimum, so this only removes slack. */
  .sf-app select,
  .sf-app input:not([type='checkbox']):not([type='radio']) {
    padding-top: 0.625rem;
    padding-bottom: 0.625rem;
  }

  /* Filter grids stack one control per row by default, which is what makes
     three filters 300px tall. Two across fits comfortably at 16px type. */
  .sf-app .grid.grid-cols-1.sm\:grid-cols-3 {
    grid-template-columns: repeat(2, minmax(0, 1fr));
    gap: 0.5rem;
  }
}

/* ═══════════════════════════════════════════════════════════
   Toast notifications (see lib/services/toast_service.dart)
   ═══════════════════════════════════════════════════════════ */

#sfee-toasts {
  position: fixed;
  z-index: 100;
  left: 50%;
  transform: translateX(-50%);
  bottom: calc(env(safe-area-inset-bottom, 0px) + 5.5rem);
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 0.5rem;
  width: min(92vw, 24rem);
  pointer-events: none;
}
@media (min-width: 1024px) {
  #sfee-toasts {
    bottom: 1.5rem;
    left: auto;
    right: 1.5rem;
    transform: none;
    align-items: flex-end;
  }
}
.sfee-toast {
  pointer-events: auto;
  display: flex;
  align-items: flex-start;
  gap: 0.625rem;
  width: 100%;
  padding: 0.875rem 1rem;
  border-radius: 1rem;
  background: #171717;
  color: #fff;
  font-size: 0.8125rem;
  font-weight: 600;
  line-height: 1.4;
  box-shadow: 0 10px 30px rgb(0 0 0 / 0.25);
  animation: toastIn 0.25s cubic-bezier(0.21, 1.02, 0.73, 1) forwards;
  cursor: pointer;
}
.sfee-toast.leaving {
  animation: toastOut 0.2s ease-in forwards;
}
.sfee-toast .sfee-toast-icon {
  flex-shrink: 0;
  width: 1.25rem;
  height: 1.25rem;
  border-radius: 9999px;
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 0.75rem;
  font-weight: 900;
  margin-top: 0.0625rem;
}
.sfee-toast-success .sfee-toast-icon { background: #10b981; color: #fff; }
.sfee-toast-error .sfee-toast-icon { background: #ef4444; color: #fff; }
.sfee-toast-info .sfee-toast-icon { background: #6366f1; color: #fff; }
.sfee-toast-loading .sfee-toast-icon {
  background: transparent;
  border: 2px solid rgb(255 255 255 / 0.3);
  border-top-color: #fff;
  animation: spin 0.8s linear infinite;
}

@keyframes toastIn {
  from { opacity: 0; transform: translateY(12px) scale(0.97); }
  to { opacity: 1; transform: translateY(0) scale(1); }
}
@keyframes toastOut {
  from { opacity: 1; transform: translateY(0) scale(1); }
  to { opacity: 0; transform: translateY(8px) scale(0.97); }
}

/* Skeleton shimmer for loading placeholders */
@keyframes shimmer {
  from { background-position: 200% 0; }
  to { background-position: -200% 0; }
}
.skeleton {
  border-radius: 0.75rem;
  background: linear-gradient(90deg, #f0f0ef 25%, #e6e6e4 50%, #f0f0ef 75%);
  background-size: 200% 100%;
  animation: shimmer 1.4s ease infinite;
}

/* Respect users who prefer reduced motion */
@media (prefers-reduced-motion: reduce) {
  *,
  *::before,
  *::after {
    animation-duration: 0.01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.01ms !important;
  }
}

.serif {
  font-family: "Libre Baskerville", serif;
}

.font-mono {
  font-family: "JetBrains Mono", ui-monospace, SFMono-Regular, monospace;
}

/* ═══════════════════════════════════════════════════════════
   Animation Keyframes (replaces motion/react from React app)
   ═══════════════════════════════════════════════════════════ */

@keyframes fadeIn {
  from { opacity: 0; }
  to { opacity: 1; }
}

@keyframes fadeOut {
  from { opacity: 1; }
  to { opacity: 0; }
}

@keyframes slideUp {
  from { opacity: 0; transform: translateY(10px); }
  to { opacity: 1; transform: none; }
}

@keyframes slideDown {
  from { opacity: 0; transform: translateY(-10px); }
  to { opacity: 1; transform: none; }
}

@keyframes slideInLeft {
  from { transform: translateX(-100%); }
  to { transform: translateX(0); }
}

@keyframes slideOutLeft {
  from { transform: translateX(0); }
  to { transform: translateX(-100%); }
}

@keyframes scaleIn {
  from { opacity: 0; transform: scale(0.95); }
  to { opacity: 1; transform: scale(1); }
}

@keyframes spin {
  from { transform: rotate(0deg); }
  to { transform: rotate(360deg); }
}

.animate-fadeIn {
  animation: fadeIn 0.3s ease-out forwards;
}

.animate-slideUp {
  animation: slideUp 0.3s ease-out forwards;
}

.animate-slideDown {
  animation: slideDown 0.3s ease-out forwards;
}

.animate-slideInLeft {
  animation: slideInLeft 0.3s cubic-bezier(0.4, 0, 0.2, 1) forwards;
}

@keyframes slideInRight {
  from { transform: translateX(100%); }
  to { transform: translateX(0); }
}

.animate-slideInRight {
  animation: slideInRight 0.3s cubic-bezier(0.4, 0, 0.2, 1) forwards;
}

.animate-scaleIn {
  animation: scaleIn 0.2s ease-out forwards;
}

/* Staggered entrance for card grids. Put .stagger-children on the container;
   each direct child fades up shortly after the one before it. Capped at the
   10th child — beyond that the wait reads as lag, not polish.

   Only use this where the set of children is stable. On a filtered list (the
   students table, the finance ledger) the nth-child indices shift as the user
   types, which re-runs the delays on rows that had already settled. */
.stagger-children > * {
  animation: slideUp 0.35s ease-out both;
}
.stagger-children > *:nth-child(1) { animation-delay: 0ms; }
.stagger-children > *:nth-child(2) { animation-delay: 45ms; }
.stagger-children > *:nth-child(3) { animation-delay: 90ms; }
.stagger-children > *:nth-child(4) { animation-delay: 135ms; }
.stagger-children > *:nth-child(5) { animation-delay: 180ms; }
.stagger-children > *:nth-child(6) { animation-delay: 225ms; }
.stagger-children > *:nth-child(7) { animation-delay: 270ms; }
.stagger-children > *:nth-child(8) { animation-delay: 315ms; }
.stagger-children > *:nth-child(9) { animation-delay: 360ms; }
.stagger-children > *:nth-child(n + 10) { animation-delay: 405ms; }

/* Hide scrollbar utility (used in tab headers) */
.hide-scrollbar {
  -ms-overflow-style: none;
  scrollbar-width: none;
}
.hide-scrollbar::-webkit-scrollbar {
  display: none;
}

/* Slow spin animation for refresh icon */
.animate-spin-slow {
  animation: spin 2s linear infinite;
}

/* Report-card print target — populated only at print time, hidden on screen. */
#print-root {
  display: none;
}

/* ═══════════════════════════════════════════════════════════
   Print Styles (matching React legacy index.css exactly)
   ═══════════════════════════════════════════════════════════ */

@media print {
  /* Hide the sidebar and any print-hide elements on all pages */
  aside,
  .print-hide,
  .print\:hidden {
    display: none !important;
  }

  /* Reset layout constraints to allow flow printing */
  html, body {
    height: auto !important;
    min-height: auto !important;
    overflow: visible !important;
    background: white !important;
    color: black !important;
    -webkit-print-color-adjust: exact !important;
    print-color-adjust: exact !important;
  }

  /* Basic Jaspr app root resetting */
  #jaspr-app,
  #jaspr-app > div,
  main,
  main > div {
    display: block !important;
    height: auto !important;
    min-height: auto !important;
    overflow: visible !important;
    margin: 0 !important;
    padding: 0 !important;
    width: 100% !important;
    max-width: 100% !important;
    border: none !important;
    box-shadow: none !important;
    background: transparent !important;
  }

  /* Special receipt mode behavior */
  body.printing-receipt main > div > *:not(#receipt-portal-container) {
    display: none !important;
  }

  #receipt-portal-container {
    display: block !important;
    visibility: visible !important;
    position: absolute !important;
    left: 0 !important;
    top: 0 !important;
    width: 100% !important;
    margin: 0 !important;
    padding: 0 !important;
    background: white !important;
    color: black !important;
    box-shadow: none !important;
    border: none !important;
  }

  #receipt-portal-container * {
    visibility: visible !important;
  }

  /* Special report card mode behavior */
  @page {
    size: A4;
    margin: 10mm;
  }

  /* Report-card printing clones the card(s) into #print-root, a direct child
     of <body>. Hiding every other body child isolates it cleanly no matter how
     deeply nested the source was (single preview or bulk-print modal). */
  body.printing-report-card > *:not(#print-root) {
    display: none !important;
  }

  body.printing-report-card #print-root {
    display: block !important;
    position: static !important;
    width: 100% !important;
    margin: 0 !important;
    padding: 0 !important;
    background: white !important;
    color: black !important;
  }

  /* ── One-page A4 fit ──────────────────────────────────────
     A report card must fit a single A4 sheet even at ~20 subjects, so on
     paper everything is compacted: base font down, tight table rows, small
     media, reduced vertical rhythm. Screen preview is untouched. */
  body.printing-report-card #print-root {
    font-size: 9px !important;
    line-height: 1.25 !important;
  }
  /* The sheet's own card chrome wastes paper — flatten it. */
  body.printing-report-card #print-root .rounded-2xl.p-8 {
    padding: 0 !important;
    border: none !important;
    box-shadow: none !important;
    max-width: 100% !important;
  }
  /* Tighten every stacked-section gap (space-y-6 on the sheet root etc.). */
  body.printing-report-card #print-root .space-y-6 > * + * {
    margin-top: 6px !important;
  }
  body.printing-report-card #print-root .space-y-3 > * + *,
  body.printing-report-card #print-root .space-y-4 > * + * {
    margin-top: 3px !important;
  }
  /* Header: smaller name/title and logo. */
  body.printing-report-card #print-root h2 {
    font-size: 15px !important;
    line-height: 1.1 !important;
  }
  body.printing-report-card #print-root .border-b.pb-4 {
    padding-bottom: 5px !important;
  }
  body.printing-report-card #print-root img.w-16 {
    width: 40px !important;
    height: 40px !important;
  }
  body.printing-report-card #print-root .w-16 {
    width: 40px !important;
  }
  /* Passport photo. */
  body.printing-report-card #print-root .w-20.h-24 {
    width: 48px !important;
    height: 58px !important;
  }
  /* Subjects table: the big consumer. ~13px rows ≈ 20 subjects in ~95mm. */
  body.printing-report-card #print-root table {
    font-size: 8.5px !important;
  }
  body.printing-report-card #print-root th,
  body.printing-report-card #print-root td {
    padding: 1.5px 3px !important;
  }
  /* Meta cells, legend, domains, comments, financial block. */
  body.printing-report-card #print-root .text-xs {
    font-size: 9px !important;
  }
  body.printing-report-card #print-root .text-sm {
    font-size: 10px !important;
  }
  body.printing-report-card #print-root .p-3,
  body.printing-report-card #print-root .p-4 {
    padding: 4px 6px !important;
  }
  body.printing-report-card #print-root .gap-6 {
    gap: 8px !important;
  }
  /* Signatures: shrink the reserved signing space. */
  body.printing-report-card #print-root .h-12 {
    height: 26px !important;
  }
  body.printing-report-card #print-root .pt-6 {
    padding-top: 6px !important;
  }
  body.printing-report-card #print-root .gap-12 {
    gap: 24px !important;
  }
  /* Never let the table split a row across pages. */
  body.printing-report-card #print-root tr {
    page-break-inside: avoid !important;
  }

  #print-root .report-page-break-after {
    page-break-after: always !important;
    break-after: page !important;
  }
  /* Avoid a trailing blank page after the final card. */
  #print-root .report-page-break-after:last-child {
    page-break-after: auto !important;
    break-after: auto !important;
  }

  .report-page-break {
    page-break-before: always !important;
    break-before: page !important;
  }

  .report-page-break-after {
    page-break-after: always !important;
    break-after: page !important;
  }

  .pos-thermal-print {
    max-width: 320px !important;
    font-size: 11px !important;
    line-height: 1.2 !important;
    font-family: monospace !important;
    padding: 10px !important;
    margin: 0 auto !important;
  }

  .pos-thermal-print * {
    font-family: monospace !important;
    background: transparent !important;
    color: black !important;
    border-color: black !important;
  }
}

/* ═══════════════════════════════════════════════════════════
   Dark Mode (CSS filter inversion — matches React exactly)
   ═══════════════════════════════════════════════════════════ */

html.dark {
  filter: invert(1) hue-rotate(180deg);
  background-color: #0A0A0A;
}

html.dark body {
  background-color: #0A0A0A;
}

html.dark img, 
html.dark video, 
html.dark .no-invert {
  filter: invert(1) hue-rotate(180deg);
}

html.dark text, html.dark span, html.dark p, html.dark h1, html.dark h2, html.dark h3, html.dark h4, html.dark h5, html.dark h6 {
  -webkit-font-smoothing: antialiased;
}
