:root {
  --bg: #f5f6f8;
  --surface: #ffffff;
  --text: #1a1a1a;
  --muted: #555555;
  --border: #ccd2da;
  --th-bg: #eceef1;
  --shadow: rgba(0, 0, 0, 0.1);
  --link: #2563eb;
}

@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) {
    --bg: #16181d;
    --surface: #1f232b;
    --text: #e6e8eb;
    --muted: #9aa1ab;
    --border: #2d323b;
    --th-bg: #262b33;
    --shadow: rgba(0, 0, 0, 0.4);
    --link: #60a5fa;
  }
}

:root[data-theme="dark"] {
  --bg: #16181d;
  --surface: #1f232b;
  --text: #e6e8eb;
  --muted: #9aa1ab;
  --border: #2d323b;
  --th-bg: #262b33;
  --shadow: rgba(0, 0, 0, 0.4);
  --link: #60a5fa;
}

* {
  box-sizing: border-box;
}

body {
  font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Helvetica, Arial, sans-serif;
  background: var(--bg);
  color: var(--text);
  line-height: 1.4;
  margin: 0;
  padding: 0 1.5rem 1.25rem;
}

header {
  padding: 1rem 0 0.75rem;
  display: flex;
  align-items: center;
  justify-content: space-between;
}

.header-actions {
  display: flex;
  gap: 0.5rem;
}

h1 {
  font-size: 1.4rem;
  margin: 0;
}

h1 a {
  color: inherit;
  text-decoration: none;
}

h2 {
  font-size: 1.15rem;
  margin: 0 0 0.2rem;
}

a {
  color: var(--link);
}

.breadcrumb {
  margin: 0 0 0.6rem;
  font-size: 0.85rem;
}

.breadcrumb a {
  text-decoration: none;
}

.breadcrumb .crumb-sep {
  color: var(--muted);
  margin: 0 0.35rem;
}

.system-description {
  color: var(--muted);
  margin: 0 0 0.3rem;
  font-size: 0.9rem;
}

.muted-note {
  color: var(--muted);
  font-size: 0.85rem;
  margin-left: 0.4rem;
}

.page-hint {
  color: var(--muted);
  margin: 1.5rem 0 0;
  font-size: 0.75rem;
  text-align: center;
}

.system-email {
  color: var(--muted);
  margin: 0 0 0.6rem;
  font-size: 0.85rem;
  font-family: ui-monospace, Menlo, Consolas, monospace;
}

.icon-button {
  background: var(--surface);
  color: var(--text);
  border: 1px solid var(--border);
  border-radius: 6px;
  padding: 0.3rem 0.7rem;
  font-size: 0.95rem;
  cursor: pointer;
}

.hamburger-button {
  display: inline-block;
}

.mobile-menu {
  display: none;
}

.mobile-menu.open {
  display: flex;
  flex-direction: column;
  position: fixed;
  top: 3.5rem;
  right: 1.5rem;
  min-width: 12rem;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: 8px;
  box-shadow: 0 4px 16px var(--shadow);
  z-index: 1000;
  overflow: hidden;
}

:root[data-nav-side="left"] .mobile-menu.open {
  right: auto;
  left: 1.5rem;
}

.mobile-menu form {
  display: contents;
}

.mobile-menu button,
.mobile-menu a {
  display: flex;
  align-items: center;
  font: inherit;
  text-align: left;
  background: none;
  border: none;
  color: var(--text);
  text-decoration: none;
  padding: 0.7rem 1rem;
  cursor: pointer;
  transition: background-color 0.1s ease;
}

.menu-icon {
  display: inline-block;
  min-width: 1.5rem;
  margin-right: 0.5rem;
  text-align: center;
}

.mobile-menu button:hover,
.mobile-menu a:hover {
  background: var(--th-bg);
}

.mobile-menu .menu-divider {
  border-top: 1px solid var(--border);
}

.mobile-menu .mobile-only {
  display: none;
}

table {
  width: 100%;
  border-collapse: collapse;
  background: var(--surface);
  box-shadow: 0 1px 3px var(--shadow);
}

th, td {
  text-align: left;
  padding: 0.4rem 0.7rem;
  border-bottom: 1px solid var(--border);
  font-size: 0.9rem;
}

th {
  background: var(--th-bg);
  font-weight: 600;
}

tr:last-child td {
  border-bottom: none;
}

.raw-content {
  white-space: pre-wrap;
  word-break: break-word;
  font-size: 0.85rem;
  margin: 0;
}

/* CCUs and RTUs are separate <table> elements but meant to read as one aligned
   grid when stacked - table-layout: auto sizes each table's columns from its own
   content, which drifts out of alignment whenever the two tables' text lengths
   differ (e.g. a short CCU name vs. longer siren names). Fixed, shared percentage
   widths keep both tables' 5 columns lined up regardless of content. Both tables
   use the same column order (Unit #, Name, Location, Status, last-event column),
   so one shared set of widths covers both. */
.rtu-ccu-table {
  table-layout: fixed;
}

.rtu-ccu-table th:nth-child(1) {
  width: 7%;
}

/* Enough for the longest real siren name to still fit on one line without
   reserving so much that Location (the very next column) ends up visually far
   from Name whenever names are short - the width that frees up compared to
   Location/Status goes to the last column below instead, since it's only ever a
   single short timestamp with room to spare either way. */
.rtu-ccu-table th:nth-child(2) {
  width: 30%;
}

.rtu-ccu-table th:nth-child(3) {
  width: 22%;
}

/* Status only ever holds one short badge ("Normal", "Trouble (1)", "Critical (2)"),
   never worth the 20% it used to reserve - the space freed here goes to Name
   above, which was wrapping onto multiple lines for longer siren names. */
.rtu-ccu-table th:nth-child(4) {
  width: 12%;
}

.rtu-ccu-table th:nth-child(5) {
  width: 29%;
}

/* Each condition is one row instead of a flat label/input stack, so the existing
   th/td border-bottom already gives clear separation between conditions - this
   just gives the interactive elements inside cells the same look .edit-form
   inputs/selects get, without .edit-form's narrow 28rem max-width. */
.ticket-threshold-table input,
.ticket-threshold-table select {
  font: inherit;
  color: var(--text);
  background: var(--bg);
  border: 1px solid var(--border);
  border-radius: 6px;
  padding: 0.4rem 0.5rem;
}

.ticket-threshold-table input {
  width: 6rem;
}

.ticket-threshold-table select {
  width: 100%;
  max-width: 16rem;
}

.ticket-threshold-table td label {
  font-size: 0.9rem;
}

/* The default value/unit no longer fits as an input placeholder now that the
   input shares its cell with a unit <select> (a 6rem-wide input can't show
   "(default: 1470 minutes)" without clipping mid-word) - shown as its own hint
   next to the fields instead, always visible regardless of what's typed. */
.threshold-default-hint {
  display: block;
  margin-top: 0.25rem;
  color: var(--muted);
  font-size: 0.8rem;
}

.badge {
  display: inline-block;
  padding: 0.15rem 0.6rem;
  border-radius: 999px;
  font-size: 0.78rem;
  font-weight: 600;
  text-transform: capitalize;
  color: #fff;
  margin-right: 0.3rem;
}

.badge:last-child {
  margin-right: 0;
}

/* Keeps a multi-badge cell (e.g. systems.html's RTU/CCU Status Breakdown columns)
   on one line instead of wrapping - without this, table-layout: auto picks one
   shared pixel width per column across every row, and each row's specific badge
   combination (which varies slightly in total width - "17 Normal" vs "5 Normal"
   already differ by a digit) either fits under that width or doesn't, so some
   rows wrap to a second line and others don't, for no reason a reader can see.
   .table-scroll's existing horizontal scroll (already used to handle any
   too-wide table) takes over for the rare row that doesn't fit at all. */
.badge-nowrap {
  white-space: nowrap;
}

.badge-operational {
  background: #1a7f37;
}

.badge-dead {
  background: #6b7280;
  color: #f3f4f6;
  cursor: help;
}

.badge-archived {
  background: #6b7280;
  color: #f3f4f6;
}

/* Marks an event Director generated itself (see Event.is_synthetic) rather than
   one parsed from a real Commander email - a distinct informational blue, not
   .badge-dead's "this didn't matter" gray (a synthetic event DID clear a fault)
   and not any of the severity colors (this isn't a severity signal). */
.badge-inferred {
  background: #3b5bdb;
  color: #f3f4f6;
  cursor: help;
}

.badge-warning {
  background: #d69e00;
  color: #1a1a1a;
  cursor: help;
}

/* .badge-ok is kept as its own class (not renamed to .badge-normal) because
   info.html/users.html reuse it for unrelated green-badge concepts (scheduler
   running, ticket forwarding enabled, active user) that have nothing to do with
   condition severity - .badge-normal below is the siren/CCU severity scheme's own
   "nothing's wrong" class, styled identically. */
.badge-ok {
  background: #1a7f37;
}

.badge-normal {
  background: #1a7f37;
}

.badge-supervisory {
  background: #ffdd00;
  color: #1a1a1a;
  cursor: help;
}

/* .badge-trouble/.badge-critical are the two severity levels above Supervisory
   (see ConditionStatusLevel) - a traffic-light progression from Supervisory's
   bright yellow through Trouble's bright orange to Critical's red, each a clear
   step up in visual urgency. .badge-alarm itself is kept
   (not renamed/reused) because info.html still reuses it for an unrelated
   red-badge concept (scheduler not running / ticket forwarding disabled) - it's
   simply no longer emitted by siren/CCU status badges, which use .badge-critical
   instead. */
.badge-alarm {
  background: #8a1f1f;
  cursor: help;
}

.badge-trouble {
  background: #ff8800;
  color: #1a1a1a;
  cursor: help;
}

.badge-critical {
  background: #dc2626;
  cursor: help;
}

/* Map System View mode only (see templates/map.html's SirenSystem.overview_status
   strings) - same color values as .badge-supervisory/.badge-alarm above, but a
   distinct class so a "system" item's status string never collides with the
   unit-level tiers' meaning (a system-level Alarm is yellow, not the unit-level
   Alarm's dark red). Solid/non-animated even for heartbeat-fail - only the map
   marker itself blinks, driven by JS (see markerIcon's `dim` param), not this
   badge. */
.badge-system-alarm {
  background: #d69e00;
  color: #1a1a1a;
  cursor: help;
}

.badge-heartbeat-fail {
  background: #8a1f1f;
  cursor: help;
}

.contributing-issues {
  margin: 0.75rem 0;
}

.contributing-issues-label {
  display: block;
  font-weight: 600;
  margin-bottom: 0.3rem;
}

.contributing-issues-list {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 0.3rem;
}

/* These badges are links to the causing event, not just hover-for-info text like
   .badge-supervisory/.badge-alarm elsewhere on the page - cursor: pointer (not the
   inherited cursor: help) signals that clicking does something. */
.contributing-issues-list a.badge {
  cursor: pointer;
  text-decoration: none;
}

.tooltip {
  cursor: help;
}

.tooltip::after {
  content: attr(data-tooltip);
  /* Fixed (viewport-relative) positioning, driven by --tooltip-x/--tooltip-y set in
     JS from the trigger's on-screen position. Unlike absolute positioning against an
     ancestor, this can't be clipped by, or add scrollable width to, a scrolling
     ancestor like .table-scroll. */
  position: fixed;
  left: var(--tooltip-x, 0px);
  top: var(--tooltip-y, 0px);
  transform: translate(-50%, -100%);
  background: var(--text);
  color: var(--bg);
  padding: 0.4rem 0.6rem;
  border-radius: 6px;
  font-size: 0.75rem;
  font-weight: 400;
  text-transform: none;
  white-space: pre-line;
  width: max-content;
  max-width: 16rem;
  box-shadow: 0 4px 16px var(--shadow);
  opacity: 0;
  pointer-events: none;
  transition: opacity 0.15s ease;
  z-index: 10;
}

.tooltip:hover::after,
.tooltip:focus::after {
  opacity: 1;
}

.tooltip.tooltip-flip::after {
  transform: translate(-50%, 0.5rem);
}

.table-scroll {
  overflow-x: auto;
  -webkit-overflow-scrolling: touch;
}

.list-cards {
  display: none;
  flex-direction: column;
  gap: 0.6rem;
}

.list-card {
  background: var(--surface);
  box-shadow: 0 1px 3px var(--shadow);
  border-radius: 8px;
  padding: 0.7rem 0.9rem;
}

.list-card-name {
  font-weight: 600;
  margin-bottom: 0.4rem;
}

.list-card-badges {
  margin-bottom: 0.5rem;
}

.list-card-row {
  display: flex;
  justify-content: space-between;
  gap: 0.5rem;
  font-size: 0.85rem;
  color: var(--muted);
}

.list-card-row > span:last-child {
  min-width: 0;
  overflow-wrap: break-word;
  text-align: right;
}

.list-card-row:not(:last-child) {
  margin-bottom: 0.15rem;
}

.ticket-recent {
  background: #8a1f1f;
  color: #fff;
}

.ticket-stale {
  background: #6b7280;
  color: #f3f4f6;
}

.empty-state {
  color: var(--muted);
}

.filter-tabs {
  display: flex;
  gap: 0.5rem;
  margin: 0 0 0.9rem;
}

.filter-tabs a {
  display: inline-block;
  text-decoration: none;
  color: var(--text);
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: 6px;
  padding: 0.3rem 0.8rem;
  font-size: 0.9rem;
}

.filter-tabs a.active {
  color: #fff;
  background: var(--link);
  border-color: var(--link);
}

/* Independent on/off toggles (CCUs / RTUs), unlike .filter-tabs above which is a
   mutually-exclusive radio-style group - kept as a separate class so the two don't
   read as one shared selection. */
.filter-toggles {
  display: flex;
  gap: 0.5rem;
  margin: 0 0 0.9rem;
}

.filter-toggles a {
  display: inline-block;
  text-decoration: none;
  color: var(--text);
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: 6px;
  padding: 0.3rem 0.8rem;
  font-size: 0.9rem;
}

.filter-toggles a.active {
  color: #fff;
  background: var(--link);
  border-color: var(--link);
}

.pagination {
  display: flex;
  align-items: center;
  gap: 1rem;
  margin-top: 0.7rem;
  font-size: 0.9rem;
}

.pagination a {
  text-decoration: none;
}

.pagination-status {
  color: var(--muted);
}

.edit-form {
  display: flex;
  flex-direction: column;
  max-width: 28rem;
  background: var(--surface);
  border: 1px solid var(--border);
  box-shadow: 0 1px 3px var(--shadow);
  padding: 0.8rem 1rem;
}

.edit-form label {
  font-size: 0.85rem;
  font-weight: 600;
  margin: 0.5rem 0 0.25rem;
}

.edit-form input,
.edit-form select,
.edit-form textarea {
  font: inherit;
  color: var(--text);
  background: var(--bg);
  border: 1px solid var(--border);
  border-radius: 6px;
  padding: 0.5rem 0.6rem;
}

.edit-form input[readonly] {
  background: var(--border);
  color: var(--muted);
  cursor: default;
}

.form-actions {
  display: flex;
  align-items: center;
  gap: 0.8rem;
  margin-top: 0.9rem;
}

/* Users table's action column reuses .form-actions for its buttons' shared style
   and inter-button gap, but it's the cell's only content (not below a stack of
   form fields), so the top margin above would just misalign it from the rest of
   the row. */
td .form-actions {
  margin-top: 0;
}

.form-actions button {
  font: inherit;
  font-weight: 600;
  color: #fff;
  background: var(--link);
  border: none;
  border-radius: 6px;
  padding: 0.5rem 1rem;
  cursor: pointer;
}

.button-secondary {
  text-decoration: none;
}

.button-primary {
  display: inline-block;
  font-weight: 600;
  color: #fff;
  background: var(--link);
  border: none;
  border-radius: 6px;
  padding: 0.5rem 1rem;
  text-decoration: none;
}

.delete-form {
  max-width: 28rem;
  margin-top: 0.7rem;
}

.button-danger,
.form-actions .button-danger {
  font: inherit;
  font-weight: 600;
  color: #fff;
  background: #8a1f1f;
  border: none;
  border-radius: 6px;
  padding: 0.5rem 1rem;
  cursor: pointer;
}

.button-archive,
.form-actions .button-archive {
  font: inherit;
  font-weight: 600;
  color: #fff;
  background: #6b7280;
  border: none;
  border-radius: 6px;
  padding: 0.5rem 1rem;
  cursor: pointer;
}

.error {
  color: #fff;
  background: #8a1f1f;
  border-radius: 6px;
  padding: 0.5rem 0.8rem;
  font-size: 0.9rem;
  max-width: 28rem;
}

.toast {
  position: fixed;
  top: 1.5rem;
  left: 50%;
  background: var(--surface);
  color: var(--text);
  border: 1px solid var(--border);
  border-radius: 10px;
  padding: 0.9rem 1.8rem;
  box-shadow: 0 4px 16px var(--shadow);
  font-size: 1.15rem;
  font-weight: 600;
  opacity: 0;
  transform: translateX(-50%) translateY(-0.5rem);
  pointer-events: none;
  transition: opacity 0.2s ease, transform 0.2s ease;
  z-index: 1000;
}

.toast.show {
  opacity: 1;
  transform: translateX(-50%) translateY(0);
}

/* Unlike .toast (auto-hides after 3s), this stays up until the user acts on it -
   a data change happened somewhere on the page, not a one-off confirmation of
   something the user themselves just did. */
.live-update-banner {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 0.6rem;
  background: var(--link);
  color: #fff;
  padding: 0.6rem 1rem;
  font-size: 0.9rem;
  font-weight: 600;
  border-radius: 6px;
  margin: 0.5rem 0;
}

.live-update-banner a {
  color: #fff;
  text-decoration: underline;
}

/* .live-update-banner's own `display: flex` above outranks the [hidden]
   attribute's built-in `display: none` - both are author vs. UA-stylesheet origin,
   not a specificity tie, so the class rule always wins without this override (see
   the identical map.html #map-legend-badges/#map-legend-detail fix for the same
   underlying cause). */
.live-update-banner[hidden] {
  display: none;
}

@media (max-width: 640px) {
  .desktop-table {
    display: none;
  }

  .list-cards {
    display: flex;
  }

  #sync-button,
  #theme-toggle {
    display: none;
  }

  :root[data-nav-side="left"] .header-actions {
    order: -1;
  }

  .mobile-menu .mobile-only {
    display: block;
  }
}

/* Map page */

#map-toolbar {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 0.75rem;
  margin-bottom: 0.75rem;
  flex-wrap: wrap;
}

#map-legend {
  display: flex;
  align-items: center;
  gap: 0.3rem;
  flex-wrap: wrap;
}

#map-legend-badges,
#map-legend-badges-system {
  display: flex;
  gap: 0.3rem;
  flex-wrap: wrap;
}

#map-legend-detail {
  display: flex;
  flex-direction: column;
  gap: 0.15rem;
  max-width: 24rem;
  font-size: 0.85rem;
}

/* #map-legend-badges/#map-legend-badges-system/#map-legend-detail's own
   `display` rules above outrank the [hidden] attribute's built-in
   `display: none` on specificity (id selector vs. attribute selector) - these
   overrides restore the native hidden-attribute behavior for all three, so JS
   can toggle `.hidden = true/false` and have it stick. */
#map-legend-badges[hidden],
#map-legend-badges-system[hidden],
#map-legend-detail[hidden] {
  display: none;
}

.map-legend-detail-title {
  font-weight: 700;
}

.map-legend-detail-label {
  font-weight: 600;
  margin-top: 0.2rem;
}

.map-legend-detail-list {
  margin: 0.1rem 0;
  padding-left: 1.1rem;
}

.map-legend-detail-muted {
  color: var(--muted);
}

.map-legend-detail-view-link {
  margin-top: 0.2rem;
}

#map-controls {
  display: flex;
  align-items: center;
  gap: 0.4rem;
  padding: 0.3rem;
  border: 1px solid var(--border);
  border-radius: 8px;
  background: var(--surface);
  flex-wrap: wrap;
}

/* Flush/borderless within the panel - #map-controls itself is now the only
   outer border, so a second border per button would look like boxes-in-a-box
   instead of one grouped control panel. */
#map-controls .icon-button {
  border: none;
  background: transparent;
}

/* Only #dark-map-toggle-button, #poi-markers-toggle-button, and
   #poi-labels-toggle-button use .active among #map-controls' icon-buttons -
   save/kiosk are one-shot actions with no persistent on/off state to show, same
   distinction as .map-type-button.active below. */
#map-controls .icon-button.active {
  background: var(--link);
  color: #fff;
  border-radius: 6px;
}

#map-type-buttons {
  display: inline-flex;
  border-right: 1px solid var(--border);
  padding-right: 0.4rem;
}

.map-type-button {
  background: var(--surface);
  color: var(--text);
  border: none;
  border-right: 1px solid var(--border);
  padding: 0.3rem 0.7rem;
  font-size: 0.85rem;
  cursor: pointer;
}

.map-type-button:last-child {
  border-right: none;
}

.map-type-button.active {
  background: var(--link);
  color: #fff;
}

/* One boxed panel holding both the legend-scope (All/In View) and type-filter
   (CCUs/RTUs) button groups, same treatment as #map-controls below - every
   button inside uses .map-type-button, so all four end up the same height and
   baseline-aligned regardless of which group they're in. */
#legend-controls {
  display: flex;
  align-items: center;
  gap: 0.4rem;
  padding: 0.3rem;
  border: 1px solid var(--border);
  border-radius: 8px;
  background: var(--surface);
  flex-wrap: wrap;
}

/* Dividers between the three groups, same pattern as #map-type-buttons dividing
   off from the action buttons inside #map-controls. #type-filter-buttons gets
   one too now that #system-view-buttons follows it - it's no longer the last
   group (it's hidden outright while System View is on, see map.html's
   updateSystemViewButton, so this divider disappears right along with it). */
#legend-scope-buttons {
  display: inline-flex;
  border-right: 1px solid var(--border);
  padding-right: 0.4rem;
}

#type-filter-buttons {
  display: inline-flex;
  border-right: 1px solid var(--border);
  padding-right: 0.4rem;
}

/* #type-filter-buttons' own `display: inline-flex` above outranks the [hidden]
   attribute's built-in `display: none` on specificity (id selector vs.
   attribute selector) - same underlying cause as #map-legend-badges[hidden]
   above, same fix - restores the native hidden-attribute behavior so
   map.html's updateSystemViewButton() can toggle `.hidden = true/false` on it
   and have it actually stick. */
#type-filter-buttons[hidden] {
  display: none;
}

#system-view-buttons {
  display: inline-flex;
}

#map-container {
  width: 100%;
  height: 70vh;
  min-height: 24rem;
  border: 1px solid var(--border);
  border-radius: 6px;
  background: var(--surface);
}

/* Un-fullscreened map page: stretch #map-container down to fill the rest of the
   viewport instead of stopping at a fixed 70vh and leaving blank space below it.
   Standard "sticky footer" flex trick - body is a min-height: 100vh column, main
   grows to fill it (flex: 1), and #map-container in turn grows to fill main
   (also flex: 1), so the map always reaches the bottom of the viewport regardless
   of how tall the (wrapping) toolbar above it ends up being. The page-hint
   footer is dropped entirely on this page (see body.map-page .page-hint below)
   so it doesn't eat into that space. min-height: 0 on main overrides flexbox's
   default min-height: auto, which would otherwise refuse to shrink main below
   its content size and break the fill-to-bottom effect. */
body.map-page {
  display: flex;
  flex-direction: column;
  min-height: 100vh;
}

body.map-page main {
  flex: 1;
  display: flex;
  flex-direction: column;
  min-height: 0;
}

body.map-page #map-container {
  flex: 1;
  height: auto;
}

/* Removed on the map page (not just hidden in kiosk mode) - it's dead space
   below the map that serves no purpose here, since none of the map's own
   controls rely on hover/tap-for-detail the way tables elsewhere do. */
body.map-page .page-hint {
  display: none;
}

/* Kiosk mode: hide everything but the map itself and let it fill the viewport. */
body.kiosk-mode {
  padding: 0;
  margin: 0;
}

body.kiosk-mode header,
body.kiosk-mode .breadcrumb,
body.kiosk-mode .page-hint,
body.kiosk-mode main > h2 {
  display: none;
}

body.kiosk-mode #map-toolbar {
  position: fixed;
  top: 0.5rem;
  right: 0.5rem;
  z-index: 10;
  background: var(--surface);
  padding: 0.4rem 0.6rem;
  border-radius: 6px;
  box-shadow: 0 1px 4px var(--shadow);
}

body.kiosk-mode #map-container {
  width: 100vw;
  height: 100vh;
  min-height: 100vh;
  border: none;
  border-radius: 0;
}

/* Google's InfoWindow renders its own chrome (background/border/close button)
   outside our normal document flow, always with a white background regardless of
   the page's own theme - Google doesn't read our --bg/--surface vars. Content
   colors in here are deliberately fixed to the light-mode palette, not
   var(--text)/var(--muted)/var(--link), since those resolve to light colors under
   dark mode and would render near-invisible against Google's white box (this was
   exactly the low-contrast bug seen in dark mode before this fix). */
.map-info-window {
  position: relative;
  color: #1a1a1a;
  max-width: 16rem;
  /* headerDisabled (see map.html's initMap) drops Google's default close button
     and the header row it reserved - .map-info-close (below) replaces it, aligned
     with the first line of text instead of floating in blank space above it. */
  padding-right: 1.3rem;
}

.map-info-window a {
  color: #2563eb;
}

.map-info-close {
  position: absolute;
  top: 0;
  right: 0;
  width: 1.1rem;
  height: 1.1rem;
  padding: 0;
  border: none;
  background: transparent;
  color: #555555;
  font-size: 1.1rem;
  line-height: 1;
  cursor: pointer;
}

.map-info-close:hover {
  color: #1a1a1a;
}

.map-info-location {
  color: #555555;
  font-size: 0.85rem;
}

.map-info-conditions {
  margin: 0.4rem 0;
  padding-left: 1.1rem;
  font-size: 0.85rem;
}

.map-info-detail-link {
  margin-top: 0.4rem;
}
