/* =====================================================================
   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); } }
/* The title takes the slack, so everything after it sits hard right whatever is
   rendered. The push used to live on the notification bell alone - and a Manager
   or Viewer has no notifications.view, so for them nothing pushed and the user
   menu sat against the page title. margin-right:auto on a flex child is the only
   part of this that has to be true. */
.wa-topbar__title{ font-weight:670; font-size:1.02rem; color:var(--wa-green); margin:0 auto 0 0;
  letter-spacing:-.01em; min-width:0; overflow:hidden; text-overflow:ellipsis; white-space:nowrap; }
.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; }
.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;
}
.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%; }
}

/* ------------------------------ 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' Bootstrap 5 integration renders the active page as
   .paginate_button.page-item.active > .page-link, so a rule on
   .paginate_button.current never matched and every list page paginated in
   Bootstrap blue. Same for the settings tabs, which had no brand rule at
   all. */
.dataTables_wrapper .dataTables_paginate .paginate_button.current,
.dataTables_wrapper .dataTables_paginate .page-item.active > .page-link{
  background:var(--wa-green)!important; border-color:var(--wa-green)!important; color:#fff!important; border-radius:6px;
}
.dataTables_wrapper .dataTables_paginate .page-link{ color:var(--wa-green); }
.dataTables_wrapper .dataTables_paginate .page-link:focus{ box-shadow:0 0 0 .2rem rgba(0,121,63,.18); }
.nav-tabs .nav-link,.nav-pills .nav-link{ color:var(--wa-green); }
.nav-pills .nav-link.active,.nav-pills .show > .nav-link{
  background-color:var(--wa-green); color:#fff;
}
.nav-tabs .nav-link.active{ color:var(--wa-green); border-bottom-color:transparent; font-weight:600; }
.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; }
/* Below sm the dom layout's col-sm-6 columns stack, so the length menu, the
   export buttons and the search each get a line. Left alone, .dt-buttons is
   an inline block in a narrow column and its buttons wrap one per row - which
   is what put Excel above Print with the search adrift beside them. Make the
   buttons a nowrap flex row pinned right of the length menu, and give the
   search the full width it already assumes. */
@media (max-width:575.98px){
  .dataTables_wrapper .dataTables_length{ flex:0 0 auto; }
  /* 301px of room against 320px of controls, so Print was clipped. The words
     "per page" cost 63px of that; the select already reads "25" beside a
     table. font-size:0 hides the wording visually but leaves it in the
     accessibility tree, where it is the only thing naming the control. */
  .dataTables_wrapper .dataTables_length label{ font-size:0; gap:0; }
  .dataTables_wrapper .dataTables_length select{ font-size:.84rem; }
  .dataTables_wrapper .dt-buttons{
    display:flex; flex:1 1 auto; justify-content:flex-end; gap:8px; margin:0;
  }
  .dataTables_wrapper .dt-buttons .btn{ margin-right:0; white-space:nowrap; }
  .dataTables_wrapper .dataTables_filter{ text-align:left; margin-top:10px; }
  .dataTables_wrapper .dataTables_filter label{ width:100%; }
  .dataTables_wrapper .dataTables_filter input{ width:100%; min-width:0; }

  /* Two KPI tiles per row leaves ~165px each. At the full padding and a 46px
     chip the label and the chip cannot both fit, and overflow:hidden clipped
     the chip rather than letting it show. */
  .wa-kpi{ padding:16px 16px 14px; }
  .wa-kpi__top{ gap:8px; }
  .wa-kpi__icon{ width:38px; height:38px; flex:0 0 38px; border-radius:11px; font-size:.95rem; }
  .wa-kpi__value{ font-size:1.8rem; }

  /* Pagination is a flex row that cannot shrink past its buttons, so a table
     with several pages pushed Next past the card edge. Let it wrap. */
  .dataTables_wrapper .dataTables_paginate .pagination{ flex-wrap:wrap; justify-content:flex-start; }
}

/* Below 360px two KPI tiles per row leaves ~140px each, which cannot hold the
   label and the chip side by side at any sane size. One per row instead: the
   markup is col-6 from the dashboard script, so the width is overridden here
   rather than by branching the JS. */
@media (max-width:359.98px){
  #kpiRow > [class*="col-"]{ flex:0 0 100%; max-width:100%; }
}

/* Action cells keep their buttons on one line. A td wraps between inline-block
   buttons like any other content, which split four icons across two rows and
   left the column looking broken. Sized down on a phone, where the column has
   to share the row with the record it acts on. */
td.wa-actions{ white-space:nowrap; text-align:left; }
td.wa-actions .btn{ margin:0 4px 0 0; vertical-align:middle; }
td.wa-actions .btn:last-child{ margin-right:0; }
@media (max-width:575.98px){
  td.wa-actions .btn{ padding:.22rem .42rem; margin-right:3px; font-size:.78rem; }
}

/* Roster pick lists. People, shifts and checkpoints are all multi-select, and a
   save writes one assignment per combination - so all three use the same
   scrolling tick list rather than a <select multiple>, which is unusable on a
   phone and hides what is selected. */
.wa-picklist{ max-height:200px; overflow:auto; }
.wa-roster-sum:empty{ display:none; }
.wa-roster-sum{ font-size:.85rem; border-radius:12px; padding:10px 12px;
  background:rgba(0,121,63,.07); color:var(--wa-green); border:1px solid rgba(0,121,63,.18); }
.wa-roster-sum.is-over{ background:rgba(193,50,43,.07); color:#C1322B; border-color:rgba(193,50,43,.26); }
.wa-roster-sum__warn{ display:block; margin-top:6px; color:#8A5200; font-weight:500; }
.wa-roster-sum.is-over .wa-roster-sum__warn{ color:#C1322B; }

/* 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; }
/* 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;
  /* A light brand tint over the photograph, plus a gentle vignette that settles
     the edges. Light on purpose: the photograph is the backdrop, not something
     to be hidden.

     The scrim here does NOT carry any text contrast. Every word on this screen
     sits on the brand panel or on the white form card, each of which owns an
     opaque background — see .wa-auth__brand, which is what actually keeps the
     white feature list legible. Earlier versions ran this up to .74/.76 as if
     it were protecting something, and the result was a near-black sheet with
     the photograph lost behind it.

     NOT background-attachment:fixed. Fixed sizes `cover` against the viewport
     rather than the element, so a tall narrow phone cropped the image to a
     sliver and stacked both gradients over it; it is also long broken on iOS
     Safari. */
  background-image:
    radial-gradient(130% 100% at 50% 40%, rgba(2,26,18,.00) 0%, rgba(2,26,18,.10) 60%, rgba(1,18,12,.30) 100%),
    linear-gradient(118deg, rgba(3,34,23,.34) 0%, rgba(0,96,50,.22) 52%, rgba(14,154,138,.18) 100%),
    var(--wa-auth-image);
  background-size:cover, cover, cover;
  background-position:center, center, center;
  background-repeat:no-repeat, no-repeat, no-repeat;
}
.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 — and evenly so. The
     second stop used to fall to .62, which let a bright patch of the photo
     lift the bottom of the panel exactly where the feature list sits. */
  background:linear-gradient(160deg, rgba(2,26,17,.84), rgba(4,52,34,.78));
  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; }
}

/* 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; } }

/* ---------------------------------------------------------- patrol: my round */
/* Big tap targets and high-contrast state colours: this screen is used
   one-handed, at 2 AM, on a gate, often in the rain. */
.wa-round__head{display:flex;flex-wrap:wrap;gap:12px;align-items:center;justify-content:space-between;margin-bottom:16px}
.wa-round__stats{display:grid;grid-template-columns:repeat(3,1fr);gap:10px;margin-bottom:16px}
.wa-stat{border-radius:16px;padding:14px 12px;text-align:center;border:1px solid var(--wa-line);
  background:linear-gradient(180deg,#fff,#fcfdfc);
  box-shadow:0 1px 0 rgba(16,24,40,.04),0 12px 28px -18px rgba(16,24,40,.35)}
.wa-stat__n{display:block;font-size:1.65rem;font-weight:700;font-variant-numeric:tabular-nums;line-height:1}
.wa-stat__l{display:block;font-size:.74rem;text-transform:uppercase;letter-spacing:.04em;color:var(--wa-ink-soft);margin-top:4px}
.wa-stat.is-done   .wa-stat__n{color:var(--wa-green)}
.wa-stat.is-due    .wa-stat__n{color:#B26A00}
.wa-stat.is-missed .wa-stat__n{color:#C1322B}

/* Card lists are a responsive grid, not a single stacked column.
   A guard's round is twelve checkpoints; one per row wastes the whole width of
   a desktop or tablet and pushes the bottom of the round below the fold.
   auto-fill with a min() floor gives one column on a phone and as many as fit
   above that, with no breakpoints to maintain. */
/* A day can span more than one shift - a Section Incharge is rostered across
   A, B and C - so the round is drawn one block per shift. The block header is
   the only place a shift is named; the page header carries the date, because
   labelling the whole list with the shift that happens to be running now is
   wrong for anyone who patrols more than one. */
.wa-round__shift{display:flex;flex-wrap:wrap;align-items:baseline;gap:10px;
  margin:22px 0 10px;padding-bottom:8px;border-bottom:1px solid var(--wa-line-soft)}
.wa-round__shift:first-child{margin-top:0}
.wa-round__shift-name{font-weight:700;font-size:.98rem;color:var(--wa-ink)}
.wa-round__shift-count{margin-left:auto;font-size:.8rem;font-variant-numeric:tabular-nums;
  color:var(--wa-ink-soft)}
.wa-round__shift-now{font-size:.68rem;font-weight:700;text-transform:uppercase;letter-spacing:.04em;
  color:var(--wa-green);background:rgba(0,121,63,.09);border:1px solid rgba(0,121,63,.18);
  border-radius:999px;padding:2px 9px;box-shadow:inset 0 1px 0 rgba(255,255,255,.6)}
.wa-round__shift.is-running .wa-round__shift-name{color:var(--wa-green)}

.wa-round__list{display:grid;grid-template-columns:repeat(auto-fill,minmax(min(100%,320px),1fr));
  gap:12px;align-items:stretch}
.wa-cp{display:flex;align-items:center;gap:12px;padding:14px 16px;border-radius:16px;text-decoration:none;
  border:1px solid var(--wa-line);background:#fff;color:var(--wa-ink);min-height:72px;height:100%;
  min-width:0;
  box-shadow:0 1px 0 rgba(16,24,40,.04),0 14px 30px -20px rgba(16,24,40,.4);
  transition:transform .14s ease,box-shadow .14s ease}
.wa-cp:active{transform:scale(.995)}
.wa-cp__icon{font-size:1.5rem;flex:0 0 auto}
.wa-cp__thumb{width:56px;height:56px;object-fit:cover;border-radius:12px;flex:0 0 auto;border:1px solid var(--wa-line)}
.wa-cp__body{flex:1 1 auto;min-width:0}
.wa-cp__name{display:block;font-weight:600;font-size:1.02rem;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.wa-cp__sub{display:block;font-size:.82rem;color:var(--wa-ink-soft)}
.wa-cp__badge{flex:0 0 auto;font-size:.72rem;font-weight:600;padding:5px 10px;border-radius:999px;
  text-transform:uppercase;letter-spacing:.03em;white-space:nowrap}
.wa-cp.is-done     .wa-cp__icon{color:var(--wa-green)}
.wa-cp.is-done     .wa-cp__badge{background:rgba(0,121,63,.10);color:var(--wa-green)}
.wa-cp.is-due      .wa-cp__icon{color:#B26A00}
.wa-cp.is-due      .wa-cp__badge{background:rgba(178,106,0,.12);color:#B26A00}
.wa-cp.is-due{border-color:rgba(178,106,0,.35)}
.wa-cp.is-missed   .wa-cp__icon{color:#C1322B}
.wa-cp.is-missed   .wa-cp__badge{background:rgba(193,50,43,.10);color:#C1322B}
.wa-cp.is-missed{border-color:rgba(193,50,43,.3)}
.wa-cp.is-upcoming .wa-cp__icon{color:var(--wa-ink-soft)}
.wa-cp.is-upcoming .wa-cp__badge{background:rgba(76,77,79,.08);color:var(--wa-ink-soft)}

@media (prefers-reduced-motion:reduce){.wa-cp{transition:none}}

/* ---------------------------------------------------------- patrol: punch */
.wa-punch{max-width:520px;margin:0 auto;padding-bottom:32px}

.wa-gate{display:flex;align-items:center;justify-content:center;min-height:60vh}
.wa-gate__card{background:#fff;border:1px solid var(--wa-line);border-radius:20px;padding:28px 22px;text-align:center;
  box-shadow:0 1px 0 rgba(16,24,40,.04),0 24px 48px -28px rgba(16,24,40,.45);width:100%}
.wa-gate__icon{font-size:2.6rem;color:#B26A00}
.wa-gate__title{font-size:1.3rem;font-weight:700;margin:12px 0 6px}
.wa-gate__msg{color:var(--wa-ink-soft);margin-bottom:14px}
.wa-gate__steps{text-align:left;background:var(--wa-bg);border-radius:12px;padding:12px 14px;font-size:.86rem;margin-bottom:16px}
.wa-gate__steps ol{padding-left:18px}

.wa-acq{text-align:center;padding:48px 16px}
.wa-acq__ring{width:92px;height:92px;margin:0 auto 18px;border-radius:50%;display:grid;place-items:center;
  font-size:2rem;color:var(--wa-green);background:rgba(0,121,63,.08);
  box-shadow:0 0 0 0 rgba(0,121,63,.35);animation:waPulse 1.8s ease-out infinite}
@keyframes waPulse{to{box-shadow:0 0 0 26px rgba(0,121,63,0)}}
@media (prefers-reduced-motion:reduce){.wa-acq__ring{animation:none}}
.wa-acq__msg{font-weight:600;margin-bottom:2px}
.wa-acq__sub{color:var(--wa-ink-soft);font-size:.88rem}

.wa-chip-cp{display:flex;align-items:center;gap:10px;padding:14px 16px;border-radius:16px;font-weight:600;margin-bottom:10px}
.wa-chip-cp.is-in{background:rgba(0,121,63,.10);color:var(--wa-green);border:1px solid rgba(0,121,63,.28)}
.wa-chip-cp.is-out{background:rgba(193,50,43,.08);color:#C1322B;border:1px solid rgba(193,50,43,.26)}
.wa-chip-cp__name{flex:1 1 auto;font-size:1.05rem}
.wa-chip-cp__dist{font-size:.82rem;font-weight:600;opacity:.85;font-variant-numeric:tabular-nums}

.wa-acc{display:flex;align-items:center;justify-content:space-between;gap:10px;font-size:.85rem;
  padding:8px 12px;border-radius:12px;margin-bottom:12px}
.wa-acc.is-ok{background:rgba(0,121,63,.07);color:var(--wa-green)}
.wa-acc.is-poor{background:rgba(178,106,0,.1);color:#B26A00}

/* The preview is a framing aid, not the point of the screen - Take photo is.
   At 3/4 on a 375px phone the preview alone is 500px tall, which pushed the
   capture button and the Normal/Abnormality choice below the fold: a guard
   had to scroll before they could shoot. Cap it against the viewport so the
   actions are always in the first view, and let object-fit:cover crop the
   feed rather than letterbox it. The reserve covers the topbar, checkpoint
   chip, accuracy row, capture button and status row. dvh tracks the mobile
   browser chrome as it hides and shows; vh is the fallback for older
   WebKit. On a tall phone the aspect ratio is still the smaller value and
   nothing changes. */
.wa-cam{position:relative;border-radius:18px;overflow:hidden;background:#111;aspect-ratio:3/4;
  max-height:calc(100vh - 320px);
  max-height:calc(100dvh - 320px);
  /* Capping the height makes the browser shrink the width too, to hold the
     3/4 ratio - so the block is narrower than the column and would sit left
     against it. Centre it. */
  min-height:180px;margin:0 auto 12px}
.wa-cam video,.wa-cam img{width:100%;height:100%;object-fit:cover;display:block}
.wa-cam__fallback{position:absolute;inset:0;display:grid;place-content:center;gap:8px;text-align:center;
  color:#fff;padding:24px;background:#111}
.wa-cam__fallback i{font-size:2.2rem}

.wa-punch__actions{display:flex;flex-direction:column;gap:8px}

.wa-status{display:grid;grid-template-columns:1fr 1fr;gap:10px;margin-top:16px}
.wa-status__opt{border:1px solid var(--wa-line);background:#fff;border-radius:14px;padding:14px 10px;
  font-weight:600;color:var(--wa-ink-soft);display:flex;align-items:center;justify-content:center;gap:8px;
  min-height:56px;transition:background .15s ease,border-color .15s ease,color .15s ease}
.wa-status__opt[data-status="normal"].is-active{background:rgba(0,121,63,.10);border-color:rgba(0,121,63,.4);color:var(--wa-green)}
.wa-status__opt[data-status="abnormal"].is-active{background:rgba(193,50,43,.10);border-color:rgba(193,50,43,.4);color:#C1322B}
.wa-status__opt:focus-visible{outline:2px solid var(--wa-green);outline-offset:2px}
@media (prefers-reduced-motion:reduce){.wa-status__opt{transition:none}}

/* A punch that completed no visit. Amber, not red: the punch was saved and
   nothing is broken - it simply counted towards nothing, and the officer
   needs to know that rather than see an unchanged round. */
.wa-unmatched{border:1px solid rgba(178,106,0,.3);background:rgba(178,106,0,.06);
  border-radius:16px;padding:14px 16px;margin-bottom:16px}
.wa-unmatched__head{font-weight:700;color:#8A5200;display:flex;align-items:center;gap:8px;
  font-size:.95rem;margin-bottom:8px}
.wa-unmatched__list{list-style:none;margin:0;padding:0;display:flex;flex-direction:column;gap:8px}
.wa-unmatched__row{font-size:.9rem;color:var(--wa-ink);font-variant-numeric:tabular-nums}
.wa-unmatched__why{display:block;font-size:.8rem;color:var(--wa-ink-soft);margin-top:2px;
  font-variant-numeric:normal}
.wa-unmatched__foot{font-size:.78rem;color:var(--wa-ink-soft);margin:10px 0 0}

.wa-done{text-align:center;padding:48px 16px}
.wa-done__icon{font-size:3.4rem;color:var(--wa-green)}
.wa-done__title{font-size:1.4rem;font-weight:700;margin:12px 0 6px}
.wa-done__msg{color:var(--wa-ink-soft);margin-bottom:22px}

/* ---------------------------------------------------------- notification bell */
.wa-bell{position:relative}
.wa-bell__btn{position:relative;border:0;background:transparent;font-size:1.15rem;color:var(--wa-ink);padding:6px 10px;border-radius:10px}
.wa-bell__btn:focus-visible{outline:2px solid var(--wa-green);outline-offset:2px}
.wa-bell__dot{position:absolute;top:2px;right:2px;min-width:18px;height:18px;padding:0 5px;border-radius:999px;
  background:#C1322B;color:#fff;font-size:.66rem;font-weight:700;line-height:18px;text-align:center;
  box-shadow:0 0 0 2px #fff}
.wa-bell__menu{width:min(360px,calc(100vw - 24px));padding:0;overflow:hidden;border-radius:14px}
.wa-bell__head{display:flex;align-items:center;justify-content:space-between;padding:10px 14px;border-bottom:1px solid var(--wa-line-soft)}
.wa-bell__list{max-height:340px;overflow:auto}
.wa-bell__item{display:block;padding:10px 14px;border-bottom:1px solid var(--wa-line-soft);text-decoration:none;color:var(--wa-ink)}
.wa-bell__item.is-unread{background:rgba(0,121,63,.05)}
.wa-bell__item:hover{background:var(--wa-bg)}
.wa-bell__title{display:block;font-weight:600;font-size:.9rem}
.wa-bell__body{display:-webkit-box;font-size:.8rem;color:var(--wa-ink-soft);
  -webkit-line-clamp:2;-webkit-box-orient:vertical;overflow:hidden}
.wa-bell__when{display:block;font-size:.72rem;color:var(--wa-ink-soft);margin-top:2px}
.wa-bell__empty{padding:22px 14px;text-align:center;color:var(--wa-ink-soft);font-size:.88rem}

/* Report row thumbnail — the photo column in the daily detail report. */
.wa-thumb{width:48px;height:48px;object-fit:cover;border-radius:10px;border:1px solid var(--wa-line)}

/* Compliance bar — a percentage read at a glance, colour before number. */
.wa-bar{display:inline-block;vertical-align:middle;width:92px;height:8px;border-radius:999px;
  background:rgba(76,77,79,.12);overflow:hidden;margin-right:8px}
.wa-bar__fill{display:block;height:100%;border-radius:999px}
.wa-bar__n{font-variant-numeric:tabular-nums;font-weight:600;font-size:.86rem}

/* Coverage heatmap — day rows, hour columns. */
.wa-heat{border-collapse:separate;border-spacing:2px;font-size:.7rem;width:100%}
.wa-heat th{font-weight:600;color:var(--wa-ink-soft);text-align:center;padding:2px 4px;white-space:nowrap}
.wa-heat tbody th{text-align:right;padding-right:8px}
.wa-heat td{width:3.4%;height:22px;text-align:center;border-radius:4px;color:#fff;
  font-variant-numeric:tabular-nums;background:rgba(76,77,79,.06)}

/* Live map — Leaflet needs an explicitly sized box or it collapses to 0px. */
.wa-map{height:min(70vh,640px);border-radius:14px;overflow:hidden;border:1px solid var(--wa-line)}
.wa-dot{display:inline-block;width:10px;height:10px;border-radius:50%;margin-right:4px;vertical-align:middle;
  box-shadow:0 0 0 2px #fff}
.wa-dot--in{background:#00793F}
.wa-dot--out{background:#B26A00}
.wa-dot--abn{background:#C1322B}
