/* ============================================================
   UnityBridge console design system
   ------------------------------------------------------------
   The shell, panels, tables, tiles, badges and controls that all
   four apps share: admin, barangay, rescue and resident. Each
   app also loads its own stylesheet for the pieces only it has
   (the resident SOS button, the rescue mission cards, the admin
   emergency bar), and loads THIS file after it so the shared
   look wins over whatever those files said before.

   Tokens are declared on body[data-page] rather than :root
   because frontend/css/theme.css loads last and defines the
   shared surfaces on :root; an attribute selector outranks it.
   ============================================================ */

/* ============================================================
   UnityBridge - CDRRMO administrator console
   ------------------------------------------------------------
   The console keeps its structured layout - ruled panels, a stat
   strip, dense tables - and wears the CDRRMO Batangas green taken
   from the office's own seal: a pale green sidebar, a deep green
   topbar carrying white type, green primary buttons, and surfaces
   tinted the near-white the office artwork sits on.

   Tokens are declared on body[data-page] rather than :root
   because frontend/css/theme.css loads AFTER this file and
   defines the shared surfaces on :root. An attribute
   selector outranks :root, so the console's own palette wins
   without touching the other three apps.
   ============================================================ */

body[data-page]{
  /* the office green (its seal is #27AF4C) and the gradients built from it */
  --brand-300:#45BE62;
  --brand-500:#27AF4C;
  --brand-600:#1E8C3D;
  --brand-700:#176B2F;
  --brand-900:#0F4A20;
  --grad-chrome:linear-gradient(168deg,#EDFBEA 0%,#CFF2C9 48%,#A8E3A4 100%);   /* sidebar */
  --grad-bar:linear-gradient(90deg,#1E8C3D 0%,#176B2F 55%,#11552A 100%);       /* topbar: white type sits on it, so it is the deep end of the green */
  --grad-action:linear-gradient(90deg,#45BE62,#239A45);                        /* buttons */
  --grad-head:linear-gradient(90deg,#F0FBEE,#F9FEFA);                          /* panel headers */

  /* neutrals - green-tinted, so white panels sit on a soft green rather
     than on a flat grey, the way the office artwork does */
  --slate-900:#16271A;
  --slate-600:#566159;
  --slate-400:#9CB0A0;
  --slate-200:#D7E6DB;
  --slate-100:#EAF3EC;
  --slate-50:#F5FBF6;

  /* surfaces (overriding the shared set in css/theme.css) */
  --surface:#FFFFFF;
  --surface-2:#F1F7F2;
  --surface-3:#F8FDF9;
  --surface-side:var(--brand-500);
  --line:#D9E9DD;
  --line-soft:#E8F3EB;
  --shadow-card:none;
  --shadow-pop:0 18px 44px rgba(29,80,41,0.22);

  /* status - each with its own rule colour */
  /* amber is pending and medium severity, and is no longer the brand:
     aliasing it to --brand-* would turn every pending badge green. */
  --amber-100:#FDECD1; --amber-300:#F6B25A; --amber-500:#F2994A; --amber-700:#B96A1E;
  --brand-tint:#E3F6E7;   /* the brand at badge strength */
  --blue-100:#E4EEFB; --blue-500:#3B82F6; --blue-700:#1D4ED8;
  --coral-100:#FCEAE7; --coral-500:#E8604C; --coral-700:#B8402F;
  --purple-100:#F0EAFB; --purple-500:#8B5CF6; --purple-700:#6D28D9;
  --teal-100:#DEF5F0; --teal-500:#0F9C8A; --teal-700:#0B7767;
  --green-100:#E3F6E9; --green-600:#1F9D55;
  --gray-100:var(--slate-100); --gray-400:var(--slate-400);

  /* the accent colour for links, tabs and the active state */
  --steel-600:#15742F; --steel-500:var(--brand-600); --steel-100:#FDECD1;

  --ink:var(--slate-900); --ink-soft:var(--slate-600); --cream:#F2FEF5;

  --chrome-h:58px;         /* topbar height, used by the sticky offsets */
}

*{box-sizing:border-box; margin:0; padding:0; font-family:'Inter',sans-serif;}
body{background:var(--surface-2); color:var(--ink); -webkit-font-smoothing:antialiased;}
a{text-decoration:none; color:inherit;}
h1,h2,h3,h4{font-family:'Inter',sans-serif; letter-spacing:-0.01em;}
ul{list-style:none;}
button{font-family:inherit; cursor:pointer;}

/* ---------- shell layout ----------
   The sidebar and topbar are fixed furniture: a long table now scrolls
   under them instead of pushing the navigation off the screen. */
.admin-shell{display:flex; min-height:100vh;}

.sidebar{
  width:244px; flex-shrink:0; position:sticky; top:0; align-self:flex-start;
  height:100vh; overflow-y:auto; overflow-x:hidden;
  background:var(--grad-chrome); color:#1B5929;
  display:flex; flex-direction:column; padding:0 0 14px;
  transition:width .2s ease;
}
.admin-shell.sidebar-collapsed .sidebar{width:0;}

/* Masthead: the office identifies itself before anything else on the page */
.brand-block{
  display:flex; align-items:center; gap:11px; padding:15px 18px 16px;
  border-bottom:1px solid rgba(41,174,72,0.20); margin-bottom:12px;
}
.brand-block .brand-seal{
  width:38px; height:38px; border-radius:10px; overflow:hidden; flex-shrink:0; background:#fff;
  box-shadow:0 1px 4px rgba(28,132,52,.18);
  display:flex; align-items:center; justify-content:center;
}
.brand-block .brand-seal img{width:100%; height:100%; object-fit:cover;}

/* The two official marks: the Batangas City seal and the CDRRMO logo, as the
   office uses them - side by side, round, on white so they read against the
   green chrome. object-fit:contain, because a seal cropped at the edge is a
   seal misused. */
.brand-block .brand-seals{display:flex; align-items:center; gap:3px; flex-shrink:0;}
.brand-block .brand-seals img{
  width:28px; height:28px; border-radius:50%; background:#fff; object-fit:contain;
  box-shadow:0 1px 4px rgba(28,132,52,.20);
}
/* Two seals take more of the 244px column than one mark did. Measured: the
   office line needs 143px beside them, so the block gives back side padding
   and the line drops its letter-spacing - otherwise "CDRRMO Batangas City"
   wraps or runs under the sidebar edge. */
.brand-block:has(.brand-seals){padding-left:14px; padding-right:12px; gap:9px;}
.brand-block .brand-office{white-space:nowrap; letter-spacing:0;}
.brand-block .brand-word{
  font-family:'Poppins',sans-serif; font-weight:700; font-size:16px; letter-spacing:1.2px; color:var(--ink);
}
.brand-block .brand-office{font-size:12.5px; color:var(--brand-900); margin-top:2px; letter-spacing:.2px; font-weight:600;}

.sidebar nav{display:flex; flex-direction:column; gap:1px; padding:0 10px;}
.nav-section{
  font-size:11.5px; font-weight:800; letter-spacing:1.1px; text-transform:uppercase;
  color:#19732E; padding:14px 10px 6px;
}
.nav-section:first-child{padding-top:2px;}
.sidebar nav a{
  display:flex; align-items:center; gap:11px; padding:9px 10px; border-radius:9px;
  font-size:15px; font-weight:600; color:#1B5929; border-left:2px solid transparent;
}
.sidebar nav a i{font-size:18px; color:#2E7A43;}
.sidebar nav a:hover{background:rgba(255,255,255,0.58); color:#13461F;}
.sidebar nav a:hover i{color:#1B5929;}
.sidebar nav a.active{
  background:#fff; color:#15742F; font-weight:700;
  border-left-color:var(--brand-600); border-radius:0 9px 9px 0;
  box-shadow:0 2px 8px rgba(28,132,52,.14);
}
.sidebar nav a.active i{color:var(--brand-500);}

.nav-logout{
  margin:auto 20px 0; display:flex; align-items:center; gap:10px; padding:10px 0 0;
  border-top:1px solid rgba(41,174,72,0.20); font-size:14.5px; font-weight:600; color:#1B5929;
}
.nav-logout:hover{color:#1B5929;}
.nav-logout i{font-size:17.5px;}

.main{flex:1; min-width:0; display:flex; flex-direction:column;}

/* ---------- topbar: office identity and who is signed in ---------- */
.topbar{
  background:var(--grad-bar); color:#fff; height:var(--chrome-h);
  padding:0 22px; display:flex; align-items:center; gap:16px;
  position:sticky; top:0; z-index:940;
  box-shadow:inset 0 -1px 0 rgba(255,255,255,0.14), 0 1px 0 rgba(12,60,26,.18);
}
.topbar .menu-toggle{
  width:32px; height:32px; border-radius:9px; background:rgba(255,255,255,0.18); border:none;
  color:#fff; display:flex; align-items:center; justify-content:center; font-size:17.5px; flex-shrink:0;
}
.topbar .menu-toggle:hover{background:rgba(255,255,255,0.32);}
.topbar-meta{min-width:0; flex:1;}
.topbar-office{
  font-size:14.5px; font-weight:700; color:#fff; letter-spacing:.2px;
  white-space:nowrap; overflow:hidden; text-overflow:ellipsis;
}
.topbar-sub{font-size:12.5px; color:rgba(255,255,255,0.85); margin-top:1px; letter-spacing:.3px;}
.topbar .actions{display:flex; align-items:center; gap:14px; margin-left:auto;}
.topbar .icon-btn{
  width:34px; height:34px; border-radius:9px; background:rgba(255,255,255,0.18); border:none;
  display:flex; align-items:center; justify-content:center; font-size:17.5px; color:#fff; position:relative;
}
.topbar .icon-btn:hover{background:rgba(255,255,255,0.32);}
.topbar .icon-btn .dot{
  position:absolute; top:7px; right:8px; width:7px; height:7px; border-radius:50%;
  background:var(--coral-500); box-shadow:0 0 0 2px #176B2F;
}
.user-chip{display:flex; align-items:center; gap:9px; padding-left:14px; border-left:1px solid rgba(255,255,255,0.28);}
.user-chip .user-avatar{
  width:32px; height:32px; border-radius:50%; background:rgba(255,255,255,0.22); color:#fff;
  display:flex; align-items:center; justify-content:center; font-size:16.5px; flex-shrink:0;
}
.user-chip .user-meta{display:flex; flex-direction:column; line-height:1.25;}
.user-chip .user-name{font-size:14.5px; font-weight:700; color:#fff;}
.user-chip .user-role{font-size:12px; color:rgba(255,255,255,0.85); letter-spacing:.4px; text-transform:uppercase;}

.content{padding:22px 26px 40px; flex:1;}

/* ---------- page header band ---------- */
.page-head{
  display:flex; align-items:flex-end; justify-content:space-between; gap:16px; flex-wrap:wrap;
  padding-bottom:14px; margin-bottom:20px; border-bottom:1px solid var(--line);
}
.page-title{font-size:20px; font-weight:700; letter-spacing:-0.015em; display:flex; align-items:center; gap:8px;}
.page-subtitle{font-size:14.5px; color:var(--ink-soft); margin-top:4px; line-height:1.5;}
.page-head .page-subtitle{margin-bottom:0;}
.page-head-actions{display:flex; align-items:center; gap:8px;}

/* ---------- stat strip ----------
   One bordered panel divided by hairlines, not four floating cards: the
   figures are one reading, so they are presented as one object. */
.stat-tiles{
  display:grid; grid-template-columns:repeat(4,minmax(0,1fr)); gap:14px; margin-bottom:20px;
}
.stat-tile{
  background:var(--surface); border:1px solid var(--line); border-radius:14px;
  padding:16px 18px; display:flex; align-items:center; gap:13px;
  box-shadow:0 1px 2px rgba(28,132,52,0.04);
}
.stat-tile .icon-circle{
  width:42px; height:42px; border-radius:12px; display:flex; align-items:center; justify-content:center;
  font-size:19px; flex-shrink:0;
}
.stat-tile .num{font-size:24px; font-weight:700; line-height:1.1; font-variant-numeric:tabular-nums;}
.stat-tile .label{
  /* Uppercase with letter-spacing is wide, and five tiles across a laptop do
     not leave much room for it. Slightly tighter tracking than the rest of
     the console's micro-labels, so "PENDING REPORTS" stays on one line at
     this size rather than wrapping under its own number. */
  font-size:13px; color:var(--ink-soft); text-transform:uppercase; letter-spacing:.2px;
  font-weight:600; margin-top:4px; line-height:1.25;
}
/* The tile is a number and its name; neither needs to be squeezed by the icon. */
.stat-tile{min-width:0;}
.stat-tile .label, .stat-tile .num{white-space:normal;}
.tile-amber .icon-circle{background:var(--amber-100); color:var(--amber-700);}
.tile-blue .icon-circle{background:var(--steel-100); color:var(--steel-600);}
.tile-green .icon-circle{background:var(--green-100); color:var(--green-600);}
.tile-coral .icon-circle{background:var(--coral-100); color:var(--coral-700);}
.tile-purple .icon-circle{background:var(--purple-100); color:var(--purple-700);}
.tile-gray .icon-circle{background:var(--gray-100); color:var(--ink-soft);}

/* ---------- panels ---------- */
.card{
  background:var(--surface); border:1px solid var(--line); border-radius:14px; padding:16px 18px;
  box-shadow:none;
}
/* The head is a band across the full width of the panel, ruled off from
   its contents, the way a form or a report section is titled. */
.card-head{
  display:flex; align-items:center; justify-content:space-between; gap:12px;
  margin:-16px -18px 14px; padding:11px 18px;
  background:var(--grad-head); border-bottom:1px solid var(--line); border-radius:13px 13px 0 0;
}
.card-head h3{
  font-size:13.5px; font-weight:700; text-transform:uppercase; letter-spacing:.7px; color:var(--slate-600);
  display:flex; align-items:center; gap:7px;
}
.card-head .link{font-size:13.5px; font-weight:600; color:var(--steel-600);}
.card-head .link:hover{text-decoration:underline;}
.select-chip{
  border:1px solid var(--line); background:var(--surface); border-radius:9px; padding:5px 9px;
  font-size:14px; color:var(--ink-soft); display:flex; align-items:center; gap:6px;
}

.grid-2{display:grid; grid-template-columns:1.4fr 1fr; gap:16px;}
.grid-2-even{display:grid; grid-template-columns:1fr 1fr; gap:16px;}
.grid-3{display:grid; grid-template-columns:repeat(3,1fr); gap:16px;}

/* A grid item will not shrink below its content's minimum size unless it is
   told it may, and a Chart.js canvas carries an explicit pixel width. So
   collapsing the sidebar let the charts grow into the space, and bringing it
   back could not squeeze them down again: the page kept the wider layout and
   grew a horizontal scrollbar. The canvas cap is the second line of defence,
   for the frame before Chart.js has resized itself. */
.grid-2 > *, .grid-2-even > *, .grid-3 > *, .stat-tiles > *, .em-layout > *{min-width:0;}
.card{min-width:0;}
canvas{max-width:100%;}

/* ---------- empty state ---------- */
.empty-state{
  display:flex; flex-direction:column; align-items:center; justify-content:center; text-align:center;
  padding:34px 20px; color:var(--ink-soft);
}
.empty-state i{font-size:27px; color:var(--slate-400); margin-bottom:10px;}
.empty-state p{font-size:15px; font-weight:600; color:var(--ink); margin-bottom:4px;}
.empty-state span{font-size:14px; max-width:240px; line-height:1.5;}

/* ---------- tables ----------
   Full-bleed inside their panel, hairline rows, figures on tabular
   numerals so columns of numbers line up. */
.table-wrap{overflow-x:auto; margin:0 -18px;}

/* A table in a half-width panel - Recent Reports beside the risk map - has
   nowhere near the room of a full page table, and at the console's larger
   text the last column was being squeezed to nothing with the rest behind a
   sideways scroll. Here the cells wrap instead: a two-line date or address is
   readable, a column you cannot see is not. Headers wrap too, so "REPORT ID"
   stops setting a 96px floor for a column holding "#0002". */
.table-compact thead th,
.table-compact tbody td{white-space:normal;}
/* Only the address column may break inside a word. Applied to all of them it
   produced "#003 / 2" and "RESO / LVED", which is worse than the scrollbar it
   was meant to remove; addresses are the one column long enough to need it. */
.table-compact td.wrap-any{overflow-wrap:anywhere;}
/* Some values only make sense whole: a date broken after the comma reads as
   two facts. The address column beside it can break anywhere, so it is the one
   that gives up the width. */
.table-compact th.nowrap, .table-compact td.nowrap{white-space:nowrap;}
/* A status pill is two-thirds letter-spacing at this size; it does not need to
   set the width of its column. */
.table-compact .badge{letter-spacing:0; padding:2px 7px;}
.table-compact thead th{padding:8px 8px; letter-spacing:.3px;}
.table-compact tbody td{padding:10px 8px; vertical-align:middle;}
.table-compact thead th:first-child, .table-compact tbody td:first-child{padding-left:18px;}
.table-compact thead th:last-child, .table-compact tbody td:last-child{padding-right:18px;}
/* The hazard cell is an icon and a word; let the word drop under the icon
   rather than widen the column. */
.table-compact .row-icon{margin-right:7px;}
table{width:100%; border-collapse:collapse; font-size:14.5px;}
thead th{
  text-align:left; font-size:12px; letter-spacing:.7px; color:var(--slate-600);
  text-transform:uppercase; font-weight:700; padding:9px 12px; white-space:nowrap;
  background:var(--grad-head); border-bottom:1px solid var(--slate-200);
}
/* A table reads as part of its panel: the column header sits directly under
   the panel header, or against the top edge when the panel has no header. */
.card-head + .table-wrap{margin-top:-14px;}
/* overflow:hidden here was rounding the top corners and, in the same stroke,
   taking away the sideways scroll every wide table depends on: a phone could
   see the first three columns of such a table and had no way to reach the
   rest. Clipping one axis and scrolling the other keeps both. */
.card > .table-wrap:first-child{
  margin-top:-16px; border-radius:13px 13px 0 0;
  overflow-x:auto; overflow-y:hidden;
}
tbody td{
  padding:10px 12px; border-bottom:1px solid var(--line-soft); color:var(--ink); white-space:nowrap;
  font-variant-numeric:tabular-nums;
}
thead th:first-child, tbody td:first-child{padding-left:18px;}
thead th:last-child, tbody td:last-child{padding-right:18px;}
tbody tr:last-child td{border-bottom:none;}
tbody tr:hover{background:var(--slate-50);}
.row-icon{
  width:24px; height:24px; border-radius:9px; display:inline-flex; align-items:center; justify-content:center;
  font-size:15px; margin-right:8px; vertical-align:middle;
}
.avatar{
  width:26px; height:26px; border-radius:50%; background:var(--slate-100); color:var(--slate-600);
  display:inline-flex; align-items:center; justify-content:center; font-size:14px; margin-right:8px; vertical-align:middle;
}

/* ---------- list rows (notifications) ---------- */
.list-row{
  display:flex; align-items:flex-start; gap:12px; padding:13px 4px; border-bottom:1px solid var(--line-soft);
}
.list-row:last-child{border-bottom:none;}
.list-row .icon-circle{
  width:34px; height:34px; border-radius:10px; display:flex; align-items:center; justify-content:center;
  font-size:17.5px; flex-shrink:0; color:#fff;
}
.list-row .body{flex:1; min-width:0;}
.list-row .title{font-size:15px; font-weight:600; color:var(--ink);}
.list-row .desc{font-size:14px; color:var(--ink-soft); margin-top:2px;}
.list-row .meta{font-size:13.5px; color:var(--ink-soft); margin-top:4px;}
.list-row .right{display:flex; align-items:center; gap:10px; flex-shrink:0; flex-wrap:nowrap; justify-content:flex-end;}
.list-row .time{font-size:13px; color:var(--slate-400); white-space:nowrap; font-variant-numeric:tabular-nums;}
.list-row.unread{background:var(--steel-100); border-radius:9px; padding-left:10px; padding-right:10px;}
.list-row.urgent{
  background:#FDF2F0; border-left:3px solid var(--coral-500); border-radius:0 9px 9px 0;
  padding-left:10px; padding-right:10px;
}

/* ---------- badges ---------- */
.badge{
  display:inline-flex; align-items:center; gap:4px; padding:2px 7px; border-radius:6px;
  font-size:12px; font-weight:700; letter-spacing:.5px; text-transform:uppercase;
  border:1px solid transparent;
}
.badge-pending{background:var(--amber-100); color:var(--amber-700); border-color:#EBD6A8;}
.badge-approved,.badge-verified,.badge-active,.badge-resolved{background:var(--green-100); color:var(--green-600); border-color:#BFDCC7;}
/* A hazard that is still happening. Green said "fine" next to a resolved row
   that was also green, so the one thing on the list that still needs someone
   is the one thing that reads as urgent. Accounts keep .badge-active green:
   an active account is good standing, not a live emergency. */
.badge-live{background:var(--coral-100); color:var(--coral-700); border-color:#EFC7C0;}
.badge-rejected,.badge-suspended{background:var(--coral-100); color:var(--coral-700); border-color:#EFC7C0;}
.badge-responding{background:var(--steel-100); color:var(--steel-600); border-color:#C6D8F6;}
.badge-assigned{background:var(--purple-100); color:var(--purple-700); border-color:#D3C9F0;}
.badge-high{background:var(--coral-100); color:var(--coral-700); border-color:#EFC7C0;}
.badge-medium{background:var(--amber-100); color:var(--amber-700); border-color:#EBD6A8;}
.badge-low{background:var(--slate-100); color:var(--slate-600); border-color:var(--slate-200);}
.badge-resolved-strong{background:var(--teal-100); color:var(--teal-700); border-color:#B8D9D3;}

.status-dot{width:7px; height:7px; border-radius:50%; display:inline-block; margin-right:6px;}
.dot-green{background:var(--green-600);} .dot-amber{background:var(--amber-500);} .dot-gray{background:var(--slate-400);}

/* ---------- inline messages ---------- */
.message{font-size:14.5px; padding:9px 12px; border-radius:9px; display:none; border-left:3px solid transparent;}
.message.error{background:var(--coral-100); color:var(--coral-700); border-left-color:var(--coral-500); display:block;}
.message.success{background:var(--green-100); color:var(--green-600); border-left-color:var(--green-600); display:block;}

/* ---------- tabs ---------- */
.tabs{display:flex; gap:6px; margin-bottom:16px; border-bottom:1px solid var(--line); flex-wrap:wrap;}
.tabs button{
  background:none; border:none; padding:9px 2px; font-size:14.5px; font-weight:600; color:var(--slate-600);
  border-bottom:2px solid transparent; margin-right:20px; cursor:pointer;
}
.tabs button:hover{color:var(--ink);}
.tabs button.active{color:var(--steel-600); border-color:var(--steel-600);}

/* ---------- filters and controls ---------- */
.filters-bar{display:flex; align-items:center; gap:8px; margin-bottom:16px; flex-wrap:wrap;}
.search-input{
  display:flex; align-items:center; gap:8px; background:var(--surface); border:1px solid var(--line); border-radius:10px;
  padding:8px 12px; font-size:14.5px; color:var(--slate-400); flex:1; min-width:180px;
}
.search-input:focus-within{border-color:var(--steel-500); box-shadow:0 0 0 3px rgba(37,99,235,0.10);}
.search-input input{border:none; outline:none; font-size:14.5px; width:100%; background:transparent; color:var(--ink);}
.filter-select{
  background:var(--surface); border:1px solid var(--line); border-radius:10px; padding:8px 11px; font-size:14.5px;
  color:var(--ink-soft); display:flex; align-items:center; gap:6px;
}
.filter-select:focus{outline:none; border-color:var(--steel-500); box-shadow:0 0 0 3px rgba(37,99,235,0.10);}

.btn{
  border:1px solid transparent; border-radius:10px; padding:9px 15px; font-size:14.5px; font-weight:600;
  display:inline-flex; align-items:center; gap:6px; transition:background .15s ease, border-color .15s ease;
}
.btn-primary{background:var(--grad-action); color:#fff; box-shadow:0 4px 10px rgba(64,207,97,.28);}
.btn-primary:hover{background:linear-gradient(90deg,#5DD679,#35CD59);}
.btn-outline{background:var(--surface); border-color:var(--line); color:var(--ink);}
.btn-outline:hover{background:var(--slate-50); border-color:var(--slate-400);}
.btn-green{background:var(--green-600); color:#fff;}
.btn-green:hover{background:#156334;}
.btn-red{background:var(--coral-500); color:#fff;}
.btn-red:hover{background:var(--coral-700);}
.btn-red-outline{background:var(--surface); border-color:var(--coral-500); color:var(--coral-500);}
.btn-red-outline:hover{background:var(--coral-100);}
.btn-danger{background:var(--coral-500); color:#fff; border:none; box-shadow:none;}
.btn-danger:hover{background:var(--coral-700);}
.btn-sm{padding:7px 12px; font-size:14px;}
.btn-block{width:100%; justify-content:center;}
.btn:focus-visible, .icon-btn:focus-visible, a:focus-visible, select:focus-visible, input:focus-visible{
  outline:2px solid var(--steel-500); outline-offset:2px;
}

/* ---------- pagination ---------- */
.pagination{
  display:flex; align-items:center; justify-content:space-between; margin-top:14px; padding-top:12px;
  border-top:1px solid var(--line-soft); font-size:14px; color:var(--ink-soft);
}
.page-nums{display:flex; align-items:center; gap:5px;}
.page-nums button{
  min-width:27px; height:27px; border-radius:8px; border:1px solid var(--line); background:var(--surface);
  font-size:14px; color:var(--ink-soft);
}
.page-nums button:hover{background:var(--slate-50);}
.page-nums button.active{background:var(--grad-action); border-color:var(--brand-600); color:#fff; font-weight:700;}
.page-nums button.nav{border:none; background:transparent;}

/* ---------- modal ---------- */
.modal-overlay{
  position:fixed; inset:0; background:rgba(10,30,56,0.55); display:none; align-items:center; justify-content:center;
  z-index:1000; padding:20px;
}
.modal-overlay.active{display:flex;}
.modal-box{
  background:var(--surface); border-radius:16px; width:100%; max-width:1100px; max-height:94vh; overflow-y:auto;
  padding:0 28px 26px; box-shadow:var(--shadow-pop);
}
.modal-head{
  display:flex; align-items:flex-start; justify-content:space-between; gap:12px;
  margin:0 -28px 20px; padding:18px 28px; border-bottom:1px solid var(--line); background:var(--grad-head);
  position:sticky; top:0; z-index:2; border-radius:15px 15px 0 0;
}
.modal-head .title-group{display:flex; gap:12px;}
.modal-head .icon-circle{
  width:36px; height:36px; border-radius:10px; background:var(--steel-100); color:var(--steel-600);
  display:flex; align-items:center; justify-content:center; font-size:18px; flex-shrink:0;
}
.modal-head h2{font-size:18px; font-weight:700;}
.modal-head p{font-size:14.5px; color:var(--ink-soft); margin-top:3px;}
.modal-close{
  width:28px; height:28px; border-radius:9px; border:1px solid var(--line); background:var(--surface);
  color:var(--slate-600); font-size:16.5px; display:flex; align-items:center; justify-content:center;
}
.modal-close:hover{background:var(--slate-100);}

.detail-row{display:flex; align-items:center; gap:10px; font-size:15.5px; padding:10px 0; border-bottom:1px solid var(--line-soft);}
.detail-row i{color:var(--slate-400); width:16px;}
.detail-row .k{color:var(--ink-soft); min-width:96px;}
.detail-row .v{font-weight:600;}

.notice{
  display:flex; gap:10px; background:var(--steel-100); color:var(--steel-600); font-size:14px;
  padding:10px 12px; border-radius:9px; border-left:3px solid var(--steel-500); margin-top:14px; line-height:1.5;
}

.map-placeholder{
  border-radius:10px; overflow:hidden; position:relative; height:180px; border:1px solid var(--line);
  background:var(--slate-100);
}
/* No rule for svg inside here. There was one, sizing a decorative placeholder
   illustration to the box, and no page draws that illustration any more - but
   every .map-placeholder is a real Leaflet map, and the rule was stretching
   Leaflet's own SVG: the little flag in its attribution blew up into a blue
   and yellow block across the map. */
.map-pin{
  position:absolute; width:24px; height:24px; border-radius:50% 50% 50% 0; transform:rotate(-45deg);
  display:flex; align-items:center; justify-content:center; box-shadow:0 2px 5px rgba(10,30,56,0.3);
}
.map-pin i{transform:rotate(45deg); color:#fff; font-size:14px;}

.attachments{display:flex; gap:10px; margin-top:8px;}
.attachments .thumb{
  width:62px; height:62px; border-radius:9px; background:var(--slate-100); border:1px solid var(--line);
  display:flex; align-items:center; justify-content:center; color:var(--slate-600); font-size:17.5px;
  position:relative; overflow:hidden;
}
.attachments .thumb.more{background:var(--steel-100); color:var(--steel-600); font-size:13px; font-weight:700; flex-direction:column; gap:2px;}

/* The frame is large enough that on a short screen the box scrolls, so the
   decision buttons stay pinned to its bottom edge rather than disappearing
   below a photo. The shadow paints over the box's own bottom padding. */
.modal-actions{
  display:flex; gap:10px; margin-top:24px; padding-top:14px;
  position:sticky; bottom:0; z-index:3;
  background:var(--surface); box-shadow:0 26px 0 var(--surface);
  border-top:1px solid var(--line-soft);
}
.modal-actions .btn{flex:1; justify-content:center; padding:13px; font-size:15.5px;}

/* ---------- user detail / validation ---------- */
.ud-section{
  font-size:12px; font-weight:700; letter-spacing:.8px; text-transform:uppercase;
  color:var(--slate-600); margin:18px 0 4px; padding-bottom:4px; border-bottom:1px solid var(--line-soft);
}
.ud-section:first-child{margin-top:0;}
.ud-proof{
  display:block; width:100%; max-height:260px; object-fit:contain;
  border:1px solid var(--line); border-radius:10px; background:var(--slate-50); margin-top:6px;
}
.ud-member{border:1px solid var(--line); border-radius:10px; padding:10px 12px; margin-top:8px; font-size:14.5px;}
.ud-member-meta{display:flex; flex-wrap:wrap; gap:4px 14px; font-size:14px; color:var(--ink-soft); margin-top:4px;}
.ud-member-meta i{font-size:15px;}

/* ---------- click-to-view rows ---------- */
.clickable-row{cursor:pointer;}
.clickable-row:hover{background:var(--slate-50);}

/* ---------- leaflet, squared off to match the panels ---------- */
/* Leaflet numbers its own furniture from the page's stacking order: the zoom
   buttons and the attribution credit are z-index 1000, and .leaflet-container
   sets no z-index of its own, so those numbers competed with the console's
   chrome rather than staying inside the map. The +/- buttons and the OSM
   credit floated over the open sidebar (960) and could reach a modal overlay
   (1000) too. z-index on a positioned element makes each map its own stacking
   context, so every layer Leaflet creates is confined to it whatever number it
   is given - and 0 keeps the map itself exactly where it was in the page. */
.leaflet-container{border-radius:9px; font-family:'Inter',sans-serif; position:relative; z-index:0;}
.leaflet-control-zoom a{border-radius:8px !important; color:var(--ink) !important;}
.leaflet-popup-content-wrapper{border-radius:10px;}

/* ---------- responsive ---------- */
@media (max-width:1100px){
  /* !important because pages set grid-template-columns inline to size their
     own two columns (the map beside its legend, the trend beside the donut).
     An inline style outranks a plain rule here, so without this the phone
     kept the desktop split and squeezed a map into a 40mm strip. */
  .stat-tiles{grid-template-columns:repeat(2,1fr) !important;}
  .grid-2, .grid-2-even, .grid-3{grid-template-columns:1fr !important;}
}
@media (max-width:1000px){
  .em-layout{grid-template-columns:1fr;}
  .em-map-card{position:relative; top:0;}
  .em-map{height:320px;}
}
/* The dimmed sheet behind the open drawer. Below the sidebar (960) and above
   the topbar (940), so the drawer stays lit and everything the drawer covers
   is both dimmed and tappable-to-close. It is only ever shown on the narrow
   layout, where the sidebar is a drawer at all. */
.sidebar-scrim{
  position:fixed; inset:0; z-index:950; background:rgba(10,30,56,0.42);
  opacity:0; pointer-events:none; transition:opacity .2s ease;
}
.sidebar-scrim.show{opacity:1; pointer-events:auto;}
@media (min-width:821px){ .sidebar-scrim{display:none;} }

@media (max-width:820px){
  .sidebar{position:fixed; left:-244px; top:0; bottom:0; height:100%; z-index:960; transition:left .2s;}
  .sidebar.open{left:0;}
  .topbar-sub{display:none;}
  .topbar{padding:0 12px; gap:10px;}
  .user-chip{padding-left:10px;}
  .user-chip .user-meta{display:none;}
  .content{padding:18px 16px 32px;}
}
@media (max-width:640px){
  .sos-alarm{padding:9px 14px; font-size:14.5px;}
  .sos-alarm-text{white-space:normal;}
  .stat-tiles{grid-template-columns:1fr !important;}
  .em-grid{grid-template-columns:1fr;}

  /* Stacked, the second card is a scroll away, so neither needs to fill the
     screen: a map taller than the viewport cannot be panned past on a phone,
     because the drag scrolls the map instead of the page. */
  .card{padding:14px;}
  .card-head{margin:-14px -14px 12px; padding:10px 14px;}
  .table-wrap{margin:0 -14px;}
  thead th:first-child, tbody td:first-child{padding-left:14px;}
  thead th:last-child, tbody td:last-child{padding-right:14px;}
  .page-head{padding-bottom:10px; margin-bottom:14px;}
  .page-title{font-size:18px;}
  .modal-box{padding:0 16px 16px;}
  .modal-head{margin:0 -16px 14px; padding:14px 16px;}

  /* Controls that sit side by side on a desktop have nowhere to go on a
     phone: the map's Map/Satellite switch and its status filter were running
     off the right edge rather than wrapping, because the row justifies them
     apart and the select never shrinks. Stack them instead. */
  .map-toolbar{flex-direction:column; align-items:stretch; gap:8px;}
  .map-toolbar .map-toggle{justify-content:center;}
  .map-filter-select, .filter-select, .search-input{width:100%; min-width:0;}
  .filters-bar{gap:8px;}
  .page-head{flex-direction:column; align-items:flex-start;}
  .modal-actions{flex-direction:column;}
}

/* ---------- installed on a phone ----------
   Once the app is on an iPhone's home screen there is no browser chrome left
   to hold the status bar and the home indicator off the page: the viewport
   runs edge to edge (viewport-fit=cover in every page head), so the topbar
   would sit under the clock and the sidebar's last menu item under the home
   indicator. env() is 0 on every device without those, so these rules cost
   nothing elsewhere. */
@media (display-mode: standalone) {
  .topbar{
    height:calc(var(--chrome-h) + env(safe-area-inset-top, 0px));
    padding-top:env(safe-area-inset-top, 0px);
  }
  .sidebar{padding-top:env(safe-area-inset-top, 0px); padding-bottom:calc(14px + env(safe-area-inset-bottom, 0px));}
  .content{
    padding-left:calc(26px + env(safe-area-inset-left, 0px));
    padding-right:calc(26px + env(safe-area-inset-right, 0px));
    padding-bottom:calc(40px + env(safe-area-inset-bottom, 0px));
  }
}
@media (display-mode: standalone) and (max-width:820px) {
  .content{
    padding-left:calc(16px + env(safe-area-inset-left, 0px));
    padding-right:calc(16px + env(safe-area-inset-right, 0px));
    padding-bottom:calc(32px + env(safe-area-inset-bottom, 0px));
  }
}

/* The hidden attribute must always win. Class rules like .empty-state{display:flex}
   otherwise override it, which kept "No reports yet" showing on top of charts
   that had data, and left things like the bell dot visible when they shouldn't be. */
[hidden]{display:none !important;}

/* ---------- paper ----------
   css/theme.css carries the print layout for Report Generation. It restores
   print values on :root, which this file's body[data-page] block would
   otherwise outrank, so the paper values are restated here. */
@media print{
  body[data-page]{
    --surface:#fff; --surface-2:#fff; --surface-3:#fff;
    --line:#C9CDD4; --line-soft:#E3E6EA;
    --ink:#000; --ink-soft:#333;
    --slate-50:#fff; --slate-100:#fff; --slate-600:#333; --slate-200:#C9CDD4;
  }
  .card-head{background:#fff !important; margin:0 0 8px; padding:0 0 6px;}
  .table-wrap{margin:0;}
  thead th:first-child, tbody td:first-child{padding-left:6px;}
  .sos-alarm, .nav-badge{display:none !important;}
}


/* ---------- photos being attached ----------
   The picker's chips: used by a resident attaching photos to a report and
   by a rescue team attaching proof when it closes a mission, so they live
   here rather than in either app's own stylesheet. */
.photo-chip{
  display:flex; align-items:center; gap:10px; margin-top:8px; padding:8px 10px;
  border:1px solid var(--line); border-radius:10px; background:var(--surface-3);
}
.photo-chip img{
  width:46px; height:46px; object-fit:cover; border-radius:8px; flex-shrink:0;
  background:var(--surface-2);
}
.photo-chip .photo-meta{flex:1; min-width:0;}
.photo-chip .photo-name{
  font-size:14px; font-weight:600; color:var(--ink);
  overflow:hidden; text-overflow:ellipsis; white-space:nowrap;
}
.photo-chip .photo-size{font-size:12.5px; color:var(--ink-soft);}
.photo-chip button{
  border:none; background:none; cursor:pointer; color:var(--ink-soft);
  font-size:17px; padding:6px; line-height:1;
}
.photo-chip button:hover{color:var(--coral-600);}
.photo-hint{font-size:12.5px; color:var(--ink-soft); margin-top:8px;}

/* ---------- report photos ----------
   A report can carry up to five photos. One fills the panel, because a single
   photo of a flooded street is worth the room; several tile, because what
   matters then is seeing at a glance what was sent. Every one of them opens
   full size, and none is cropped - a resident's photo is evidence, and a crop
   can cut out the thing they were photographing. */
.photo-grid{display:grid; gap:8px;}
.photo-grid.one{grid-template-columns:1fr;}
.photo-grid.many{grid-template-columns:repeat(auto-fill, minmax(150px, 1fr));}
.photo-grid a{display:block; border:1px solid var(--line); border-radius:10px; overflow:hidden; background:var(--slate-50);}
.photo-grid img{display:block; width:100%; object-fit:contain; background:var(--slate-50);}
.photo-grid.one img{max-height:420px;}
.photo-grid.many img{height:150px;}
.photo-count{font-size:12.5px; color:var(--ink-soft); margin:0 0 8px;}
