/*
 * This is a manifest file that'll be compiled into application.css.
 *
 * With Propshaft, assets are served efficiently without preprocessing steps. You can still include
 * application-wide styles in this file, but keep in mind that CSS precedence will follow the standard
 * cascading order, meaning styles declared later in the document or manifest will override earlier ones,
 * depending on specificity.
 *
 * Consider organizing styles into separate files for maintainability.
 */

/* ── Typography ────────────────────────────────────────────────── */
body {
  font-family: 'DM Sans', ui-sans-serif, system-ui, -apple-system, sans-serif;
}

/* Archivo set wide (its `wdth` axis, loaded 100–125 in layouts/_head). The
   stretch travels with the family: at its normal width it reads as a plain
   grotesk next to DM Sans. `font-display` (tailwind/application.css) is the
   same face for display text that isn't a heading. */
h1, h2, h3, h4 {
  font-family: 'Archivo', ui-sans-serif, system-ui, sans-serif;
  font-stretch: 118%;
}

/* Modal dialog — full-viewport overlay with centered content */
dialog[open] {
  display: flex;
  position: fixed;
  inset: 0;
  width: 100%;
  height: 100%;
  max-width: 100%;
  padding: 1rem;
  overflow-y: auto;
  overscroll-behavior: contain;
  background: transparent;
  border: none;
  outline: none;
}

/* Constrain the turbo-frame so the modal card has a sensible width.
   margin: auto centers it when it fits, but pins it to the top (scrollable)
   when the card is taller than the viewport. */
#modal_form {
  width: min(100%, 32rem);
  margin: auto;
}

/* Forms laid out as a row per item (the equines to enroll in a health plan)
   opt into a wider card by marking their content data-modal-size="wide". */
#modal_form:has([data-modal-size="wide"]) {
  width: min(100%, 56rem);
}

/* A table too wide for the form card but not a row-per-item form (the
   start-date modal's due-date preview). */
#modal_form:has([data-modal-size="medium"]) {
  width: min(100%, 42rem);
}

/* ── Animations ───────────────────────────────────────────────── */

/* Backdrop */
dialog::backdrop {
  background: rgba(0, 0, 0, 0.5);
  backdrop-filter: blur(4px);
  animation: modal-backdrop-in 0.2s ease-out;
}
dialog.is-closing::backdrop {
  animation: modal-backdrop-out 0.2s ease-in forwards;
}

/* Card (the turbo-frame content) */
dialog[open] #modal_form {
  animation: modal-card-in 0.2s ease-out;
}
dialog.is-closing #modal_form {
  animation: modal-card-out 0.2s ease-in forwards;
}

@keyframes modal-backdrop-in  { from { opacity: 0; } to { opacity: 1; } }
@keyframes modal-backdrop-out { from { opacity: 1; } to { opacity: 0; } }

@keyframes modal-card-in {
  from { opacity: 0; transform: scale(0.95) translateY(8px); }
  to   { opacity: 1; transform: scale(1)    translateY(0);   }
}
@keyframes modal-card-out {
  from { opacity: 1; transform: scale(1)    translateY(0);   }
  to   { opacity: 0; transform: scale(0.95) translateY(8px); }
}

/* Batch card — "just updated" double pulse (see card_pulse_controller.js).
   box-shadow drives both the emerald ring and the elevation; transform scales.
   Two beats baked into one keyframe: the second decays to ~55% of the first so
   it reads like a natural physical settle rather than two identical thumps. The
   0%/100% frames match the card's resting state, so it settles with no jump. */
@keyframes card-pulse {
  0% {
    transform: scale(1);
    box-shadow: 0 0 0 0 rgba(16, 185, 129, 0), 0 1px 2px rgba(0, 0, 0, 0.04);
  }
  13% { /* beat 1 — full strength */
    transform: scale(1.045);
    box-shadow: 0 0 0 3px rgba(16, 185, 129, 0.55), 0 12px 24px -8px rgba(16, 185, 129, 0.35);
  }
  34% { /* trough between beats */
    transform: scale(1);
    box-shadow: 0 0 0 0 rgba(16, 185, 129, 0), 0 1px 2px rgba(0, 0, 0, 0.02);
  }
  48% { /* beat 2 — softer */
    transform: scale(1.024);
    box-shadow: 0 0 0 2px rgba(16, 185, 129, 0.3), 0 6px 14px -6px rgba(16, 185, 129, 0.22);
  }
  100% { /* long ease-out settle to baseline */
    transform: scale(1);
    box-shadow: 0 0 0 0 rgba(16, 185, 129, 0), 0 1px 2px rgba(0, 0, 0, 0);
  }
}

.card-pulse-active {
  animation: card-pulse 1.3s ease-out;
  will-change: transform, box-shadow;
  z-index: 10; /* float the glow above adjacent cards in the dense grid */
}

/* ── Slim Select — match app design tokens ────────────────────── */
:root {
  --ss-primary-color: #9333ea;   /* purple-600 */
  --ss-border-color:  #e2e8f0;   /* slate-200  */
  --ss-border-radius: 0.5rem;    /* rounded-lg */
  --ss-font-size:     0.875rem;  /* text-sm    */
  --ss-font-color:    #1e293b;   /* slate-800  */
}

/* Dropdown appended to <body> must sit above the modal dialog */
.ss-content { z-index: 9999; }

/* ── FullCalendar — weekend columns ──────────────────────────────
   v7 hashes its internal fc-* classes, so we tint via our own classes
   injected by calendar_controller.js (dayCellClass / dayHeaderClass). */
.fc-weekend {
  background-color: #f1f5f9; /* slate-100 — weekend day cells */
}

.fc-weekend-header {
  background-color: #f1f5f9; /* slate-100 */
  color: #94a3b8;            /* slate-400 — dimmer header text */
}

/* ── FullCalendar — clickable events ─────────────────────────────
   Every event opens the tooltip (eventClick), so it reads as clickable in
   every view. Keyed off our own eventClass hook, two selectors deep so it
   outranks whatever cursor v7's hashed event classes set. */
[data-calendar-target="calendar"] .app-fc-event {
  cursor: pointer;
}

/* ── FullCalendar — sticky date header ───────────────────────────
   v7 pins the date-header row at top:0, which parks it behind the sticky
   mobile top bar (h-16); re-offset it like the storage-tank sticky headers
   (top-16). From `lg` (64rem) up the navigation is a sidebar, nothing covers
   the viewport's top edge, and the row goes back to top:0.
   Two class-level selectors so this outranks v7's own `top: 0 !important`.
   The `app-fc-table-header` hook (calendar_controller.js) replaces the Breezy
   theme's tableHeaderClass, whose only job is the background — re-declared here. */
[data-calendar-target="calendar"] .app-fc-table-header {
  top: 4rem !important;
  background-color: var(--fc-breezy-background);
}

@media (width >= 64rem) {
  [data-calendar-target="calendar"] .app-fc-table-header {
    top: 0 !important;
  }
}

/* ── Page width: large screens and the folded sidebar ──────────────
   Every page centres its content in `max-w-7xl`, which Tailwind v4 emits as
   `max-width: var(--container-7xl)`, so the page width is set here once rather
   than in each view.

   --page-max steps up with the screen: 80rem up to `2xl`, then 96rem, then
   112rem from `3xl` (1920px). Below 1536px nothing changes. Past 112rem pages
   stop growing on purpose: wider, and table rows and text lines get too long
   to scan, so a 2560px monitor gets margins rather than 2200px-wide rows.

   The steps sit on :root, not .app-shell, so every layout that uses
   max-w-7xl follows them: the admin panel renders the same members table
   as the team page, and it now does so at the same width.

   Folding the sidebar frees 180px (256px card → 76px rail); without the
   .app-shell rule that only widens the centring margins. So while it is
   folded the container grows by exactly that much, animated over the same
   300ms as the fold, and the content keeps its side gaps. */
@media (width >= 64rem) {
  :root {
    --page-max: 80rem;
    --container-7xl: var(--page-max);
  }

  .app-shell:has(> #app_sidebar[data-collapsed="true"]) {
    --container-7xl: calc(var(--page-max) + 180px);
  }

  .app-shell .max-w-7xl {
    transition: max-width 300ms ease-in-out;
  }
}

@media (width >= 96rem) {
  :root { --page-max: 96rem; }
}

@media (width >= 120rem) {
  :root { --page-max: 112rem; }
}

@media (prefers-reduced-motion: reduce) {
  .app-shell .max-w-7xl {
    transition: none;
  }
}

@media (prefers-reduced-motion: reduce) {
  dialog::backdrop,
  dialog.is-closing::backdrop,
  dialog[open] #modal_form,
  dialog.is-closing #modal_form,
  .card-pulse-active { animation-duration: 0.01ms !important; }
}

/* A parameter cell whose write is still in flight — the outward sign the sheet
   is catching up with what was typed. */
[data-saving] { opacity: 0.5; }

/* ── Printing the hospitalization sheet ─────────────────────────────
   The sheet is meant to print one page per day. On screen the two grids
   scroll inside overflow-x-auto containers; on paper that would clip every
   hour column past the page edge, so the whole width has to lay out instead.
   The app chrome around the sheet is dropped, and a day is kept whole. */
@media print {
  /* Let the wide grids print their full width rather than a clipped window. */
  .hospitalization-sheet .overflow-x-auto { overflow: visible !important; }

  /* Sticky columns have no containing block once overflow is visible; pin them
     back into the normal flow so they print in place. */
  .hospitalization-sheet .sticky {
    position: static !important;
    left: auto !important;
  }

  /* Keep a treatment or parameter row, and each grid, from splitting a page. */
  .hospitalization-sheet tr,
  .hospitalization-sheet table { break-inside: avoid; }
}
