/* Fire Extinguisher Management System -- hand-written, dependency-free
   stylesheet. Deliberately not built on Bootstrap/a CDN framework so the
   whole app works with zero external network calls on an internal LAN
   server. Mobile-first: large tap targets, high contrast status colors.

   Lives under public/ (a stable, non-hashed URL via WHITENOISE_ROOT) rather
   than Django's {% static %}/collectstatic pipeline -- that pipeline serves
   files under a content-hashed filename that changes on every deploy, which
   public/sw.js (a plain static file with no way to know that hash) can't
   precache correctly. See the comment at the top of public/js/offline.js
   for the same reasoning applied to the offline JS modules. */

:root {
  --color-bg: #f5f6f8;
  --color-surface: #ffffff;
  --color-text: #1c2230;
  --color-muted: #5b6472;
  --color-border: #dde1e7;
  --color-primary: #b3261e;
  --color-primary-dark: #8f1e18;
  --color-primary-contrast: #ffffff;

  --color-ok-bg: #e3f6e8;
  --color-ok-fg: #1c7a34;
  --color-due-soon-bg: #fff5db;
  --color-due-soon-fg: #8a6300;
  --color-overdue-bg: #fde2e1;
  --color-overdue-fg: #a11c11;
  --color-unknown-bg: #eceef1;
  --color-unknown-fg: #5b6472;

  /* Deliberately NOT tied to --color-text: that variable flips light/dark
     with the color-scheme media query below, but the header bar should
     always stay a solid dark brand color in both themes -- otherwise it
     goes near-white and stops reading as a header in dark mode. */
  --color-navbar-bg: #1c2230;
  --color-navbar-text: #ffffff;

  --color-input-bg: #ffffff;

  --radius: 10px;
  --tap-min: 48px;
}

* { box-sizing: border-box; }

html, body {
  margin: 0;
  padding: 0;
  background: var(--color-bg);
  color: var(--color-text);
  font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;
  font-size: 16px;
  line-height: 1.45;
}

a { color: var(--color-primary); text-decoration: none; }
a:hover { text-decoration: underline; }

.app-shell {
  display: flex;
  flex-direction: column;
  min-height: 100vh;
}

/* ---- Top navbar ---- */
.navbar {
  background: var(--color-navbar-bg);
  color: var(--color-navbar-text);
  border-bottom: 3px solid var(--color-primary);
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  padding: 0.6rem 1rem;
  position: sticky;
  top: 0;
  z-index: 50;
}
.navbar .brand {
  color: #fff;
  font-weight: 700;
  font-size: 1.05rem;
  flex-shrink: 0;
}
.navbar .brand small {
  display: block;
  font-weight: 400;
  opacity: 0.75;
  font-size: 0.7rem;
}
/* Below 900px, the brand's subtitle and the offline status bar both fought
   the search box for room in one cramped row -- shrinking the brand to a
   single compact line and moving the status bar onto its own full-width row
   (below) gives the search input back the space it needs. */
@media (max-width: 899px) {
  .navbar .brand {
    font-size: 0.95rem;
    line-height: 1.1;
  }
  .navbar .brand small { display: none; }
}
.navbar-links {
  display: none;
  gap: 1rem;
  align-items: center;
}
.navbar-links a { color: #fff; opacity: 0.9; }
.navbar-links a:hover { opacity: 1; text-decoration: underline; }
@media (min-width: 900px) {
  .navbar-links { display: flex; }
  .navbar-toggle { display: none; }
}
.navbar-toggle {
  background: none;
  border: 1px solid rgba(255,255,255,0.4);
  color: #fff;
  border-radius: 8px;
  padding: 0.4rem 0.7rem;
  min-height: var(--tap-min);
}
.offline-status-bar {
  display: flex;
  align-items: center;
  gap: 0.5rem;
  flex-shrink: 0;
}
@media (max-width: 899px) {
  /* Forces this onto its own full-width row below the brand/search/toggle
     row (which .navbar's flex-wrap now allows), instead of squeezing into
     the same cramped row as the search box. */
  .offline-status-bar {
    order: 4;
    flex: 1 1 100%;
    justify-content: center;
    margin-top: 0.4rem;
  }
}
.offline-status-bar .btn-sm {
  padding: 0.3rem 0.6rem;
  min-height: auto;
  font-size: 0.8rem;
}
.navbar-mobile-menu {
  background: var(--color-navbar-bg);
  padding: 0.5rem 1rem 1rem;
  display: flex;
  flex-direction: column;
  gap: 0.75rem;
}
.navbar-mobile-menu a { color: #fff; padding: 0.5rem 0; font-size: 1.05rem; }

.logout-form { display: inline-flex; margin: 0; }
.navbar-mobile-menu .logout-form { padding: 0.5rem 0; }
.link-button {
  background: none;
  border: none;
  padding: 0;
  margin: 0;
  color: inherit;
  opacity: 0.9;
  font: inherit;
  cursor: pointer;
  min-height: auto;
}
.link-button:hover { opacity: 1; text-decoration: underline; }
.navbar-mobile-menu .link-button { font-size: 1.05rem; opacity: 1; }

/* ---- Search bar ---- */
.search-form {
  flex: 1;
  min-width: 100px;
  max-width: 480px;
  margin: 0 1rem;
}
@media (max-width: 899px) {
  .search-form { margin: 0 0.6rem; }
}
.search-form input[type="search"] {
  width: 100%;
  padding: 0.55rem 0.8rem;
  border-radius: 999px;
  border: none;
  min-height: var(--tap-min);
}

/* ---- Layout ---- */
.container {
  width: 100%;
  max-width: 1100px;
  margin: 0 auto;
  padding: 1.25rem 1rem 5.5rem;
  flex: 1;
}
@media (min-width: 900px) {
  .container { padding-bottom: 2rem; }
}

.page-header {
  display: flex;
  flex-wrap: wrap;
  gap: 0.75rem;
  align-items: center;
  justify-content: space-between;
  margin-bottom: 1.25rem;
}
.page-header h1 { margin: 0; font-size: 1.5rem; }
.page-subtitle { color: var(--color-muted); margin-top: 0.15rem; }

.card {
  background: var(--color-surface);
  border: 1px solid var(--color-border);
  border-radius: var(--radius);
  padding: 1.1rem;
  margin-bottom: 1rem;
}
.card h2, .card h3 { margin-top: 0; }

/* ---- Buttons ---- */
.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 0.4rem;
  min-height: var(--tap-min);
  padding: 0.6rem 1.1rem;
  border-radius: 8px;
  border: 1px solid var(--color-border);
  background: var(--color-surface);
  color: var(--color-text);
  font-size: 1rem;
  font-weight: 600;
  cursor: pointer;
  text-decoration: none;
}
.btn:hover { text-decoration: none; border-color: var(--color-primary); }
.btn-primary { background: var(--color-primary); border-color: var(--color-primary); color: #fff; }
.btn-primary:hover { background: var(--color-primary-dark); }
.btn-lg { min-height: 60px; font-size: 1.1rem; width: 100%; }
.btn-secondary { background: var(--color-bg); }
.btn-danger { color: var(--color-overdue-fg); border-color: var(--color-overdue-fg); }
.btn-block { width: 100%; }
.btn-row { display: flex; flex-wrap: wrap; gap: 0.6rem; }

.action-grid {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 0.75rem;
}
@media (min-width: 600px) {
  .action-grid { grid-template-columns: repeat(4, 1fr); }
}
.action-grid .btn { flex-direction: column; min-height: 84px; }

/* ---- Forms ---- */
label { display: block; font-weight: 600; margin-bottom: 0.3rem; margin-top: 0.9rem; }
input:not([type="checkbox"]):not([type="radio"]), select, textarea {
  width: 100%;
  padding: 0.6rem 0.7rem;
  border-radius: 8px;
  border: 1px solid var(--color-border);
  font-size: 1rem;
  min-height: var(--tap-min);
  background: var(--color-input-bg);
  color: var(--color-text);
}
textarea { min-height: 90px; }
.helptext { color: var(--color-muted); font-size: 0.85rem; }
.errorlist { color: var(--color-overdue-fg); list-style: none; padding: 0; margin: 0.2rem 0; }
.field-errors { color: var(--color-overdue-fg); font-size: 0.9rem; }
.checkbox-row { display: flex; align-items: center; gap: 0.5rem; }

/* Django's CheckboxSelectMultiple renders a plain <ul> of
   <li><label><input>text</label></li> -- style it directly rather than
   requiring every template to wrap each item in .checkbox-row by hand.
   Apply the .checklist class to a wrapper div around {{ form.field }} in
   the template to opt a given multi-checkbox field into this styling. */
.checklist ul {
  list-style: none;
  padding: 0;
  margin: 0.3rem 0 0.9rem;
}
.checklist li { margin-bottom: 0.4rem; }
.checklist label {
  display: flex;
  align-items: center;
  gap: 0.5rem;
  font-weight: 400;
  min-height: var(--tap-min);
  padding: 0.3rem 0;
  margin: 0;
  cursor: pointer;
}

/* ---- Badges / status ---- */
.badge {
  display: inline-block;
  padding: 0.2rem 0.6rem;
  border-radius: 999px;
  font-size: 0.8rem;
  font-weight: 700;
}
.status-ok { background: var(--color-ok-bg); color: var(--color-ok-fg); }
.status-due_soon, .status-due-soon { background: var(--color-due-soon-bg); color: var(--color-due-soon-fg); }
.status-overdue { background: var(--color-overdue-bg); color: var(--color-overdue-fg); }
.status-unknown { background: var(--color-unknown-bg); color: var(--color-unknown-fg); }

.status-dot {
  display: inline-block;
  width: 12px;
  height: 12px;
  border-radius: 50%;
  vertical-align: middle;
}

/* ---- Tables ---- */
table { width: 100%; border-collapse: collapse; }
th, td { text-align: left; padding: 0.55rem 0.5rem; border-bottom: 1px solid var(--color-border); }
th { color: var(--color-muted); font-size: 0.8rem; text-transform: uppercase; letter-spacing: 0.03em; }
.table-scroll { overflow-x: auto; }

/* ---- Stat tiles ---- */
.stat-grid {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 0.9rem;
  margin-bottom: 1.25rem;
}
@media (min-width: 700px) {
  .stat-grid { grid-template-columns: repeat(4, 1fr); }
}
.stat-tile {
  background: var(--color-surface);
  border: 1px solid var(--color-border);
  border-radius: var(--radius);
  padding: 1rem;
}
.stat-tile .stat-value { font-size: 1.8rem; font-weight: 800; }
.stat-tile .stat-label { color: var(--color-muted); font-size: 0.85rem; }
.stat-tile.tile-overdue .stat-value { color: var(--color-overdue-fg); }
.stat-tile.tile-due-soon .stat-value { color: var(--color-due-soon-fg); }

/* ---- Messages ---- */
.messages { list-style: none; padding: 0; margin: 0 0 1rem; }
.messages li {
  padding: 0.65rem 0.9rem;
  border-radius: 8px;
  margin-bottom: 0.5rem;
  border: 1px solid var(--color-border);
}
.messages li.success { background: var(--color-ok-bg); color: var(--color-ok-fg); }
.messages li.error { background: var(--color-overdue-bg); color: var(--color-overdue-fg); }
.messages li.warning { background: var(--color-due-soon-bg); color: var(--color-due-soon-fg); }
.messages li.info { background: var(--color-unknown-bg); color: var(--color-text); }

/* ---- Bottom mobile nav ---- */
.mobile-tabbar {
  position: fixed;
  bottom: 0;
  left: 0;
  right: 0;
  display: flex;
  background: var(--color-surface);
  border-top: 1px solid var(--color-border);
  z-index: 50;
}
.mobile-tabbar a {
  flex: 1;
  text-align: center;
  padding: 0.55rem 0.2rem 0.7rem;
  color: var(--color-text);
  font-size: 0.75rem;
}
.mobile-tabbar a .icon { display: block; font-size: 1.3rem; }
.mobile-tabbar a.scan-cta { color: var(--color-primary); font-weight: 700; }
@media (min-width: 900px) {
  .mobile-tabbar { display: none; }
}

/* ---- Offline sync toast ---- */
.offline-toast {
  position: fixed;
  bottom: 70px;
  left: 50%;
  transform: translateX(-50%) translateY(20px);
  background: var(--color-navbar-bg);
  color: #fff;
  padding: 0.6rem 1.1rem;
  border-radius: 8px;
  font-size: 0.85rem;
  max-width: 90%;
  text-align: center;
  opacity: 0;
  pointer-events: none;
  transition: opacity 0.2s ease, transform 0.2s ease;
  z-index: 100;
}
.offline-toast-visible { opacity: 1; transform: translateX(-50%) translateY(0); }
.offline-toast-error { background: var(--color-overdue-fg); }
@media (min-width: 900px) {
  .offline-toast { bottom: 20px; }
}

/* ---- Footer ---- */
.app-footer {
  margin-top: 2rem;
  padding-top: 1rem;
  border-top: 1px solid var(--color-border);
  color: var(--color-muted);
  font-size: 0.8rem;
  text-align: center;
}
.app-footer a { color: var(--color-muted); text-decoration: underline; }
.app-footer a:hover { color: var(--color-primary); }

/* ---- Misc ---- */
.muted { color: var(--color-muted); }
.text-center { text-align: center; }
.mt-0 { margin-top: 0; }
.mb-0 { margin-bottom: 0; }
.section-divider { border: none; border-top: 1px solid var(--color-border); margin: 1.25rem 0; }
.photo-thumb {
  width: 100%;
  aspect-ratio: 1;
  object-fit: cover;
  border-radius: 8px;
  border: 1px solid var(--color-border);
}
.photo-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(110px, 1fr));
  gap: 0.6rem;
}
.photo-item { display: flex; flex-direction: column; gap: 0.3rem; }
.photo-type-before { background: var(--color-due-soon-bg); color: var(--color-due-soon-fg); }
.photo-type-after { background: var(--color-ok-bg); color: var(--color-ok-fg); }
.photo-type-general { background: var(--color-unknown-bg); color: var(--color-unknown-fg); }
.photo-caption {
  font-size: 0.78rem;
  color: var(--color-muted);
  overflow-wrap: break-word;
  margin: 0;
}
.photo-service-link { font-size: 0.75rem; }
.photo-service-link a { color: var(--color-muted); }
.qr-preview { max-width: 220px; }
.empty-state { text-align: center; color: var(--color-muted); padding: 2.5rem 1rem; }

@media (prefers-color-scheme: dark) {
  :root {
    --color-bg: #14171c;
    --color-surface: #1c2027;
    --color-text: #e7e9ec;
    --color-muted: #9aa2ad;
    --color-border: #2b3138;
    --color-input-bg: #20242b;
  }
  /* No separate input/select/textarea rule needed here anymore -- they
     already read var(--color-input-bg)/var(--color-text) from the base
     rule above, which only re-resolves the same variables redefined
     just above. Keeping color rules here in the past (duplicating the
     base selector with hardcoded values) was exactly what let this drift
     out of sync with a specificity change elsewhere and silently stopped
     applying in dark mode. */
}
