/* ══════════════════════════════════════════════════════════════════════════
   RESPONSIVE PRIMITIVES — shared layout/motion building blocks for every
   modal, drawer, table and form across the app (both the internal
   fleet/finance dashboard and the customer booking funnel).

   WHY THIS FILE EXISTS
   Before it, each of the ~45 modals in index.html (plus a few built at
   runtime in admin.js/fleet-calendar.js/auth-ui.js) hand-rolled its own
   responsive treatment — some converted to an edge-to-edge bottom sheet
   below 640px with a sticky header/footer, some stayed a centered dialog
   at every width with the header scrolling away with the content, a few
   had no max-height/overflow handling at all. Media queries across the
   CSS files ranged over 20+ different ad hoc cutoffs (360, 375, 379, 380,
   400, 480, 540, 900px, ...). This file is the fix: one breakpoint scale,
   and one implementation each of the patterns that kept getting
   reinvented slightly differently — so a new popup/page adopts a proven,
   already-consistent behavior by using these classes, instead of a
   fourteenth variant of the same idea.

   CANONICAL BREAKPOINTS — identical to tailwind.config.js's (default,
   unoverridden) screens, and to public/js/utils/breakpoints.js. Every new
   media query in this file — and every new one added anywhere else in the
   app going forward — should snap to one of these, not introduce a new
   one-off number:
     sm   640px   phone -> larger phone / small tablet
     md   768px   tablet portrait
     lg  1024px   tablet landscape / small laptop
     xl  1280px   desktop
     2xl 1536px   large desktop
   The Phase 1 audit's test widths map onto this scale as: 320-430px is
   "below sm" (mobile, the default/unprefixed styles below), 768px is md,
   1024px is lg, 1440px+ falls in the xl range.
   ══════════════════════════════════════════════════════════════════════ */


/* ── Touch targets — WCAG 2.5.5/2.5.8 44x44px minimum ────────────────────
   .icon-btn-center already marks every icon-only button in the app (45
   call sites, confirmed — audit found none of it used on non-<button>
   elements), most sized at Tailwind's w-8 h-8 (32x32px). Rather than
   editing every call site, bumping the box here via min-width/min-height
   fixes all of them at once: those two properties clamp the used width/
   height AFTER Tailwind's width:2rem/height:2rem has already cascaded, so
   this wins without needing !important or a stylesheet-order fight.
   Scoped to (pointer: coarse) — touch input — so mouse/trackpad desktop
   keeps the existing, intentionally compact 32px icon buttons; only
   touch breakpoints grow to the accessible minimum. */
@media (pointer: coarse) {
  .icon-btn-center,
  .rp-touch-target {
    min-width: 44px;
    min-height: 44px;
  }
}

/* Utility for any one-off control that isn't an icon-button (a checkbox, a
   small text link acting as a button, a dot indicator, etc.) — apply
   directly where .icon-btn-center doesn't fit semantically. */
.rp-touch-target {
  display: inline-flex;
  align-items: center;
  justify-content: center;
}


/* ── Fluid typography/spacing — clamp() instead of a fixed px + a media
   query per breakpoint. Formula: clamp(min, min + (max-min)*vw-slope,
   max) — the middle term is the only part that needs recalculating for a
   new scale step; min/max stay the actual design values. Use these for
   any new heading/section that currently would have needed its own
   sm:/lg: font-size overrides. ─────────────────────────────────────────── */
.rp-text-fluid-sm   { font-size: clamp(0.8125rem, 0.78rem + 0.2vw, 0.9375rem); }
.rp-text-fluid-base  { font-size: clamp(0.9375rem, 0.9rem + 0.25vw, 1.0625rem); }
.rp-text-fluid-lg    { font-size: clamp(1.0625rem, 1rem + 0.4vw, 1.375rem); }
.rp-text-fluid-xl    { font-size: clamp(1.25rem, 1.1rem + 0.9vw, 1.75rem); }
.rp-text-fluid-2xl   { font-size: clamp(1.5rem, 1.2rem + 1.6vw, 2.25rem); }
.rp-space-fluid-sm  { padding: clamp(0.75rem, 0.65rem + 0.5vw, 1.25rem); }
.rp-space-fluid-md  { padding: clamp(1rem, 0.8rem + 1vw, 2rem); }


/* ══════════════════════════════════════════════════════════════════════
   MODAL / DRAWER PRIMITIVE
   Structure any modal's markup as:
     <div class="rp-modal" data-rp-modal>              (backdrop + positioner)
       <div class="rp-modal__panel" data-rp-panel>      (the visible card)
         <div class="rp-modal__header">...</div>        (stays put)
         <div class="rp-modal__body">...</div>           (the only part that scrolls)
         <div class="rp-modal__footer">...</div>         (stays put, optional)
       </div>
     </div>
   Toggle `.rp-modal` between `hidden` and (nothing) exactly like the
   existing modals do — this primitive only replaces the CSS, not the
   open/close mechanism. Pair with responsive-modal.js's
   wireResponsiveModal() for Escape/backdrop-click/scroll-lock behavior.

   Below `sm` (640px): full-bleed bottom sheet, rounded top corners only,
   panel height capped so it never exceeds the viewport (dvh, so mobile
   browser chrome showing/hiding doesn't cause a jump), header/footer
   pinned via flex-shrink:0, body is the sole `overflow-y:auto` region.
   At `sm` and up: centered dialog, rounded on all corners, same
   header/body/footer split so long content still scrolls internally
   instead of pushing the dialog taller than the viewport. ────────────── */
.rp-modal {
  position: fixed;
  inset: 0;
  z-index: 1000;
  display: flex;
  align-items: flex-end;
  justify-content: center;
  background: rgba(0, 0, 0, 0.7);
  backdrop-filter: blur(2px);
}
/* responsive-primitives.css deliberately loads after tailwind.css so its
   own rules win property fights without !important (see the file header)
   — but that same load order means Tailwind's `.hidden{display:none}`
   would lose to any single-class rule below that also sets `display` on
   the same element (e.g. `.rp-modal__footer{display:flex}`), silently
   leaving a "hidden" footer/header/body visibly on screen. Every element
   this file gives its own `display` needs the matching `.hidden` override
   here so toggling Tailwind's `hidden` class on it still actually hides
   it — caught by testing crmFeedbackModal's Add/History tab toggle, where
   the Add footer stayed visible under the History footer despite having
   `hidden` applied. */
.rp-modal.hidden,
.rp-modal__header.hidden,
.rp-modal__body.hidden,
.rp-modal__footer.hidden {
  display: none;
}

.rp-modal__panel {
  width: 100%;
  max-width: 40rem;
  max-height: 92dvh;
  display: flex;
  flex-direction: column;
  background: #1e293b; /* slate-800 — matches the app's existing modal surface color */
  border: 1px solid #334155; /* slate-700 */
  border-radius: 1rem 1rem 0 0;
  box-shadow: 0 25px 50px -12px rgba(0, 0, 0, 0.5);
  overflow: hidden; /* clips corners; header/body/footer each control their own scroll */
}

.rp-modal__header,
.rp-modal__footer {
  flex-shrink: 0;
}
.rp-modal__header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 0.75rem;
  /* Tighter than the 1rem/1.25rem used at sm+ (restored below) — on a
     360-430px phone this row was taking up as much vertical space as the
     title text itself; every modal that reuses this primitive (~15 of
     them) shrinks together. */
  padding: 0.75rem 1rem;
  /* Matches .rp-modal__panel's own top-corner rounding (1rem, minus the
     1px the panel's own border eats into) — the header is the panel's
     first child and panel's overflow:hidden clips it to that same
     boundary either way, but without its OWN matching radius the header
     is a square-cornered rectangle sitting inside a round-cornered clip,
     so at each top corner a sliver of the panel's plain background (and
     its animated glow border, see [data-modal-inner] below) shows
     through in the gap — invisible on a header that happens to share the
     panel's own dark color, glaring on any header with its own
     background (e.g. #footerTermsModal's cyan-to-blue gradient). */
  border-radius: calc(1rem - 1px) calc(1rem - 1px) 0 0;
  border-bottom: 1px solid #334155;
}
.rp-modal__footer {
  padding: 1rem 1.25rem;
  border-top: 1px solid #334155;
  display: flex;
  gap: 0.75rem;
}
/* Title + subtitle on ONE line, for the 6 legal/marketing overlays below
   (Terms/Privacy/Cookie x2, footer + checkout versions) — these used to
   stack a <h2> title and a <p class="mt-1"> subtitle as two full lines,
   roughly doubling .rp-modal__header's height on every device. The title
   never shrinks or wraps (it's the thing identifying which modal this is);
   the subtitle is the one that gives way, truncating with an ellipsis
   instead of wrapping to a second line, so the header stays exactly one
   line tall at every width down to the narrowest phones — a mobile-width
   subtitle may show only a few words before the ellipsis, which is an
   acceptable trade for never growing the header.
     justify-content:space-between spreads title and subtitle to opposite
   ends of the row (title flush left, subtitle flush right against the
   close button) instead of them sitting bunched together right after the
   title — reads as two deliberate pieces of information rather than one
   run-on line, and still collapses correctly: as the row narrows the
   subtitle (flex-shrink, min-width:0) is what gives up its width first,
   sliding left and truncating, while the title stays put. */
.rp-modal__title-row {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 0.625rem;
  flex: 1 1 auto;
  min-width: 0;
}
.rp-modal__title {
  display: flex;
  align-items: center;
  gap: 0.4rem;
  flex-shrink: 0;
  white-space: nowrap;
  font-size: 0.875rem;
  font-weight: 700;
  color: #fff;
}
.rp-modal__title i {
  font-size: 0.9em;
}
.rp-modal__subtitle {
  flex-shrink: 1;
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  text-align: right;
  font-size: 0.6875rem;
}
@media (min-width: 640px) {
  .rp-modal__title {
    font-size: 1.125rem;
  }
  .rp-modal__subtitle {
    font-size: 0.8125rem;
  }
}
/* The 6 legal/marketing overlays' header is otherwise identical to every
   other .rp-modal__header (shared padding/border below) — scoped smaller
   padding here rather than shrinking the shared rule, so this doesn't
   also tighten the ~15 other unrelated modals (Reschedule Booking, Add
   Customer, etc.) that reuse .rp-modal__header with a single-line title
   and were never the two-line problem this is fixing. */
.rp-modal__panel--wide .rp-modal__header {
  padding: 0.4rem;
}
/* Stacked full-width buttons (a primary action above a secondary one)
   instead of the default side-by-side row — e.g. a single "Save" CTA that
   needs to stay full-width and thumb-reachable on mobile rather than
   sharing a row with a same-size Cancel button. */
.rp-modal__footer--stack {
  flex-direction: column;
}
.rp-modal__body {
  flex: 1 1 auto;
  min-height: 0; /* required for flex children to actually scroll instead of overflowing the panel */
  overflow-y: auto;
  padding: 1.25rem;
  -webkit-overflow-scrolling: touch;
}

@media (min-width: 640px) {
  .rp-modal {
    align-items: center;
    padding: 1rem;
  }
  .rp-modal__panel {
    max-height: 85dvh;
    border-radius: 1rem;
  }
  .rp-modal__header {
    padding: 1rem 1.25rem;
  }
}

/* Wide-content modifier — for the 6 legal/marketing overlays (Terms,
   Privacy, Cookies, both nav-footer and in-flow booking-page copies),
   whose long-form text is genuinely easier to read wider once there's
   room, growing in the same steps their old bespoke template used
   (max-w-lg -> 2xl -> 4xl -> 5xl) rather than the primitive's flat
   default max-width. */
.rp-modal__panel--wide { max-width: 32rem; }
@media (min-width: 640px)  { .rp-modal__panel--wide { max-width: 42rem; } }
@media (min-width: 1024px) { .rp-modal__panel--wide { max-width: 56rem; } }
@media (min-width: 1280px) { .rp-modal__panel--wide { max-width: 64rem; } }

/* Drawer variant — same scroll/pin structure, slides from the right on
   wide screens (a side panel, e.g. filters or a record inspector) instead
   of centering; still collapses to the same full-bleed bottom sheet below
   `sm` as the plain modal, since a side drawer on a 375px-wide screen has
   nowhere to be beside. */
.rp-modal--drawer .rp-modal__panel {
  max-width: 28rem;
}
@media (min-width: 640px) {
  .rp-modal--drawer {
    justify-content: flex-end;
    align-items: stretch;
    padding: 0;
  }
  .rp-modal--drawer .rp-modal__panel {
    max-height: 100dvh;
    height: 100dvh;
    border-radius: 0;
    border-left: 1px solid #334155;
  }
  /* The panel itself goes square at this breakpoint (flush side panel,
     not a floating card) — .rp-modal__header's own top-corner rounding
     needs to follow suit, otherwise it's now the header that's rounded
     inside a square-cornered panel instead of the other way around. */
  .rp-modal--drawer .rp-modal__header {
    border-radius: 0;
  }
}


/* ══════════════════════════════════════════════════════════════════════
   RESPONSIVE TABLE PRIMITIVE
   Pattern A — horizontal scroll container (use for wide, genuinely
   tabular data — ledgers, booking lists — where a row's columns need to
   stay aligned and losing that alignment would make the data harder to
   read, not easier):
     <div class="rp-table-scroll"><table class="rp-table">...</table></div>

   Pattern B — card fallback (use when a table's rows are really just a
   record with 3-6 fields — better read as a stacked card than a cramped
   row below md): add `.rp-table-cards` on the same <table> as well; each
   <td> needs a `data-label="Column Name"` attribute (the value CSS uses
   to print the column header inline, since real <th> cells aren't in the
   layout flow anymore below md).
   ────────────────────────────────────────────────────────────────────── */
.rp-table-scroll {
  overflow-x: auto;
  -webkit-overflow-scrolling: touch;
  scrollbar-width: thin;
  /* Fade hint at the trailing edge so a horizontally-clipped table reads
     as "more to scroll" rather than looking like the row just ends. */
  background:
    linear-gradient(to right, #1e293b 30%, rgba(30, 41, 59, 0)),
    linear-gradient(to right, rgba(30, 41, 59, 0), #1e293b 70%) 100% 0,
    radial-gradient(farthest-side at 0 50%, rgba(0, 0, 0, 0.35), rgba(0, 0, 0, 0)),
    radial-gradient(farthest-side at 100% 50%, rgba(0, 0, 0, 0.35), rgba(0, 0, 0, 0)) 100% 0;
  background-repeat: no-repeat;
  background-size: 40px 100%, 40px 100%, 14px 100%, 14px 100%;
  background-attachment: local, local, scroll, scroll;
}
.rp-table {
  width: 100%;
  min-width: max-content;
  border-collapse: collapse;
  font-size: 0.875rem;
}
.rp-table th,
.rp-table td {
  padding: 0.625rem 0.875rem;
  text-align: left;
  white-space: nowrap;
  border-bottom: 1px solid #334155;
}
.rp-table th {
  color: #94a3b8; /* slate-400 */
  font-weight: 600;
  font-size: 0.75rem;
  text-transform: uppercase;
  letter-spacing: 0.03em;
}

@media (max-width: 767.98px) {
  .rp-table-cards,
  .rp-table-cards tbody,
  .rp-table-cards tr {
    display: block;
    width: 100%;
  }
  .rp-table-cards thead { display: none; }
  .rp-table-cards tr {
    margin-bottom: 0.75rem;
    border: 1px solid #334155;
    border-radius: 0.75rem;
    overflow: hidden;
  }
  .rp-table-cards td {
    display: flex;
    justify-content: space-between;
    align-items: center;
    gap: 1rem;
    white-space: normal;
    text-align: right;
  }
  .rp-table-cards td[data-label]::before {
    content: attr(data-label);
    color: #94a3b8;
    font-weight: 600;
    font-size: 0.75rem;
    text-transform: uppercase;
    letter-spacing: 0.03em;
    text-align: left;
  }
}


/* ══════════════════════════════════════════════════════════════════════
   FORM-FIELD GRID PRIMITIVE
   The app already had this pattern proven in ~70% of its modals as plain
   Tailwind utilities (`grid grid-cols-1 sm:grid-cols-2 gap-4`) — that
   remains the preferred way to write it in new static HTML. `.rp-form-grid`
   exists only for the runtime-templated modals (admin.js, fleet-
   calendar.js, ...) where reaching for a hand-written class is simpler
   than confirming a given Tailwind class combination was already compiled
   into tailwind.css (a `npm run build:css` away, but easy to forget) —
   same 640px collapse, same look. ────────────────────────────────────── */
.rp-form-grid {
  display: grid;
  grid-template-columns: 1fr;
  gap: 1rem;
}
@media (min-width: 640px) {
  .rp-form-grid--2col { grid-template-columns: 1fr 1fr; }
  .rp-form-grid--3col { grid-template-columns: 1fr 1fr 1fr; }
}


/* ══════════════════════════════════════════════════════════════════════
   DATE INPUT FAKE PLACEHOLDER
   Wired by public/js/utils/date-placeholder.js's wireDatePlaceholders() —
   see that file for why: native <input type="date"> doesn't reliably show
   a "dd-mm-yyyy" empty-state hint across browsers (confirmed blank, no
   hint at all, on real Android devices), so this renders it ourselves as
   a positioned sibling instead of trusting the browser's own rendering.
   .rp-date-wrap replaces the input as its parent's direct child (same
   place in a grid/flex row the bare input used to occupy) and becomes the
   positioning context for the overlay text sitting on top of it. ──────── */
.rp-date-wrap {
  display: block;
  position: relative;
  width: 100%;
}
/* The real input's own day/month/year text is made fully transparent —
   this overlay renders BOTH the placeholder and (once a value is picked)
   the formatted value itself, entirely replacing native rendering rather
   than layering on top of it. An earlier version left the native text
   visible and only added this overlay on top for the empty state; on any
   browser whose native placeholder DOES render (confirmed: it's not just
   Android that's inconsistent here — even Chromium's desktop engine still
   draws its own "dd-mm-yyyy" underneath), the two overlapped into
   unreadable doubled/garbled text instead of fixing anything.
   color:transparent is purely visual — screen readers still read the
   input's real value from the DOM regardless of its paint color, so this
   doesn't hide the field from assistive tech. */
.rp-date-wrap input[type="date"],
.rp-date-wrap input[type="date"]::-webkit-datetime-edit,
.rp-date-wrap input[type="date"]::-webkit-datetime-edit-fields-wrapper,
.rp-date-wrap input[type="date"]::-webkit-datetime-edit-text,
.rp-date-wrap input[type="date"]::-webkit-datetime-edit-day-field,
.rp-date-wrap input[type="date"]::-webkit-datetime-edit-month-field,
.rp-date-wrap input[type="date"]::-webkit-datetime-edit-year-field {
  color: transparent;
}
.rp-date-placeholder {
  position: absolute;
  inset: 0;
  display: flex;
  align-items: center;
  pointer-events: none; /* clicks/taps pass through to the real input underneath */
  white-space: nowrap;
  overflow: hidden;
  /* No color set here on purpose — date-placeholder.js toggles the real
     text-slate-500 / text-white Tailwind classes on this element instead
     of a hardcoded hex. Those classes already resolve correctly across
     every theme (including pearl, which forces text-white to dark navy
     via !important since it's a light theme) — a hardcoded white would
     have stayed white-on-white and unreadable there once a date was
     picked. */
}
/* Our own calendar glyph, positioned roughly where the (now fully
   transparent, see below) native icon used to sit. Fixed offset rather
   than matching each input's own padding — the browser reserves a
   similar-sized blank icon area on the right of every date input
   regardless of that input's own text padding, so this lines up closely
   enough across every field in the app.
   One rule, one color, for every date input in the app — this used to
   branch in JS (date-placeholder.js set an inline style on .dt-compact
   icons and a separate Tailwind class on everything else), which meant
   two places to touch for what should be a single design decision.
   White is correct as the default for every current theme except pearl
   on non-.dt-compact fields — see themes.css's one override for that
   specific case, right next to every other theme-driven color decision
   instead of split across a stylesheet and a JS file. */
.rp-date-icon {
  position: absolute;
  right: 1em;
  top: 50%;
  transform: translateY(-50%);
  pointer-events: none;
  font-size: 0.85em;
  color: #fff;
}
