/* ═══════════════════════════════════════════════════
   app-utils.css  —  AWQATY V2 shared UI primitives
   Toast, confirm, modal, fields, segments, menu, pickers
   ═══════════════════════════════════════════════════ */

/* ── Toast stack ──
   z-index is the CSS spec max (2^31-1), not just "high enough" — several legacy
   Bootstrap modals across the app hardcode ad-hoc values up to 100000+ trying to
   win their own stacking fights, and a toast's whole job is to stay visible over
   whatever is on screen, including those. */
.sv2-toasts {
  position: fixed; bottom: 24px; left: 50%;
  transform: translateX(-50%);
  display: flex; flex-direction: column; gap: 10px;
  z-index: 2147483647;
  width: min(400px, calc(100vw - 32px));
  pointer-events: none;
}
.sv2-toast {
  display: flex; align-items: center; gap: 11px;
  background: #1A1A2E; color: #fff;
  border-radius: 12px; padding: 13px 15px;
  box-shadow: 0 18px 48px rgba(16,24,40,.24);
  animation: sv2TtIn .25s ease;
  pointer-events: auto;
}
@keyframes sv2TtIn { from { opacity:0; transform:translateY(10px); } to { opacity:1; transform:none; } }
.sv2-toast.leaving { opacity:0; transform:translateY(10px); transition:.25s; }
.sv2-toast .sv2-t-ic {
  width:28px; height:28px; border-radius:8px;
  background:rgba(255,255,255,.15);
  display:flex; align-items:center; justify-content:center; flex-shrink:0;
}
.sv2-toast .sv2-t-tx { font-size:13.5px; font-weight:600; flex:1; min-width:0; }
.sv2-toast .sv2-t-tx small { display:block; font-size:12px; opacity:.8; font-weight:400; margin-top:1px; }
.sv2-toast .sv2-t-close {
  flex-shrink:0;
  width:28px; height:28px;
  margin-inline-start:4px;
  border:none; border-radius:8px;
  background:rgba(255,255,255,.15);
  color:#fff;
  display:flex; align-items:center; justify-content:center;
  padding:0; cursor:pointer;
  opacity:.85;
  transition:opacity .15s, background .15s;
}
.sv2-toast .sv2-t-close:hover { opacity:1; background:rgba(255,255,255,.28); }
.sv2-toast .sv2-t-close:focus-visible { outline:2px solid #fff; outline-offset:2px; }

body.sv2-modal-open { overflow: hidden; }

/* ── Overlay / modal shell ── */
.sv2-overlay {
  position: fixed;
  /* --sv2-vvt / --sv2-vvh are set by app-utils.js while the iPhone keyboard is
     open, so the overlay covers only the area above it. Without them the
     overlay stays full-height and a bottom sheet ends up behind the keyboard. */
  top: var(--sv2-vvt, 0px); left: 0; right: 0;
  height: var(--sv2-vvh, 100%);
  background: rgba(15,15,30,.55);
  backdrop-filter: blur(4px);
  -webkit-backdrop-filter: blur(4px);
  display: none;
  z-index: 9800;
  align-items: center; justify-content: center;
  padding: 24px;
  /* The overlay scrolls, not the page: when the iPhone keyboard opens, iOS has
     to be able to scroll the focused input into view. With nothing scrollable
     it pans the page instead and leaves a white gap above the keyboard.
     overscroll-behavior keeps that scroll from reaching the page behind. */
  overflow-y: auto;
  overscroll-behavior: contain;
}
/* `.closing` holds the overlay on screen for the length of the exit. Without it
   dropping `.open` hits display:none on the same frame and the close is a hard
   cut — the JS already waited out an exit that could never be seen. Both
   classes keep display:flex; JS strips `.closing` when the animation ends. */
.sv2-overlay.open,
.sv2-overlay.closing { display:flex; }
.sv2-overlay.open    { animation:sv2FadeIn .2s ease; }
.sv2-overlay.closing { animation:sv2FadeOut .2s ease forwards; pointer-events:none; }

/* The blur ramps with the fade rather than snapping to 4px, so the page behind
   goes out of focus as the dialog arrives — and comes back as it leaves. */
@keyframes sv2FadeIn {
  from { opacity:0; backdrop-filter:blur(0px);   -webkit-backdrop-filter:blur(0px); }
  to   { opacity:1; backdrop-filter:blur(4px);   -webkit-backdrop-filter:blur(4px); }
}
@keyframes sv2FadeOut {
  from { opacity:1; backdrop-filter:blur(4px);   -webkit-backdrop-filter:blur(4px); }
  to   { opacity:0; backdrop-filter:blur(0px);   -webkit-backdrop-filter:blur(0px); }
}
@keyframes sv2Spin { to { transform: rotate(360deg); } }

.sv2-modal-inner {
  background: #fff;
  border-radius: 18px;
  width: 420px;
  max-width: calc(100vw - 40px);
  max-height: calc(100vh - 48px);
  /* dvh tracks the area left after the mobile browser bars, so the header stays on screen. */
  max-height: calc(100dvh - 48px);
  max-height: calc(var(--sv2-vvh, 100dvh) - 48px);
  overflow-y: auto;
  /* Reaching the end of the modal's own scroll must not start scrolling the page. */
  overscroll-behavior: contain;
  /* margin:auto centres the box and, unlike align-items:center, never clips its
     top when it is taller than the overlay. */
  margin: auto;
  box-shadow: 0 30px 80px rgba(16,24,40,.3);
  /* Scroll stays fully usable (wheel/touch/drag) — just the visible track/thumb
     is hidden, since a modal's own scrollbar reads as UI chrome next to content. */
  scrollbar-width: none;
  -ms-overflow-style: none;
}
.sv2-modal-inner::-webkit-scrollbar {
  display: none;
}
/* Scoped to .open so persistent (non-recreated) modals replay the slide-in on every
   open, not just the first time the element is ever painted. */
.sv2-overlay.open .sv2-modal-inner {
  animation: sv2SlideIn .26s cubic-bezier(.34, 1.56, .64, 1);
}
/* Mirror of the entrance. `.open` is gone by the time this applies, so the two
   rules never fight over the same element. */
.sv2-overlay.closing .sv2-modal-inner {
  animation: sv2SlideOut .2s cubic-bezier(.4, 0, 1, 1) forwards;
}

/* Applied by sv2LoadModal() when it swaps the spinner for fetched content. */
.sv2-content-fade-in { animation: sv2ContentFadeIn .25s ease; }
@keyframes sv2ContentFadeIn { from { opacity: 0; transform: translateY(4px); } to { opacity: 1; transform: none; } }
.sv2-modal-inner.sv2-modal-lg { width: 720px; }
.sv2-modal-inner.sv2-modal-xl { width: 960px; }
/* Pops open and pops out from its own centre, rather than sliding up a few
   pixels. The entrance rides cubic-bezier(.34,1.56,.64,1) — the same overshoot
   the booking hero uses for confPop — so it settles with a slight bounce; over
   a .92→1 range that overshoot is only a couple of percent, which reads as
   lively on a small dialog without throwing a large modal around.

   The exit runs shorter and eases *in* rather than out, so it leaves briskly
   instead of playing the entrance backwards — that asymmetry is what makes a
   close feel dismissed rather than rewound. Keep its duration in step with
   SV2_EXIT_MS in app-utils.js. */
@keyframes sv2SlideIn  { from { opacity:0; transform:scale(.92); } to { opacity:1; transform:none; } }
@keyframes sv2SlideOut { from { opacity:1; transform:none; }      to { opacity:0; transform:scale(.94); } }
/* Movement-free counterparts, used under prefers-reduced-motion. */
@keyframes sv2CardFadeIn  { from { opacity:0; } to { opacity:1; } }
@keyframes sv2CardFadeOut { from { opacity:1; } to { opacity:0; } }

.pm-head  { display:flex; align-items:center; justify-content:space-between; padding:18px 22px; border-bottom:1px solid var(--sv2-border-light, #F1F3F5); }
.pm-title { font-size:18px; font-weight:800; letter-spacing:-.4px; color: var(--sv2-text, #1A1A2E); }
.pm-body  { padding:20px 22px; }
.pm-foot  { display:flex; justify-content:flex-end; align-items:stretch; gap:12px; padding:14px 22px 20px; border-top:1px solid var(--sv2-border-light, #F1F3F5); }
.pm-close {
  width:30px; height:30px; border-radius:8px; border:none;
  background:#F9FAFB; color:#6B7280;
  display:flex; align-items:center; justify-content:center;
  cursor:pointer; flex-shrink:0; transition:background .15s;
}
.pm-close:hover { background:#E5E7EB; }

/* Confirm dialog — reuses the shared .sv2-modal-inner / .pm-* shell above,
   so it looks like every other v2 modal instead of a bespoke dialog. */
.sv2-confirm-text {
  font-size: 14px; color: var(--sv2-muted, #6B7280);
  line-height: 1.6; margin: 0;
}

/* ── Alert dialog (sv2Alert) ──────────────────────────────────────────────
   The centred "moment" dialog: hero icon, headline, supporting line, one
   primary action. Replaces the SweetAlert popups the v1 dashboard used, so
   success/error moments read as part of v2 instead of a third-party skin.

   Deliberately NOT built on .pm-head/.pm-body/.pm-foot: those centre on a
   left-aligned title bar with a divider, and this dialog has no title bar —
   the icon is the header. Reusing them meant fighting three borders and a
   flex-end footer on every rule below. It keeps .sv2-modal-inner, so width,
   radius, shadow and the slide-in stay shared with every other v2 modal. */
.sv2-alert-dialog {
  position: relative;
  z-index: 1;
  text-align: center;
  padding: 34px 26px 26px;
}
/* Carries tabindex="-1" and is focused on open so the dialog is announced and
   Escape / Enter land somewhere sensible. It is a container, not a control, so
   it must not draw a ring — the buttons inside keep their own. */
.sv2-alert-dialog:focus { outline: none; }
.sv2-alert-close {
  position: absolute; top: 14px;
  /* Logical property, not `right` — the dashboard runs RTL in Arabic and a
     hard `right` would drop the X on top of the icon's own side. */
  inset-inline-end: 14px;
  width: 30px; height: 30px; border-radius: 8px; border: none;
  background: #F9FAFB; color: #6B7280;
  display: flex; align-items: center; justify-content: center;
  cursor: pointer; transition: background .15s;
}
.sv2-alert-close:hover { background: #E5E7EB; }

.sv2-alert-icon {
  width: 72px; height: 72px; border-radius: 50%;
  margin: 0 auto 18px;
  display: flex; align-items: center; justify-content: center;
  position: relative;
}
.sv2-alert-icon svg {
  width: 34px; height: 34px;
  overflow: visible;
  /* Above the ripple, which is painted behind it. */
  position: relative; z-index: 1;
}

/* ── Icon choreography ────────────────────────────────────────────────────
   Ported from the booking confirmation hero (`.conf-hero` / `.conf-check` in
   booking-v2.css) so a success in the dashboard and a success at the end of a
   booking move the same way, rather than each inventing its own timing.

     t=0.35  disc pops        (0.45s) → 0.80
     t=0.75  tick draws       (0.35s) → 1.10
     t=0.60  cross stroke 1   (0.25s) → 0.85
     t=0.85  cross stroke 2   (0.25s) → 1.10

   Every delay derives from --sv2-alert-intro, exactly as the booking hero
   derives its own from --conf-fill, so retiming the sequence is one value.

   That intro is deliberately a fixed 1.1s rather than keyed to the timer the
   way booking keys it to its bar: booking's bar runs once and means "done", so
   its strokes can land with it, whereas this timer may be 3s or absent
   entirely — a tick that waited three seconds to draw would read as broken. */
.sv2-alert-dialog { --sv2-alert-intro: 1.1s; }

.sv2-alert-icon {
  animation: sv2AlertPop .45s cubic-bezier(.34, 1.56, .64, 1)
             calc(var(--sv2-alert-intro) - .75s) both;
}
@keyframes sv2AlertPop { from { transform: scale(0); } to { transform: scale(1); } }

/* Ripple, success only — the booking page withholds it from its failure state
   on the grounds that a failure should not pulse for attention, and the same
   reasoning applies to error and warning here. `background: inherit` picks up
   whichever variant tint the disc is wearing, so this needs no per-variant rule. */
.sv2-alert-success .sv2-alert-icon::before {
  content: '';
  position: absolute;
  width: 100%; height: 100%;
  border-radius: 50%;
  background: inherit;
  opacity: .5;
  animation: sv2AlertRipple 2s ease-out infinite;
}
@keyframes sv2AlertRipple {
  0%   { transform: scale(1);   opacity: .5; }
  100% { transform: scale(1.5); opacity: 0; }
}

/* pathLength="1" normalises each shape's stroke length, so one dash value
   works for the tick and the cross regardless of their real geometry — the
   same trick booking-v2.css uses, rather than hard-coding measured lengths. */
.sv2-alert-success .sv2-alert-icon polyline,
.sv2-alert-error   .sv2-alert-icon line {
  stroke-dasharray: 1;
  stroke-dashoffset: 1;
}
.sv2-alert-success .sv2-alert-icon polyline {
  animation: sv2AlertDraw .35s cubic-bezier(.65, 0, .35, 1)
             calc(var(--sv2-alert-intro) - .35s) forwards;
}
/* Two strokes rather than a fade: the second starts as the first ends. */
.sv2-alert-error .sv2-alert-icon line {
  animation: sv2AlertDraw .25s cubic-bezier(.65, 0, .35, 1)
             calc(var(--sv2-alert-intro) - .5s) forwards;
}
.sv2-alert-error .sv2-alert-icon line:last-of-type {
  animation-delay: calc(var(--sv2-alert-intro) - .25s);
}
@keyframes sv2AlertDraw { to { stroke-dashoffset: 0; } }

/* warning and info are multi-part glyphs — an outline, a stem and a dot — where
   a stroke draw reads as three unrelated things assembling. They scale in as one
   piece instead, landing on the same beat the drawn glyphs do. */
.sv2-alert-warning .sv2-alert-icon svg,
.sv2-alert-info    .sv2-alert-icon svg {
  animation: sv2AlertGlyph .35s ease calc(var(--sv2-alert-intro) - .35s) both;
}
@keyframes sv2AlertGlyph {
  from { opacity: 0; transform: scale(.55); }
  to   { opacity: 1; transform: none; }
}
/* Tinted disc + saturated glyph, one pair per variant. */
.sv2-alert-success .sv2-alert-icon { background: #E7F8F0; color: var(--sv2-green, #12B76A); }
.sv2-alert-error   .sv2-alert-icon { background: #FDECEC; color: var(--sv2-red,   #EF4444); }
.sv2-alert-warning .sv2-alert-icon { background: #FEF4E6; color: var(--sv2-amber, #F59E0B); }
.sv2-alert-info    .sv2-alert-icon { background: var(--sv2-blue-light, #EEF4FF); color: var(--sv2-blue, #0069FF); }

.sv2-alert-title {
  font-size: 20px; font-weight: 800; letter-spacing: -.4px;
  color: var(--sv2-text, #1A1A2E);
  margin: 0 0 8px;
  /* Keep the headline clear of the corner close control in both LTR and RTL. */
  padding-inline: 28px;
}
.sv2-alert-text {
  font-size: 14px; line-height: 1.6;
  color: var(--sv2-muted, #6B7280);
  margin: 0;
  /* Break long tokens (URLs, slugs) without splitting ordinary words. */
  overflow-wrap: break-word;
}
/* Caller-supplied slot between the text and the buttons — the copy-link row on
   setup-complete, an order summary after payment. */
.sv2-alert-extra { margin-top: 18px; }

.sv2-alert-actions {
  display: flex; gap: 10px;
  margin-top: 24px;
}
/* .sv2-btn is flex:1, so a lone button fills the width and a pair splits it
   evenly without either needing its own width rule. */

/* Timer bar. Width is animated rather than transform-scaled so it grows from
   one end instead of expanding out of its centre, and it anchors to
   inset-inline-start so it fills right-to-left in Arabic without extra rules. */
.sv2-alert-timer {
  position: absolute; bottom: 0; inset-inline-start: 0;
  /* 6px and a three-stop gradient, matching the booking confirmation hero's
     own bar (.conf-hero::before) so the two read as the same component. */
  height: 6px; width: 100%;
  border-radius: 0 0 18px 18px;
  overflow: hidden;
  /* A faint track the bar runs along, so the distance still to travel is
     visible rather than the bar ending in nothing. */
  background: rgba(16,24,40,.07);
}
.sv2-alert-timer i {
  display: block; height: 100%; width: 0;
  /* currentColor is the variant tint; the lightened middle stop reproduces the
     booking bar's green → #34D399 → green ramp without needing a second hex
     per variant. */
  background-color: currentColor;
  background-image: linear-gradient(90deg,
    rgba(255,255,255,0) 0%,
    rgba(255,255,255,.38) 50%,
    rgba(255,255,255,0) 100%);
  animation: sv2AlertFill linear forwards;
}
.sv2-alert-success .sv2-alert-timer { color: var(--sv2-green, #12B76A); }
.sv2-alert-error   .sv2-alert-timer { color: var(--sv2-red,   #EF4444); }
.sv2-alert-warning .sv2-alert-timer { color: var(--sv2-amber, #F59E0B); }
.sv2-alert-info    .sv2-alert-timer { color: var(--sv2-blue,  #0069FF); }
/* Fills toward the close rather than draining away from it: the bar reaching
   the far edge is what the dialog closing looks like. */
@keyframes sv2AlertFill { from { width: 0; } to { width: 100%; } }

/* Respect a reduced-motion preference: the pop, the sheen and the enter/exit
   are decoration, but the drain doubles as the only signal that the dialog will
   self-close, so keep the bar visible and simply stop animating it. The exit
   also has to collapse to display:none, or `.closing` would hold a fully opaque
   overlay on screen until the JS timer strips it. */
/* What gets dropped here follows the booking hero's own reasoning: the pop, the
   draw and the fill are the content arriving and the timer reporting itself, so
   they stay. What goes is the large movement of the overlay and, above all, the
   ripple — the one animation that never stops.

   The icon's draw and the bar's fill are deliberately NOT disabled: both carry a
   hidden start state (stroke-dashoffset:1, width:0) that only the animation
   undoes, so switching them off would leave an empty coloured disc and a bar
   stuck at zero. If either is ever disabled here, reset that state too. */
@media (prefers-reduced-motion: reduce) {
  /* Cross-fade, not a hard cut. Killing these outright made the dialog appear
     and vanish instantly — the setting asks for less *movement*, not for no
     transition at all, so the scale is dropped and the fade kept. The overlay's
     own fade is opacity and blur only, no movement, so it runs unchanged. */
  /* Their own keyframes, not sv2FadeIn/Out — those carry the backdrop blur,
     which on the card would blur the overlay sitting directly behind it. */
  .sv2-overlay.open .sv2-modal-inner    { animation: sv2CardFadeIn .2s ease; }
  .sv2-overlay.closing .sv2-modal-inner { animation: sv2CardFadeOut .2s ease forwards; }

  /* The one animation that never stops. */
  .sv2-alert-success .sv2-alert-icon::before { animation: none; opacity: 0; }
}

/* Confetti canvas. Sits on the overlay backdrop, behind the dialog, so pieces
   frame the card instead of covering the title, close button or action.
   pointer-events none so a stray piece never blocks a click. */
.sv2-confetti {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  pointer-events: none;
  z-index: 0;
}

/* Shared buttons */
.sv2-btn {
  flex: 1;
  border: 1px solid var(--sv2-border, #E5E7EB);
  background: #fff;
  border-radius: 11px;
  padding: 12px;
  font-size: 14px;
  font-weight: 600;
  color: var(--sv2-text, #1A1A2E);
  cursor: pointer;
  font-family: inherit;
  transition: background .15s, border-color .15s, filter .15s;
  display: inline-flex; align-items: center; justify-content: center; gap: 8px;
}
.sv2-btn:hover { background: var(--sv2-bg, #F8F9FB); }
.sv2-btn:disabled { opacity: .65; cursor: not-allowed; }
/* A designed keyboard ring, and only for keyboard: with nothing defined here
   the browser fell back to its own default outline. :focus-visible means a
   mouse click never rings, while Tab still shows clearly where focus is.
   Offset so it sits outside the fill and stays visible on the solid variants. */
.sv2-btn:focus-visible {
  outline: 2px solid var(--sv2-blue, #0069FF);
  outline-offset: 2px;
}
.sv2-btn-ghost { background: #fff; }
.sv2-btn-danger { background: #EF4444; border-color: #EF4444; color: #fff; }
.sv2-btn-danger:hover { background: #DC2626; border-color: #DC2626; }
.sv2-btn-warning { background: #F59E0B; border-color: #F59E0B; color: #fff; }
/* Must repaint the background, not just filter it. `.sv2-btn:hover` sets a
   near-white background and outranks `.sv2-btn-warning` (two classes vs one),
   so a filter-only hover left this button white with white text on it — the
   label disappeared and only the orange border survived. danger and primary
   already darken explicitly; this now matches them. */
.sv2-btn-warning:hover { background: #D97706; border-color: #D97706; }
.sv2-btn-primary { background: #0069FF; border-color: #0069FF; color: #fff; }
.sv2-btn-primary:hover { background: #0050CC; border-color: #0050CC; }

/* Legacy button aliases used by older settings modals */
.set-btn-cancel {
  padding:11px 20px; border-radius:11px;
  border:1.5px solid #E5E7EB; background:#fff; color:#1A1A2E;
  font-size:14px; font-weight:700; cursor:pointer;
  transition:all .15s; font-family:inherit;
}
.set-btn-cancel:hover { border-color:#9CA3AF; }
.set-btn-save {
  padding:11px 24px; border-radius:11px; border:none;
  background:#0069FF; color:#fff;
  font-size:14px; font-weight:700; cursor:pointer;
  transition:all .15s; display:inline-flex; align-items:center; gap:8px;
  font-family:inherit;
}
.set-btn-save:hover { filter:brightness(.9); }
.set-btn-save:disabled { opacity:.4; cursor:not-allowed; pointer-events:none; }
@keyframes sv2BtnSpin { to { transform:rotate(360deg); } }
/* Spinner ring for sv2BtnBusy() / settings save buttons.
   Must NOT be a bare .btn-spinner rule — onboarding pages pre-render a hidden
   .btn-spinner and only reveal it under .btn-primary.loading. A global
   display:inline-block here made Create Account / Continue look "loading"
   on page load with no user action. */
.is-busy > .btn-spinner,
.set-btn-save .btn-spinner {
  width:15px; height:15px;
  border:2px solid rgba(255,255,255,.4); border-top-color:#fff;
  border-radius:50%; animation:sv2BtnSpin .7s linear infinite; flex-shrink:0;
  display:inline-block;
}
/* Wrapper for sv2BtnBusy()'s label (see app-utils.js) — a real flex item,
   not a bare text node, so it centers with the spinner the same way across
   engines instead of sitting in an inconsistently-sized anonymous box. */
.btn-spinner-label { white-space: nowrap; }

/* ── Field validation ── */
.sv2-field { display: flex; flex-direction: column; gap: 6px; }
.sv2-field-label { font-size: 13px; font-weight: 600; color: var(--sv2-text, #1A1A2E); }
.sv2-field-error {
  display: none;
  font-size: 11.5px;
  color: var(--sv2-red, #EF4444);
  margin-top: 4px;
  font-weight: 500;
}
.sv2-field .is-invalid,
input.is-invalid,
select.is-invalid,
textarea.is-invalid {
  border-color: var(--sv2-red, #EF4444) !important;
  box-shadow: 0 0 0 3px rgba(239, 68, 68, .12) !important;
}

/* Alias settings inline errors onto shared class */
.sf-field-error {
  display: none;
  font-size: 11.5px;
  color: var(--sv2-red, #EF4444);
  margin-top: 4px;
  font-weight: 500;
}

/* ── Breadcrumb ── */
.sv2-breadcrumb {
  display: flex; flex-wrap: wrap; align-items: center; gap: 6px;
  list-style: none; padding: 0; margin: 0 0 14px;
  font-size: 13px; color: var(--sv2-muted, #6B7280);
}
.sv2-breadcrumb a { color: var(--sv2-muted, #6B7280); text-decoration: none; }
.sv2-breadcrumb a:hover { color: var(--sv2-blue, #0069FF); }
.sv2-breadcrumb .sep { opacity: .5; }
.sv2-breadcrumb .current { color: var(--sv2-text, #1A1A2E); font-weight: 600; }

/* ── Segments ── */
.sv2-segs {
  display: flex; gap: 4px;
  background: var(--sv2-border-light, #F1F3F5);
  border-radius: 12px; padding: 4px;
  margin-bottom: 16px; width: fit-content; max-width: 100%; overflow-x: auto;
}
.sv2-seg {
  border: none; background: none;
  padding: 8px 16px; border-radius: 9px;
  font-size: 13px; font-weight: 600;
  color: var(--sv2-muted, #6B7280);
  cursor: pointer; white-space: nowrap;
  transition: .15s; display: inline-flex; align-items: center; gap: 7px;
  text-decoration: none; font-family: inherit;
}
.sv2-seg:hover { color: var(--sv2-text, #1A1A2E); }
.sv2-seg.active {
  background: #fff; color: var(--sv2-blue, #0069FF);
  box-shadow: 0 1px 3px rgba(16,24,40,.08);
}
.sv2-seg-n {
  font-size: 11px; font-weight: 700;
  background: var(--sv2-border-light, #F1F3F5);
  color: var(--sv2-muted, #6B7280);
  border-radius: 100px; padding: 1px 7px;
}
.sv2-seg.active .sv2-seg-n {
  background: var(--sv2-blue-light, #EEF4FF);
  color: var(--sv2-blue, #0069FF);
}

/* ── Action / filter menus ── */
.sv2-menu {
  position: absolute; z-index: 1200;
  min-width: 200px; background: #fff;
  border: 1px solid var(--sv2-border, #E5E7EB);
  border-radius: 12px;
  box-shadow: 0 18px 48px rgba(16,24,40,.16);
  padding: 6px; display: none;
}
.sv2-menu.open { display: block; }
.sv2-menu-item {
  width: 100%; border: none; background: none;
  display: flex; align-items: center; gap: 10px;
  padding: 10px 12px; border-radius: 8px;
  font-size: 13.5px; font-weight: 600;
  color: var(--sv2-text, #1A1A2E);
  cursor: pointer; text-align: start; font-family: inherit;
}
.sv2-menu-item:hover { background: var(--sv2-bg, #F8F9FB); }
.sv2-menu-item.danger { color: var(--sv2-red, #EF4444); }
.sv2-menu-item.danger:hover { background: #FEE2E2; }
.sv2-menu-sep { height: 1px; background: var(--sv2-border-light, #F1F3F5); margin: 4px 6px; }

/* ── Date / time inputs ── */
.sv2-date-input,
.sv2-time-input {
  width: 100%;
  border: 1.5px solid var(--sv2-border, #E5E7EB);
  border-radius: 11px;
  padding: 11px 14px;
  font-size: 14px;
  color: var(--sv2-text, #1A1A2E);
  background: #fff;
  font-family: inherit;
}
.sv2-date-input:focus,
.sv2-time-input:focus {
  outline: none;
  border-color: var(--sv2-blue, #0069FF);
  box-shadow: 0 0 0 3px rgba(0,105,255,.12);
}

/* Shared flatpickr skin */
.flatpickr-calendar {
  border-radius: 14px !important;
  border: 1px solid var(--sv2-border, #E5E7EB) !important;
  box-shadow: 0 18px 48px rgba(16,24,40,.16) !important;
  font-family: inherit !important;
  padding: 12px !important;
}
.flatpickr-calendar::before,
.flatpickr-calendar::after { display: none !important; }
.flatpickr-months { display: flex; align-items: center; margin-bottom: 14px; }
.flatpickr-month { background: transparent !important; height: 36px; display: flex; align-items: center; flex: 1; justify-content: center; }
.flatpickr-prev-month,
.flatpickr-next-month {
  width: 32px; height: 32px; border-radius: 8px;
  border: 1px solid var(--sv2-border, #E5E7EB) !important;
  display: flex !important; align-items: center; justify-content: center;
  background: #fff !important;
}
.flatpickr-prev-month:hover,
.flatpickr-next-month:hover { background: #EEF4FF !important; border-color: #0069FF !important; }
.flatpickr-prev-month svg,
.flatpickr-next-month svg { fill: #6B7280 !important; }
.flatpickr-day {
  border-radius: 8px !important;
  height: 36px !important; line-height: 36px !important;
  max-width: 36px !important;
}
.flatpickr-day:hover:not(.flatpickr-disabled):not(.selected):not(.today) {
  background: #EEF4FF !important; color: #0069FF !important;
}
.flatpickr-day.today { background: #EEF4FF !important; color: #0069FF !important; font-weight: 700 !important; border: none !important; }
.flatpickr-day.selected,
.flatpickr-day.selected:hover {
  background: #0069FF !important; color: #fff !important; border-color: #0069FF !important;
}
/* Range mode (mode: 'range') — the two ends are startRange/endRange rather than
   .selected, and every day between them is .inRange. The box-shadow is how
   flatpickr bridges the gap between day cells so the band reads as continuous. */
.flatpickr-day.startRange,
.flatpickr-day.endRange,
.flatpickr-day.startRange:hover,
.flatpickr-day.endRange:hover {
  background: #0069FF !important; color: #fff !important; border-color: #0069FF !important;
  font-weight: 700 !important;
}
.flatpickr-day.inRange,
.flatpickr-day.inRange:hover {
  background: #EEF4FF !important; color: #0069FF !important; border-color: #EEF4FF !important;
  box-shadow: -5px 0 0 #EEF4FF, 5px 0 0 #EEF4FF !important;
}

@media (max-width: 600px) {
  .sv2-overlay { padding:0; align-items:flex-end; }
  .sv2-modal-inner,
  .sv2-confirm-dialog { border-radius:18px 18px 0 0; width:100%; max-width:100%; }
  /* Bottom sheet: keep it on the bottom edge (margin:auto would centre it). */
  .sv2-modal-inner { margin: auto 0 0; }
  /* Celebration and warning alerts stay a centred card. A bottom sheet gets
     clipped by the mobile browser chrome (the action and timer bar vanish
     under the toolbar) and the ticket asks for that banner to stay fully
     readable in both languages. */
  .sv2-alert-overlay {
    padding: 16px;
    padding-bottom: max(16px, env(safe-area-inset-bottom));
    align-items: center;
    justify-content: center;
  }
  .sv2-alert-dialog {
    border-radius: 18px;
    width: 100%;
    max-width: 420px;
    max-height: calc(100vh - 32px);
    max-height: calc(100dvh - 32px - env(safe-area-inset-bottom));
    overflow-y: auto;
  }
  /* Stacked, primary on top: at this width a side-by-side pair squeezes both
     labels into two lines each. */
  .sv2-alert-actions { flex-direction:column-reverse; }
}

/* ── Bootstrap datepicker grid fix (v2 dashboard) ── */
body.v2-dash .datepicker.dropdown-menu {
  z-index: 1065 !important;
  padding: 12px 14px 10px;
  border-radius: 14px;
  border: 1px solid #E5E7EB;
  box-shadow: 0 18px 48px rgba(16, 24, 40, .16);
  font-family: inherit;
  min-width: 280px;
}
body.v2-dash .datepicker table {
  width: 100%;
  margin: 0;
  border-collapse: separate;
  border-spacing: 0;
  table-layout: fixed;
}
body.v2-dash .datepicker table tr { display: table-row; }
body.v2-dash .datepicker table tr td,
body.v2-dash .datepicker table tr th {
  display: table-cell !important;
  float: none !important;
  position: static !important;
  width: 36px; height: 36px; max-width: 36px;
  padding: 0; text-align: center; vertical-align: middle;
  line-height: 36px; font-size: 13px; font-weight: 500;
  border: none; border-radius: 8px; box-sizing: border-box;
}
body.v2-dash .datepicker table thead tr:nth-child(2) th {
  height: auto !important; width: auto !important; max-width: none;
  line-height: 1.2; padding: 8px 0 6px;
  font-size: 12px; font-weight: 700; color: #6B7280;
}
body.v2-dash .datepicker table thead tr th.prev,
body.v2-dash .datepicker table thead tr th.next,
body.v2-dash .datepicker table thead tr th.datepicker-switch { cursor: pointer; }
body.v2-dash .datepicker table tbody tr td.day { color: #1A1A2E; cursor: pointer; }
body.v2-dash .datepicker table tbody tr td.day.old,
body.v2-dash .datepicker table tbody tr td.day.new { color: #9CA3AF; }
body.v2-dash .datepicker table tbody tr td.day:hover,
body.v2-dash .datepicker table tbody tr td.day.focused { background: #F8F9FB; }
body.v2-dash .datepicker table tbody tr td.day.active,
body.v2-dash .datepicker table tbody tr td.day.active:hover {
  background: #0069FF; color: #fff;
}
body.v2-dash .datepicker table tbody tr td.today:not(.active) {
  display: table-cell !important;
  background: #EEF4FF; color: #0069FF; font-weight: 700;
}
body.v2-dash .datepicker tfoot tr th {
  padding-top: 8px; font-size: 12px; font-weight: 700;
  color: #0069FF; cursor: pointer;
}
body.v2-dash .datepicker tfoot tr th:hover { color: #0050CC; }
body.v2-dash .datepicker table tbody tr td.day.disabled,
body.v2-dash .datepicker table tbody tr td.day.reuse-day-blocked {
  color: #D1D5DB !important;
  background: #F3F4F6 !important;
  cursor: not-allowed;
  pointer-events: none;
}

/* ============================================================
   Flatpickr — v2 theme (shared by every sv2InitDate() field —
   see sv2InitDate/sv2InitTime in app-utils.js)
   ============================================================ */

/* ── Alt-input inherits ed-inp look (added via JS .addClass) ─ */
.flatpickr-input[readonly] { cursor: pointer; }

/* ── Popup container ── */
.flatpickr-calendar {
    font-family: 'DM Sans', system-ui, -apple-system, sans-serif !important;
    background: #ffffff;
    border: 1px solid #E5E7EB;
    border-radius: 16px;
    box-shadow: 0 8px 32px rgba(16,24,40,.13), 0 2px 8px rgba(16,24,40,.06);
    padding: 18px;
    width: 310px !important;
    margin-top: 6px;
}
.flatpickr-calendar::before,
.flatpickr-calendar::after { display: none !important; }
.flatpickr-calendar.open { display: inline-block; }

/* ── Month navigation ── */
.flatpickr-months {
    display: flex;
    align-items: center;
    margin-bottom: 14px;
}
.flatpickr-month {
    background: transparent !important;
    height: 36px;
    display: flex;
    align-items: center;
    flex: 1;
    justify-content: center;
}
.flatpickr-prev-month,
.flatpickr-next-month {
    position: static !important;
    top: unset !important;
    display: flex !important;
    align-items: center !important;
    justify-content: center !important;
    width: 34px !important;
    height: 34px !important;
    border-radius: 10px !important;
    border: 1.5px solid #E5E7EB !important;
    padding: 0 !important;
    flex-shrink: 0;
    transition: background .15s, border-color .15s;
}
.flatpickr-prev-month:hover,
.flatpickr-next-month:hover {
    background: #EEF4FF !important;
    border-color: #0069FF !important;
}
.flatpickr-prev-month svg,
.flatpickr-next-month svg { fill: #6B7280 !important; transition: fill .15s; }
.flatpickr-prev-month:hover svg,
.flatpickr-next-month:hover svg { fill: #0069FF !important; }
.flatpickr-current-month {
    font-size: 14.5px !important;
    font-weight: 700 !important;
    color: #1A1A2E !important;
    padding: 0 !important;
    left: unset !important;
    width: auto !important;
    display: flex !important;
    align-items: center !important;
    gap: 4px !important;
    justify-content: center;
}
.flatpickr-monthDropdown-months {
    font-family: 'DM Sans', system-ui, sans-serif !important;
    font-size: 14.5px !important;
    font-weight: 700 !important;
    color: #1A1A2E !important;
    background: transparent !important;
    border: none !important;
    padding: 0 !important;
    cursor: pointer;
    appearance: none !important;
    -webkit-appearance: none !important;
}
.flatpickr-current-month input.cur-year {
    font-family: 'DM Sans', system-ui, sans-serif !important;
    font-size: 14.5px !important;
    font-weight: 700 !important;
    color: #1A1A2E !important;
    background: transparent !important;
    border: none !important;
    padding: 0 !important;
    width: 54px !important;
}
.flatpickr-current-month .arrowUp,
.flatpickr-current-month .arrowDown { display: none !important; }

/* ── Weekday row ── */
.flatpickr-weekdays { background: transparent !important; margin-bottom: 6px; height: 30px; }
.flatpickr-weekday {
    background: transparent !important;
    color: #9CA3AF !important;
    font-size: 11px !important;
    font-weight: 600 !important;
    text-transform: uppercase !important;
    letter-spacing: .05em !important;
}

/* ── Day cells ── */
.flatpickr-days { width: 100% !important; }
.dayContainer {
    width: 100% !important;
    min-width: 100% !important;
    max-width: 100% !important;
}
.flatpickr-day {
    font-family: 'DM Sans', system-ui, sans-serif !important;
    border-radius: 9px !important;
    font-size: 13px !important;
    font-weight: 500 !important;
    color: #1A1A2E !important;
    height: 36px !important;
    line-height: 36px !important;
    max-width: 36px !important;
    border: none !important;
    box-shadow: none !important;
    transition: background .12s, color .12s;
    margin: 1px auto;
}
.flatpickr-day:hover:not(.flatpickr-disabled):not(.selected):not(.today) {
    background: #EEF4FF !important;
    color: #0069FF !important;
}
.flatpickr-day.today {
    background: #EEF4FF !important;
    color: #0069FF !important;
    font-weight: 700 !important;
    border: none !important;
}
.flatpickr-day.today:hover { background: #dce8ff !important; }
.flatpickr-day.selected,
.flatpickr-day.selected:hover {
    background: #0069FF !important;
    color: #fff !important;
    font-weight: 700 !important;
    border: none !important;
    box-shadow: 0 2px 8px rgba(0,105,255,.28) !important;
}
.flatpickr-day.flatpickr-disabled,
.flatpickr-day.flatpickr-disabled:hover {
    color: #D1D5DB !important;
    cursor: not-allowed !important;
    background: transparent !important;
    opacity: .5 !important;
}
.flatpickr-day.prevMonthDay,
.flatpickr-day.nextMonthDay { color: #D1D5DB !important; }

/* ── Time section (within date+time picker) ── */
.flatpickr-time {
    background: transparent !important;
    border-top: 1px solid #F1F3F5 !important;
    margin-top: 12px !important;
    padding-top: 12px !important;
    height: auto !important;
    max-height: none !important;
    display: flex !important;
    align-items: center !important;
    justify-content: center !important;
    gap: 4px;
}
.flatpickr-time .numInputWrapper {
    display: flex;
    flex-direction: column;
    align-items: center;
    flex: 0 0 auto;
    width: 52px;
}
.flatpickr-time input.flatpickr-hour,
.flatpickr-time input.flatpickr-minute {
    font-family: 'DM Sans', system-ui, sans-serif !important;
    font-size: 22px !important;
    font-weight: 700 !important;
    color: #1A1A2E !important;
    background: #F8F9FB !important;
    border: 1.5px solid #E5E7EB !important;
    border-radius: 10px !important;
    box-shadow: none !important;
    width: 52px !important;
    height: 46px !important;
    text-align: center !important;
    padding: 0 !important;
    line-height: 46px !important;
    transition: border-color .15s, background .15s;
}
.flatpickr-time input:focus {
    border-color: #0069FF !important;
    background: #EEF4FF !important;
    box-shadow: 0 0 0 3px rgba(0,105,255,.08) !important;
    outline: none !important;
}
.flatpickr-time-separator {
    font-size: 18px !important;
    font-weight: 500 !important;
    color: #D1D5DB !important;
    margin: 0 !important;
    padding-bottom: 4px;
    flex-shrink: 0;
    align-self: center;
}
.flatpickr-time .arrowUp,
.flatpickr-time .arrowDown {
    display: flex !important;
    align-items: center !important;
    justify-content: center !important;
    width: 28px !important;
    height: 18px !important;
    border-radius: 5px !important;
    border: none !important;
    background: transparent !important;
    cursor: pointer;
    transition: background .12s, color .12s;
    margin: 2px auto !important;
    padding: 0 !important;
}
.flatpickr-time .arrowUp:hover,
.flatpickr-time .arrowDown:hover {
    background: #EEF4FF !important;
}
.flatpickr-time .arrowUp::after {
    content: '' !important;
    display: block;
    width: 0; height: 0;
    border-left: 3.5px solid transparent;
    border-right: 3.5px solid transparent;
    border-bottom: 4px solid #C4C9D4;
    border-top: none;
}
.flatpickr-time .arrowUp:hover::after { border-bottom-color: #0069FF !important; }
.flatpickr-time .arrowDown::after {
    content: '' !important;
    display: block;
    width: 0; height: 0;
    border-left: 3.5px solid transparent;
    border-right: 3.5px solid transparent;
    border-top: 4px solid #C4C9D4;
    border-bottom: none;
}
.flatpickr-time .arrowDown:hover::after { border-top-color: #0069FF !important; }

/* AM / PM toggle — neutral, understated */
.flatpickr-am-pm {
    font-family: 'DM Sans', system-ui, sans-serif !important;
    font-size: 11px !important;
    font-weight: 600 !important;
    letter-spacing: .04em !important;
    color: #6B7280 !important;
    background: #F1F3F5 !important;
    border: 1px solid #E5E7EB !important;
    border-radius: 7px !important;
    padding: 5px 9px !important;
    cursor: pointer;
    transition: background .12s, color .12s, border-color .12s;
    align-self: center;
    margin-left: 4px;
    user-select: none;
}
.flatpickr-am-pm:hover {
    background: #EEF4FF !important;
    border-color: #0069FF !important;
    color: #0069FF !important;
}

/* ── Time-only popup: compact card ── */
.flatpickr-calendar.hasTime.noCalendar {
    width: 210px !important;
    padding: 14px 12px !important;
}
.flatpickr-calendar.hasTime.noCalendar .flatpickr-time {
    border-top: none !important;
    margin-top: 0 !important;
    padding-top: 0 !important;
}


/* ============================================================
   Bootstrap Timepicker Widget — v2 refined theme (shared by
   every sv2InitTime() field)
   ============================================================ */

.bootstrap-timepicker-widget {
    font-family: 'DM Sans', system-ui, -apple-system, sans-serif !important;
    background: #ffffff !important;
    border: 1px solid #E5E7EB !important;
    border-radius: 12px !important;
    box-shadow: 0 4px 20px rgba(16,24,40,.09), 0 1px 4px rgba(16,24,40,.04) !important;
    padding: 14px 12px !important;
    min-width: 196px !important;
}
.bootstrap-timepicker-widget::before,
.bootstrap-timepicker-widget::after { display: none !important; }

.bootstrap-timepicker-widget table { width: 100%; border-collapse: separate; border-spacing: 0; }
.bootstrap-timepicker-widget table td {
    border: none !important;
    padding: 3px 3px !important;
    text-align: center;
    vertical-align: middle;
}
.bootstrap-timepicker-widget table td.separator {
    font-size: 18px;
    font-weight: 500;
    color: #D1D5DB;
    width: 14px;
    padding: 0 !important;
    line-height: 1;
}

/* Up/Down arrow buttons — minimal, borderless by default */
.bootstrap-timepicker-widget table td > a {
    display: flex !important;
    align-items: center !important;
    justify-content: center !important;
    width: 28px !important;
    height: 20px !important;
    margin: 0 auto !important;
    border: none !important;
    border-radius: 5px !important;
    background: transparent !important;
    color: #C4C9D4 !important;
    text-decoration: none !important;
    transition: background .12s, color .12s;
}
.bootstrap-timepicker-widget table td > a:hover {
    background: #EEF4FF !important;
    color: #0069FF !important;
}

/* Custom chevron arrows (replace glyphicons) */
.bootstrap-timepicker-widget a span.glyphicon-chevron-up,
.bootstrap-timepicker-widget a span.glyphicon-chevron-down {
    display: inline-block !important;
    width: 6px !important;
    height: 6px !important;
    border-left:   1.5px solid currentColor !important;
    border-bottom: 1.5px solid currentColor !important;
    border-right:  none !important;
    border-top:    none !important;
    background:    transparent !important;
    transform:     rotate(135deg) !important;
}
.bootstrap-timepicker-widget a:hover span.glyphicon-chevron-up,
.bootstrap-timepicker-widget a:hover span.glyphicon-chevron-down {
    border-left-color:   currentColor !important;
    border-bottom-color: currentColor !important;
}
.bootstrap-timepicker-widget a span.glyphicon-chevron-down {
    transform: rotate(-45deg) !important;
}

/* Hour / minute inputs */
.bootstrap-timepicker-hour,
.bootstrap-timepicker-minute {
    font-family: 'DM Sans', system-ui, sans-serif !important;
    font-size: 12px !important;
    font-weight: 600 !important;
    color: #7E8299 !important;
    background: #F8F9FB !important;
    border: 1.5px solid #E5E7EB !important;
    border-radius: 10px !important;
    width: 52px !important;
    height: 46px !important;
    text-align: center !important;
    outline: none !important;
    box-shadow: none !important;
    transition: border-color .15s, background .15s;
}
.bootstrap-timepicker-widget table td input { width: 52px !important; }
.bootstrap-timepicker-hour:focus,
.bootstrap-timepicker-minute:focus {
    border-color: #0069FF !important;
    background: #EEF4FF !important;
    box-shadow: 0 0 0 3px rgba(0,105,255,.08) !important;
}

/* AM/PM toggle — neutral segmented-control style */
.bootstrap-timepicker-meridian {
    font-family: 'DM Sans', system-ui, sans-serif !important;
    font-size: 11px !important;
    font-weight: 600 !important;
    color: #6B7280 !important;
    background: #F1F3F5 !important;
    border: 1px solid #E5E7EB !important;
    border-radius: 7px !important;
    width: 42px !important;
    height: 46px !important;
    text-align: center !important;
    outline: none !important;
    box-shadow: none !important;
    cursor: pointer;
    transition: background .12s, color .12s, border-color .12s;
    letter-spacing: .03em;
}
.bootstrap-timepicker-meridian:hover {
    background: #EEF4FF !important;
    border-color: #0069FF !important;
    color: #0069FF !important;
}

/* Both widgets are appended to <body> (appendTo/appendWidgetTo), so they need a
   z-index above the sv2-overlay (9800) to render on top of a modal instead of
   under it — every sv2InitDate()/sv2InitTime() caller gets this for free. */
body.v2-dash .bootstrap-timepicker-widget.open {
    z-index: 9850 !important;
}
body.v2-dash .flatpickr-calendar {
    z-index: 9850 !important;
}

/* ── Modal footers on phones ───────────────────────────────────────────────
   Every modal's action footer looks the same on phones: two equal buttons
   (Cancel, then the main action), same height and radius, labels on one line.
   A footer with a single button gets the full width. */
@media (max-width: 500px) {
  .sv2-dlg-foot,
  .q-dlg-foot,
  .pkg-foot-acts,
  .sv2-alert-actions,
  .sv2-modal-foot {
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: 10px;
    width: 100%;
  }
  .sv2-dlg-foot > button,
  .q-dlg-foot > button,
  .pkg-foot-acts > button,
  .sv2-alert-actions > button,
  .sv2-modal-foot > button {
    width: 100%;
    min-width: 0;
    justify-content: center;
    white-space: nowrap;
    padding: 12px 10px;
    font-size: 14px;
    border-radius: 12px;
  }
  .sv2-dlg-foot > button:only-child,
  .q-dlg-foot > button:only-child,
  .pkg-foot-acts > button:only-child,
  .sv2-alert-actions > button:only-child,
  .sv2-modal-foot > button:only-child {
    grid-column: 1 / -1;
  }
}
