/* =====================================================================
   WAAREE ENTERPRISE PORTAL — Design System
   Brand: Waaree Energies. Built on Bootstrap 5.3, mobile-first.
   ===================================================================== */

:root{
  /* Brand */
  --wa-green:#00793F;        /* primary / dark green */
  --wa-green-600:#026B39;
  --wa-green-700:#015C31;
  --wa-accent:#37B34B;       /* bright brand green */
  --wa-accent-soft:#E8F6EC;
  --wa-teal:#0E9A8A;         /* gradient partner */
  --wa-ink:#4C4D4F;          /* body text */
  --wa-ink-soft:#7A7D80;
  --wa-line:#E9EFEB;
  --wa-line-soft:#F1F5F2;
  --wa-bg:#F3F7F4;
  --wa-surface:#FFFFFF;
  --wa-sidebar:#083826;
  --wa-sidebar-hover:rgba(55,179,75,.16);
  /* Semantic */
  --wa-success:#37B34B; --wa-info:#0E9A8A; --wa-warning:#E8A33D; --wa-danger:#DC3545;
  /* System — layered shadows: a 1px contact edge plus a wide, soft, mostly
     transparent ambient. A single mid-opacity blur reads as grey haze. */
  --wa-radius:16px; --wa-radius-sm:10px; --wa-radius-lg:22px;
  --wa-shadow:0 1px 2px rgba(16,40,28,.04), 0 10px 28px -12px rgba(16,40,28,.20);
  --wa-shadow-lg:0 2px 4px rgba(16,40,28,.05), 0 20px 48px -18px rgba(16,40,28,.34);
  --wa-shadow-brand:0 8px 20px -8px rgba(0,121,63,.45);
  --wa-sidebar-w:228px;          /* compact: nav is 5-9 items, not a file tree */
  --bs-primary:#00793F;
  /* Typography — Inter with tabular figures so KPI numbers do not jitter */
  --wa-font:"Inter","Segoe UI",Roboto,Arial,sans-serif;
  /* Auth background — overridden per page by auth_header.php */
  --wa-auth-image:none;
}

*{ -webkit-tap-highlight-color:transparent; }
body{
  background:var(--wa-bg); color:var(--wa-ink);
  font-family:var(--wa-font);
  font-size:.9375rem; line-height:1.55; letter-spacing:-.005em;
  font-feature-settings:"cv11","ss01"; -webkit-font-smoothing:antialiased;
  overflow-x:hidden;
}
h1,h2,h3,h4,h5,.wa-stat__value,.wa-kpi__value{ letter-spacing:-.02em; }
.fw-500{ font-weight:500; }
.wa-num{ font-variant-numeric:tabular-nums; }
a{ color:var(--wa-green); text-decoration:none; }
a:hover{ color:var(--wa-accent); }
/* Keyboard focus stays visible everywhere; mouse clicks do not draw a ring. */
:focus-visible{ outline:2px solid var(--wa-accent); outline-offset:2px; border-radius:4px; }
.btn:focus-visible{ box-shadow:0 0 0 .2rem rgba(55,179,75,.28); }
@media (prefers-reduced-motion: reduce){
  *,*::before,*::after{ animation-duration:.01ms!important; transition-duration:.01ms!important; }
}
::-webkit-scrollbar{ width:8px; height:8px; }
::-webkit-scrollbar-thumb{ background:#c8d3cd; border-radius:8px; }

/* ------------------------------ Sidebar ------------------------------
   Compact by default. The nav scrolls; the logout foot never does.
   -------------------------------------------------------------------- */
.wa-sidebar{
  position:fixed; inset:0 auto 0 0; width:var(--wa-sidebar-w); z-index:1045;
  background:linear-gradient(180deg,var(--wa-sidebar) 0%, #04251A 100%);
  display:flex; flex-direction:column; transition:transform .25s ease;
}
.wa-sidebar__brand{
  height:60px; flex:0 0 60px; display:flex; align-items:center; justify-content:center;
  padding:0 14px; background:#fff; border-bottom:1px solid var(--wa-line);
}
/* Square, never rounded — the mark carries its own lockup. */
.wa-sidebar__brand img{ height:38px; width:auto; max-width:100%; border-radius:0; }
.wa-sidebar__nav{ overflow-y:auto; padding:10px 10px 14px; flex:1 1 auto; min-height:0; }
.wa-sidebar__label{
  font-size:.64rem; letter-spacing:.10em; text-transform:uppercase;
  color:rgba(255,255,255,.40); padding:12px 10px 5px; font-weight:650;
}
.wa-nav-link{
  display:flex; align-items:center; gap:10px; padding:8px 10px; margin-bottom:1px;
  border-radius:var(--wa-radius-sm); color:rgba(255,255,255,.80);
  font-weight:500; font-size:.855rem; transition:.15s; position:relative;
}
.wa-nav-link i{ width:18px; text-align:center; font-size:.95rem; opacity:.9; }
.wa-nav-link:hover{ background:var(--wa-sidebar-hover); color:#fff; }
.wa-nav-link.active{
  background:linear-gradient(135deg,var(--wa-accent) 0%, #22A03D 100%); color:#fff;
  box-shadow:0 8px 18px -8px rgba(55,179,75,.75), inset 0 1px 0 rgba(255,255,255,.20);
}
.wa-nav-link .badge{ margin-left:auto; }

/* Pinned logout: outside the scroll area, so it is reachable at any nav length */
.wa-sidebar__foot{
  flex:0 0 auto; padding:8px 10px 12px;
  border-top:1px solid rgba(255,255,255,.10);
  background:rgba(0,0,0,.16);
}
.wa-nav-link--out{ color:#FFC9C9; font-weight:550; }
.wa-nav-link--out:hover{ background:rgba(220,53,69,.22); color:#fff; }

/* Collapsed (full-width content) — desktop only; below xl the sidebar is off-canvas anyway */
@media (min-width:1200px){
  body.wa-nav-collapsed .wa-sidebar{ transform:translateX(-100%); }
  body.wa-nav-collapsed .wa-main{ margin-left:0; }
}

/* ------------------------------ Topbar ------------------------------- */
.wa-main{ margin-left:var(--wa-sidebar-w); min-height:100vh; transition:margin .25s ease; }
/* Translucent + blurred: content scrolling under the bar stays legible without a
   hard shadow line. Falls back to the solid colour where backdrop-filter is absent. */
.wa-topbar{
  height:60px; background:rgba(255,255,255,.86); border-bottom:1px solid var(--wa-line);
  backdrop-filter:blur(10px) saturate(150%); -webkit-backdrop-filter:blur(10px) saturate(150%);
  position:sticky; top:0; z-index:1030; display:flex; align-items:center;
  gap:12px; padding:0 20px;
}
@supports not (backdrop-filter: blur(2px)){ .wa-topbar{ background:var(--wa-surface); } }
.wa-topbar__title{ font-weight:670; font-size:1.02rem; color:var(--wa-green); margin:0; letter-spacing:-.01em; }
.wa-topbar .btn-icon{ border:1px solid var(--wa-line); background:#fff; color:var(--wa-ink); }
.wa-topbar .btn-icon:hover{ background:var(--wa-accent-soft); color:var(--wa-green); border-color:#CDEBD6; }
.wa-avatar{
  width:38px; height:38px; border-radius:50%;
  background:linear-gradient(145deg,#E8F6EC,#D3EEDB);
  color:var(--wa-green); font-weight:750; display:flex; align-items:center; justify-content:center;
  font-size:.84rem; box-shadow:inset 0 0 0 1px rgba(0,121,63,.10);
}
.wa-content{ padding:24px; }
@media (max-width:1199.98px){
  .wa-sidebar{ transform:translateX(-100%); }
  .wa-sidebar.show{ transform:translateX(0); box-shadow:var(--wa-shadow-lg); }
  .wa-main{ margin-left:0; }
  .wa-content{ padding:16px 14px; }
}
.wa-backdrop{ position:fixed; inset:0; background:rgba(8,32,22,.5); z-index:1040; display:none; }
.wa-backdrop.show{ display:block; }

/* ------------------------------ Cards -------------------------------- */
.wa-card{
  background:linear-gradient(180deg,#FFFFFF 0%, #FCFEFD 100%);
  border:1px solid var(--wa-line);
  border-radius:var(--wa-radius); box-shadow:var(--wa-shadow); margin-bottom:20px;
  transition:box-shadow .2s ease;
}
.wa-card__head{
  padding:18px 22px; border-bottom:1px solid var(--wa-line-soft);
  display:flex; align-items:center; justify-content:space-between; gap:14px; flex-wrap:wrap;
}
.wa-card__title{
  font-size:1rem; font-weight:680; color:var(--wa-green); margin:0;
  display:flex; align-items:center; gap:2px; letter-spacing:-.01em;
}
.wa-card__body{ padding:22px; }

/* ----------------------------- KPI tiles -----------------------------
   Value first and largest, label above it, trend and sparkline below.
   The accent colour is carried by the icon chip and the trend pill only —
   the number itself stays ink-dark so it is never the weakest contrast.
   --------------------------------------------------------------------- */
.wa-kpi{
  position:relative; height:100%; padding:20px 22px 18px; overflow:hidden; isolation:isolate;
  background:linear-gradient(180deg,#FFFFFF 0%, #FAFDFB 100%);
  border:1px solid var(--wa-line);
  border-radius:var(--wa-radius); box-shadow:var(--wa-shadow);
  transition:transform .18s ease, box-shadow .18s ease, border-color .18s ease;
}
/* Brand-tinted corner glow. Purely decorative, so it must never take pointer
   events and must stay far below text contrast — it tints, it does not colour. */
.wa-kpi::before{
  content:""; position:absolute; inset:-48px -46px auto auto; width:168px; height:168px;
  border-radius:50%; z-index:-1; pointer-events:none;
  background:radial-gradient(circle, rgba(55,179,75,.13) 0%, rgba(55,179,75,0) 68%);
}
.wa-kpi--teal::before  { background:radial-gradient(circle, rgba(14,154,138,.14) 0%, rgba(14,154,138,0) 68%); }
.wa-kpi--amber::before { background:radial-gradient(circle, rgba(232,163,61,.16) 0%, rgba(232,163,61,0) 68%); }
.wa-kpi--slate::before { background:radial-gradient(circle, rgba(75,108,121,.13) 0%, rgba(75,108,121,0) 68%); }
.wa-kpi:hover{ transform:translateY(-3px); box-shadow:var(--wa-shadow-lg); border-color:#DCE7E0; }
.wa-kpi__top{ display:flex; align-items:flex-start; justify-content:space-between; gap:12px; }
.wa-kpi__label{
  font-size:.72rem; font-weight:650; text-transform:uppercase; letter-spacing:.08em;
  color:var(--wa-ink-soft); margin:0;
}
.wa-kpi__value{
  font-size:2.2rem; font-weight:800; line-height:1.05; margin:8px 0 0;
  color:#102E21; font-variant-numeric:tabular-nums; letter-spacing:-.03em;
}
/* Inset highlight on the chip reads as a lit surface rather than a flat swatch. */
.wa-kpi__icon{
  width:46px; height:46px; flex:0 0 46px; border-radius:14px; display:grid; place-items:center;
  font-size:1.05rem; color:#fff; background:linear-gradient(145deg,var(--wa-accent),var(--wa-green));
  box-shadow:var(--wa-shadow-brand), inset 0 1px 0 rgba(255,255,255,.30);
}
.wa-kpi--teal  .wa-kpi__icon{ background:linear-gradient(145deg,#2CC6B0,var(--wa-teal)); box-shadow:0 8px 20px -8px rgba(14,154,138,.55), inset 0 1px 0 rgba(255,255,255,.30); }
.wa-kpi--amber .wa-kpi__icon{ background:linear-gradient(145deg,#F2BC5C,#D98A1F); box-shadow:0 8px 20px -8px rgba(217,138,31,.55), inset 0 1px 0 rgba(255,255,255,.30); }
.wa-kpi--slate .wa-kpi__icon{ background:linear-gradient(145deg,#8FAFBB,#4B6C79); box-shadow:0 8px 20px -8px rgba(75,108,121,.55), inset 0 1px 0 rgba(255,255,255,.30); }
.wa-kpi__foot{
  display:flex; align-items:center; gap:10px; margin-top:14px; min-height:26px;
  padding-top:12px; border-top:1px solid var(--wa-line-soft);
}
.wa-trend{
  display:inline-flex; align-items:center; gap:5px; font-size:.73rem; font-weight:700;
  padding:.24rem .55rem; border-radius:999px; white-space:nowrap;
  border:1px solid transparent;
}
.wa-trend--up{ background:var(--wa-accent-soft); color:#12662F; border-color:#CDEBD6; }
.wa-trend--down{ background:#FDECEC; color:#A32020; border-color:#F5D2D2; }
.wa-trend--flat{ background:#EEF2F0; color:var(--wa-ink-soft); border-color:#E2E9E5; }
.wa-kpi__note{ font-size:.72rem; color:var(--wa-ink-soft); }
/* Sized PARENT for the sparkline canvas. Chart.js writes width/height attributes
   onto the canvas itself, so a bare absolutely-positioned canvas ignores its CSS
   height and stretches to the whole tile. */
.wa-kpi__spark{
  position:absolute; right:0; bottom:0; left:0; height:40px;
  z-index:-1; opacity:.95; pointer-events:none;
}
.wa-kpi__spark canvas{ width:100%!important; height:100%!important; }
.wa-kpi--spark{ padding-bottom:44px; }

/* --------------------------- Stat tiles ------------------------------ */
.wa-stat{
  background:var(--wa-surface); border:1px solid var(--wa-line); border-radius:var(--wa-radius);
  padding:18px 20px; height:100%; position:relative; overflow:hidden; box-shadow:var(--wa-shadow);
  transition:transform .18s, box-shadow .18s;
}
.wa-stat:hover{ transform:translateY(-2px); box-shadow:var(--wa-shadow-lg); }
.wa-stat::after{ content:""; position:absolute; left:0; top:0; bottom:0; width:4px; background:var(--wa-accent); }
.wa-stat--teal::after{ background:var(--wa-teal); }
.wa-stat--amber::after{ background:var(--wa-warning); }
.wa-stat--red::after{ background:var(--wa-danger); }
.wa-stat__label{ font-size:.76rem; text-transform:uppercase; letter-spacing:.06em; color:var(--wa-ink-soft); font-weight:600; }
.wa-stat__value{ font-size:1.7rem; font-weight:700; color:var(--wa-green); line-height:1.2; margin-top:4px; }
.wa-stat__icon{
  position:absolute; right:16px; top:16px; width:42px; height:42px; border-radius:11px;
  background:var(--wa-accent-soft); color:var(--wa-green); display:flex; align-items:center; justify-content:center; font-size:1.05rem;
}

/* ------------------------------ Buttons ------------------------------ */
.btn{
  border-radius:var(--wa-radius-sm); font-weight:600; font-size:.875rem; padding:.5rem 1rem;
  transition:transform .12s ease, box-shadow .18s ease, background .18s ease;
}
.btn:active{ transform:translateY(1px); }
.btn-wa{
  background:linear-gradient(180deg,#00874648,#0000), var(--wa-green);
  border-color:var(--wa-green); color:#fff; box-shadow:var(--wa-shadow-brand);
}
.btn-wa:hover,.btn-wa:focus{ background:var(--wa-green-700); border-color:var(--wa-green-700); color:#fff; }
.btn-wa-accent{ background:var(--wa-accent); border-color:var(--wa-accent); color:#fff; box-shadow:0 8px 20px -8px rgba(55,179,75,.55); }
.btn-wa-accent:hover{ background:#2E9C40; border-color:#2E9C40; color:#fff; }
.btn-wa-outline{ border:1px solid var(--wa-green); color:var(--wa-green); background:#fff; }
.btn-wa-outline:hover{ background:var(--wa-green); color:#fff; }
/* THE SELECTED STATE. Bootstrap generates .active only for the variants it builds with
   its own button-variant() mixin, so a custom .btn-wa-outline silently had none: the
   chosen quick-range chip rendered identically to the four it was chosen over, and
   .wa-count--on painted its badge white-on-white. Which range you are looking at is the
   single most important thing on that filter bar, so it is filled, not merely outlined. */
.btn-wa-outline.active,
.btn-wa-outline.active:hover,
.btn-wa-outline.active:focus{
  background:var(--wa-green); border-color:var(--wa-green); color:#fff;
  box-shadow:inset 0 1px 0 rgba(255,255,255,.18);
}
.btn-wa-outline.active:focus-visible{ outline:2px solid var(--wa-green); outline-offset:2px; }
.btn-icon{ width:32px; height:32px; padding:0; display:inline-flex; align-items:center; justify-content:center; }

/* ------------------------------ Forms -------------------------------- */
.form-label{ font-size:.82rem; font-weight:600; color:var(--wa-ink); margin-bottom:.35rem; }
.form-label .req{ color:var(--wa-danger); }
.form-control,.form-select{
  border-radius:var(--wa-radius-sm); border:1px solid #D9E0DC; font-size:.9rem; padding:.55rem .8rem;
}
/* THE CARET NEEDS ITS OWN ROOM. The rule above sets a single padding for both
   controls, which overrides the 2.25rem Bootstrap reserves on a <select> for the arrow
   it draws in the background - so the arrow sat on the last letter and "Last 30 days"
   read as "Last 30 day". .wa-filters already carried this exact correction locally;
   this is the same value, moved to where every select gets it. */
.form-select{ padding-right:2.2rem; }
.form-control:focus,.form-select:focus{ border-color:var(--wa-accent); box-shadow:0 0 0 .2rem rgba(55,179,75,.16); }
.input-group-text{ background:#F6F9F7; border-color:#D9E0DC; color:var(--wa-ink-soft); }

/* ---------------------------- Filter bars -----------------------------
   Bootstrap sets .form-select/.form-control to width:100%. Dropped into a
   wrapping flex row that makes every control claim its own full-width line,
   which is why a filter row must never be a bare `d-flex flex-wrap`.
   --------------------------------------------------------------------- */
.wa-filters{ display:flex; flex-wrap:wrap; align-items:flex-end; gap:10px; }
.wa-filters .form-control{ width:auto; min-width:0; }
/* width:auto sizes a select to its selected option, which leaves no room for the
   caret Bootstrap paints on the right — the last glyph ends up under it. Give
   every select a floor and explicit caret room rather than fixing one per page. */
.wa-filters .form-select{ width:auto; min-width:140px; padding-right:2.2rem; }
.wa-filters__group{ display:flex; flex-direction:column; gap:3px; }
.wa-filters__group > label{
  font-size:.66rem; font-weight:650; letter-spacing:.06em; text-transform:uppercase;
  color:var(--wa-ink-soft); line-height:1;
}
.wa-filters__group--sel .form-select{ min-width:158px; }   /* longer option text */
.wa-filters__actions{ display:flex; align-items:center; gap:8px; }
/* Below md the bar owns its own row and the controls share it two-up. */
@media (max-width:767.98px){
  .wa-filters{ width:100%; }
  .wa-filters__group{ flex:1 1 44%; }
  .wa-filters .form-select,
  .wa-filters .form-control{ width:100%; }
  .wa-filters__actions{ flex:1 1 100%; }
}

/* Status chips on the dashboard: a badge, the head count, and what it is made of.
   Sized so a row of eight wraps tidily on a laptop and two-up on a phone. */
.wa-statchip{
  display:flex; flex-direction:column; gap:4px; min-width:150px; flex:1 1 150px;
  padding:12px 14px; border:1px solid var(--wa-line); border-radius:var(--wa-radius-sm);
  background:linear-gradient(180deg,#FFFFFF 0%, #FCFEFD 100%); text-decoration:none;
}
.wa-statchip__n{ font-size:1.5rem; font-weight:700; line-height:1.1; color:var(--wa-ink);
                 font-variant-numeric:tabular-nums; }
.wa-statchip__sub{ font-size:.7rem; color:var(--wa-ink-soft); }
.wa-statchip .wa-badge{ align-self:flex-start; }
a.wa-statchip--link{ transition:box-shadow .18s ease, border-color .18s ease; }
a.wa-statchip--link:hover{ border-color:#CDEBD6; box-shadow:var(--wa-shadow); }
a.wa-statchip--link:focus-visible{ outline:2px solid var(--wa-green); outline-offset:2px; }

/* The badge box in the visitors list. A max-width on its own let the column squeeze it
   to about two characters, so a three-digit badge was clipped while being typed; the
   min-width is what actually fixes that, and the max keeps the column from sprawling. */
.wa-badge-in{ min-width:6rem; max-width:8rem; }

/* Enter is the ONLY way a badge is saved — there is no Save button beside the box
   and no blur handler — so the box has to say so or the number is typed, the row
   is left, and nothing was written. Deliberately tiny and tight: this repeats on
   every row of a 25-row page, and at .form-text's size it added visible height to
   all of them. Capped to the input's own width so it wraps under the box instead
   of widening the column. */
.wa-badge-hint{
  font-size:.66rem; line-height:1.15; margin-top:.15rem;
  max-width:8rem; color:var(--bs-secondary-color, #6c757d);
}

/* One step below .btn-sm, for a control that sits inside a table row rather than beside
   a heading. Bootstrap 5.3 buttons read these variables, so this follows whatever the
   theme does to padding elsewhere. nowrap because "Check out" breaking over two lines
   is what made the row tall. */
.btn-xs{
  --bs-btn-padding-y:.15rem; --bs-btn-padding-x:.5rem;
  --bs-btn-font-size:.735rem; --bs-btn-border-radius:var(--wa-radius-sm);
  white-space:nowrap;
}
.btn-xs .fa-solid{ font-size:.7rem; }

/* ------------------------------ Tables ------------------------------- */
table.dataTable thead th{
  background:linear-gradient(180deg,#F7FAF8,#F2F7F4); color:var(--wa-green);
  font-size:.72rem; text-transform:uppercase; letter-spacing:.07em; font-weight:700;
  border-bottom:1px solid var(--wa-line)!important; white-space:nowrap; padding-top:.85rem; padding-bottom:.85rem;
}
table.dataTable tbody td{ font-size:.875rem; vertical-align:middle; padding-top:.72rem; padding-bottom:.72rem; }
table.dataTable tbody tr{ transition:background .12s ease; }
table.dataTable tbody tr:hover{ background:#F6FBF8; }
table.dataTable tbody tr td{ border-top-color:var(--wa-line-soft); }
.dataTables_wrapper .dataTables_paginate .paginate_button.current{
  background:var(--wa-green)!important; border-color:var(--wa-green)!important; color:#fff!important; border-radius:6px;
}
.dataTables_wrapper .dataTables_filter input{ border-radius:var(--wa-radius-sm); border:1px solid #D9E0DC; padding:.35rem .7rem; }
.dt-buttons .btn{ margin-right:6px; }

/* DataTables controls: the length menu and search need explicit sizing, or the
   select renders too narrow to show its own caret. */
.dataTables_wrapper .dataTables_length label,
.dataTables_wrapper .dataTables_filter label{
  display:flex; align-items:center; gap:8px; margin:0;
  font-size:.82rem; color:var(--wa-ink-soft); font-weight:500;
}
.dataTables_wrapper .dataTables_length select{
  width:auto; min-width:74px; padding:.3rem 1.9rem .3rem .6rem;
  border-radius:var(--wa-radius-sm); border:1px solid #D9E0DC; font-size:.84rem;
}
.dataTables_wrapper .dataTables_filter{ text-align:right; }
.dataTables_wrapper .dataTables_filter input{ min-width:210px; }
.dataTables_wrapper .dataTables_info{ font-size:.8rem; color:var(--wa-ink-soft); padding-top:0; }
.dataTables_wrapper .dataTables_paginate{ padding-top:0; }
@media (max-width:575.98px){
  .dataTables_wrapper .dataTables_filter{ text-align:left; }
  .dataTables_wrapper .dataTables_filter input{ width:100%; min-width:0; }
}

/* Long free-text cells (audit descriptions) wrap instead of stretching the table */
.wa-cell-wrap{ white-space:normal; min-width:220px; max-width:420px; }
.wa-cell-id{ color:var(--wa-ink-soft); font-variant-numeric:tabular-nums; }

/* ------------------------------ Badges ------------------------------- */
.wa-badge{ font-size:.72rem; font-weight:600; padding:.3rem .6rem; border-radius:999px; display:inline-block; }
.wa-badge--on{ background:var(--wa-accent-soft); color:#12662F; }
.wa-badge--off{ background:#FDECEC; color:#A32020; }
.wa-badge--role{ background:#EAF3FA; color:#0C5C86; }
/* Waaree employee on a self-service pass. Teal, matching .vcard--emp on the printed
   card and the staff figures on the dashboard, so the three surfaces agree. */
.wa-badge--teal{ background:#E4F5F2; color:#0B7A6D; }
/* Visit statuses — one background per status, so a list is readable at a glance
   without reading the words. The three waiting states are deliberately different
   hues rather than three shades of amber: they differ in WHO is holding the
   request up, which is the thing a supervisor scans the list for.
   Every pair clears 4.5:1 against its own background. */
.wa-badge--invited  { background:#EAF3FA; color:#0C5C86; }   /* blue   - sent, nothing owed */
.wa-badge--submitted{ background:#E4F5F2; color:#0B7A6D; }   /* teal   - visitor has replied */
.wa-badge--alloc    { background:#FFF3DF; color:#8A5A11; }   /* amber  - the desk owes an action */
.wa-badge--host     { background:#F0EBFB; color:#5A3EA6; }   /* violet - the host owes an action */
.wa-badge--hod      { background:#FDEADF; color:#A2451A; }   /* burnt  - escalated, most urgent */
.wa-badge--cancelled{ background:#EEF2F0; color:#556158; }   /* grey   - withdrawn, not refused */
.wa-badge--expired  { background:#E9EDF2; color:#4A5A6A; }   /* slate  - simply out of time */
/* Audit actions — tone carries the meaning so a denial is visible while scanning */
.wa-badge--act{ background:#EEF2F0; color:#4C5A53; font-weight:550; }
.wa-badge--act-ok{ background:var(--wa-accent-soft); color:#12662F; }
.wa-badge--act-warn{ background:#FDF3E3; color:#8A5A11; }
.wa-badge--act-bad{ background:#FDECEC; color:#A32020; }

/* --------------------------- Auth screens ----------------------------
   Photographic background + a green scrim. The scrim is not decoration:
   the image is uncontrolled artwork, and white text on it is only legible
   because the gradient guarantees contrast.
   --------------------------------------------------------------------- */
.wa-auth-body{ background:#04251A; }
.wa-auth{
  position:relative; min-height:100vh; display:flex; flex-direction:column;
  align-items:center; justify-content:center; padding:24px 16px;
  /* Two layers over the photo: a soft directional tint for brand, plus a wide
     radial vignette that darkens the edges and lifts the centre where the card
     sits. A single flat gradient washes the photograph out to a green sheet. */
  /* background-image:
    radial-gradient(120% 95% at 50% 45%, rgba(2,26,18,.10) 0%, rgba(2,26,18,.52) 62%, rgba(1,18,12,.78) 100%),
    linear-gradient(118deg, rgba(3,34,23,.72) 0%, rgba(0,96,50,.46) 48%, rgba(14,154,138,.30) 100%),
    var(--wa-auth-image); */
    
    background-image:
     var(--wa-auth-image);
    

  background-size:cover, cover, cover;
  background-position:center, center, center;
  background-repeat:no-repeat, no-repeat, no-repeat;
  background-attachment:fixed, fixed, fixed;
}
.wa-auth__shell{
  width:100%; max-width:940px; display:grid; grid-template-columns:1fr;
  border-radius:var(--wa-radius-lg); overflow:hidden;
  box-shadow:0 30px 80px rgba(2,20,13,.45);
}
@media (min-width:992px){ .wa-auth__shell{ grid-template-columns:1.05fr .95fr; } }

/* Left: frosted brand panel over the photo */
.wa-auth__brand{
  flex-direction:column; padding:44px 40px; color:#fff;
  /* Dark enough for white body text at 0.86rem over an unknown photo, whatever
     the scrim above the image happens to let through. */
  background:linear-gradient(160deg, rgba(2,26,17,.80), rgba(4,52,34,.62));
  backdrop-filter:blur(8px) saturate(120%);
  -webkit-backdrop-filter:blur(8px) saturate(120%);
  border-right:1px solid rgba(255,255,255,.10);
}
/* Square white plate, never rounded. The plate stays because the logo is dark
   green on transparent and would vanish against the panel; only the radius goes. */
.wa-auth__brand-logo{
  height:58px; width:auto; align-self:flex-start; margin-bottom:34px;
  background:#fff; border-radius:0; padding:10px 16px;
}
.wa-auth__brand-title{ font-size:1.42rem; font-weight:700; line-height:1.3; margin:0 0 10px; }
.wa-auth__brand-text{ font-size:.9rem; color:rgba(255,255,255,.82); margin:0 0 26px; max-width:34ch; }
.wa-auth__points{ list-style:none; padding:0; margin:0 0 auto; }
.wa-auth__points li{
  display:flex; align-items:center; gap:12px; font-size:.86rem;
  color:rgba(255,255,255,.90); padding:9px 0;
}
.wa-auth__points i{
  width:30px; height:30px; flex:0 0 30px; border-radius:9px; display:grid; place-items:center;
  background:rgba(255,255,255,.14); color:#9BE7AE; font-size:.82rem;
}
.wa-auth__brand-foot{ font-size:.74rem; color:rgba(255,255,255,.6); margin:34px 0 0; }

/* Right: the form panel — near-opaque, because forms must stay readable */
.wa-auth__panel{ background:rgba(255,255,255,.97); padding:40px 36px; }
@media (max-width:575.98px){ .wa-auth__panel{ padding:30px 22px; } }
/* Small-screen logo sits on the white form panel, so no plate and no radius. */
.wa-auth__logo{ display:block; height:52px; width:auto; margin:0 auto 22px; border-radius:0; }
.wa-auth__title{ font-size:1.44rem; font-weight:750; color:var(--wa-green); margin:0 0 6px; }
.wa-auth__sub{ font-size:.875rem; color:var(--wa-ink-soft); margin:0 0 26px; }
.wa-auth__notice{
  font-size:.72rem; color:var(--wa-ink-soft); text-align:center;
  margin:26px 0 0; padding-top:16px; border-top:1px solid var(--wa-line);
}
.wa-auth__foot{ text-align:center; font-size:.76rem; color:rgba(255,255,255,.72); margin:18px 0 0; }
@media (max-width:991.98px){
  .wa-auth__shell{ max-width:460px; }
  .wa-auth__title,.wa-auth__sub{ text-align:center; }
}

/* Standalone single-panel card: 403 / error screens sit on the same photo
   background as login but have no two-column shell to hold them. */
.wa-auth__card{
  width:100%; max-width:440px; background:rgba(255,255,255,.97);
  border-radius:var(--wa-radius); padding:40px 34px;
  box-shadow:0 30px 70px -30px rgba(0,0,0,.55);
}
@media (max-width:575.98px){ .wa-auth__card{ padding:30px 22px; } }

/* Confirmation / dead-end states (link expired, check your inbox) */
.wa-auth__done{ text-align:center; }
.wa-auth__done-icon{
  width:58px; height:58px; border-radius:50%; display:grid; place-items:center; margin:4px auto 18px;
  background:var(--wa-accent-soft); color:var(--wa-green); font-size:1.4rem;
}
.wa-auth__done-icon--ok{ background:var(--wa-accent); color:#fff; }
.wa-auth__done-icon--bad{ background:#FDECEC; color:#A32020; }
.wa-auth__done-text{ font-size:.88rem; color:var(--wa-ink); margin:0 0 24px; }

/* Inputs on auth screens + the remember-me control */
/* Icon prefix owns the left border; the input keeps real padding so the
   placeholder is not clipped against the icon cell. */
.wa-field .form-control{ border-left:0; padding-left:.7rem; }
.wa-field .input-group-text:first-child{ background:#fff; border-right:0; color:var(--wa-ink-soft); }
.wa-field:focus-within .input-group-text{ border-color:var(--wa-accent); }
.wa-check .form-check-input{ width:1.05em; height:1.05em; margin-top:.15em; border-color:#C6D2CB; }
.wa-check .form-check-input:checked{ background-color:var(--wa-green); border-color:var(--wa-green); }
.wa-check .form-check-label{ font-size:.86rem; font-weight:500; color:var(--wa-ink); cursor:pointer; }
.wa-check__hint{ display:block; font-size:.72rem; font-weight:400; color:var(--wa-ink-soft); }
.btn-wa-ghost{ color:var(--wa-ink-soft); background:transparent; border:1px solid var(--wa-line); }
.btn-wa-ghost:hover{ color:var(--wa-green); border-color:var(--wa-green); background:#F6FAF7; }
.pw-toggle{ cursor:pointer; }
.pw-meter{ height:5px; border-radius:4px; background:#E9EDEB; overflow:hidden; margin-top:8px; }
.pw-meter span{ display:block; height:100%; width:0; transition:width .25s, background .25s; }

/* ------------------------- Email test mode ---------------------------- */
.wa-chip-test{
  display:inline-flex; align-items:center; gap:7px; padding:.32rem .7rem;
  border-radius:999px; font-size:.74rem; font-weight:650; white-space:nowrap;
  background:#FDF3E3; color:#8A5A11; border:1px solid #EBC98A;
}
.wa-chip-test:hover{ background:#FBE9CB; color:#6E470D; }
.wa-testmode{ border:1px solid var(--wa-line); border-radius:var(--wa-radius-sm); padding:14px 16px; }
.wa-testmode--on{ background:#FFF9EE; border-color:#EBC98A; }
.wa-testmode--on .form-check-label{ color:#7A4A00; }
.wa-testmode--off{ background:#F8FBF9; }

/* ------------------- Branding previews & email preview ---------------- */
.wa-brand-prev{
  display:grid; place-items:center; border:1px dashed var(--wa-line);
  border-radius:var(--wa-radius-sm); background:#F8FBF9; padding:10px; min-height:74px; overflow:hidden;
}
.wa-brand-prev img{ max-width:100%; max-height:54px; width:auto; border-radius:0; }
.wa-brand-prev--icon img{ max-height:34px; }
/* Background is wide artwork: show the crop, not a letterboxed thumbnail. */
.wa-brand-prev--bg{ padding:0; min-height:96px; background:#04251A; }
.wa-brand-prev--bg img{ width:100%; max-height:96px; object-fit:cover; }

/* Email preview — a real iframe so the email's own CSS cannot touch the portal */
.wa-mail-preview{ background:#EEF2F0; }
.wa-mail-preview iframe{
  display:block; width:100%; height:62vh; min-height:380px; border:0; background:#fff;
}

/* ------------------------------ Misc --------------------------------- */
.wa-empty{ text-align:center; padding:48px 20px; color:var(--wa-ink-soft); }
.wa-empty i{ font-size:2.4rem; color:#C9D5CE; margin-bottom:12px; display:block; }
.wa-chart-box{ position:relative; height:286px; }
.wa-chart-box--sm{ height:242px; }
@media (max-width:575.98px){ .wa-chart-box,.wa-chart-box--sm{ height:240px; } }

/* Doughnut centre readout — the total belongs inside the hole, not in a legend */
.wa-donut{ position:relative; }
.wa-donut__mid{
  position:absolute; inset:0; display:grid; place-items:center; text-align:center; pointer-events:none;
}
.wa-donut__mid b{ display:block; font-size:1.5rem; font-weight:780; color:#123024; line-height:1; }
.wa-donut__mid span{ font-size:.7rem; text-transform:uppercase; letter-spacing:.07em; color:var(--wa-ink-soft); }

/* Activity feed — a timeline reads faster than a five-column table */
.wa-feed{ list-style:none; margin:0; padding:6px 4px; }
.wa-feed li{ display:flex; gap:14px; padding:11px 16px; border-radius:var(--wa-radius-sm); }
.wa-feed li:hover{ background:#F8FBF9; }
.wa-feed__dot{
  width:34px; height:34px; flex:0 0 34px; border-radius:50%; display:grid; place-items:center;
  background:var(--wa-accent-soft); color:var(--wa-green); font-size:.76rem;
  box-shadow:inset 0 0 0 1px rgba(0,121,63,.10);
}
.wa-feed__dot--warn{ background:#FDF3E3; color:#8A5A11; }
.wa-feed__dot--bad{ background:#FDECEC; color:#A32020; }
.wa-feed__body{ min-width:0; flex:1; }
.wa-feed__line{ font-size:.86rem; color:var(--wa-ink); margin:0; }
.wa-feed__line b{ font-weight:600; color:#123024; }
.wa-feed__meta{ font-size:.72rem; color:var(--wa-ink-soft); }
.table-responsive{ border-radius:var(--wa-radius-sm); }
.wa-loading{ opacity:.55; pointer-events:none; }
@media print{ .wa-sidebar,.wa-topbar,.no-print{ display:none!important; } .wa-main{ margin:0; } }

/* =====================================================================
   VISITOR MODULE — added on top of the base kit stylesheet.
   Tokens only: no new colours are invented here, everything reuses the
   Waaree variables declared at the top of this file.
   ===================================================================== */

/* --- extra badge tones (the base kit ships on/off/role only) ---------- */
.wa-badge--info{ background:rgba(14,154,138,.12); color:#0B7A6D; }
.wa-badge--warn{ background:rgba(232,163,61,.16); color:#8A5A11; }
.wa-badge--bad { background:rgba(220,53,69,.12);  color:#A32330; }

/* --- definition list used on the request detail page ------------------ */
.wa-dl{ display:grid; grid-template-columns:repeat(auto-fit, minmax(220px, 1fr)); gap:2px 22px; }
.wa-dl > div{ padding:9px 0; border-bottom:1px solid var(--wa-line-soft); min-width:0; }
.wa-dl span{ display:block; font-size:.68rem; letter-spacing:.07em; text-transform:uppercase;
             color:var(--wa-ink-soft); margin-bottom:2px; }
.wa-dl strong{ font-size:.9rem; font-weight:600; color:var(--wa-ink); word-break:break-word; }

/* --- masters tab strip ------------------------------------------------ */
.wa-tabs .nav-link{ color:var(--wa-ink-soft); font-weight:600; font-size:.86rem; border-radius:var(--wa-radius-sm);
                    padding:.45rem .95rem; border:0; background:transparent;
                    transition:background .15s, color .15s; }
/* Hover was never styled, so every strip fell through to whatever Bootstrap does with
   a .nav-link - which is its own blue, not ours. Named here rather than per page so
   the seven strips in this app cannot drift apart again. */
.wa-tabs .nav-link:hover,
.wa-tabs .nav-link:focus-visible{ background:rgba(0,121,63,.08); color:var(--wa-green); }
.wa-tabs .nav-link.active{ background:var(--wa-green); color:#fff; box-shadow:var(--wa-shadow-brand); }
/* The active tab keeps its fill on hover: a selected tab that lightens under the
   pointer reads as if the click did not take. */
.wa-tabs .nav-link.active:hover,
.wa-tabs .nav-link.active:focus-visible{ background:var(--wa-green-600); color:#fff; }
/* A badge inside a tab - the gate tray's "1 waiting" - has to read against both the
   plain and the filled state. */
.wa-tabs .nav-link.active .wa-badge{ background:rgba(255,255,255,.22); color:#fff; }

/* --- gate scan -------------------------------------------------------- */
.wa-scan{ width:100%; min-height:230px; border:1px dashed var(--wa-line); border-radius:var(--wa-radius);
          background:#F7FAF8; overflow:hidden; }
.wa-scan video{ width:100% !important; height:auto !important; display:block; }

.wa-verify{ border:1px solid var(--wa-line); border-radius:var(--wa-radius); overflow:hidden; }
.wa-verify__head{ display:flex; align-items:center; gap:12px; padding:14px 16px; color:#fff; }
.wa-verify__head i{ font-size:1.5rem; }
.wa-verify--ok  .wa-verify__head{ background:linear-gradient(120deg, var(--wa-green), var(--wa-accent)); }
.wa-verify--bad .wa-verify__head{ background:linear-gradient(120deg, #A32330, var(--wa-danger)); }
.wa-verify__photo{ width:110px; height:132px; object-fit:cover; border-radius:var(--wa-radius-sm);
                   border:1px solid var(--wa-line); margin:16px 16px 0; display:block; }
.wa-verify__name{ font-size:1.35rem; font-weight:800; letter-spacing:-.02em; color:#102E21; margin:14px 16px 0; }
.wa-verify__sub { font-size:.85rem; color:var(--wa-ink-soft); margin:2px 16px 12px; }
.wa-verify__kv{ width:100%; border-collapse:collapse; margin:0 0 4px; }
.wa-verify__kv td{ padding:7px 16px; font-size:.85rem; border-top:1px solid var(--wa-line-soft); }
.wa-verify__kv td:first-child{ color:var(--wa-ink-soft); width:140px; }
.wa-verify__kv td:last-child { font-weight:600; color:var(--wa-ink); }
.wa-verify__act{ display:flex; gap:8px; flex-wrap:wrap; padding:14px 16px; border-top:1px solid var(--wa-line-soft);
                 background:#FAFCFB; }

/* Scan-to-verify screen (visit/verify.php). Read at arm's length, one-handed, in a
   doorway — so the verdict is a full-width band before any detail, and it is carried
   by an icon and wording as well as colour, because a colour-blind guard reads the
   same badge as everyone else. */
.wa-verify__state{ text-align:center; padding:22px 16px; border-radius:var(--wa-radius);
                   margin-bottom:18px; border:1px solid transparent; }
.wa-verify__state i{ font-size:2.6rem; display:block; margin-bottom:8px; }
.wa-verify__state h2{ font-size:1.25rem; font-weight:800; letter-spacing:-.02em; margin:0 0 6px; }
.wa-verify__state p{ font-size:.86rem; margin:0 0 4px; }
.wa-verify__state--ok { background:#EAF7EF; border-color:#B9E3C9; color:#14663C; }
.wa-verify__state--ok i{ color:var(--wa-green); }
.wa-verify__state--bad{ background:#FDECEC; border-color:#F0C2C0; color:#8A2A26; }
.wa-verify__state--bad i{ color:var(--wa-danger); }

.wa-verify__who{ display:flex; align-items:center; gap:14px; margin-bottom:14px; }
/* Reset the margins the gate-console card puts on the same class. */
.wa-verify__who .wa-verify__photo{ margin:0; flex:0 0 auto; }
.wa-verify__who .wa-verify__name{ margin:0; }
.wa-verify__who .wa-verify__sub { margin:6px 0 0; display:flex; gap:6px; flex-wrap:wrap; }
.wa-verify__photo--none{ display:flex; align-items:center; justify-content:center;
                         background:var(--wa-bg); color:var(--wa-ink-soft); font-size:2rem; }

/* A pass number and a date must never break mid-token. 'WT-260824-0010' split
   across two lines is a number a guard has to reassemble by eye at a doorway. */
.wa-verify__kv .wa-num,
.wa-verify__kv .text-nowrap{ white-space:nowrap; }

@media (max-width:576px){
  .wa-verify__who{ flex-direction:column; align-items:flex-start; }

  /* Below 576px the two-column layout has no room left: a 120px label column leaves
     ~150px for the value on a 320px phone, which is what forces those mid-token
     breaks. Stack instead — label above, value across the full width. Applies to the
     gate console's result card too, which shares this table. */
  .wa-verify__kv,
  .wa-verify__kv tbody,
  .wa-verify__kv tr,
  .wa-verify__kv td{ display:block; width:100%; }

  .wa-verify__kv tr{ border-top:1px solid var(--wa-line-soft); padding:8px 0; }
  /* Bootstrap draws cell borders and stripes on .table descendants; in stacked mode
     they land in the wrong place, so the row owns the rule instead. */
  .wa-verify__kv td{ border:0 !important; box-shadow:none !important; padding:0 2px; }
  .wa-verify__kv td:first-child{ width:auto; font-size:.68rem; letter-spacing:.07em;
                                 text-transform:uppercase; margin-bottom:1px; }
  .wa-verify__kv td:last-child{ font-size:.92rem; }

  .wa-verify__state{ padding:18px 12px; }
  .wa-verify__state i{ font-size:2.2rem; }
  .wa-verify__state h2{ font-size:1.12rem; }
}

/* =====================================================================
   PUBLIC (VISITOR-FACING) PAGES — invite form and pass view.
   Deliberately calmer than the portal: no sidebar, no nav, larger targets,
   because these are opened by strangers on phones at a plant gate.
   ===================================================================== */
.wa-pub-body{ margin:0; background:var(--wa-bg); }
.wa-pub{ min-height:100vh; display:flex; flex-direction:column; }
.wa-pub__bar{ display:flex; align-items:center; gap:14px; padding:14px 20px; background:#fff;
              border-bottom:1px solid var(--wa-line); position:sticky; top:0; z-index:5; }
.wa-pub__logo{ width:118px; height:auto; border-radius:0; display:block; }
.wa-pub__title{ font-size:1rem; font-weight:700; letter-spacing:-.01em; color:#102E21; line-height:1.25; }
.wa-pub__sub{ font-size:.78rem; color:var(--wa-ink-soft); }
.wa-pub__body{ flex:1 1 auto; width:100%; max-width:860px; margin:0 auto; padding:22px 16px 40px; }
.wa-pub__foot{ text-align:center; font-size:.72rem; color:var(--wa-ink-soft); padding:18px 16px 26px; line-height:1.7; }

.wa-pub__card{ background:linear-gradient(180deg,#FFFFFF,#FCFEFD); border:1px solid var(--wa-line);
               border-radius:var(--wa-radius); box-shadow:var(--wa-shadow); padding:22px; margin-bottom:18px; }


.wa-pub__section{ padding-top:18px; margin-top:18px; border-top:1px solid var(--wa-line-soft); }
.wa-pub__section:first-of-type{ border-top:0; margin-top:0; padding-top:0; }
.wa-pub__section h3{ font-size:.95rem; font-weight:700; color:#102E21; letter-spacing:-.01em; margin:0 0 12px; }
.wa-pub__hint{ font-size:.78rem; color:var(--wa-ink-soft); line-height:1.6; margin-bottom:14px; }

/* Numbered steps. A gate form is long and is filled standing up on a phone; a
   number beside each heading turns "a wall of fields" into "four of these, then done",
   which is the difference between finishing it and going to the desk instead. */
.wa-pub__section h3{ display:flex; align-items:center; gap:10px; }
.wa-pub__step{ flex:0 0 auto; width:26px; height:26px; border-radius:50%;
               display:inline-flex; align-items:center; justify-content:center;
               background:var(--wa-green); color:#fff; font-size:.78rem; font-weight:700;
               font-variant-numeric:tabular-nums; box-shadow:0 1px 2px rgba(0,121,63,.30); }

/* The required marker has to survive a glance in daylight. */
.wa-pub .req{ color:var(--wa-danger); font-weight:700; margin-left:2px; }

/* Inputs get a visible ring, not just a border tint: a gate is a bright place and a
   1px colour change is invisible in sunlight. */
.wa-pub .form-control:focus, .wa-pub .form-select:focus{
  border-color:var(--wa-accent); box-shadow:0 0 0 .2rem rgba(55,179,75,.22); }
.wa-pub .form-control::placeholder{ color:#A8B2AC; }

/* Grouping: a hint belongs to the field above it, not floating between two. */
.wa-pub .form-text{ font-size:.74rem; line-height:1.5; margin-top:5px; }

/* The final action, always reachable. On a phone the submit sits below several
   screenfuls; docking it means the visitor never has to scroll back to finish. */
.wa-pub__submit{ display:grid; gap:10px; padding-top:6px; }

@media (max-width:768px){
  .wa-pub__submit{ position:sticky; bottom:0; z-index:4; margin:0 -16px -6px;
                   padding:12px 16px calc(12px + env(safe-area-inset-bottom));
                   background:rgba(255,255,255,.94); border-top:1px solid var(--wa-line);
                   backdrop-filter:blur(6px); }
  @supports not (backdrop-filter: blur(6px)) { .wa-pub__submit{ background:#fff; } }
  .wa-pub__submit .btn{ width:100%; }
}

/* ---------------------------------------------------------------- walk-in layout
   One tall column centred in an empty 1900px page is what the desktop looked like
   before: the width existed and nothing used it. Two columns — a rail that stays put
   and the form beside it — fill the screen and tell the visitor how much is left.
   Below 992px the grid collapses and the rail simply stacks above the form, which is
   the phone layout that already worked. */
.wa-pub__layout{ display:grid; gap:22px; align-items:start; }

@media (min-width:992px){
  .wa-pub__body{ max-width:1100px; }
  .wa-pub__layout{ grid-template-columns:300px minmax(0,1fr); gap:28px; }
  /* 84px clears the sticky header bar plus a little breathing room. */
  .wa-pub__rail{ position:sticky; top:84px; }
  .wa-pub__card{ padding:30px 34px; }
}

.wa-pub__railcard{ background:linear-gradient(160deg,#0B5233,#00793F 55%,#0E8A4B);
                   color:#fff; border-radius:var(--wa-radius); padding:20px;
                   box-shadow:0 10px 30px -14px rgba(11,82,51,.55); }

.wa-pub__plant{ display:flex; align-items:center; gap:12px; padding-bottom:14px;
                border-bottom:1px solid rgba(255,255,255,.18); }
.wa-pub__plant i{ flex:0 0 auto; width:38px; height:38px; border-radius:10px;
                  background:rgba(255,255,255,.14); display:flex; align-items:center;
                  justify-content:center; font-size:1rem; }
.wa-pub__plant span{ display:block; font-size:.64rem; letter-spacing:.1em;
                     text-transform:uppercase; color:rgba(255,255,255,.72); }
.wa-pub__plant strong{ font-size:1rem; font-weight:700; line-height:1.25; }

.wa-pub__facts{ display:flex; gap:18px; flex-wrap:wrap; margin:14px 0 0; }
.wa-pub__facts dt{ font-size:.64rem; letter-spacing:.1em; text-transform:uppercase;
                   color:rgba(255,255,255,.72); font-weight:500; }
.wa-pub__facts dd{ margin:2px 0 0; font-size:.86rem; font-weight:700; }

.wa-pub__steps{ list-style:none; margin:18px 0 0; padding:14px 0 0;
                border-top:1px solid rgba(255,255,255,.18); }
.wa-pub__steps a{ display:flex; align-items:center; gap:10px; padding:7px 8px;
                  margin:0 -8px; border-radius:9px; color:rgba(255,255,255,.82);
                  text-decoration:none; font-size:.84rem; transition:background .15s, color .15s; }
.wa-pub__steps a:hover{ background:rgba(255,255,255,.12); color:#fff; }
.wa-pub__stepdot{ flex:0 0 auto; width:22px; height:22px; border-radius:50%;
                  border:1px solid rgba(255,255,255,.45); display:inline-flex;
                  align-items:center; justify-content:center; font-size:.7rem;
                  font-weight:700; font-variant-numeric:tabular-nums; }
/* The section currently on screen. Marked by weight and a filled dot as well as
   colour, so it still reads for anyone who cannot separate the two greens. */
.wa-pub__steps .is-current a{ background:rgba(255,255,255,.16); color:#fff; font-weight:700; }
.wa-pub__steps .is-current .wa-pub__stepdot{ background:#fff; color:var(--wa-green); border-color:#fff; }

.wa-pub__note{ display:flex; gap:10px; margin-top:14px; padding:14px 16px;
               background:#F1F7F3; border:1px solid var(--wa-line-soft);
               border-radius:var(--wa-radius-sm); }
.wa-pub__note i{ color:var(--wa-green); margin-top:2px; }
.wa-pub__note p{ margin:0; font-size:.78rem; line-height:1.6; color:var(--wa-ink-soft); }

.wa-pub__card--done{ max-width:620px; margin-left:auto; margin-right:auto; }

/* Fields: a touch taller and a hair softer than the portal's, because these are filled
   once, by a stranger, standing up. */
.wa-pub .form-control, .wa-pub .form-select{ border-radius:10px; padding:.55rem .8rem; }
.wa-pub .form-label{ font-size:.82rem; font-weight:600; color:#33403A; margin-bottom:5px; }
.wa-pub__state{ text-align:center; padding:26px 12px; }
.wa-pub__state i{ font-size:2.6rem; margin-bottom:14px; display:block; }
.wa-pub__state h2{ font-size:1.2rem; font-weight:700; color:#102E21; margin-bottom:8px; }
.wa-pub__state p{ font-size:.9rem; color:var(--wa-ink-soft); margin-bottom:6px; }
.wa-pub__state--ok  i{ color:var(--wa-accent); }
.wa-pub__state--bad i{ color:var(--wa-danger); }

/* Validity chooser: five tiles, all visible, one click. The native radio is kept in
   the DOM (not display:none) so the keyboard and screen readers still drive it — the
   tile is just its label, and :focus-visible on the input styles the tile. */
.wa-valopts{ display:flex; flex-wrap:wrap; gap:10px; }
.wa-valopt{ margin:0; cursor:pointer; }
.wa-valopt input{ position:absolute; opacity:0; width:0; height:0; }
.wa-valopt__box{ display:flex; flex-direction:column; align-items:center; justify-content:center;
                 min-width:92px; padding:10px 14px; border:1.5px solid var(--wa-line);
                 border-radius:var(--wa-radius-sm); background:#fff; line-height:1.2;
                 transition:border-color .15s, background .15s, box-shadow .15s; }
.wa-valopt__big{ font-size:1.25rem; font-weight:800; color:var(--wa-ink);
                 font-variant-numeric:tabular-nums; }
.wa-valopt__lbl{ font-size:.72rem; color:var(--wa-ink-soft); margin-top:2px; white-space:nowrap; }
.wa-valopt:hover .wa-valopt__box{ border-color:var(--wa-accent); }

/* Selected is carried by the border, the fill AND the weight — not colour alone. */
.wa-valopt input:checked + .wa-valopt__box{
  border-color:var(--wa-green); background:#EAF7EF; box-shadow:inset 0 0 0 1px var(--wa-green); }
.wa-valopt input:checked + .wa-valopt__box .wa-valopt__big{ color:var(--wa-green); }
.wa-valopt input:checked + .wa-valopt__box .wa-valopt__lbl{ color:#14663C; font-weight:600; }
.wa-valopt input:focus-visible + .wa-valopt__box{ box-shadow:0 0 0 .2rem rgba(55,179,75,.30); }

@media (max-width:576px){
  .wa-valopts{ gap:8px; }
  .wa-valopt__box{ min-width:0; flex:1 0 auto; padding:9px 12px; }
}

/* One worker row on the contract batch screen. The number is a plain counter that
   renumbers on removal — the INPUT indices deliberately do not, because renaming a
   file input the browser has already accepted silently discards the chosen photo. */
.wa-wrow{ padding:10px 12px; border:1px solid var(--wa-line-soft); border-radius:var(--wa-radius-sm);
          background:#FCFEFD; }
/* Thumbnail of whatever photograph a row currently holds — captured or chosen.
   Small on purpose: it is a confirmation that something was taken, not a preview. */
.wa-wrow__thumb{ width:34px; height:42px; object-fit:cover; border-radius:4px;
                 border:1px solid var(--wa-line); }

.wa-wrow__no{ display:inline-flex; align-items:center; justify-content:center;
              width:26px; height:26px; margin-top:5px; border-radius:50%;
              background:var(--wa-green); color:#fff; font-size:.76rem; font-weight:700;
              font-variant-numeric:tabular-nums; }

/* one person block on the visitor form */
/* One of these per visitor, up to the invited count, so it has to read as a repeated
   UNIT and not as more of the same form. A hairline under its own heading and a dot
   beside the number does that, and costs nothing on a phone. */
.wa-person{ border:1px solid var(--wa-line); border-radius:var(--wa-radius-sm); padding:16px;
            margin-bottom:14px; background:#fff; box-shadow:0 1px 2px rgba(16,40,28,.035); }
.wa-person__head{ display:flex; align-items:center; justify-content:space-between; gap:10px;
                  padding-bottom:10px; margin-bottom:14px;
                  border-bottom:1px solid var(--wa-line-soft); }
.wa-person__no{ display:inline-flex; align-items:center; gap:8px;
                font-size:.72rem; letter-spacing:.09em; text-transform:uppercase; font-weight:700;
                color:var(--wa-green); }
.wa-person__no::before{ content:''; flex:0 0 auto; width:7px; height:7px; border-radius:50%;
                        background:var(--wa-green); }

/* --- a capture field --------------------------------------------------
   An ID photograph can arrive two ways and both have to be offered: the camera,
   which is what a visitor on a phone actually uses, and a file, which is the
   desktop case and the fallback when getUserMedia is refused. Loose, that was a
   button and a file input stacked in a column reading as TWO fields under one
   label. Boxed with "or" between them it reads as one field with two ways in. */
.wa-pick{ display:grid; gap:8px; padding:9px 10px; background:#FAFCFB;
          border:1px solid var(--wa-line); border-radius:10px; }
.wa-pick__row{ display:flex; align-items:center; gap:9px; flex-wrap:wrap; }
.wa-pick__or{ font-size:.72rem; color:var(--wa-ink-soft); }
/* The file input carries its own padding and a border inside a bordered tile is a
   box in a box; and at .78rem "No file chosen" stops being the widest thing in the
   column on a laptop. */
.wa-pick input[type="file"]{ font-size:.78rem; background:#fff; }

/* Note inside a filter bar. flex-basis:100% so it drops to its own line rather
   than squeezing the controls it is explaining. */
.wa-filters__note{ flex:1 0 100%; margin:-2px 0 2px; }

/* Shared in-page viewer for ID documents, photographs and printable passes.
   A tall fixed viewport rather than an auto height: the frame holds anything from a
   square selfie to a full A4 pass, and a box that resizes per document makes the
   modal jump about as the operator flicks between them. */
.wa-preview__frame{ width:100%; height:min(72vh, 760px); border:0; display:block;
                    background:var(--wa-bg); border-radius:0 0 var(--wa-radius) var(--wa-radius); }
@media (max-width:576px){ .wa-preview__frame{ height:68vh; } }

/* Two-line combo option: the name people search for, then what tells two people
   of the same name apart. Used by the walk-in host picker. */
.wa-opt{ display:flex; flex-direction:column; gap:2px; line-height:1.35; }
.wa-opt__name{ font-weight:600; color:var(--wa-ink); }
.wa-opt__meta{ font-size:.72rem; color:var(--wa-ink-soft); }
/* break-all: an address that overflows a narrow panel is worse than one that wraps. */
.wa-opt__mail{ font-size:.7rem; color:var(--wa-ink-soft); opacity:.85; word-break:break-all; }
.wa-opt__meta-inline{ font-size:.78rem; color:var(--wa-ink-soft); }
/* The dropdown sits inside a card with its own stacking context; without this the
   list is clipped by the panel rather than floating over it. */
.ts-dropdown{ z-index:1056; }

/* Printable walk-in QR card. The print rules matter more than the screen ones:
   this page exists to come out of a printer, get laminated and go on a wall. */
.wa-qrcard__plant{ font-size:1.05rem; font-weight:700; color:var(--wa-green); }
.wa-qrcard__type{ font-size:.72rem; letter-spacing:.09em; text-transform:uppercase; font-weight:700;
                  color:var(--wa-ink-soft); margin-bottom:10px; }
.wa-qrcard__type--temp{ color:#B4761A; }
.wa-qrcard__qr{ width:100%; max-width:230px; height:auto; display:block; margin:0 auto 10px; }
.wa-qrcard__lead{ font-size:.82rem; font-weight:600; margin-bottom:6px; }
/* break-all, not ellipsis: a truncated URL is useless to somebody typing it. */
.wa-qrcard__url{ font-size:.64rem; color:var(--wa-ink-soft); word-break:break-all; line-height:1.5; }
.wa-qrcard__meta{ font-size:.68rem; color:var(--wa-ink-soft); margin-top:8px; }

/* A4 portrait, because that is what these are printed on and then laminated.
   Naming the size stops the browser guessing Letter and reflowing the grid. */
@page{ size:A4 portrait; margin:12mm; }

@media print{
  /* Two to a row, always. Bootstrap's col-md-6 cannot do this: A4 less its margins is
     roughly 700px, below the 768px md breakpoint, so every column falls back to full
     width and you get one card per row. An explicit grid ignores breakpoints entirely. */
  .wa-qrgrid{ display:grid !important; grid-template-columns:repeat(2, 1fr) !important;
              gap:8mm !important; margin:0 !important; }
  .wa-qrgrid > *{ width:auto !important; max-width:none !important; flex:none !important;
                  padding:0 !important; }

  .wa-qrcard{ break-inside:avoid; page-break-inside:avoid; border:1px solid #999 !important;
              box-shadow:none !important; height:auto !important; }
  .wa-qrcard__qr{ max-width:56mm; }
  .wa-qrcard__url{ font-size:7pt; }

  /* Single-card mode, set by the per-card Print button. The marker sits on the COLUMN
     rather than the card, so hiding the siblings needs only a child selector — no
     :has(), and therefore no dependency on a recent browser. */
  body.wa-print-one .wa-qrgrid{ display:block !important; }
  body.wa-print-one .wa-qrgrid > *{ display:none !important; }
  body.wa-print-one .wa-qrgrid > .is-print-one{ display:block !important; margin:0 auto;
                                                max-width:120mm; }
  /* Alone on the page it can afford to be big enough to scan from across a doorway. */
  body.wa-print-one .wa-qrcard__qr{ max-width:88mm; }
  body.wa-print-one .wa-qrcard__url{ font-size:8pt; }
}

/* Thumbnail of the ID card the visitor just chose. Wide rather than square — a
   card is landscape, and a square crop would hide the half with the number on it. */
.wa-idshot{ display:block; margin-top:10px; max-width:280px; width:100%; height:auto;
            border:1px solid var(--wa-line); border-radius:var(--wa-radius-sm); }

/* Walk-in photo capture. The stage keeps a fixed square whatever is inside it —
   video, still, or nothing — so the buttons below do not jump as the state changes. */
.wa-shot{ border:1px solid var(--wa-line); border-radius:var(--wa-radius-sm); padding:14px;
          background:#FCFEFD; }
.wa-shot__stage{ width:100%; max-width:260px; aspect-ratio:1/1; margin:0 auto 12px;
                 border-radius:var(--wa-radius-sm); overflow:hidden; background:#EDF1EF;
                 display:flex; align-items:center; justify-content:center; }
.wa-shot__video, .wa-shot__img{ width:100%; height:100%; object-fit:cover; display:block; }
/* Mirrored ONLY for a selfie, so the preview behaves like a mirror; the CAPTURED still
   is never flipped, because a badge photo that disagrees with the face at the barrier is
   worse than none. A document must not be mirrored at all — reversed text is unreadable,
   and the desk photographing a card with the rear camera has the same problem. */
.wa-shot--selfie .wa-shot__video{ transform:scaleX(-1); }

/* A card is landscape. A square stage would show the visitor a crop that is not what
   gets captured, which is how you end up with half an Aadhaar number. */
.wa-shot--doc .wa-shot__stage{ aspect-ratio:4/3; max-width:340px; }
/* The small confirmation beside a Take-photo button. Fixed size so a row does not
   jump when a picture lands in it. */
.wa-shot__thumb{ width:38px; height:38px; object-fit:cover; border-radius:6px;
                 box-shadow:0 0 0 2px var(--wa-green); flex:0 0 auto; }
.wa-shot__idle{ display:flex; flex-direction:column; align-items:center; gap:6px;
                color:var(--wa-ink-soft); font-size:.76rem; }
.wa-shot__idle i{ font-size:1.6rem; opacity:.5; }
.wa-shot__acts{ display:flex; flex-wrap:wrap; gap:8px; justify-content:center; }

/* Touch targets on the public pages: a gate is not a desk. */
@media (max-width:576px){
  .wa-pub__card{ padding:16px; }
  .wa-pub .form-control, .wa-pub .form-select{ min-height:44px; }
  .wa-shot__acts .btn{ min-height:44px; }
}

/* ------------------------------------------------------------------ modals */
/* Our modals wrap .modal-body + .modal-footer in a <form> so one submit handler
   covers the whole dialog. Bootstrap's scrollable modal assumes .modal-body is a
   direct child of the flex .modal-content, so that extra <form> breaks the chain:
   the body's overflow-y never gets a bounded height and tall forms spill past the
   viewport instead of scrolling. Re-establish the column flow through the form. */
.modal-content > form{ display:flex; flex-direction:column; min-height:0; }
.modal-dialog-scrollable .modal-content > form{ flex:1 1 auto; max-height:100%; overflow:hidden; }
.modal-dialog-scrollable .modal-content > form > .modal-body{ overflow-y:auto; min-height:0; }
.modal-dialog-scrollable .modal-content > form > .modal-footer{ flex:0 0 auto; }

/* Never let a dialog grow taller than the screen, whatever the field count. */
.modal-dialog-scrollable{ max-height:calc(100% - var(--bs-modal-margin, .5rem) * 2); }

/* Active/inactive switch in a table's Action column. Green = the account can sign
   in; grey = it cannot. Sized to sit on the same baseline as the icon buttons. */
.wa-switch{ min-height:auto; padding-left:2.4em; margin:0; }
.wa-switch .form-check-input{
  width:2em; height:1.1em; margin-top:.06em; margin-left:-2.4em; cursor:pointer;
  background-color:#C6D2CB; border-color:#C6D2CB; transition:background-color .18s, border-color .18s;
}
.wa-switch .form-check-input:checked{ background-color:var(--wa-green); border-color:var(--wa-green); }
.wa-switch .form-check-input:focus{ box-shadow:0 0 0 .18rem rgba(0,121,63,.18); border-color:var(--wa-green); }
.wa-switch .form-check-input:disabled{ opacity:.55; cursor:progress; }

/* ------------------------------------------------- select-or-type combo boxes */
/* Tom Select ships a Bootstrap 5 theme; these only pull it onto the Waaree palette
   and match the height of a .form-select so rows stay on one baseline. */
.ts-wrapper{ min-width:0; }
.ts-wrapper .ts-control{
  border:1px solid var(--wa-line); border-radius:var(--wa-radius-sm);
  padding:.42rem .75rem; min-height:calc(1.5em + .84rem + 2px); background:#fff;
}
.ts-wrapper.focus .ts-control{
  border-color:var(--wa-green); box-shadow:0 0 0 .18rem rgba(0,121,63,.15);
}
.ts-dropdown{
  border:1px solid var(--wa-line); border-radius:var(--wa-radius-sm);
  box-shadow:var(--wa-shadow-lg); margin-top:4px; overflow:hidden;
}
.ts-dropdown .active{ background:#EAF5EF; color:var(--wa-green); }
.ts-dropdown .create{ color:var(--wa-ink-soft); }
.ts-dropdown .create strong{ color:var(--wa-green); }
.ts-dropdown .no-results{ padding:8px 12px; color:var(--wa-ink-soft); font-size:.86rem; }
/* The hidden native select must stay in the DOM — it is what serialize() reads. */
.ts-hidden-accessible{ position:absolute !important; opacity:0; height:1px; width:1px; }

/* ------------------------------------------------ invalid field highlighting */
/* Bootstrap's .is-invalid gives the red border; these add the message and make the
   mark survive our own control styling (combo boxes, file inputs, checkboxes). */
.wa-invalid-msg{
  display:block; width:100%; margin-top:.28rem;
  font-size:.8rem; font-weight:500; color:var(--wa-danger);
}
.form-control.is-invalid, .form-select.is-invalid{
  border-color:var(--wa-danger); background-image:none;   /* no icon: it collides with the select caret */
}
.form-control.is-invalid:focus, .form-select.is-invalid:focus{
  border-color:var(--wa-danger); box-shadow:0 0 0 .18rem rgba(220,53,69,.16);
}
.form-check-input.is-invalid{ border-color:var(--wa-danger); }
.form-check-input.is-invalid ~ .form-check-label{ color:var(--wa-danger); }
/* A combo hides its native <select>, so the mark has to reach the visible control. */
.is-invalid + .ts-wrapper .ts-control{ border-color:var(--wa-danger); }

/* A KPI tile that leads somewhere. It is an <a>, so the browser would otherwise
   underline it and paint it link-blue - the card already carries its own colour. */
.wa-kpi--link { display: block; text-decoration: none; color: inherit; cursor: pointer; }
.wa-kpi--link:hover { text-decoration: none; color: inherit; transform: translateY(-1px); }
.wa-kpi--link:focus-visible { outline: 2px solid var(--wa-primary, #00793F); outline-offset: 2px; }

/* Count badge on a quick-range button. Brand green rather than Bootstrap's grey, so
   the number reads as information and not as a disabled control; inverted on the
   selected button, where the green fill would otherwise swallow it. */
.wa-count {
  display: inline-block; margin-left: .4rem; padding: .05rem .4rem;
  font-size: .75em; font-weight: 600; line-height: 1.5; border-radius: 10rem;
  background: var(--wa-primary, #00793F); color: #fff;
}
.wa-count--on { background: #fff; color: var(--wa-primary, #00793F); }

/* The second number on a quick-range chip. People and requests answer different
   questions, so they are told apart by weight rather than by position alone: the head
   count is the filled badge, the request count is outlined and quieter. */
.wa-count--ghost{
  background:transparent; color:var(--wa-primary, #00793F);
  border:1px solid var(--wa-primary, #00793F); margin-left:.25rem;
}
.btn-wa-outline.active .wa-count--ghost{ background:transparent; color:#fff; border-color:rgba(255,255,255,.6); }
.wa-count i{ font-size:.85em; margin-right:.2rem; opacity:.85; }

/* Five chips, each now carrying two figures, must not force a sideways scroll on a
   phone - so they wrap instead of riding in a rigid btn-group. */
.wa-quickset{ display:flex; flex-wrap:wrap; gap:.35rem; }
.wa-quickset .btn{ border-radius:.5rem; }

/* --------------------- Dashboard date-range bar -----------------------
   Three bands stacked in one .wa-filters flex row: the two dates plus their
   actions, then the quick-range chips, then the note. The chips and the note
   each claim a full line (flex-basis:100%) because the chips are far too wide
   to share one - given a column they wrapped anyway and left the note crushed
   into a six-line ribbon down the right-hand gutter.
   --------------------------------------------------------------------- */
.wa-dashfilter{ gap:12px 14px; }
/* .wa-filters sets form-control to width:auto, which sizes a date input to its
   own text and leaves the two boxes visibly different widths as the value
   changes. A floor keeps From and To the same size. */
.wa-filters .wa-dashfilter__date{ min-width:152px; }
.wa-dashfilter .wa-quickset{
  flex:1 0 100%; gap:.4rem; padding-top:11px; margin-top:1px;
  border-top:1px solid var(--wa-line-soft);
}
/* The label and the two count badges sit on one baseline; inline-block leaves
   the icons riding a pixel low against the larger label text. */
.wa-quickset .btn{ display:inline-flex; align-items:center; }
.wa-quickset__label{ font-weight:600; }
.wa-dashfilter__note{
  display:flex; flex-wrap:wrap; align-items:center; gap:2px 10px;
  font-size:.72rem; color:var(--wa-ink-soft); margin:0;
}
.wa-dashfilter__note > i{ opacity:.75; }
/* The icon key is the one part of the note that is a legend rather than a
   sentence, so it is set apart as a chip instead of running on in prose. */
.wa-dashfilter__legend{
  display:inline-flex; align-items:center; gap:.25rem;
  padding:1px 8px; border-radius:10rem;
  background:var(--wa-line-soft); color:var(--wa-ink-soft);
}
@media (max-width:767.98px){
  .wa-filters .wa-dashfilter__date{ min-width:0; }
  .wa-dashfilter .wa-quickset .btn{ flex:1 1 auto; justify-content:center; }
}

/* ---------------------------------------------------------------- EHS card
   Sized to the physical card the plants already buy: 86mm x 54mm, the ID-1
   size, so a printed sheet can be guillotined to match the stock in
   circulation. Emphasis by rule and weight only: office printers drop
   background graphics by default, and a due date that depends on a fill is a
   due date that prints invisible.

   Do NOT hand-version this file. asset() appends its filemtime(), so editing
   it changes its URL by itself. */
.ehssheet { display: flex; flex-wrap: wrap; gap: 6mm; }
.ehscard { width: 86mm; }
.ehscard__face,
.ehscard__back {
  width: 86mm; height: 54mm; box-sizing: border-box; padding: 3mm;
  border: 1px solid #4C4D4F; border-radius: 2mm;
  background-size: cover; background-position: center; background-repeat: no-repeat;
  font-family: Inter, 'Segoe UI', Arial, sans-serif; color: #4C4D4F;
}
.ehscard__back { margin-top: 3mm; }
.ehscard__head { display: flex; justify-content: space-between; align-items: baseline; }
.ehscard__plant { font-weight: 700; font-size: 3mm; color: #00793F; }
.ehscard__no { font-weight: 700; font-size: 3mm; }
.ehscard__title { text-align: center; font-weight: 700; font-size: 3.4mm; margin: 1mm 0; letter-spacing: .3mm; }
.ehscard__body { display: flex; gap: 2mm; }
.ehscard__fields { flex: 1; margin: 0; font-size: 2.5mm; line-height: 1.5; }
.ehscard__fields dt { float: left; clear: left; width: 24mm; font-weight: 600; }
.ehscard__fields dd { margin: 0 0 .6mm 25mm; border-bottom: .2mm solid #9AA3A0; min-height: 3.4mm; }
.ehscard__due { font-weight: 700; }
.ehscard__aside { width: 20mm; display: flex; flex-direction: column; gap: 1mm; }
.ehscard__photo { width: 20mm; height: 24mm; object-fit: cover; border: .2mm solid #4C4D4F; }
.ehscard__photo--none { display: flex; align-items: center; justify-content: center; font-size: 8mm; }
.ehscard__qr { width: 13mm; height: 13mm; align-self: center; }
.ehscard__viol { font-size: 2.2mm; margin-top: 1mm; }
.ehscard__box { display: inline-block; width: 2.4mm; height: 2.4mm; border: .2mm solid #4C4D4F; margin: 0 .8mm 0 2mm; vertical-align: -.2mm; }
.ehscard__tag { text-align: center; font-size: 2.2mm; font-style: italic; margin-top: .8mm; }
/* A worker's card is read at a work front: the due date leads. */
.ehscard--worker .ehscard__due { font-size: 3mm; text-decoration: underline; }
@media print {
  .ehssheet { gap: 4mm; }
  .ehscard { break-inside: avoid; }
}

/* ------------------------------------------------- tables that stop being tables
   For HAND-ROLLED tables only. A DataTables list already collapses through
   responsive:true; these are the ones built by hand — the self-service journey
   legs and the pass list — where six or seven columns at 375px means a
   horizontal scrollbar, and percentage widths crush a <select> to about 40px:
   an arrow, and no room for the plant name it is meant to be showing.

   Below md each row becomes a card and each cell takes its heading from
   data-label, so the header row can be dropped without losing what the values
   mean. A cell with no data-label prints no heading, which is what the action
   column wants.

   Do NOT hand-version this file. asset() appends its filemtime(), so editing
   it changes its URL by itself. */
@media (max-width:767.98px){
  .wa-stack-sm thead{ display:none; }
  .wa-stack-sm,
  .wa-stack-sm tbody,
  .wa-stack-sm tr,
  .wa-stack-sm td{ display:block; width:100%; }

  .wa-stack-sm tr{
    position:relative; background:var(--wa-surface);
    border:1px solid var(--wa-line-soft); border-radius:var(--wa-radius-sm);
    padding:12px 14px; margin-bottom:12px;
  }
  .wa-stack-sm td{ border:0; padding:5px 0; }
  .wa-stack-sm td::before{
    content:attr(data-label); display:block;
    font-size:.68rem; font-weight:700; letter-spacing:.04em; text-transform:uppercase;
    color:var(--wa-ink-soft); margin-bottom:3px;
  }
  .wa-stack-sm td:not([data-label])::before{ display:none; }

  /* Two narrow fields share a line instead of each taking a whole one —
     a start and an end time read as a pair or they read as nothing. */
  .wa-stack-sm td.wa-stack-half{ display:inline-block; width:calc(50% - 5px); }
  .wa-stack-sm td.wa-stack-half + td.wa-stack-half{ margin-left:8px; }

  /* The row's own action belongs in the corner, not on a line of its own. */
  .wa-stack-sm td.wa-stack-act{
    position:absolute; top:8px; right:10px; width:auto; padding:0; text-align:right;
  }

  /* A numbered card, for rows that are steps rather than records. The top
     strip is reserved by the padding above so the number and the remove
     button never sit over the first field. */
  .wa-stack-num tbody{ counter-reset:wastack; }
  .wa-stack-num tr{ counter-increment:wastack; padding-top:36px; }
  .wa-stack-num tr::before{
    content:"Stop " counter(wastack);
    position:absolute; top:11px; left:14px;
    font-size:.68rem; font-weight:700; letter-spacing:.06em; text-transform:uppercase;
    color:var(--wa-green);
  }

  /* A .table-responsive wrapper around a stacked table would keep its own
     scrollbar and clip the cards' rounded corners. */
  .table-responsive:has(> .wa-stack-sm){ overflow:visible; }
}

/* A cell that carries nothing worth a line of its own once the table has
   stacked — a running row number, say, where the row already shows the
   reference that identifies it. */
@media (max-width:767.98px){
  .wa-stack-sm td.wa-stack-hide{ display:none; }
}

/* A file input that should not stretch across a wide desk column, but MUST
   use the whole width once the table has stacked — a control narrower than
   the filename it is showing is worse on a phone than on a desk. Capped by a
   class rather than an inline style, because an inline style cannot be
   relaxed by a media query. */
.wa-file-cap{ max-width:260px; }
@media (max-width:767.98px){
  .wa-stack-sm .wa-file-cap{ max-width:none; width:100%; }
}

/* ---------------------------------------------------------------------------
   SHORTCUT CARDS — the dashboard's own way into the screens a reader can reach.

   Why: a Host's dashboard is a page of numbers about other people's visits with
   nothing on it to act on, and on a phone the screens they actually use sit
   behind the hamburger. These put them one tap away, above the filter, without
   changing what the dashboard is.

   Named .wa-shortcut, NOT .wa-quick — .wa-quickset already exists on this page
   for the date-range chips, and two near-identical names on one screen is how
   the wrong rule gets edited six months from now.

   Permission-driven, never role-driven (see dashboard.php), so Roles &
   Permissions stays the single place navigation is decided.
   --------------------------------------------------------------------------- */
.wa-shortcut{
  display:flex; align-items:center; gap:14px;
  padding:14px 16px; height:100%;
  /* TINTED, NOT WHITE. This row is navigation sitting above a page of data cards;
     sharing their surface made it read as another statistic. The wash is the brand
     green, and the solid 3px leading rule carries the same distinction into
     greyscale print and to a reader who cannot separate the hues. */
  background:linear-gradient(180deg, rgba(0,121,63,.075), rgba(0,121,63,.03));
  border:1px solid rgba(0,121,63,.22);
  border-left:3px solid var(--wa-green);
  border-radius:var(--wa-radius-sm);
  text-decoration:none; color:inherit;
  transition:transform .12s ease, box-shadow .12s ease, background .12s ease;
}
.wa-shortcut:hover{
  text-decoration:none; color:inherit; transform:translateY(-1px);
  background:linear-gradient(180deg, rgba(0,121,63,.13), rgba(0,121,63,.06));
  box-shadow:0 6px 18px rgba(0,121,63,.12);
}
.wa-shortcut:focus-visible{ outline:2px solid var(--wa-green); outline-offset:2px; }

/* The icon carries the colour so the text can stay in ink tokens — a label in a
   series colour is the thing that stops reading as a label. */
.wa-shortcut__icon{
  flex:0 0 42px; width:42px; height:42px; border-radius:12px;
  display:grid; place-items:center;
  background:#fff; color:var(--wa-green); font-size:1.05rem;
  box-shadow:0 1px 3px rgba(0,0,0,.06);
}
.wa-shortcut__body{ min-width:0; }   /* lets the subtitle ellipsis instead of pushing the arrow off */
.wa-shortcut__title{
  margin:0; font-weight:700; font-size:.95rem; color:var(--wa-ink,#4C4D4F); line-height:1.2;
}
.wa-shortcut__sub{
  margin:2px 0 0; font-size:.76rem; color:var(--wa-ink-soft); line-height:1.3;
}
/* Pushed to the far edge rather than floated, so it stays put when the title wraps. */
.wa-shortcut__go{ margin-left:auto; flex:0 0 auto; color:var(--wa-green); }

/* A count only appears when there is something waiting — a permanent "0" is noise
   that teaches people to stop reading the badge. */
.wa-shortcut__count{
  display:inline-block; margin-left:.4rem; padding:.05rem .4rem;
  font-size:.7rem; font-weight:700; line-height:1.5; border-radius:10rem;
  background:#E8A33D; color:#fff;
}

/* ---------------------------------------------------------------------------
   HOST BOX + SECTION LABEL — the invitation form's two halves.

   The form asks for a visitor but is filed against the person raising it, and
   nothing on screen said so. These print the four host facts that were already
   settled before the form opened, so the reader can see what the record will say
   about them without being offered an input that visit_invite.php would ignore.

   Deliberately NOT disabled inputs: a greyed-out field still reads as something
   you failed to fill in. Text in a tinted box reads as a statement.
   --------------------------------------------------------------------------- */
.wa-hostbox{
  background:linear-gradient(180deg, rgba(0,121,63,.055), rgba(0,121,63,.02));
  border:1px solid rgba(0,121,63,.18); border-left:3px solid var(--wa-green);
  border-radius:var(--wa-radius-sm); padding:12px 14px;
}
.wa-hostbox__head{
  font-size:.74rem; font-weight:700; letter-spacing:.04em; text-transform:uppercase;
  color:var(--wa-green); margin-bottom:8px;
}
/* Sits on its own line below md so it never squeezes the heading to one word. */
.wa-hostbox__note{
  display:inline-block; margin-left:.5rem; font-weight:500; letter-spacing:0;
  text-transform:none; color:var(--wa-ink-soft); font-size:.72rem;
}
@media (max-width: 575.98px){
  .wa-hostbox__note{ display:block; margin-left:0; margin-top:2px; }
}
/* auto-fit rather than fixed columns: four facts on a desktop, one on a phone,
   with no breakpoint to keep in step with the number of rows PHP emitted. */
.wa-hostbox__grid{
  display:grid; gap:6px 18px;
  grid-template-columns:repeat(auto-fit, minmax(170px, 1fr));
}
.wa-hostbox__grid > div{ min-width:0; }
.wa-hostbox__grid span{
  display:block; font-size:.7rem; color:var(--wa-ink-soft); text-transform:uppercase;
  letter-spacing:.03em;
}
.wa-hostbox__grid strong{
  display:block; font-size:.88rem; color:var(--wa-ink,#4C4D4F); font-weight:600;
  overflow-wrap:anywhere;        /* an email is one long token and would overflow the cell */
}

/* ---------------------------------------------------------------------------
   NUMBERED SECTION HEADERS — the invitation form, read as four steps.

   A single 21-field form reads as a wall. Numbering the groups turns it into a
   sequence somebody can be halfway through, and the subtitle says what the group
   is FOR so nobody has to infer it from the field names.

   A full-width col-12 inside the existing Bootstrap row rather than a wrapper
   around each group: the row's own gutters keep the rhythm, and the .js-visitor-only
   / .js-temp-only toggles that hide individual fields keep working untouched.
   --------------------------------------------------------------------------- */
.wa-formsec{
  display:flex; align-items:baseline; gap:10px; flex-wrap:wrap;
  margin:6px 0 2px; padding-bottom:9px;
  border-bottom:1px solid var(--wa-line-soft);
}
.wa-formsec__n{
  flex:0 0 auto; width:22px; height:22px; border-radius:50%;
  display:inline-grid; place-items:center; align-self:center;
  background:rgba(0,121,63,.10); color:var(--wa-green);
  font-size:.72rem; font-weight:700; line-height:1;
}
.wa-formsec__n--solid{ background:var(--wa-green); color:#fff; margin-right:8px; }
.wa-formsec__t{
  font-size:.92rem; font-weight:700; color:var(--wa-ink,#4C4D4F); letter-spacing:.01em;
}
/* Pushed to its own line below sm so a long subtitle never squeezes the title. */
.wa-formsec__s{ font-size:.76rem; color:var(--wa-ink-soft); }
@media (max-width: 575.98px){
  .wa-formsec__s{ flex:1 0 100%; margin-left:32px; }
}

/* The host box is step 1, so it carries the same rhythm as the headers below it. */
.wa-hostbox{ padding:14px 16px; }
.wa-hostbox__head{ display:flex; align-items:center; flex-wrap:wrap; margin-bottom:10px; }

/* A required field's asterisk, loud enough to scan for and quiet enough to ignore. */
.req{ color:#DC3545; font-weight:700; }

/* ---------------------------------------------------------------------------
   GROUPED DETAIL BOXES — the request view, read as two sides and a visit.

   A visit has two parties and twenty facts, and in one flat list the reader had
   to know which fact belonged to whom: Host sat between "Coming from" and
   "Purpose", and the plant's own details were threaded through the visitor's.
   Three titled groups answer "who is this person" and "whose guest are they,
   and where do they go" in one glance each.

   Deliberately NOT .wa-hostbox with modifiers: that block is the invitation
   form's step 1 and ten of its rules are tuned for a form. This is its own
   block so restyling one cannot move the other.

   The tint is decoration, never the signal — every group carries a title, so a
   reader who cannot tell the three hues apart loses nothing. Kept at 5-9%
   alpha for the same reason the permit pass avoids fills: a plant desktop
   prints these screens, and a background graphic is the first thing a laser
   drops.
   --------------------------------------------------------------------------- */
/* The two side-by-side groups. minmax(0, 1fr) rather than 1fr, which is really
   minmax(auto, 1fr) and lets a long unbreakable value - an email, a plant name -
   make its column wider than half: that is what had the boxes overlapping at 100%
   zoom while looking fine zoomed out. A grid also stretches its items to equal
   height on its own, and brings none of the negative margins a Bootstrap .row
   sets against the card's own padding. */
.wa-grp-pair{ display:grid; gap:14px; margin-bottom:14px; }
@media (min-width: 1200px){
  .wa-grp-pair{ grid-template-columns:minmax(0, 1fr) minmax(0, 1fr); }
}

/* The accent reads along the TOP, under the heading rather than beside it: a left
   rule competes with the fixed label column for the same edge, and the two
   verticals a few pixels apart read as a seam. */
.wa-grp{
  min-width:0;              /* so a long value shrinks the box instead of bursting it */
  border:1px solid var(--wa-line);
  border-top:3px solid var(--wa-ink-soft);
  border-radius:var(--wa-radius);
  padding:12px 17px 14px;
  box-shadow:0 1px 2px rgba(16,40,28,.035);
}

/* --- the group's title -------------------------------------------------
   The icon in a rounded tile rather than loose beside the words: at .72rem
   an inline glyph sits on a different baseline from the text and reads as a
   stray mark. A tile gives it a box of its own to be centred in. */
.wa-grp__head{
  display:flex; align-items:center; gap:9px;
  font-size:.715rem; font-weight:700; letter-spacing:.055em; text-transform:uppercase;
  color:var(--wa-ink);
  padding-bottom:11px; margin-bottom:5px;
  border-bottom:1px solid var(--wa-line);
}
.wa-grp__head i{
  flex:0 0 auto; width:23px; height:23px; border-radius:8px;
  display:inline-grid; place-items:center;
  font-size:.72rem; line-height:1;
  background:rgba(122,125,128,.12); color:var(--wa-ink-soft);
}

/* --- label / value rows -----------------------------------------------
   A FIXED label column, which is the whole point: every value in every group
   starts at the same x, so the eye runs down one edge instead of hunting for
   where each one begins. Labels above values re-align on every row and that
   is what read as ragged.

   8.5rem is measured off "LAPTOP / EQUIPMENT", the longest label any of the
   three groups emits, at this size and tracking - at 7.5rem it wrapped to two
   lines and left that one row a head taller than its neighbours. A label longer
   still wraps rather than pushing the values out of line, which is the right
   failure: the column edge is the thing worth keeping.

   No row rules. In a multi-column grid :last-child is the last DOM node, not
   the last row of each column, so a hairline either dangles above the box's
   own edge or appears under some columns and not others — there is no nth-child
   arithmetic that survives a group growing a field. Rhythm separates the rows
   instead, and it cannot go wrong. */
/* min(290px, 100%), not a bare 290px: a bare minimum is a FLOOR, so on a phone the
   single column still demanded 290px inside a ~270px box and overflowed it. The
   min() lets the one column give up the minimum when there is not room for it,
   while two columns still need 290px each to appear. */
.wa-kv{
  display:grid; gap:0 30px;
  grid-template-columns:repeat(auto-fit, minmax(min(290px, 100%), 1fr));
}
.wa-kv > div{
  display:grid; grid-template-columns:8.5rem minmax(0, 1fr);
  align-items:baseline; gap:3px 14px;
  padding:7px 0; min-width:0;
}
.wa-kv > div > span{
  font-size:.665rem; font-weight:600; letter-spacing:.06em; text-transform:uppercase;
  color:var(--wa-ink-soft); padding-top:.12rem;
}
.wa-kv > div > strong{
  font-size:.9rem; font-weight:600; color:var(--wa-ink); min-width:0;
  overflow-wrap:anywhere;        /* an email is one long token and would overflow */
}
/* Below sm the label column would leave ~60px for the value, so the pair
   stacks and the label simply sits above what it names. */
@media (max-width: 575.98px){
  .wa-kv > div{ grid-template-columns:1fr; gap:1px; }
  .wa-kv > div > span{ padding-top:0; }
}

/* The host's department and address, under their name rather than beside it:
   a name, a department and an email joined by separators is one line that
   wraps mid-address. Each is its own line, tight against the name so the three
   read as one person and not as three facts.

   text-transform and letter-spacing are reset explicitly. These sit inside the
   value, and without the reset they inherited the LABEL's own uppercase — which
   is how an email came out reading YOGESHAMANE@WAAREE.COM. */
.wa-kv__sub{
  display:block; margin-top:1px;
  font-weight:500; font-size:.785rem; color:var(--wa-ink-soft);
  text-transform:none; letter-spacing:normal; overflow-wrap:anywhere;
}
/* An address is case-insensitive in the part that routes it, and every address
   in `users` is stored lower — so lowercase here is what is on file, and it
   also means no stored stray capital reaches the screen as one. */
.wa-kv__mail{ text-transform:lowercase; }

.wa-grp--host{
  background:linear-gradient(180deg, rgba(0,121,63,.055), rgba(0,121,63,.015));
  border-color:rgba(0,121,63,.17); border-top-color:var(--wa-green);
}
.wa-grp--host .wa-grp__head{ color:var(--wa-green); border-bottom-color:rgba(0,121,63,.14); }
.wa-grp--host .wa-grp__head i{ background:rgba(0,121,63,.11); color:var(--wa-green); }

.wa-grp--visitor{
  background:linear-gradient(180deg, rgba(232,163,61,.08), rgba(232,163,61,.022));
  border-color:rgba(232,163,61,.25); border-top-color:var(--wa-warning);
}
.wa-grp--visitor .wa-grp__head{ color:#9A6714; border-bottom-color:rgba(232,163,61,.22); }
.wa-grp--visitor .wa-grp__head i{ background:rgba(232,163,61,.16); color:#9A6714; }

/* SLATE BLUE, not the brand teal it started as. At the 5% alpha these tints live
   at, teal and the host box's green were the same pale mint and the third group
   looked like a continuation of the first. Blue is the one hue that separates
   cleanly from BOTH green and amber, which is the whole job of the third tint.
   It is also the right register for this box: these are the visit's own facts,
   belonging to neither party. */
.wa-grp--visit{
  background:linear-gradient(180deg, rgba(61,111,166,.075), rgba(61,111,166,.02));
  border-color:rgba(61,111,166,.22); border-top-color:#3D6FA6;
}
.wa-grp--visit .wa-grp__head{ color:#2C5B8C; border-bottom-color:rgba(61,111,166,.2); }
.wa-grp--visit .wa-grp__head i{ background:rgba(61,111,166,.13); color:#2C5B8C; }

/* --- the one row that holds a control --------------------------------
   A <select> is about twice the height of a line of text, so this row centres
   its two cells instead of sitting them on a shared baseline: baselined, the
   label dropped towards the bottom of a tall row and read as belonging to
   nothing. Tighter vertical padding too, because the control brings its own.

   The picker is capped rather than filling the column - a full-width input on a
   screen of facts reads as a form - but 15rem leaves "Without mobile cover"
   room to sit on one line.

   padding-right is restored because the shared .form-control/.form-select rule
   up at the top of this file sets padding:.55rem .8rem, which OVERRIDES the
   2.25rem Bootstrap reserves on a select for its arrow - so the caret is drawn
   against the last letter. .wa-filters carries the same correction for the same
   reason; this is the second instance, not a new quirk. */
.wa-kv > div.wa-kv__ctl{ align-items:center; padding:4px 0; }
/* width:auto lets the browser size the select to its widest OPTION, which is the
   only measurement that cannot clip: a fixed 15rem cut "Without mobile cover"
   mid-word once the shared .form-select font-size and the -sm padding were both
   in play. max-width keeps it inside its column on a phone. */
.wa-kv__ctl .js-cover{ width:auto; max-width:100%; padding-right:2.2rem; }

/* Printing a request is how a desk hands one to a guard. Tints and gradients
   are dropped by most printers anyway, so say so and keep the rules, which are
   what still separates the groups on paper. */
@media print{
  .wa-grp{ background:none !important; border-top-width:2px; box-shadow:none; }
  .wa-grp__head i{ background:none; }
}

/* ---------------------------------------------------------------------------
   PUBLIC FORM FLOW — visit/form.php and visit/walkin.php, single column.

   These two are the same job (a stranger, on a phone, standing up, filling a
   long form once) and they are now the same layout. One column of section
   cards, each numbered, read top to bottom: nothing beside anything, nothing
   to scan back up to, and on a phone no second column waiting to be reached.

   It replaces a two-column rail. The rail filled a desktop nicely and was the
   wrong shape for the device these forms are actually opened on - and a fact
   panel pinned beside the form is a fact panel nobody reads.
   --------------------------------------------------------------------------- */

/* SINGLE COLUMN, enforced here rather than in forty class attributes across two
   files and a JS-built template. Every grid column inside the flow goes full
   width, so a field added later cannot quietly arrive as a half. The .row keeps
   its own vertical gutter, which is what still spaces them. */
.wa-pub__flow .row > [class*="col-"]{ flex:0 0 100%; max-width:100%; }

/* Each section IS the card now; the page is the gap between them. A top rule in
   the brand green rather than a left one, matching the request view. */
.wa-pub__flow .wa-pub__section{
  background:#fff; border:1px solid var(--wa-line); border-top:3px solid var(--wa-green);
  border-radius:var(--wa-radius); box-shadow:var(--wa-shadow);
  padding:18px 20px; margin:0 0 16px;
}
/* The shared .wa-pub__section rules draw a hairline between sections inside one
   card. There is no "between" any more. */
.wa-pub__flow .wa-pub__section,
.wa-pub__flow .wa-pub__section:first-of-type{ border-top-width:3px; padding-top:18px; margin-top:0; }
.wa-pub__flow .wa-pub__section h3{
  margin:0 0 15px; padding-bottom:12px; border-bottom:1px solid var(--wa-line-soft);
}

/* The facts the visitor cannot change: reference, where, when, how many. At the
   TOP, where they answer "is this the right link" before anything is typed -
   not in a sidebar, and not repeated beside every field. */
.wa-pub__factbar{
  display:grid; gap:12px 20px; grid-template-columns:repeat(auto-fit, minmax(min(150px, 100%), 1fr));
  padding:15px 18px; margin:0 0 16px;
  background:linear-gradient(170deg, rgba(0,121,63,.06), rgba(0,121,63,.02));
  border:1px solid rgba(0,121,63,.16); border-top:3px solid var(--wa-green);
  border-radius:var(--wa-radius);
}
.wa-pub__factbar > div{ min-width:0; }
.wa-pub__factbar dt, .wa-pub__factbar span{
  display:block; font-size:.645rem; font-weight:600; letter-spacing:.08em;
  text-transform:uppercase; color:var(--wa-ink-soft);
}
.wa-pub__factbar dd, .wa-pub__factbar strong{
  display:block; margin:2px 0 0; font-size:.86rem; font-weight:700; color:var(--wa-green);
  overflow-wrap:anywhere;
}

/* FULL WIDTH ON A PHONE. The cards lose their side borders and corners and run
   to the gutter, so the field inside gets every pixel of a 360px screen instead
   of 360 minus two paddings minus two borders. */
@media (max-width: 575.98px){
  .wa-pub__body{ padding:14px 12px 30px; }
  .wa-pub__flow .wa-pub__section{
    padding:15px 14px; margin-bottom:12px; border-radius:12px;
  }
  .wa-pub__factbar{ padding:13px 14px; border-radius:12px; gap:10px 14px; }
  .wa-pub__flow .wa-person{ padding:13px 12px; }
  .wa-pub__flow .wa-pub__section h3{ margin-bottom:13px; }
}

/* A single column has no use for 1100px, and an input that wide stops reading as
   an input. Wide enough to feel like the page, narrow enough to fill in. */
@media (min-width: 992px){
  .wa-pub__body:has(.wa-pub__flow){ max-width:900px; }
}
/* Same ceiling without :has(), for anything that does not support it: the flow
   pages are the only ones that set this class on the form wrapper. */
.wa-pub__flow{ width:100%; max-width:900px; margin:0 auto; }

/* The photograph already on file for a returning worker, shown in their row on the
   desk form. Small on purpose: it is there for the desk to check a face against the
   man in front of them, not to be looked at, and the row is five controls wide
   already. Capturing a new one stays optional - contract_submit.php carries this one
   onto the new pass when nothing is uploaded. */
.wa-wphoto{
  width:38px; height:46px; object-fit:cover; border-radius:6px;
  border:1px solid var(--wa-line); background:#F6F9F7; display:block;
}

/* The camera button and its Browse fallback, stacked beside the thumbnail inside a
   two-column cell. Browse is a link rather than a second button because it is the
   fallback, not the choice: at a gate the camera is what gets used. */
.wa-wphoto__acts{ display:flex; flex-direction:column; align-items:flex-start; gap:1px; min-width:0; }
.wa-wphoto__acts .js-wbrowse{ font-size:.7rem; text-decoration:none; }
.wa-wphoto__acts .js-wbrowse:hover{ text-decoration:underline; }

/* "No photograph on file", which is the usual state: 70 of 725 worker person rows
   carry one. Same box as the thumbnail so the row does not change height when one
   appears, and a muted glyph rather than an empty cell — blank reads as still
   loading. */
.wa-wphoto--none{
  display:flex; align-items:center; justify-content:center;
  color:#B9C4BD; background:#F6F9F7; font-size:.9rem;
}

/* --- the rest of a walk-in party -------------------------------------
   One block per extra person on visit/walkin.php. Lighter than the lead visitor's
   four sections because it asks for less: a name is required, an ID and a photograph
   are offered. It has to read as a repeated unit rather than as more of the same
   form, which a tinted head and a hairline do in two rules. */
.wa-other{
  border:1px solid var(--wa-line); border-top:2px solid var(--wa-green);
  border-radius:var(--wa-radius-sm); padding:14px 16px; margin-bottom:12px; background:#fff;
}
.wa-other__head{
  display:flex; align-items:center; justify-content:space-between; gap:10px;
  padding-bottom:10px; margin-bottom:13px; border-bottom:1px solid var(--wa-line-soft);
}
.wa-other__no{
  display:inline-flex; align-items:center; gap:8px;
  font-size:.72rem; letter-spacing:.09em; text-transform:uppercase; font-weight:700;
  color:var(--wa-green);
}
.wa-other__no::before{
  content:''; flex:0 0 auto; width:7px; height:7px; border-radius:50%; background:var(--wa-green);
}
@media (max-width: 575.98px){
  .wa-other{ padding:13px 13px; border-radius:12px; }
}

/* --- the rest of a walk-in party, on the allocation panel ------------------
   The lead visitor has a camera stage above; these are the people who arrived with
   them, whose photograph and ID the desk may capture and usually has to. Boxed and
   tinted so the panel reads as "the visitor, then the others" rather than as one long
   column of file inputs. */
.wa-allocparty{
  margin:0 0 14px; padding:11px 12px;
  background:linear-gradient(180deg, rgba(0,121,63,.045), rgba(0,121,63,.015));
  border:1px solid rgba(0,121,63,.16); border-radius:var(--wa-radius-sm);
}
.wa-allocparty__head{
  font-size:.72rem; font-weight:700; letter-spacing:.04em; text-transform:uppercase;
  color:var(--wa-green); margin-bottom:9px;
}
.wa-allocparty__head .text-muted{ font-weight:500; letter-spacing:0; text-transform:none; }
.wa-allocperson{
  background:#fff; border:1px solid var(--wa-line); border-radius:9px;
  padding:9px 10px; margin-bottom:8px;
}
.wa-allocperson:last-child{ margin-bottom:0; }
.wa-allocperson__who{ display:flex; align-items:flex-start; gap:10px; }
.wa-allocperson__who strong{ font-size:.88rem; display:block; overflow-wrap:anywhere; }
/* So a long name shortens instead of pushing the thumbnail out of the box. */
.wa-allocperson .min-w-0{ min-width:0; }

/* The period picker on the courier register. Wide enough for its longest option plus
   the caret - at the shared .form-select width "Last 30 days" was clipped mid-word,
   which reads as a bug in the data rather than in the box. */
.wa-period{ min-width:9.5rem; }
