/* ============================================================
   Kids FunZone – Admin Console Stylesheet
   Simple, high-contrast, large-touch-target UI for staff/manager/admin.
   No gradients, no decorative animation, no horizontal scrolling.
   ============================================================ */

:root {
  --adm-bg:          #f4f6f8;
  --adm-surface:     #ffffff;
  --adm-card:        #ffffff;
  --adm-border:      #d7dde3;

  --adm-accent:      #2563eb;
  --adm-accent-soft: #e8f0fe;
  --adm-green:       #15803d;
  --adm-green-soft:  #dcfce7;
  --adm-yellow:      #92400e;
  --adm-yellow-soft: #fef3c7;
  --adm-red:         #b91c1c;
  --adm-red-soft:    #fee2e2;

  --adm-text-primary:   #111827;
  --adm-text-secondary: #4b5563;
  --adm-text-muted:     #9ca3af;

  --adm-font: 'Segoe UI', Inter, system-ui, sans-serif;

  --adm-sidebar-width: 240px;
  --adm-r: 8px;

  /* ── Responsive scale ──────────────────────────────────────
     The layout is driven from these four values so the topbar and the content
     below it always agree; overriding them in a media query re-flows both at
     once instead of leaving a title indented differently from the table under
     it.

     --adm-content-max caps how wide a reading column gets on a big monitor.
     Without it, a 2560px screen stretched a four-tile row across 2320px, which
     is not more information, just more travel for the eye and the mouse. The
     cap is applied as symmetric padding (see .adm-topbar / .adm-content) rather
     than max-width + auto margins, so the topbar keeps its full-bleed
     background and border while its contents still line up with the cards. */
  --adm-content-max: 1600px;
  --adm-gutter: 24px;
  --adm-nav-drawer-width: 280px;
}

*, *::before, *::after { box-sizing: border-box; }

.admin-page {
  font-family: var(--adm-font);
  background: var(--adm-bg);
  color: var(--adm-text-primary);
  min-height: 100vh;
  /* dvh accounts for Safari's address bar showing/hiding as the page
     scrolls — plain vh is fixed to the viewport's largest possible size, so
     on iOS specifically that overstates the visible height while the bar is
     shown. Declared after vh (never before): a browser that doesn't
     understand dvh ignores the line outright and keeps the vh value, so
     this only ever upgrades the result, never leaves min-height unset. */
  min-height: 100dvh;
  font-size: 16px;
  line-height: 1.5;
}
.admin-page a { color: var(--adm-accent); text-decoration: none; }

/* ── Layout ────────────────────────────────────────────────── */
.adm-layout { display: flex; min-height: 100vh; min-height: 100dvh; }

/* Reveal-gate: base.html's <body> starts with .adm-pending, hiding page
   content until admin-auth-guard.js confirms the session and role are valid
   for this page. Without this, a disallowed role's page (reached via a
   stale link, direct URL, or a leftover session from another account on a
   shared computer) would render and paint in full before the async role
   check redirects it away. Only admin-auth-guard.js's revealPage() removes
   this class — never via inline style, so there's no gap where it could be
   half-hidden. */
.adm-pending .adm-main { visibility: hidden; }

/* ── Sidebar ───────────────────────────────────────────────── */
.adm-sidebar {
  width: var(--adm-sidebar-width);
  background: #ffffff;
  border-right: 1px solid var(--adm-border);
  display: flex;
  flex-direction: column;
  position: fixed;
  height: 100vh;
  /* The one spot this matters most: a fixed, full-height sidebar whose
     bottom holds the sign-out control. Plain vh on iOS Safari is sized to
     the viewport with the address bar hidden, so while it's showing (the
     default on page load) this drew past the actually-visible area —
     exactly the kind of cut-off the dvh unit exists to fix. See the note by
     .admin-page above for why this is additive, not a replacement. */
  height: 100dvh;
  top: 0;
  left: 0;
  z-index: 1000;
}
.adm-sidebar-logo {
  height: 64px;
  display: flex;
  align-items: center;
  padding: 0 20px;
  border-bottom: 1px solid var(--adm-border);
  flex-shrink: 0;
}
.adm-logo-text { font-weight: 700; font-size: 1.15rem; color: var(--adm-text-primary); }
.adm-logo-text span { color: var(--adm-accent); }
.adm-logo-img { width: 34px; height: 34px; margin-right: 10px; flex-shrink: 0; }
.adm-logo-banner { height: 46px; width: auto; max-width: 100%; object-fit: contain; }
.adm-sidebar-logo { display: flex; align-items: center; }

/* Active fun zone, directly under the logo — the one thing that must be true on
   every page, since acting on the wrong branch's books is the mistake this whole
   feature makes possible. */
.adm-firm-block {
  padding: 10px 20px 12px;
  border-bottom: 1px solid var(--adm-border);
  flex-shrink: 0;
}
.adm-firm-strip {
  display: flex;
  align-items: center;
  gap: 7px;
  font-weight: 700;
  font-size: .9rem;
  color: var(--adm-accent);
  line-height: 1.25;
}
.adm-firm-strip i { flex: 0 0 auto; }
.adm-firm-switch {
  margin-top: 8px;
  background: transparent;
  border: 1px solid var(--adm-border);
  border-radius: 8px;
  padding: 5px 10px;
  font-size: .78rem;
  font-weight: 600;
  color: var(--adm-text-primary);
  cursor: pointer;
  display: flex;
  align-items: center;
  gap: 6px;
}
.adm-firm-switch:hover,
.adm-firm-switch:focus-visible {
  background: var(--adm-accent-soft);
  border-color: var(--adm-accent);
  color: var(--adm-accent);
  outline: none;
}

.adm-nav {
  flex: 1;
  padding: 12px;
  overflow-y: auto;
  display: flex;
  flex-direction: column;
  gap: 4px;
}
.adm-nav-link {
  display: flex;
  align-items: center;
  gap: 14px;
  padding: 14px 14px;
  border-radius: var(--adm-r);
  color: var(--adm-text-secondary);
  font-weight: 600;
  font-size: 1rem;
  border-left: 4px solid transparent;
}
.adm-nav-link:hover { background: #f1f5f9; color: var(--adm-text-primary); }
.adm-nav-link.active {
  background: var(--adm-accent-soft);
  color: var(--adm-accent);
  border-left-color: var(--adm-accent);
  font-weight: 700;
}
.adm-nav-link.active:hover { background: var(--adm-accent-soft); color: var(--adm-accent); }
.adm-nav-link i { font-size: 1.2rem; width: 22px; text-align: center; flex-shrink: 0; }

/* Section label above a group of nav links in the Admin sidebar (e.g. "Operations") —
   not clickable, just groups the flat link list into scannable sections. */
.adm-nav-section {
  padding: 16px 14px 4px;
  font-size: 0.72rem;
  font-weight: 800;
  text-transform: uppercase;
  letter-spacing: 0.06em;
  color: var(--adm-text-secondary);
}
.adm-nav-section:first-child { padding-top: 8px; }

.adm-sidebar-footer { padding: 12px; border-top: 1px solid var(--adm-border); flex-shrink: 0; }
.adm-user-card { display: flex; align-items: center; gap: 10px; padding: 8px; }
.adm-avatar {
  width: 38px; height: 38px; border-radius: 50%;
  background: var(--adm-accent); color: #fff;
  display: flex; align-items: center; justify-content: center;
  font-weight: 700; font-size: 0.9rem; flex-shrink: 0;
}
.adm-avatar-manager { background: var(--adm-green); }
.adm-user-info { min-width: 0; flex: 1; }
.adm-user-name { font-size: 0.9rem; font-weight: 700; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.adm-user-role { font-size: 0.78rem; color: var(--adm-text-secondary); }
.adm-logout-btn {
  background: transparent; border: none; color: var(--adm-text-secondary);
  cursor: pointer; font-size: 1.2rem; padding: 6px;
}
.adm-logout-btn:hover { color: var(--adm-red); }

/* !important is deliberate: this is a visibility utility class applied
   alongside layout classes like .adm-filter-row (display: flex) further
   down this file — without !important, cascade order (not role) would
   decide which display value wins, silently un-hiding role-gated elements
   regardless of the logged-in role. */
.adm-role-gate { display: none !important; }
/* Per-zone feature gate (see applyFeatureUI in admin-role.js) — same rule as
   the role gate: present in the markup by default, only ever toggled by JS,
   so nothing the zone doesn't have flashes up while /api/auth/me is pending. */
.adm-feature-gate { display: none !important; }
/* A page that only exists with the new features: held back until the
   session answer decides, then either shown as normal or replaced by a
   "not enabled" notice (the topbar keeps only the clock / zone pills). */
html.adm-feature-page:not(.adm-feature-page-ready) .adm-content,
html.adm-feature-page:not(.adm-feature-page-ready) .adm-topbar-actions { visibility: hidden; }
.adm-feature-notice { display: none; }
html.adm-feature-page-off .adm-feature-notice { display: block; padding: 20px; font-weight: 600; }
html.adm-feature-page-off .adm-content > :not(.adm-feature-notice),
html.adm-feature-page-off .adm-topbar-actions > :not(.adm-live-pill) { display: none !important; }

/* ── Main content ──────────────────────────────────────────── */
.adm-main {
  flex: 1;
  /* Without this, a flex item's default automatic minimum size is its
     content's intrinsic width — so a wide table (even one meant to scroll
     inside its own .adm-table-wrap) forced this whole column, and the
     fixed-position sidebar's margin-left offset with it, wider than the
     viewport instead of just scrolling the table. That showed up as the
     entire page gaining a horizontal scrollbar on a tablet-width screen. */
  min-width: 0;
  margin-left: var(--adm-sidebar-width);
  min-height: 100vh;
  min-height: 100dvh;
  display: flex;
  flex-direction: column;
}
.adm-topbar {
  min-height: 64px;
  background: var(--adm-surface);
  border-bottom: 1px solid var(--adm-border);
  display: flex;
  align-items: center;
  padding: 0 var(--adm-gutter);
  gap: 16px;
  flex-wrap: wrap;
}
/* Centres the topbar's contents on the same axis as .adm-content's cards once
   the column is wider than --adm-content-max, while the bar itself still spans
   edge to edge. The plain `padding` above is the fallback for anything without
   max(); every browser that has it applies the line below instead. */
.adm-topbar {
  padding-inline: max(var(--adm-gutter), calc((100% - var(--adm-content-max)) / 2));
}
/* min-width:0 on both: without it a flex item refuses to shrink below its
   content's intrinsic width, which is how the greeting pill ("Good Afternoon,
   Venkataraman Krishnamurthy (Manager)", set nowrap) pushed the whole page
   wider than a 390px phone and gave every admin screen a horizontal scrollbar. */
.adm-topbar-title { font-size: 1.4rem; font-weight: 700; flex: 1 1 auto; min-width: 0; padding: 14px 0; }
.adm-topbar-actions {
  display: flex;
  align-items: center;
  gap: 10px;
  flex-wrap: wrap;
  padding: 10px 0;
  min-width: 0;
  max-width: 100%;
}
/* Opens the off-canvas sidebar below 1024px. Created by admin.js (see
   setupAdminNavDrawer) as the topbar's first child, and display:none above the
   breakpoint where the sidebar is permanently on screen. */
.adm-nav-toggle {
  display: none;
  /* Leftmost whatever the DOM order turns out to be. Both this and the Back
     button are injected into the topbar as its first child by different
     DOMContentLoaded listeners (setupAdminNavDrawer and attachBackButtons), so
     which one ends up first depends on listener registration order — a detail
     no layout should rest on. */
  order: -1;
  flex: 0 0 auto;
  align-items: center;
  justify-content: center;
  width: 44px;
  height: 44px;
  margin-left: -6px;
  padding: 0;
  border: 1px solid var(--adm-border);
  border-radius: var(--adm-r);
  background: #ffffff;
  color: var(--adm-text-primary);
  font-size: 1.5rem;
  line-height: 0;
  cursor: pointer;
}
.adm-nav-toggle:hover { background: var(--adm-accent-soft); border-color: var(--adm-accent); color: var(--adm-accent); }
.adm-nav-toggle:focus-visible { outline: 2px solid var(--adm-accent); outline-offset: 2px; }

/* Dims the page behind the open drawer and gives a tap-anywhere-to-close
   target. base.html has always contained this element; it had no styles at all
   until the drawer existed, so it rendered as a zero-height nothing. */
.adm-overlay {
  display: none;
  position: fixed;
  inset: 0;
  background: rgba(15, 23, 42, 0.45);
  z-index: 999;
}

/* Greeting + live-clock pills, shown on every admin page's topbar. */
/* The active fun zone, stated more firmly than the greeting beside it — it is the
   one thing on the topbar you can act wrongly on. */
.adm-firm-pill {
  border-color: rgba(37, 99, 235, 0.45) !important;
  background: rgba(37, 99, 235, 0.16) !important;
  font-weight: 700;
  max-width: 240px;
}
/* The zone name is admin-editable and can be long. Truncate the label rather
   than the pill so the shop icon always stays visible — a clipped pill with no
   icon reads as a rendering glitch, an ellipsis reads as a long name. */
.adm-firm-pill > span {
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.adm-live-pill {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  padding: 8px 14px;
  border-radius: 999px;
  border: 1px solid rgba(37, 99, 235, 0.25);
  background: rgba(37, 99, 235, 0.08);
  color: #1e3a8a;
  font-size: 0.9rem;
  font-weight: 600;
  white-space: nowrap;
  /* nowrap above is what keeps the clock from breaking mid-time; these two stop
     it from widening the page instead. */
  min-width: 0;
  max-width: 100%;
}
.adm-clock-pill { font-variant-numeric: tabular-nums; }

.adm-content { padding: var(--adm-gutter); flex: 1; min-width: 0; overflow-wrap: break-word; }
/* Same centring as .adm-topbar, so cards and the page title share one left
   edge at every width. See --adm-content-max. */
.adm-content { padding-inline: max(var(--adm-gutter), calc((100% - var(--adm-content-max)) / 2)); }
/* settings.html puts .adm-content-narrow on the .adm-content element itself, so
   this has to beat the rule above rather than sit beside it. Centred, which
   register-kid's narrow block already was via .adm-center — left-aligned, a
   640px form sat against the far edge of a 2320px area with the page title
   nowhere near it. */
.adm-content.adm-content-narrow {
  max-width: 640px;
  padding-inline: var(--adm-gutter);
  margin-inline: auto;
}
.adm-content-narrow { max-width: 640px; }
.adm-center { margin-left: auto; margin-right: auto; }

.adm-kid-chip-row { display: flex; flex-wrap: wrap; gap: 8px; }
.adm-kid-chip {
  display: inline-block;
  background: var(--adm-green-soft);
  color: var(--adm-green);
  border-radius: 999px;
  padding: 6px 14px;
  font-weight: 700;
  font-size: 0.95rem;
}
.adm-kid-entry {
  border: 1px dashed var(--adm-border);
  border-radius: var(--adm-r);
  padding: 14px;
  margin-bottom: 12px;
}

/* ── Filter bar (Manager & Super Admin list views) ─────────────
   A bordered toolbar card, every control labeled the same way (small
   caps label above the field) and bottom-aligned, so search/date/
   dropdown fields never sit at mismatched heights. */
.adm-filter-row {
  display: flex;
  gap: 12px;
  flex-wrap: wrap;
  align-items: flex-end;
  margin-bottom: 16px;
  background: var(--adm-surface);
  border: 1px solid var(--adm-border);
  border-radius: var(--adm-r);
  padding: 16px;
}
/* Kept compact on purpose: rows with the most controls (Search + From + To +
   Staff + Export CSV, e.g. Platform History) need to fit on one line at
   ordinary laptop widths without Export CSV overflowing onto its own row —
   the widths below are the tightest that still comfortably fit each
   control's placeholder/value. */
.adm-filter-row .adm-form-select,
.adm-filter-row input[type="date"] {
  max-width: 150px;
}
.adm-filter-row input[type="text"] {
  max-width: 220px;
}
/* A search box that is the only control in its row (Packages' Purchase
   History) has the room to show its whole placeholder. */
.adm-filter-row input[type="text"].adm-filter-grow {
  max-width: 480px;
  flex: 1;
}
.adm-filter-row .adm-filter-spacer { flex: 1; }
.adm-filter-row label.adm-inline-label {
  display: flex;
  flex-direction: column;
  gap: 6px;
  font-size: 0.75rem;
  color: var(--adm-text-secondary);
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.04em;
}
/* Every control that can sit in a filter row — text/date/select inputs, the
   Payment pill-button group, and any bare .adm-btn (Search, Export CSV) —
   gets the SAME fixed `height` (not min-height). min-height alone doesn't
   work here: each control type has different padding (buttons use 10px,
   inputs/pills use 12px), so its natural content-driven size can exceed a
   shared min-height and the row still renders uneven. An explicit height +
   box-sizing: border-box makes every control exactly 44px regardless of its
   own padding, so bottoms truly line up under align-items: flex-end. */
/* 48px, not 44px. .adm-form-control and .adm-choice-btn both carry
   min-height: 48px, which a fixed height of 44px cannot win against — the
   control rendered 48px tall inside a 44px box and spilled 4px out of it, so
   the row this rule exists to align was never actually aligned. Matching the
   real control height makes every control exactly 48px and the alignment true. */
.adm-filter-row .adm-form-control,
.adm-filter-row .adm-form-select,
.adm-filter-row .adm-btn,
.adm-filter-row .adm-choice-group,
.adm-filter-row .adm-choice-btn {
  height: 48px;
  box-sizing: border-box;
}
.adm-filter-row .adm-btn { flex-shrink: 0; }
.adm-filter-row .adm-choice-group { align-items: stretch; }
/* Wraps the Search input on pages with a live suggestions dropdown (the
   dropdown is absolutely positioned off this). Without an explicit height,
   this wrapper's own auto height could come out a hair different from a
   plain <select>/<input> sitting directly in a label, which is what made
   Search sit slightly lower than Payment/Staff on pages that use it —
   Currently Playing has no suggestions dropdown and was never wrapped, which
   is why it never showed the offset. */
.adm-search-wrap { position: relative; }
.adm-filter-row .adm-search-wrap { height: 48px; }
.adm-filter-row .adm-choice-btn { display: flex; align-items: center; justify-content: center; }
/* The narrow-screen behaviour of this row lives with every other breakpoint in
   the Responsive section at the end of this file. */

/* ── Buttons ───────────────────────────────────────────────── */
.adm-btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 8px;
  padding: 10px 18px;
  border-radius: var(--adm-r);
  font-weight: 700;
  font-size: 1rem;
  cursor: pointer;
  border: 1.5px solid transparent;
  min-height: 44px;
}
.adm-btn-primary { background: var(--adm-accent); color: #fff !important; }
.adm-btn-primary:hover { background: #1d4ed8; color: #fff !important; }
.adm-btn-secondary { background: #ffffff; color: var(--adm-text-primary) !important; border-color: var(--adm-border); }
.adm-btn-secondary:hover { background: #f1f5f9; }
.adm-btn-danger { background: var(--adm-red-soft); color: var(--adm-red) !important; border-color: var(--adm-red); }
.adm-btn-danger:hover { background: #fecaca; }
.adm-btn-accent { background: var(--adm-accent-soft); color: var(--adm-accent) !important; border-color: #bfdbfe; }
.adm-btn-accent:hover { background: #dbeafe; }
.adm-btn-solid-danger { background: var(--adm-red); color: #fff !important; border-color: var(--adm-red); }
.adm-btn-solid-danger:hover { background: #991b1b; }
.adm-btn-link { background: transparent; color: var(--adm-accent) !important; border: none; font-weight: 600; }
.adm-btn-lg { min-height: 52px; font-size: 1.1rem; padding: 12px 24px; }
.adm-btn-sm { min-height: 38px; padding: 6px 10px; font-size: 0.85rem; }
.adm-btn { white-space: nowrap; }

/* Big green check-in button — the single most important action on the
   Register Kid screen, so it gets its own unmissable style. */
.adm-btn-checkin {
  display: block;
  width: 100%;
  margin-top: 20px;
  padding: 20px;
  background: var(--adm-green);
  color: #fff;
  border: none;
  border-radius: var(--adm-r);
  font-size: 1.4rem;
  font-weight: 800;
  letter-spacing: 0.04em;
  cursor: pointer;
}
.adm-btn-checkin:hover { background: #14632f; }

/* ── Cards ─────────────────────────────────────────────────── */
.adm-card {
  background: var(--adm-card);
  border: 1px solid var(--adm-border);
  border-radius: var(--adm-r);
  padding: 20px;
  margin-bottom: 20px;
}
.adm-card-title { font-weight: 700; font-size: 1.1rem; margin-bottom: 14px; display: flex; align-items: center; gap: 12px; }
.adm-step-icon {
  width: 36px; height: 36px; border-radius: 50%;
  display: flex; align-items: center; justify-content: center;
  font-size: 1.05rem; flex-shrink: 0;
  background: var(--adm-accent-soft); color: var(--adm-accent);
}
.adm-step-icon.adm-step-icon-green { background: var(--adm-green-soft); color: var(--adm-green); }
.adm-step-icon.adm-step-icon-yellow { background: var(--adm-yellow-soft); color: var(--adm-yellow); }
.adm-mt { margin-top: 18px; }
.adm-info-line { font-size: 1.1rem; margin-bottom: 6px; }

/* ── Forms ─────────────────────────────────────────────────── */
.adm-form-label { display: block; font-size: 0.9rem; font-weight: 600; color: var(--adm-text-secondary); margin-bottom: 6px; }
.adm-form-control, .adm-form-select {
  width: 100%;
  background: #ffffff;
  border: 1.5px solid var(--adm-border);
  border-radius: var(--adm-r);
  padding: 12px 14px;
  color: var(--adm-text-primary);
  font-size: 1rem;
  min-height: 48px;
}
/* Drawn by us, not the platform: Safari's native select ignored the white
   background (grey bevelled box) and, with the 12px vertical padding inside a
   48px filter control, cut the bottom off its own text ("All Staff"). */
select.adm-form-select {
  -webkit-appearance: none;
  appearance: none;
  padding-top: 0;
  padding-bottom: 0;
  padding-right: 40px;
  line-height: 1.25;
  background-image: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'%3e%3cpath fill='none' stroke='%234b5563' stroke-linecap='round' stroke-linejoin='round' stroke-width='2' d='m2 5 6 6 6-6'/%3e%3c/svg%3e");
  background-repeat: no-repeat;
  background-position: right 14px center;
  background-size: 14px 10px;
  text-overflow: ellipsis;
}
/* iOS draws an empty date field with no height of its own and centres a
   picked date; keep it a normal, left-aligned 48px field. */
input[type="date"].adm-form-control { -webkit-appearance: none; appearance: none; display: block; text-align: left; }
input[type="date"].adm-form-control::-webkit-date-and-time-value { text-align: left; }
.adm-form-control:focus, .adm-form-select:focus {
  border-color: var(--adm-accent);
  outline: none;
}
.adm-form-control-lg { font-size: 1.2rem; padding: 16px; min-height: 56px; }
.adm-form-group { margin-bottom: 16px; }

/* Inline field validation (e.g. Register Kid's mobile number) — shown next
   to the field itself instead of a blocking alert(), and only once the user
   has actually left the field or tried to submit, so it can't complain about
   an entry still mid-typing. */
.adm-form-control.adm-input-invalid { border-color: var(--adm-red); }
.adm-field-error { color: var(--adm-red); font-size: 0.82rem; margin-top: 6px; display: none; }
/* Explains a constrained field rather than reporting an error on it — e.g. why
   a refund is capped below what the parent paid. Toggled with [hidden]. */
.adm-refund-note {
  font-size: 0.82rem;
  line-height: 1.4;
  color: var(--adm-text-secondary);
  margin-top: 6px;
}
.adm-field-error.visible { display: block; }

/* ── Inventory page ───────────────────────────────────────────
   The low-stock alert, and the socks card's inline restock control. */
.adm-inventory-alert {
  display: flex;
  align-items: flex-start;
  gap: 12px;
  background: rgba(220, 38, 38, 0.08);
  border: 1.5px solid var(--adm-red);
  border-radius: var(--adm-r);
  padding: 14px 16px;
  margin-bottom: 16px;
  color: #991b1b;
}
.adm-inventory-alert i { font-size: 1.2rem; margin-top: 2px; }

/* Low-stock banner at the top of every admin page (Admin/Manager, zones with
   the new features only) — built by admin-role.js (syncLowStockAlert). Same
   red as the Inventory page's own alert, but one compact line. */
.adm-lowstock-banner {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 0 10px;
  background: rgba(220, 38, 38, 0.08);
  border: 1.5px solid var(--adm-red);
  border-radius: var(--adm-r);
  padding: 0 2px 0 14px;
  margin-bottom: 16px;
  color: #991b1b;
  font-weight: 600;
  font-size: 0.95rem;
}
.adm-lowstock-banner[hidden] { display: none; }
.adm-lowstock-banner > .bi { font-size: 1.1rem; flex: 0 0 auto; }
.adm-lowstock-text { flex: 1 1 160px; min-width: 0; overflow-wrap: anywhere; padding: 10px 0; }
.admin-page .adm-lowstock-link {
  display: inline-flex;
  align-items: center;
  min-height: 44px;
  padding: 0 8px;
  color: #991b1b;
  font-weight: 700;
  text-decoration: underline;
  white-space: nowrap;
  touch-action: manipulation;
}
.adm-lowstock-close {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 44px;
  height: 44px;
  flex: 0 0 auto;
  margin-left: auto;
  padding: 0;
  border: 0;
  border-radius: var(--adm-r);
  background: transparent;
  color: #991b1b;
  font-size: 1rem;
  line-height: 0;
  cursor: pointer;
  touch-action: manipulation;
}
.adm-lowstock-close:hover { background: rgba(220, 38, 38, 0.12); }
.adm-lowstock-close:focus-visible,
.admin-page .adm-lowstock-link:focus-visible { outline: 2px solid var(--adm-red); outline-offset: 1px; }
.adm-inventory-alert-title { font-weight: 700; margin-bottom: 2px; }
.adm-inventory-socks-card {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 16px;
  flex-wrap: wrap;
}
.adm-inventory-socks-label { font-size: 0.85rem; color: var(--adm-text-secondary); font-weight: 600; }
.adm-inventory-socks-value { font-size: 1.8rem; font-weight: 800; margin-top: 4px; }
.adm-inventory-restock { display: flex; align-items: center; gap: 8px; }
.adm-inventory-restock .adm-qty-input { width: 90px; }

/* ── Sell Package's picked-customer row — the search field swaps for this
   once a match is chosen, with "Change" to go back to searching. ── */
.adm-picked-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  background: var(--adm-accent-soft);
  border: 1.5px solid var(--adm-border);
  border-radius: var(--adm-r);
  padding: 12px 14px;
  margin-bottom: 8px;
  font-weight: 600;
}
.adm-link-btn {
  background: none;
  border: none;
  padding: 0;
  color: var(--adm-accent);
  font-weight: 600;
  font-size: 0.9rem;
  cursor: pointer;
  text-decoration: underline;
}

/* ── Kid-named packages: Sell Package's inline new-family / new-kid box, its
   success view, and the balance lines on Register Kid. ── */
.adm-inline-panel {
  border: 1.5px dashed var(--adm-border);
  border-radius: var(--adm-r);
  padding: 12px 14px;
  margin-top: 8px;
}
.adm-inline-panel .adm-form-group:last-child { margin-bottom: 0; }
.adm-inline-panel-note { font-size: 0.88rem; color: var(--adm-text-secondary); margin-bottom: 8px; }
.adm-sell-success { text-align: center; padding: 8px 0; }
.adm-sell-success-icon { font-size: 2.6rem; color: var(--adm-green); line-height: 1; }
.adm-sell-success-title { font-size: 1.2rem; font-weight: 800; margin-top: 8px; }
.adm-sell-success-detail { color: var(--adm-text-secondary); margin-top: 6px; line-height: 1.45; }
.adm-sell-success .adm-btn { width: 100%; }
.adm-package-line { font-size: 0.82rem; font-weight: 600; color: var(--adm-accent); margin-top: 4px; }
.adm-package-box {
  border: 1.5px solid var(--adm-accent);
  background: var(--adm-accent-soft);
  border-radius: var(--adm-r);
  padding: 12px 14px;
  margin-top: 16px;
}
.adm-check-label { display: flex; align-items: center; gap: 10px; font-weight: 700; cursor: pointer; margin: 0; }
.adm-check-label input { width: 18px; height: 18px; }
.adm-package-box-lines { margin-top: 8px; display: flex; flex-direction: column; gap: 4px; font-size: 0.88rem; }
.adm-package-box-lines .adm-package-box-off { color: var(--adm-text-secondary); }

.adm-form-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(220px, 100%), 1fr));
  gap: 16px;
}
/* Short numeric fields side by side in a modal form (Package hours, price,
   validity) — full-width boxes, three to a row, stacked on a phone. */
.adm-form-grid-3 {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: 12px;
}
@media (max-width: 480px) {
  .adm-form-grid-3 { grid-template-columns: 1fr; gap: 0; }
}
.adm-search-row { display: flex; gap: 10px; flex-wrap: wrap; }
.adm-search-row .adm-form-control { flex: 1; min-width: 220px; }
.adm-search-row { position: relative; }

/* Live phone-search suggestion dropdown (Register Kid) */
/* position:fixed, not absolute-under-.adm-search-wrap: a search field inside
   a modal (.adm-confirm-card scrolls its own overflow) clipped and scrolled
   an absolutely-positioned dropdown along with it, showing up as a second,
   nested scrollbar and a jarring scroll-into-view snap whenever it opened.
   Fixed positioning escapes that entirely; admin.js sets left/top/width from
   the input's own getBoundingClientRect() each time it's shown, since fixed
   coordinates are relative to the viewport, not this element's old wrapper. */
.adm-search-suggestions {
  position: fixed;
  background: var(--adm-surface);
  border: 1.5px solid var(--adm-border);
  border-radius: var(--adm-r);
  box-shadow: 0 8px 24px rgba(17, 24, 39, 0.12);
  /* Above .adm-overlay-modal's own 2000 -- this has to float above the modal
     card it belongs to, not just above ordinary page content. */
  z-index: 2100;
  max-height: 260px;
  overflow-y: auto;
}
.adm-search-suggestions {
  /* A long list scrolls itself; reaching its end must not start scrolling
     the modal or page underneath (which would also move the field). */
  overscroll-behavior: contain;
  -webkit-overflow-scrolling: touch;
}
.adm-search-suggestion {
  display: block;
  width: 100%;
  min-height: 44px;
  text-align: left;
  padding: 12px 14px;
  border: none;
  border-bottom: 1px solid var(--adm-border);
  border-left: 3px solid transparent;
  background: none;
  font-size: 1rem;
  line-height: 1.3;
  color: var(--adm-text-primary);
  cursor: pointer;
  /* No 300ms double-tap wait and no grey iOS flash over the row. */
  touch-action: manipulation;
  -webkit-tap-highlight-color: transparent;
}
.adm-search-suggestion:last-child { border-bottom: none; }
/* .is-active marks the row the arrow keys have moved to — focus stays in the
   search input while navigating, so :focus can't show it. The accent edge
   keeps it visible even where the soft fill barely shows. */
.adm-search-suggestion:focus, .adm-search-suggestion.is-active, .adm-search-suggestion:active { background: var(--adm-accent-soft); }
.adm-search-suggestion.is-active { border-left-color: var(--adm-accent); color: var(--adm-accent); font-weight: 600; }
/* Hover only where there is a real pointer: on a phone a tapped row would
   otherwise stay "hovered" and read as the selected one. */
@media (hover: hover) {
  .adm-search-suggestion:hover { background: var(--adm-accent-soft); }
}
/* The return-gift name list (see wireGiftNameSuggestions): in the form's
   flow, directly under the field and exactly its width, pushing the modal's
   buttons down instead of floating over them. */
.adm-search-suggestions.adm-search-suggestions-inline {
  position: static;
  margin-top: 6px;
  max-height: 236px;
  background: #f8fafc;
  box-shadow: 0 6px 16px rgba(17, 24, 39, 0.10);
}
.adm-search-suggestion strong { display: block; }
.adm-search-suggestion span { font-size: 0.85rem; color: var(--adm-text-secondary); }

/* ── Choice buttons — replaces <select> for Gender / Payment Method /
   Cancellation Reason: a handful of fixed, mutually-exclusive options. ── */
.adm-choice-group { display: flex; gap: 10px; flex-wrap: wrap; }
/* Cash + UPI amounts under the payment buttons (admin.js mountPaymentPicker). */
.adm-split-pay { display: flex; gap: 10px; flex-wrap: wrap; align-items: flex-end; margin-top: 10px; }
.adm-split-pay[hidden] { display: none; }
.adm-split-part { flex: 1; min-width: 120px; display: flex; flex-direction: column; gap: 4px; font-weight: 600; font-size: 0.9rem; }
.adm-split-hint { flex-basis: 100%; font-size: 0.85rem; color: var(--adm-text-secondary); }
.adm-choice-btn {
  flex: 1;
  min-width: 110px;
  min-height: 48px;
  padding: 12px 16px;
  border: 1.5px solid var(--adm-border);
  border-radius: var(--adm-r);
  background: #ffffff;
  color: var(--adm-text-primary);
  font-size: 1rem;
  font-weight: 600;
  cursor: pointer;
  transition: background 0.15s, border-color 0.15s, color 0.15s;
}
.adm-choice-btn:hover { border-color: var(--adm-accent); }
.adm-choice-btn.active {
  background: var(--adm-accent);
  border-color: var(--adm-accent);
  color: #fff;
}

/* ── Text helpers ──────────────────────────────────────────── */
.adm-text-secondary { color: var(--adm-text-secondary); }
.adm-text-muted { color: var(--adm-text-muted); }
.adm-fw-600 { font-weight: 600; }
/* Dates in the history tables (Platform History / My History) — a distinct
   dark navy so a date reads as its own kind of value, not just body text. */
.adm-text-date { color: var(--adm-accent); font-weight: 600; white-space: nowrap; }
/* Bill, invoice and refund numbers (RCPT-RJE-1790...) are read out to parents
   and matched against paper receipts. The hyphens are legal break points, so a
   narrow column printed "RCPT-RJE-" on one line and the digits on the next. */
.adm-doc-number { white-space: nowrap; }
/* A clock time ("01:43 PM") reads as one value; split at the space it read as
   two lines of a column that was otherwise only just too narrow. */
.adm-nowrap { white-space: nowrap; }

/* Wrapper around a disabled Receipt button (still playing / not checked out
   yet). The button itself is a real disabled="" element so it truly can't be
   clicked; the wrapping span still gets hover/tap events so we can surface a
   toast explaining why, instead of a silent do-nothing button. */
.adm-receipt-disabled { display: inline-block; cursor: not-allowed; }
.adm-receipt-disabled .adm-btn[disabled] { opacity: 0.55; cursor: not-allowed; }

/* ── Toast (non-blocking notification) ────────────────────────
   Replaces alert() for messages that don't need to stop the user in their
   tracks (e.g. "receipt available after check-out") — appears bottom-center,
   auto-dismisses, never blocks the page the way a native alert() does. */
.adm-toast {
  position: fixed;
  left: 50%;
  bottom: 28px;
  transform: translateX(-50%) translateY(12px);
  background: #0f172a;
  color: #fff;
  padding: 12px 20px;
  border-radius: var(--adm-r);
  font-size: 0.95rem;
  font-weight: 600;
  box-shadow: 0 8px 24px rgba(15, 23, 42, 0.25);
  z-index: 3000;
  opacity: 0;
  pointer-events: none;
  transition: opacity 0.2s ease, transform 0.2s ease;
  max-width: min(90vw, 420px);
  text-align: center;
}
.adm-toast-visible {
  opacity: 1;
  transform: translateX(-50%) translateY(0);
}

/* ── Table ─────────────────────────────────────────────────
   overflow-x is harmless at desktop widths (every table here already fits,
   so no scrollbar appears) but is what lets a tablet-width viewport scroll
   instead of crushing columns — see the tablet-and-below override below,
   which is where the actual floor gets applied. */
.adm-table-wrap {
  width: 100%;
  max-width: 100%;
  overflow-x: auto;
  /* Momentum scrolling on iOS/Android, and contain overscroll so dragging a
     table that has reached its end does not start scrolling the page (or
     trigger pull-to-refresh) mid-gesture. */
  -webkit-overflow-scrolling: touch;
  overscroll-behavior-x: contain;
}
/* Columns size to their content at every width. This used to be
   table-layout:fixed above 1279px, which split the width dead-equal however
   much each column held; together with word-break it was what put
   "CHAUDH" / "ARI" and "WhatsAp" / "p" on two lines at a 1280px laptop once
   Today's Checked Out had ten columns. auto never makes a column narrower than
   its longest word, and a table that genuinely needs more room than there is
   scrolls inside .adm-table-wrap instead of crushing anything. */
.adm-table { width: 100%; border-collapse: collapse; table-layout: auto; }
.adm-table th, .adm-table td {
  padding: 12px 14px;
  font-size: 0.95rem;
  text-align: left;
  /* Breaks only a single string too long for any column (a long email),
     never an ordinary word -- word-break:break-word also shrank every
     column's minimum to one letter, which is how names got split. */
  overflow-wrap: break-word;
  word-break: normal;
  /* Figures in every row line up, and the live countdown on Currently
     Playing does not nudge its column as the digits change. */
  font-variant-numeric: tabular-nums;
}
.adm-table thead th {
  background: #f8fafc;
  border-bottom: 2px solid var(--adm-border);
  font-weight: 700;
  color: var(--adm-text-secondary);
}
.adm-table tbody tr { border-bottom: 1px solid var(--adm-border); }
.adm-table-empty { text-align: center; padding: 32px !important; color: var(--adm-text-muted); }

/* Date-group header row inside a table body (My History, Platform History) —
   a plain sub-heading row, not a clickable/selectable data row. */
.adm-table-group-header {
  padding: 10px 12px !important;
  font-size: 0.78rem;
  font-weight: 800;
  text-transform: uppercase;
  letter-spacing: 0.04em;
  color: var(--adm-accent);
  background: var(--adm-bg);
  border-bottom: 1px solid var(--adm-border);
}

/* A column holding one action button (Receipt, Edit, Checkout) needs a
   guaranteed minimum width — table-layout:fixed otherwise splits every
   column dead-equal, which can squeeze the button's own label into an
   ugly mid-word wrap on a narrower screen. */
.adm-col-action { width: 130px; }

/* A column holding several stacked action buttons (Extend / Cancel-Refund /
   Checkout on Currently Playing) — wider than .adm-col-action, and the
   buttons stack full-width instead of wrapping inline (which, at 130px,
   made buttons overflow the fixed-width cell and effectively disappear). */
.adm-col-actions-wide { width: 190px; }
.adm-action-stack { display: flex; flex-direction: column; gap: 6px; }
/* nowrap: a button label is one word or two, and the column grows to fit it
   now that tables size to their content. Wrapping it is what printed
   "WhatsAp" / "p". */
.adm-action-stack .adm-btn { width: 100%; white-space: nowrap; }

/* ── Comfortable table (Staff / Managers accounts, and other
   staff-facing lists) — bigger rows, bigger text, easy to scan quickly. */
.adm-table-comfortable th, .adm-table-comfortable td { padding: 14px 12px; font-size: 0.98rem; }
.adm-row-avatar {
  display: flex; align-items: center; gap: 12px;
}
.adm-row-avatar .adm-avatar { width: 34px; height: 34px; font-size: 0.85rem; }

/* ── Status pills / row tints (green / yellow / red) ─────────
   Used for the Currently Playing timer and any other status column. */
.adm-status-pill {
  display: inline-block;
  padding: 4px 12px;
  border-radius: 999px;
  font-size: 0.85rem;
  font-weight: 700;
}
.status-green, .adm-status-pill.status-green { color: var(--adm-green); background: var(--adm-green-soft); }
.status-yellow, .adm-status-pill.status-yellow { color: var(--adm-yellow); background: var(--adm-yellow-soft); }
.status-red, .adm-status-pill.status-red { color: var(--adm-red); background: var(--adm-red-soft); }
.adm-status-pill.status-muted { color: var(--adm-text-secondary); background: #f1f5f9; }
.adm-status-pill.status-blue { color: var(--adm-accent); background: var(--adm-accent-soft); }
/* Inline marker beside a name or an amount (e.g. "Package"). */
.adm-status-pill.adm-pill-sm { padding: 2px 8px; font-size: 0.72rem; vertical-align: middle; margin-left: 4px; }

tr.status-green { background: var(--adm-green-soft); }
tr.status-yellow { background: var(--adm-yellow-soft); }
tr.status-red { background: var(--adm-red-soft); }

/* ── Status cell: badge + inline toggle (Staff / Managers accounts) ──
   Flips Active/Inactive right from the row, without opening Edit. Same
   PATCH the Edit form already sends, so no new permission is created. */
.adm-status-cell { display: flex; align-items: center; gap: 10px; }
.adm-toggle { position: relative; display: inline-block; width: 40px; height: 22px; flex-shrink: 0; }
.adm-toggle input { opacity: 0; width: 0; height: 0; }
.adm-toggle-slider {
  position: absolute; cursor: pointer; inset: 0;
  background: var(--adm-border);
  border-radius: 999px;
  transition: background 0.15s ease;
}
.adm-toggle-slider::before {
  content: "";
  position: absolute;
  width: 16px; height: 16px;
  left: 3px; top: 3px;
  background: #fff;
  border-radius: 50%;
  transition: transform 0.15s ease;
  box-shadow: 0 1px 2px rgba(0, 0, 0, 0.25);
}
.adm-toggle input:checked + .adm-toggle-slider { background: var(--adm-green); }
.adm-toggle input:checked + .adm-toggle-slider::before { transform: translateX(18px); }
.adm-toggle input:disabled + .adm-toggle-slider { opacity: 0.5; cursor: not-allowed; }
.adm-toggle input:focus-visible + .adm-toggle-slider { outline: 2px solid var(--adm-accent); outline-offset: 2px; }

/* ── Kid selection cards (Register Kid screen) ───────────────
   Selecting a kid reads unmistakably as "confirmed": green fill + border. */
.adm-kid-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(min(180px, 100%), 1fr));
  gap: 12px;
}
.adm-kid-card {
  text-align: left;
  background: #ffffff;
  border: 2px solid var(--adm-border);
  border-radius: var(--adm-r);
  padding: 14px;
  cursor: pointer;
  min-height: 60px;
}
.adm-kid-card:hover { border-color: var(--adm-accent); }
.adm-kid-card.selected { background: var(--adm-green-soft); border-color: var(--adm-green); }
.adm-kid-card.is-disabled { opacity: 0.5; cursor: not-allowed; }
.adm-kid-card-name { font-weight: 700; font-size: 1.05rem; }
.adm-kid-card-meta { font-size: 0.85rem; color: var(--adm-text-secondary); margin-top: 4px; }

/* ── Price display ────────────────────────────────────────── */
.adm-price-row {
  display: flex;
  justify-content: space-between;
  align-items: center;
  background: #f8fafc;
  border: 1px solid var(--adm-border);
  border-radius: var(--adm-r);
  padding: 14px 18px;
  margin: 16px 0;
  font-size: 1.1rem;
  font-weight: 600;
}
.adm-price-value { font-size: 1.6rem; font-weight: 800; color: var(--adm-accent); }
/* What the grand total is made of, shown under it only once there is more than
   the play fee in it. */
.adm-price-breakdown {
  font-size: 0.8rem;
  font-weight: 600;
  color: var(--adm-text-secondary);
  margin-top: 2px;
}

/* ── Add-on line (socks on the check-in step) ─────────────────
   A priced extra sitting under the total: name and unit price on the left, a
   quantity stepper in the middle, this line's amount on the right. */
.adm-addon-row {
  display: flex;
  align-items: center;
  gap: 12px;
  flex-wrap: wrap;
  background: var(--adm-surface);
  border: 1px solid var(--adm-border);
  border-radius: var(--adm-r);
  padding: 12px 16px;
  margin: 0 0 16px;
}
.adm-addon-info { flex: 1 1 140px; min-width: 0; }
.adm-addon-name { font-weight: 700; display: flex; align-items: center; gap: 8px; }
.adm-addon-meta { font-size: 0.82rem; color: var(--adm-text-secondary); margin-top: 2px; }
.adm-addon-amount {
  font-weight: 800;
  font-size: 1.1rem;
  color: var(--adm-text-primary);
  min-width: 64px;
  text-align: right;
}
/* A .adm-confirm-card (Add Socks) is a fixed ~330px-wide modal regardless of
   screen size, unlike the page-width card this row was first built for — so
   it needs the same "name+price on their own line, stepper and amount
   together below" treatment the ≤767px viewport rule below gives the wider
   card, but unconditionally rather than only on a narrow screen. Without
   this, a desktop-width browser still only gave the row 330px to lay three
   things across, and the amount wrapped onto a line of its own. */
.adm-confirm-card .adm-addon-info { flex: 1 1 100%; }
.adm-confirm-card .adm-addon-amount { flex: 1 1 auto; }
.adm-qty { display: flex; align-items: center; gap: 0; flex: 0 0 auto; }
.adm-qty-btn {
  width: 44px;
  height: 44px;
  display: flex;
  align-items: center;
  justify-content: center;
  border: 1.5px solid var(--adm-border);
  background: #ffffff;
  color: var(--adm-text-primary);
  font-size: 1.25rem;
  font-weight: 700;
  cursor: pointer;
}
.adm-qty-btn:first-child { border-radius: var(--adm-r) 0 0 var(--adm-r); }
.adm-qty-btn:last-child { border-radius: 0 var(--adm-r) var(--adm-r) 0; }
.adm-qty-btn:hover:not(:disabled) { background: var(--adm-accent-soft); border-color: var(--adm-accent); color: var(--adm-accent); }
.adm-qty-btn:focus-visible { outline: 2px solid var(--adm-accent); outline-offset: 2px; z-index: 1; }
/* Greyed rather than hidden: a stepper that loses a button at zero shifts the
   whole row sideways every time it is used. */
.adm-qty-btn:disabled { opacity: 0.45; cursor: not-allowed; }
.adm-qty-input {
  width: 60px;
  height: 44px;
  border: 1.5px solid var(--adm-border);
  border-left: none;
  border-right: none;
  text-align: center;
  font-size: 1.05rem;
  font-weight: 700;
  color: var(--adm-text-primary);
  background: #ffffff;
}
.adm-qty-input:focus { outline: none; border-color: var(--adm-accent); }

/* ── Count tiles (Dashboard) ─────────────────────────────────── */
.adm-count-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(160px, 100%), 1fr));
  gap: 16px;
}
.adm-count-tile {
  background: var(--adm-card);
  border: 1px solid var(--adm-border);
  border-radius: var(--adm-r);
  padding: 24px;
  text-align: center;
}
.adm-count-value { font-size: 2.2rem; font-weight: 800; color: var(--adm-accent); }
.adm-count-label { font-size: 0.95rem; color: var(--adm-text-secondary); margin-top: 6px; }
.adm-count-tile-link {
  display: block;
  cursor: pointer;
  transition: transform 0.12s ease, box-shadow 0.12s ease, border-color 0.12s ease;
}
.adm-count-tile-link:hover {
  border-color: var(--adm-accent);
  box-shadow: 0 6px 16px rgba(37, 99, 235, 0.14);
  transform: translateY(-2px);
}

/* ── Dashboard charts ─────────────────────────────────────────── */
.adm-chart-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(360px, 100%), 1fr));
  gap: 16px;
}
.adm-chart-card { margin-bottom: 0; }
.adm-chart-subtitle { font-size: 0.85rem; margin-top: -8px; margin-bottom: 16px; }
.adm-chart-wrap { position: relative; height: 260px; }
.adm-chart-wrap-donut { height: 280px; }
.adm-chart-empty {
  height: 260px;
  display: flex;
  align-items: center;
  justify-content: center;
  text-align: center;
}

/* ── Daily Summary's date navigation ("Today", ←/→ a day at a time) ── */
/* Three flex items that can never overlap: the two 44px arrows keep their
   size, the day in between takes the rest and truncates rather than wrapping
   or sliding under an arrow (min-width:0 is what lets it shrink at 320px). */
.adm-date-nav {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 12px;
  margin-bottom: 16px;
  max-width: 420px;
  margin-inline: auto;
}
/* The day itself is the date picker: a real <input type="date"> laid over the
   label at full size, transparent. iOS Safari ignores most styling of a date
   input and will not open one that is display:none, visibility:hidden or
   zero-sized — but a full-size, opacity:0 input receives the tap itself and
   opens the native wheel/calendar like any visible one. */
.adm-date-nav-pick {
  position: relative;
  flex: 1 1 auto;
  min-width: 0;
  min-height: 44px;
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 8px;
  padding: 0 12px;
  margin: 0;
  border: 1.5px solid var(--adm-border);
  border-radius: 999px;
  background: #fff;
  cursor: pointer;
}
.adm-date-nav-pick:hover { background: var(--adm-accent-soft); }
.adm-date-nav-pick:focus-within { border-color: var(--adm-accent); }
.adm-date-nav-pick > .bi { flex: 0 0 auto; color: var(--adm-accent); }
.adm-date-nav-label {
  font-weight: 700;
  font-size: 1.05rem;
  min-width: 0;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  text-align: center;
}
.adm-date-nav-input {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  margin: 0;
  padding: 0;
  border: 0;
  opacity: 0;
  -webkit-appearance: none;
  appearance: none;
  background: transparent;
  /* 16px or more, or iOS zooms the page in when the field takes focus. */
  font-size: 16px;
  cursor: pointer;
}
.adm-date-nav-btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  flex: 0 0 auto;
  width: 44px;
  height: 44px;
  padding: 0;
  border-radius: 999px;
  border: 1.5px solid var(--adm-border);
  background: #fff;
  color: var(--adm-text-primary);
  font-size: 1.1rem;
  line-height: 0;
  cursor: pointer;
  /* Repeated taps step day by day; without this iOS reads two quick taps as
     a double-tap zoom instead. */
  touch-action: manipulation;
  -webkit-tap-highlight-color: transparent;
}
.adm-date-nav-pick { touch-action: manipulation; -webkit-tap-highlight-color: transparent; }
.adm-date-nav-btn:hover:not(:disabled) { background: var(--adm-accent-soft); }
/* Inert rather than hidden on today: a hidden arrow reads as "this page has
   no forward navigation at all"; a visibly disabled one reads as "you're at
   the latest day", which is the fact this is actually communicating. The
   colours are set outright because iOS Safari paints its own grey on a
   disabled button, which on top of the opacity alone left it barely visible
   on one phone and indistinguishable from enabled on another. */
.adm-date-nav-btn:disabled {
  opacity: 1;
  background: #f3f4f6;
  border-color: #e5e7eb;
  color: #c0c6cf;
  -webkit-text-fill-color: #c0c6cf;
  cursor: default;
}

/* ── Dashboard hero card (big "today" summary) ───────────────── */
.adm-hero-card {
  background: var(--adm-accent-soft);
  border: 1px solid var(--adm-border);
  border-radius: var(--adm-r);
  padding: 28px;
  text-align: center;
}
.adm-hero-pill {
  display: inline-block;
  background: #ffffff;
  border-radius: 999px;
  padding: 6px 18px;
  font-weight: 700;
  color: var(--adm-accent);
  margin-bottom: 14px;
}
.adm-hero-value { font-size: 2.6rem; font-weight: 800; color: var(--adm-accent); }
.adm-hero-meta { display: flex; justify-content: center; gap: 24px; margin-top: 14px; flex-wrap: wrap; }
.adm-hero-meta-item { font-size: 0.95rem; color: var(--adm-text-secondary); }
.adm-hero-meta-item strong { display: block; color: var(--adm-text-primary); font-size: 1.05rem; }

.adm-summary-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(200px, 100%), 1fr));
  gap: 16px;
}
.adm-summary-tile {
  background: var(--adm-card);
  border: 1px solid var(--adm-border);
  border-radius: var(--adm-r);
  padding: 18px;
}
.adm-summary-tile-label { font-size: 0.85rem; color: var(--adm-text-secondary); font-weight: 600; }
.adm-summary-tile-value { font-size: 1.5rem; font-weight: 800; margin-top: 6px; }
/* Socks & Gifts packs two headline figures into one tile rather than the
   usual single big number — each line sized down so the pair still reads as
   one tile's worth of content, not two numbers fighting for the same space. */
.adm-summary-tile-value-split { font-size: 1.05rem; font-weight: 700; display: flex; flex-direction: column; gap: 4px; }
.adm-summary-tile-value-split i { color: var(--adm-text-secondary); font-size: 0.95em; }

.adm-list-row {
  display: flex;
  justify-content: space-between;
  align-items: center;
  padding: 12px 0;
  border-bottom: 1px solid var(--adm-border);
  gap: 12px;
}
.adm-list-row:last-child { border-bottom: none; }
.adm-list-row-name { font-weight: 700; }
.adm-list-row-meta { font-size: 0.85rem; color: var(--adm-text-secondary); }

/* ── Expandable cards (Monthly Report — By Manager) ───────────
   Each row reads as a tappable card: a chevron + hover shading on the
   header signal "more detail on tap" before the user ever clicks. */
.adm-cancel-list { display: flex; flex-direction: column; gap: 10px; }
.adm-cancel-card {
  background: var(--adm-card);
  border: 1px solid var(--adm-border);
  border-radius: var(--adm-r);
  overflow: hidden;
}
.adm-cancel-card-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  padding: 14px 16px;
  cursor: pointer;
  user-select: none;
}
.adm-cancel-card-header:hover { background: #f8fafc; }
.adm-cancel-meta { font-size: 0.85rem; color: var(--adm-text-secondary); margin-top: 3px; }
.adm-cancel-right { display: flex; align-items: center; gap: 12px; flex-shrink: 0; }
.adm-cancel-amount { font-weight: 800; color: var(--adm-red); font-size: 1.05rem; white-space: nowrap; }
.adm-cancel-chevron { color: var(--adm-text-muted); font-size: 1rem; transition: transform 0.2s ease; }
.adm-cancel-card.expanded .adm-cancel-chevron { transform: rotate(180deg); }
.adm-cancel-detail { display: none; padding: 0 16px 14px; border-top: 1px solid var(--adm-border); }
.adm-cancel-card.expanded .adm-cancel-detail { display: block; padding-top: 12px; }
.adm-cancel-detail .adm-list-row { padding: 10px 0; }

/* ── Cancelled Bill Kid Item with Expandable Details ── */
.adm-cancel-item {
  border-bottom: 1px solid var(--adm-border);
  transition: background 0.15s ease;
}
.adm-cancel-item:last-child {
  border-bottom: none;
}
.adm-cancel-item-header {
  display: flex;
  justify-content: space-between;
  align-items: center;
  padding: 10px 8px;
  cursor: pointer;
  border-radius: var(--adm-r-sm);
  transition: background 0.15s ease;
  user-select: none;
}
.adm-cancel-item-header:hover {
  background: #f1f5f9;
}
.adm-cancel-item-chevron {
  color: var(--adm-text-muted);
  font-size: 0.85rem;
  transition: transform 0.2s ease;
  width: 16px;
  display: inline-block;
  text-align: center;
}
.adm-cancel-item.expanded .adm-cancel-item-chevron {
  transform: rotate(180deg);
  color: var(--adm-primary);
}
.adm-cancel-item-amount {
  font-weight: 700;
  color: var(--adm-text-secondary);
  font-size: 0.95rem;
}
.adm-cancel-item-body {
  display: none;
  padding: 12px 14px 14px 28px;
  background: #f8fafc;
  border-radius: var(--adm-r-sm);
  margin: 2px 0 8px 0;
  border: 1px solid var(--adm-border);
}
.adm-cancel-item.expanded .adm-cancel-item-body {
  display: block;
}
.adm-cancel-item-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(min(180px, 100%), 1fr));
  gap: 10px 16px;
}
.adm-cancel-field {
  display: flex;
  flex-direction: column;
  gap: 2px;
}
.adm-cancel-field-label {
  font-size: 0.72rem;
  font-weight: 600;
  color: var(--adm-text-muted);
  text-transform: uppercase;
  letter-spacing: 0.03em;
}
.adm-cancel-field-value {
  font-size: 0.875rem;
  color: var(--adm-text);
  font-weight: 500;
  word-break: break-word;
}
.adm-cancel-item-actions {
  display: flex;
  gap: 8px;
  margin-top: 12px;
  padding-top: 10px;
  border-top: 1px dashed var(--adm-border);
  align-items: center;
  flex-wrap: wrap;
}
.adm-btn-outline-danger {
  background: transparent;
  color: var(--adm-red);
  border: 1px solid var(--adm-red);
}
.adm-btn-outline-danger:hover {
  background: var(--adm-red);
  color: #ffffff;
}


/* ── Danger zone ──────────────────────────────────────────── */
.adm-danger-card { border-color: var(--adm-red); }

/* ── Overlay modals (receipt / confirmation) ─────────────────
   Plain fixed-position overlay — same pattern for every confirm-style
   popup so staff learn one interaction, not several. */
.adm-overlay-modal {
  position: fixed;
  inset: 0;
  background: rgba(15, 23, 42, 0.5);
  display: flex;
  align-items: center;
  justify-content: center;
  z-index: 2000;
  padding: 16px;
  /* Notched iPhones: keep the card clear of the notch / home indicator when
     the page is drawn edge to edge (0 everywhere else). */
  padding: max(16px, env(safe-area-inset-top)) max(16px, env(safe-area-inset-right)) max(16px, env(safe-area-inset-bottom)) max(16px, env(safe-area-inset-left));
  overscroll-behavior: contain;
  /* A receipt taller than the viewport (a 720px-high laptop, or any phone in
     landscape) had no way to be read: the overlay clipped it and neither the
     overlay nor the card scrolled, so the Confirm button underneath was simply
     unreachable. */
  overflow-y: auto;
}
.adm-receipt-card, .adm-confirm-card {
  background: #ffffff;
  border-radius: var(--adm-r);
  padding: 28px;
  width: 100%;
  max-width: 420px;
  /* Scroll the card itself, so its own actions stay reachable. */
  max-height: calc(100vh - 32px);
  max-height: calc(100dvh - 32px);
  overflow-y: auto;
  overscroll-behavior: contain;
  -webkit-overflow-scrolling: touch;
}
.adm-receipt-title, .adm-confirm-title { font-size: 1.3rem; font-weight: 800; margin-bottom: 16px; }
.adm-receipt-row {
  display: flex;
  justify-content: space-between;
  padding: 8px 0;
  border-bottom: 1px solid var(--adm-border);
  font-size: 1rem;
}
.adm-confirm-row { display: flex; justify-content: space-between; padding: 6px 0; font-size: 1.05rem; }
.adm-confirm-actions { display: flex; gap: 12px; margin-top: 20px; }
/* The one question a confirm card asks, e.g. "Give a return gift?" at checkout. */
.adm-confirm-question { margin-top: 18px; font-size: 1.1rem; font-weight: 700; text-align: center; }
.adm-confirm-question .bi { color: var(--adm-accent); margin-right: 4px; }
.adm-confirm-actions .adm-btn { flex: 1; }
/* Change / Add Return Gift: one field, then the actions. */
.adm-gift-card .adm-gift-field { margin-top: 18px; }
.adm-gift-card .adm-confirm-row strong { text-align: right; min-width: 0; overflow-wrap: anywhere; padding-left: 12px; }
.adm-gift-not-given {
  display: inline-flex;
  align-items: center;
  min-height: 44px;
  margin-top: 2px;
  color: var(--adm-text-secondary);
  font-weight: 500;
  touch-action: manipulation;
}
.adm-gift-not-given[hidden] { display: none; }

/* ── Modal (Bootstrap) ────────────────────────────────────── */
.adm-modal .modal-content { border-radius: var(--adm-r); }
.adm-modal .modal-header { border-bottom: 1px solid var(--adm-border); }
.adm-modal .modal-body { padding: 24px; }
.adm-modal .modal-dialog { max-width: min(560px, calc(100vw - 20px)); }

/* ── Login page ───────────────────────────────────────────── */
.adm-login-wrap {
  min-height: 100vh;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 16px;
}
.adm-login-card {
  background: #ffffff;
  border: 1px solid var(--adm-border);
  border-radius: var(--adm-r);
  padding: 36px;
  width: 100%;
  max-width: 400px;
}
.adm-login-title { font-size: 1.4rem; font-weight: 700; margin-bottom: 20px; }
/* The manual link under the login button. Sits below a divider so it reads as
   help *about* the portal rather than as another field in the form. */
.adm-login-help {
  margin: 20px 0 0;
  padding-top: 16px;
  border-top: 1px solid var(--adm-border);
  font-size: 0.82rem;
  line-height: 1.5;
  color: var(--adm-text-secondary);
  text-align: center;
}
.adm-login-help a { color: var(--adm-accent); font-weight: 600; }
.adm-mb { margin-bottom: 20px; }

/* ── Responsive ─────────────────────────────────────────────
   Every breakpoint in the portal lives here, in one descending cascade, so
   what applies at a given width can be read top to bottom. All of them are
   max-width and each only overrides what the block above got wrong at the
   next size down — nothing is restated for its own sake.

     ≤1279px  Small laptop. Wide tables start scrolling instead of being
              squeezed; gutters come in slightly.
     ≤1023px  Tablet and below. The sidebar leaves the layout and becomes a
              drawer, giving the content the full width it needs for tables.
     ≤767px   Phone. Condensed cards and tiles, decorative topbar items drop,
              side-by-side rows stack.
     ≤639px   Filter toolbars go full-width per control.
     ≤479px   Small phone. Single column everywhere, smallest type step.

   Above 1280px nothing here applies: the desktop layout is the base, and
   --adm-content-max keeps it from stretching on a large monitor. */

/* Wide, many-column tables (Cancelled Bills, Platform History, Today's Checked
   Out). table-layout:fixed forces every column dead-equal with no floor, which
   on a narrower content area squeezed headers like "Cancelled By" into one
   letter per line instead of ever scrolling. auto lets columns size to their
   content again, min-width stops any single column being crushed below that,
   and once a row genuinely needs more room than there is, .adm-table-wrap's
   overflow-x scrolls it. */
@media (max-width: 1279px) {
  :root { --adm-gutter: 20px; }
  .adm-table th, .adm-table td { min-width: 130px; }
}

/* The sidebar becomes an off-canvas drawer, opened by the topbar button that
   admin.js inserts. It used to shrink to a 72px icon rail at ≤768px with its
   labels and group headings hidden — a fifth of a 360px phone spent on
   unlabelled icons, and the fun zone (the one thing you can act wrongly on)
   dropped entirely. As a drawer it keeps its full labels, its sections and the
   zone block, and the content gets the whole viewport. */
@media (max-width: 1023px) {
  .adm-nav-toggle { display: inline-flex; }

  .adm-sidebar {
    width: var(--adm-nav-drawer-width);
    max-width: 86vw;
    transform: translateX(-100%);
    transition: transform 0.22s ease;
  }
  /* Nothing reserves space for it any more — it is position:fixed, so this
     margin was the only thing holding the content clear of it. */
  .adm-main { margin-left: 0; }

  body.adm-nav-open .adm-sidebar {
    transform: none;
    box-shadow: 0 0 40px rgba(15, 23, 42, 0.28);
  }
  body.adm-nav-open .adm-overlay { display: block; }
  /* Otherwise the page scrolls under the drawer while it is open. */
  body.adm-nav-open { overflow: hidden; }
}

@media (prefers-reduced-motion: reduce) {
  .adm-sidebar { transition: none; }
}

@media (max-width: 767px) {
  :root { --adm-gutter: 14px; }

  .adm-topbar { min-height: 56px; gap: 10px; }
  .adm-topbar-title { font-size: 1.15rem; padding: 10px 0; }
  .adm-topbar-actions { gap: 8px; padding: 8px 0; }
  .adm-live-pill { font-size: 0.82rem; padding: 6px 12px; }
  .adm-firm-pill { max-width: 200px; }
  /* The clock is the one topbar fact that isn't needed to act correctly (the
     fun zone is); dropping it on a narrow screen, alongside the page's own
     action button shrinking to .adm-btn-sm sizing, is what keeps the zone
     pill and that button sharing a single line instead of each claiming a
     whole row of their own. */
  .adm-clock-pill { display: none; }
  .adm-topbar-actions .adm-btn { min-height: 38px; padding: 6px 10px; font-size: 0.85rem; }

  .adm-card { padding: 16px; margin-bottom: 16px; }
  .adm-card-title { font-size: 1.05rem; }
  .adm-hero-card { padding: 20px; }
  .adm-hero-value { font-size: 2rem; }
  .adm-hero-meta { gap: 16px; margin-top: 12px; }
  .adm-count-tile { padding: 18px 14px; }
  .adm-count-value { font-size: 1.8rem; }
  .adm-summary-tile { padding: 14px; }
  .adm-summary-tile-value { font-size: 1.3rem; }
  .adm-price-value { font-size: 1.35rem; }
  /* 150px, not the 130px floor used from 1279px down. A single long Indian
     surname ("Balasubramanian") is wider than 130px minus cell padding, so
     word-break split it mid-word into "Balasubramania" + "n". The table is
     already scrolling horizontally at this width, so a slightly wider column
     costs a little more scrolling and buys names that read as names. */
  .adm-table th, .adm-table td { padding: 10px 12px; font-size: 0.9rem; min-width: 150px; }
  /* Columns holding only a short value or one button do not need that floor. */
  .adm-table th.adm-col-action, .adm-table td.adm-col-action { min-width: 130px; }
  .adm-table-comfortable th, .adm-table-comfortable td { padding: 12px; font-size: 0.92rem; }

  /* Label-above-value rows read better stacked than as two columns fighting
     over 300px, and neither side has to truncate. */
  .adm-price-row { flex-direction: column; align-items: flex-start; gap: 6px; }
  /* Name and unit price on their own line, then the stepper and this line's
     amount side by side — at 360px all three across cannot each stay legible. */
  .adm-addon-info { flex: 1 1 100%; }
  .adm-addon-amount { flex: 1 1 auto; }
  .adm-list-row { flex-direction: column; align-items: flex-start; }
  /* Two buttons at 50% each are too narrow here to show their own labels. */
  .adm-confirm-actions { flex-direction: column; }
  .adm-confirm-actions .adm-btn { width: 100%; }

  .adm-receipt-card, .adm-confirm-card { padding: 20px; }
  .adm-modal .modal-body { padding: 16px; }
  .adm-login-card { padding: 24px; }
  .adm-cancel-item-body { padding: 12px 12px 12px 16px; }
  .adm-password-toggle { width: 40px; height: 40px; }
}

/* Filter toolbars. A heavy one (Platform History: Search, From, To, Staff,
   Export CSV) used to stack five controls one-per-line, which pushed the
   table itself off the bottom of a phone screen before a single row of it
   was visible. A 2-column grid instead pairs most controls up, with the
   first control (Search on most pages, Date/Month on others) kept full-width
   since it's the one every list gets filtered by first. */
@media (max-width: 639px) {
  .adm-filter-row {
    display: grid;
    /* minmax(0, 1fr), not the plain 1fr that defaults to minmax(auto, 1fr):
       a <input type="date">'s native calendar affordance has a min-content
       width Chromium won't shrink below, and auto as the track floor let that
       force the track past its share of the row at 360px — overflowing the
       page by the same few pixels no matter how much further gap/padding
       below was trimmed. The 0 floor lets the browser actually shrink the
       track to fit instead of overflowing to protect the input's content. */
    grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
    gap: 10px;
    align-items: end;
  }
  .adm-filter-row > :first-child { grid-column: 1 / -1; }
  /* The Payment pill group (3 buttons, each min-width:110px) needs ~350px —
     more than a 639px screen's whole filter row, let alone half of it — so it
     keeps the full row rather than being squeezed into a cell it would only
     wrap awkwardly inside. */
  .adm-filter-row > label:has(.adm-choice-group) { grid-column: 1 / -1; }
  /* Only ever existed to push Export CSV to the far right of a flex row —
     meaningless, and an extra empty grid cell, once that row wraps. */
  .adm-filter-row .adm-filter-spacer { display: none; }

  .adm-filter-row .adm-form-select,
  .adm-filter-row input[type="date"],
  .adm-filter-row input[type="text"] { max-width: none; width: 100%; }
  .adm-filter-row label.adm-inline-label { width: 100%; }

  /* Release the 44px lock. That fixed height exists so every control's bottom
     lines up in a single-row toolbar; once controls are two-to-a-row instead
     the alignment is meaningless, and here it was actively broken. The
     Payment group is three pills with min-width:110px and flex-wrap:wrap —
     too wide for half a row, so the third wrapped onto a second line that a
     fixed-height box could not contain and drew straight over whatever sat
     below it. min-height keeps the alignment where the row still fits on
     one line, and lets it grow when it doesn't. */
  .adm-filter-row .adm-choice-group { height: auto; min-height: 48px; }
  .adm-filter-row .adm-choice-btn { height: auto; }
}

@media (max-width: 479px) {
  .adm-filter-row { gap: 10px; padding: 12px; }

  .adm-form-grid,
  .adm-kid-grid,
  .adm-summary-grid,
  .adm-count-grid,
  .adm-chart-grid,
  .adm-cancel-item-grid { grid-template-columns: 1fr; }

  .adm-topbar-title { font-size: 1.05rem; }
  .adm-date-nav { gap: 8px; }
  .adm-date-nav-pick { padding: 0 10px; gap: 6px; }
  .adm-date-nav-label { font-size: 0.98rem; }
  .adm-hero-value { font-size: 1.7rem; }
  .adm-count-value { font-size: 1.6rem; }
  .adm-hero-meta { gap: 12px; }
  .adm-firm-pill { max-width: 150px; }
  /* Stacked so a long name is not squeezed against the amount beside it. */
  .adm-cancel-card-header,
  .adm-cancel-item-header { align-items: flex-start; }
}

/* Touch screens (iPhone, Android, tablets). Apple's minimum comfortable tap
   target is 44pt; the compact buttons below were 31-38px tall, which is what
   made "Receipt" vs "WhatsApp" in a table cell, the sidebar's Switch Fun Zone
   and log-out, and a modal's close X easy to miss with a thumb. Desktop mice
   keep the compact sizes. */
@media (pointer: coarse) {
  .adm-btn-sm,
  .adm-topbar-actions .adm-btn { min-height: 44px; }
  .adm-firm-switch { min-height: 44px; padding: 8px 12px; font-size: .85rem; }
  .adm-logout-btn { min-width: 44px; min-height: 44px; display: inline-flex; align-items: center; justify-content: center; }
  /* .adm-password-wrap: outranks the base rule further down this file. */
  .adm-password-wrap .adm-password-toggle { width: 44px; height: 44px; right: 2px; }
  .adm-modal .btn-close { width: 44px; height: 44px; padding: 0; margin: -10px -10px -10px auto; background-size: 14px; }
  .adm-link-btn { min-height: 44px; display: inline-flex; align-items: center; }
}

/* Phone tables. They keep the portal's one table pattern -- the table scrolls
   sideways inside .adm-table-wrap -- but a cell of stacked action buttons
   (Currently Playing has four) made every row ~200px tall, so a phone screen
   showed one kid at a time. Side by side, the row is one button tall. */
@media (max-width: 767px) {
  .adm-action-stack { flex-direction: row; flex-wrap: nowrap; align-items: center; }
  .adm-action-stack .adm-btn { width: auto; }
}

/* The low-stock banner on a phone: the flex row wrapped its close X onto a
   line of its own, leaving a tall, mostly empty red box above every page. A
   grid keeps icon | text | X on the first line and the link under the text. */
@media (max-width: 639px) {
  .adm-lowstock-banner {
    display: grid;
    grid-template-columns: auto minmax(0, 1fr) 44px;
    align-items: center;
    column-gap: 10px;
    padding: 2px 2px 2px 14px;
  }
  .adm-lowstock-banner[hidden] { display: none; }
  .adm-lowstock-banner > .bi { grid-column: 1; grid-row: 1; }
  .adm-lowstock-text { grid-column: 2; grid-row: 1; padding: 8px 0 0; }
  .admin-page .adm-lowstock-link { grid-column: 2; grid-row: 2; justify-self: start; padding: 0; }
  .adm-lowstock-close { grid-column: 3; grid-row: 1; margin-left: 0; }
}

/* ---------- Password fields ---------- */

/* Edge (and old IE) inject their own reveal/clear controls into every password
   input. Alongside our own toggle that renders as *two* eye buttons side by
   side, which is what reception was seeing on the login screen. Ours stays,
   because the native one is absent in Chrome and Firefox. */
input[type="password"]::-ms-reveal,
input[type="password"]::-ms-clear {
  display: none;
}

.adm-password-wrap { position: relative; }
/* Room for the button, so a long password never runs underneath it. */
.adm-password-wrap .adm-form-control { padding-right: 46px; }
.adm-password-toggle {
  position: absolute;
  right: 6px;
  top: 50%;
  transform: translateY(-50%);
  display: flex;
  align-items: center;
  justify-content: center;
  width: 34px;
  height: 34px;
  padding: 0;
  border: 0;
  border-radius: 6px;
  background: transparent;
  color: var(--adm-text-secondary, #64748b);
  cursor: pointer;
  line-height: 0;
}
.adm-password-toggle:hover { color: var(--adm-text-primary); background: #f1f5f9; }
.adm-password-toggle:focus-visible {
  outline: 2px solid var(--adm-accent);
  outline-offset: 1px;
}

/* Offline mode: the server's flag on a synced visit, under its amount. */
.adm-sync-note { font-size: 0.78rem; font-weight: 400; color: var(--adm-red); margin-top: 3px; line-height: 1.3; white-space: normal; min-width: 160px; max-width: 280px; }
.adm-sync-note .bi { font-size: 0.7rem; margin-right: 2px; }
