/* ---------- Admin status bar: name, notifications, logout in one row ----------
   A long email/name has no natural break point — without flex-wrap +
   min-width:0 this row can force the whole page wider than the viewport on
   a narrow phone screen instead of just wrapping or truncating. Kept
   deliberately muted (var(--field), not a saturated var(--navy) block) —
   this renders on every single admin page, and --navy is noticeably
   brighter/more saturated in dark mode, which made a full-width banner in
   that color feel overwhelming. */
.admin-status-bar {
  display: flex;
  flex-wrap: wrap;
  justify-content: space-between;
  align-items: center;
  gap: 8px 16px;
  background: var(--field);
  color: var(--ink-soft);
  border-bottom: 1px solid var(--line);
  padding: 10px 16px;
  font-size: 13px;
  font-weight: 600;
  /* Must stay pinned directly below .navbar (sticky, top:0) rather than
     scroll away with the page — .sidebar is position:fixed at a top offset
     measured as navbar height + this bar's height, taken once from the
     page's resting layout. If this bar scrolled out of view like normal
     content, that offset would still assume it's there, leaving a gap the
     size of this bar between the navbar and the now-misplaced sidebar the
     moment you scroll down. */
  position: sticky;
  top: var(--navbar-height, 70px);
  z-index: 90;
}
.admin-status-name {
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  flex: 1 1 auto;
  color: var(--ink);
}
/* display:inline-flex would beat the hidden attribute (see consent.css), so
   the banner showed with an empty count when nothing was unread. */
.admin-status-notif[hidden] {
  display: none;
}
.admin-status-notif {
  display: inline-flex;
  align-items: center;
  gap: 4px;
  background: var(--navy-tint);
  color: var(--navy-dark);
  text-decoration: none;
  padding: 4px 12px;
  border-radius: 999px;
  flex: none;
}
.admin-status-notif:hover {
  text-decoration: underline;
}
.admin-status-logout {
  background: none;
  border: none;
  color: inherit;
  text-decoration: underline;
  cursor: pointer;
  font: inherit;
  flex: none;
}

/* ---------- Gallery event badge ---------- */
.card-image {
  position: relative;
}
/* Inline flex badge — NOT position:absolute like .gallery-event-badge
   (which is meant to overlay a position:relative image tile). This is used
   inline inside .member-row-actions' flex row, so absolute positioning
   here would render it relative to some unrelated ancestor instead. */
.pending-approval-badge {
  display: inline-block;
  background: #b45309;
  color: #fff;
  font-size: 11px;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.03em;
  padding: 4px 9px;
  border-radius: 999px;
  flex: none;
}

.gallery-event-badge {
  position: absolute;
  top: 10px;
  right: 10px;
  background: var(--navy);
  color: #fff;
  font-size: 11px;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.03em;
  padding: 4px 9px;
  border-radius: 999px;
}

/* ---------- Member row list ---------- */
.member-row-list {
  display: flex;
  flex-direction: column;
}
.member-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 16px;
  padding: 14px 4px;
  border-bottom: 1px solid var(--line);
  flex-wrap: wrap;
}
.member-row:last-child {
  border-bottom: none;
}
.member-row-info {
  display: flex;
  flex-direction: column;
  gap: 3px;
  min-width: 180px;
}
.member-row-name {
  font-weight: 600;
  font-size: 14.5px;
  color: var(--ink);
}
.member-row-meta {
  font-size: 12.5px;
  color: var(--ink-faint);
}
.member-row-dot {
  margin: 0 5px;
}
.member-age {
  font-weight: 600;
  color: var(--ink-soft);
}
.member-row-actions {
  display: flex;
  align-items: center;
  gap: 12px;
}
.age-preview {
  margin: -6px 0 12px;
}

/* ---------- Rich text toolbar (announcements) ---------- */
.text-toolbar {
  display: flex;
  gap: 4px;
  margin-bottom: 4px;
}
.bold-btn {
  width: 28px;
  height: 28px;
  padding: 0;
  border: 1px solid var(--line);
  border-radius: 6px;
  background: var(--card);
  color: var(--ink);
  font-weight: 700;
  font-size: 13px;
  cursor: pointer;
}
.bold-btn:hover {
  border-color: var(--navy);
  color: var(--navy-dark);
  background: var(--navy-tint);
}

/* ---------- Timestamp row editor (video) ---------- */
.timestamp-row {
  display: grid;
  grid-template-columns: 1fr;
  gap: 8px;
  padding: 12px;
  margin-bottom: 12px;
  border: 1px solid var(--line);
  border-radius: 8px;
}
.timestamp-row input {
  margin-bottom: 0;
}
.timestamp-row button {
  justify-self: end;
}

.checkbox-label {
  display: flex;
  align-items: center;
  gap: 8px;
  font-weight: 600;
  cursor: pointer;
}
.checkbox-label input[type="checkbox"] {
  width: 16px;
  height: 16px;
  accent-color: var(--navy);
}

.live-badge {
  position: absolute;
  top: 10px;
  right: 10px;
  background: #c0392b;
  color: #fff;
  font-size: 11px;
  font-weight: 700;
  letter-spacing: 0.04em;
  padding: 3px 8px;
  border-radius: 999px;
}

/* ---------- Schedule row editor (fellowship) ---------- */
.schedule-row {
  display: grid;
  grid-template-columns: 1fr;
  gap: 8px;
  padding: 12px;
  margin-bottom: 12px;
  border: 1px solid var(--line);
  border-radius: 8px;
}
.schedule-row select,
.schedule-row input {
  margin-bottom: 0;
}
.schedule-row button {
  justify-self: end;
}

/* ---------- Tag chips (staff) ---------- */
.tag-chip-list {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
  margin-bottom: 10px;
}
.tag-chip {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  background: var(--navy-tint);
  color: var(--navy-dark);
  font-size: 12.5px;
  font-weight: 600;
  padding: 5px 10px;
  border-radius: 999px;
}
.tag-chip button {
  background: none;
  border: 0;
  padding: 0;
  color: var(--navy-dark);
  font-size: 14px;
  line-height: 1;
  cursor: pointer;
}
.tag-input-row {
  display: flex;
  gap: 8px;
  margin-bottom: 10px;
}
.tag-input-row input {
  flex: 1;
  margin-bottom: 0;
}
.tag-suggestions {
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
}
.tag-suggestion {
  background: var(--field);
  color: var(--ink-soft);
  border: 1px solid var(--line);
  border-radius: 999px;
  padding: 4px 10px;
  font-size: 12px;
  cursor: pointer;
  transition:
    border-color 0.2s,
    color 0.2s;
}
.tag-suggestion:hover {
  border-color: var(--navy);
  color: var(--navy-dark);
}

/* ---------- Date-linked content (church program / kingdom prayer / announcement) ---------- */
.date-search-form {
  display: flex;
  /* The generic `form { flex-direction: column }` rule further down this
     file (meant for ordinary label-over-input edit forms) otherwise wins
     here too, since this rule never used to set flex-direction itself —
     stacking every field into its own full-width row instead of side by
     side, on every page that uses this class (analytics, QR stats,
     anonymous messages, and every date-linked content page). */
  flex-direction: row;
  align-items: flex-end;
  gap: 10px;
  flex-wrap: wrap;
}
/* .f-field's own default margin-bottom (styles.css, meant for stacked
   vertical form fields) leaves empty space below whichever control
   doesn't need it here — align-items:flex-end on the row above aligns
   each .f-field's own bottom edge, so that leftover space pushes a
   select/text control up relative to a sibling field with no such gap
   (e.g. the date inputs, which already zeroed only their own margin).
   Zeroing it on the .f-field container itself, not per control type,
   means any control type added to this row lines up correctly by
   default instead of needing its own selector added here every time. */
.date-search-form .f-field {
  margin-bottom: 0;
  display: flex;
  flex-direction: column;
  gap: 6px;
}
.date-search-form .f-field label {
  margin: 0;
  min-width: 0;
  font-size: 12px;
  color: var(--ink-soft);
}
/* Two classes deep on purpose: the generic input[type="text"] rule further
   down this file (margin-bottom: 15px) otherwise beats a one-class selector
   by source order, and that leftover margin lifted the search box and its
   label above the date fields. Every control and button in the row shares
   one height and corner radius. */
.date-search-form .f-field input:not([type="radio"], [type="checkbox"]),
.date-search-form .f-field select,
.date-search-form button,
.date-search-form .btn,
.date-search-form .btn-secondary {
  margin: 0;
  height: 44px;
  box-sizing: border-box;
  border-radius: 10px;
}
.date-search-form button,
.date-search-form .btn,
.date-search-form .btn-secondary {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  padding: 0 20px;
  white-space: nowrap;
}
/* The field that soaks up spare width (e.g. a text search). */
.date-search-form .f-grow {
  flex: 1;
  min-width: 120px;
}
/* A radio/checkbox group (analytics "Month / Year") stays on one line,
   control-height, with normal-size labels. */
.date-search-form .f-field:has(input[type="radio"], input[type="checkbox"]) {
  flex-direction: row;
  align-items: center;
  gap: 14px;
  height: 44px;
}
.date-search-form .f-field:has(input[type="radio"], input[type="checkbox"]) label {
  font-size: inherit;
  color: inherit;
  margin-left: 0 !important;
}
@media (max-width: 600px) {
  /* Phone: one full-width row per field, buttons sharing the last row. */
  .date-search-form .f-field {
    flex: 1 1 100%;
    min-width: 0 !important;
  }
  .date-search-form .f-field input:not([type="radio"], [type="checkbox"]),
  .date-search-form .f-field select {
    width: 100%;
  }
  .date-search-form button,
  .date-search-form .btn,
  .date-search-form .btn-secondary {
    flex: 1;
  }
}
/* Native date-picker icon and select dropdown follow the theme (the icon
   was dark-on-dark before). */
[data-theme="dark"] input,
[data-theme="dark"] select {
  color-scheme: dark;
}

.linked-program-note {
  background: var(--navy-tint);
  border: 1px solid color-mix(in srgb, var(--navy) 25%, var(--line));
  border-radius: 10px;
  padding: 12px 14px;
  margin-bottom: 1rem;
  font-size: 13.5px;
  color: var(--ink-soft);
}
.linked-program-note.missing {
  background: rgba(192, 57, 43, 0.08);
  border-color: rgba(192, 57, 43, 0.3);
  color: #96281b;
}

.segment-item,
.point-item,
.section-item {
  border: 1px solid var(--line);
  border-radius: 10px;
  padding: 14px;
  margin-bottom: 12px;
  background: var(--field);
  display: flex;
  flex-direction: column;
  gap: 8px;
}
.segment-row {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 8px;
}
.segment-item input,
.point-item textarea,
.section-item input,
.section-item textarea {
  margin-bottom: 0;
}

.section-actions {
  display: flex;
  align-items: center;
  gap: 8px;
  flex-wrap: wrap;
}
.move-btn {
  width: 32px;
  height: 32px;
  padding: 0;
  border: 1px solid var(--line);
  border-radius: 6px;
  background: var(--card);
  cursor: pointer;
  font-size: 15px;
  line-height: 1;
}
.move-btn:hover {
  border-color: var(--navy);
  color: var(--navy-dark);
  background: var(--navy-tint);
}

#add-point-btn:disabled {
  opacity: 0.5;
  cursor: not-allowed;
}

.entry-list {
  list-style: none;
}
.entry-list li {
  display: flex;
  justify-content: space-between;
  align-items: center;
  gap: 10px;
  padding: 14px 0;
  border-bottom: 1px solid var(--line);
}
.entry-list li:last-child {
  border-bottom: none;
}
.entry-list a {
  color: var(--ink-soft);
  text-decoration: none;
  flex: 1;
}
.entry-list a b {
  color: var(--navy-dark);
}
.entry-list a:hover {
  color: var(--ink);
}
.entry-list li > span {
  flex: 1;
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

/* Error Logs — full multi-line content per row, not the single-line
   flex layout .entry-list normally assumes. */
.error-log-list li {
  display: block;
}
.error-log-meta {
  display: flex;
  flex-wrap: wrap;
  gap: 4px 12px;
  align-items: baseline;
  margin-bottom: 6px;
}
.error-log-meta span {
  /* A file path has no spaces to wrap on — without this it's exactly the
     kind of unbreakable content that forces horizontal overflow. */
  overflow-wrap: anywhere;
  min-width: 0;
}
.error-log-message {
  margin: 0;
  white-space: pre-wrap;
  word-break: break-word;
  font-size: 13px;
  background: var(--navy-tint);
  border-radius: 8px;
  padding: 10px 12px;
  max-height: 300px;
  overflow-y: auto;
}

/* QR Code edit page — a dedicated layout, not a reuse of .card-image
   (that class has a second, later rule elsewhere forcing height:180px for
   grid-thumbnail tiles; reusing it here clipped the Download/Stats links
   and redirect URL below the image outside its own box, overlapping the
   form next to it). */
.qr-edit-layout {
  display: flex;
  flex-wrap: wrap;
  align-items: flex-start;
  gap: 24px;
}
.qr-preview-column {
  flex: 0 0 220px;
  max-width: 220px;
  display: flex;
  flex-direction: column;
  gap: 12px;
}
.qr-preview-image {
  width: 100%;
  border-radius: var(--radius);
  border: 1px solid var(--line);
}
.qr-redirect-url {
  word-break: break-all;
}
.qr-edit-form {
  flex: 1 1 260px;
  min-width: 260px;
}
@media (max-width: 600px) {
  .qr-preview-column {
    flex: 1 1 100%;
    max-width: 100%;
  }
}

/* Layout & Spacing */
.layout-container {
  display: grid;
  grid-template-rows: auto 1fr auto;
  min-height: 100vh;
}

.content-grid {
  display: grid;
  grid-template-columns: 260px 1fr;
  justify-content: start;
  align-items: start;
  position: relative;
}

/* position:fixed (not sticky) — sticky is bounded by its grid row's own
   height, so once a long list (e.g. Error Logs with 100+ rows) makes
   .main-content much taller than one screen, the sidebar unsticks near the
   end of that scroll and stops tracking the viewport. Fixed removes it
   from grid flow entirely, so it always spans exactly one viewport height
   regardless of how tall any list gets. .main-content picks up the
   explicit grid-column below since a fixed item no longer occupies column
   1 for auto-placement purposes. */
.sidebar {
  width: 260px;
  /* --admin-header-height is measured in admin_layout.html (navbar +
     .admin-status-bar's real height, whatever it currently is) — falls
     back to 70px (navbar alone) before that script runs or with JS
     disabled, which is only wrong on a page with no .admin-status-bar
     (logged-out) or before it's ever been measured. */
  height: calc(100vh - var(--admin-header-height, 70px));
  background: var(--card);
  box-shadow: var(--shadow);
  border-right: 1px solid var(--line);
  position: fixed;
  top: var(--admin-header-height, 70px);
  left: 0;
  /* No overflow-y/scrolling on this element itself — see .sidebar-scroll.
     A position:fixed element that is ALSO its own overflow-y:auto scroll
     container is exactly the combination that triggers a long-standing
     WebKit/mobile Safari bug: during an active touch-scroll gesture the
     fixed element can visually detach and lag behind the page, only
     snapping back into place once the scroll settles. Splitting "stay
     pinned to the viewport" (this element) from "scroll my own overflowing
     content" (the inner wrapper below) is the standard workaround. */
  overflow: hidden;
}
.sidebar-scroll {
  height: 100%;
  overflow-y: auto;
  -webkit-overflow-scrolling: touch;
  padding: 1.5rem 1rem;
  display: flex;
  flex-direction: column;
  /* The nav list is routinely taller than the available height, so this
     scrolls internally on most screens — themed so a non-overlay OS
     scrollbar (default on Windows, or macOS set to "always show
     scrollbars") doesn't render as a stark light bar against the dark
     theme. scrollbar-color covers Firefox; the pseudo-elements below cover
     Chrome/Safari/Edge. */
  scrollbar-color: var(--line) transparent;
  scrollbar-width: thin;
}
.sidebar-scroll::-webkit-scrollbar {
  width: 8px;
}
.sidebar-scroll::-webkit-scrollbar-track {
  background: transparent;
}
.sidebar-scroll::-webkit-scrollbar-thumb {
  background: var(--line);
  border-radius: 4px;
}

.main-focus {
  grid-column: 2;
  padding: 1rem;
  margin: 1rem;
}

.sidebar-menu {
  list-style: none;
  padding: 0;
  margin: 0;
}

.sidebar-menu li {
  margin-bottom: 0.25rem;
}

.sidebar-menu a {
  display: flex;
  align-items: center;
  padding: 0.75rem 1rem;
  text-decoration: none;
  color: var(--ink-soft);
  font-weight: 500;
  font-size: 14px;
  border-radius: 10px;
  transition: all 0.2s ease;
}

/* Hover State */
.sidebar-menu a:hover {
  background-color: var(--navy-tint);
  color: var(--navy-dark);
  transform: translateX(4px);
}

/* Active State */
.sidebar-menu a.active {
  background-color: var(--navy);
  color: white;
}

/* Sidebar Title/Header */
.sidebar-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  margin: 0 1rem 1rem;
}

.sidebar-title {
  font-size: 0.75rem;
  letter-spacing: 0.1rem;
  color: var(--ink-faint);
  font-weight: 700;
}

.sidebar-section-label {
  font-size: 0.7rem;
  letter-spacing: 0.08rem;
  text-transform: uppercase;
  color: var(--ink-faint);
  font-weight: 700;
  margin: 1.25rem 1rem 0.5rem;
}

/* The global `* { margin: 0 }` reset (styles.css) means headings,
   paragraphs, and cards have zero natural spacing between them unless each
   template adds its own margin by hand — inconsistent and, in most admin
   pages, just never done, making everything sit flush together. This gives
   every direct child of the main content area consistent breathing room
   without needing to touch every individual template. */
.main-focus > * + * {
  margin-top: 1.25rem;
}

.main-content {
  grid-column: 2;
  padding: 1rem;
  /* .main-content is a grid item inside .content-grid; grid items default
     to min-width:auto, meaning they refuse to shrink below their content's
     intrinsic minimum width. Some page's content (e.g. an unwrapped
     .entry-list row) can be wide enough to blow the whole grid track — and
     therefore the viewport — out sideways. min-width:0 is the standard fix:
     it lets the item actually shrink to the track size and rely on the
     page's own wrapping/overflow rules instead. */
  min-width: 0;
}

.form-container {
  background: var(--card);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  padding: 1.5rem;
  margin: 1rem;
}

form label {
  display: block;
  margin-bottom: 0.5rem;
  font-weight: 600;
  font-size: 13px;
}

form input,
form select {
  width: 100%;
  border: 1px solid var(--line);
  border-radius: 10px;
  padding: 10px 12px;
  margin-bottom: 1rem;
  font-family: inherit;
  font-size: 14px;
  background: var(--field);
  color: var(--ink);
  transition: border-color 0.2s;
}

form input:focus,
form select:focus,
form textarea:focus {
  outline: 2px solid var(--navy);
  outline-offset: 0;
  border-color: var(--navy);
}

form button {
  background-color: var(--navy);
  color: white;
  padding: 11px 22px;
  border: none;
  border-radius: 8px;
  font-weight: 600;
  cursor: pointer;
  transition: background 0.2s;
}

form button:hover {
  background-color: var(--navy-dark);
}

form .error {
  color: #c0392b;
  padding: 0.5rem;
}
form .success {
  color: #2e7d4f;
  padding: 0.5rem;
}

form .form-group {
  margin-bottom: 1rem;
  border-bottom: 1px solid var(--line);
  padding-bottom: 1rem;
}

.form-group {
  margin-bottom: 1rem;
  border-bottom: 1px solid var(--line);
  padding-bottom: 1rem;
}

form {
  display: flex;
  flex-direction: column;
}
label {
  margin-bottom: 8px;
  font-weight: 600;
  display: inline-block;
  min-width: 100px;
}
input[type="text"],
input[type="email"],
input[type="url"],
textarea {
  padding: 10px 12px;
  margin-bottom: 15px;
  border: 1px solid var(--line);
  border-radius: 10px;
  background: var(--field);
  color: var(--ink);
  font-family: inherit;
}
input[type="text"],
input[type="url"],
input[type="email"] {
  width: 100%;
}
button {
  padding: 11px 22px;
  background-color: var(--navy);
  color: white;
  border: none;
  border-radius: 8px;
  font-weight: 600;
  cursor: pointer;
  transition: background 0.2s;
}
button:hover {
  background-color: var(--navy-dark);
}

/* Logo Management */
.logo-comparison {
  display: flex;
  gap: 20px;
  margin-bottom: 15px;
  align-items: center;
}
.logo-preview-container {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 5px;
}
.label-hint {
  font-size: 10px;
  text-transform: uppercase;
  color: var(--ink-faint);
  font-weight: bold;
}
.logo-circle {
  height: 80px;
  width: 80px;
  border-radius: 50%;
  object-fit: cover;
  border: 2px solid var(--line);
  box-shadow: var(--shadow);
  background-color: var(--field);
}
.new-preview {
  border-color: var(--navy);
  animation: fadeIn 0.5s;
}
@keyframes fadeIn {
  from {
    opacity: 0;
  }
  to {
    opacity: 1;
  }
}

.link-item {
  margin: 10px 0;
}

.del {
  background-color: #c0392b;
  color: #fff;
  font-weight: 600;
}

.del:hover {
  background-color: #96281b;
}

.btn-secondary {
  background: transparent;
  color: var(--navy);
  border: 1.5px solid var(--line);
}
.btn-secondary:hover {
  background: var(--navy-tint);
  border-color: var(--navy);
  color: var(--navy-dark);
}

.event-video-row {
  display: flex;
  align-items: center;
  gap: 12px;
  margin-bottom: 10px;
}
.event-video-row .ev-video-id {
  flex: 1;
  margin-bottom: 0;
}

/* ---------- Events & Gallery: two sections on one admin page ---------- */
.admin-section {
  margin-bottom: 2.5rem;
  padding-bottom: 2rem;
  border-bottom: 1px solid var(--line);
}
.admin-section:last-child {
  border-bottom: none;
}

/* ---------- Hero slide management ---------- */
.header-flex {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 1rem;
  flex-wrap: wrap;
}

.btn-add,
.btn-save {
  background: var(--navy);
  color: #fff;
  border: 0;
  border-radius: 8px;
  padding: 10px 20px;
  font-weight: 600;
  cursor: pointer;
  transition: background 0.2s;
}
.btn-add:hover,
.btn-save:hover {
  background: var(--navy-dark);
}

.btn-cancel {
  background: transparent;
  color: var(--ink-soft);
  border: 1.5px solid var(--line);
  border-radius: 8px;
  padding: 10px 20px;
  font-weight: 600;
  cursor: pointer;
  transition:
    border-color 0.2s,
    color 0.2s;
}
.btn-cancel:hover {
  border-color: var(--navy);
  color: var(--navy-dark);
}

.form-card {
  background: var(--card);
  padding: 2rem;
  border-radius: var(--radius);
  margin-bottom: 2rem;
  border: 1px solid var(--line);
}

.form-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(220px, 1fr));
  gap: 1rem;
}

.input-group {
  margin-bottom: 1rem;
}
.input-group label {
  display: block;
  margin-bottom: 0.4rem;
  font-weight: 600;
  font-size: 13px;
}

.hero-grid {
  display: grid;
  width: 100%;
  grid-template-columns: repeat(auto-fit, minmax(280px, 1fr));
  gap: 1.5rem;
  margin-top: 1.5rem;
}

.hero-card {
  border: 1px solid var(--line);
  border-radius: var(--radius);
  overflow: hidden;
  background: var(--card);
  transition:
    transform 0.25s,
    box-shadow 0.25s;
}
.hero-card:hover {
  transform: translateY(-4px);
  box-shadow: var(--shadow);
}

.card-image {
  position: relative;
  height: 180px;
  cursor: pointer;
  background: var(--field);
}
.card-image img {
  width: 100%;
  height: 100%;
  object-fit: cover;
}
.img-placeholder {
  width: 100%;
  height: 100%;
  display: flex;
  align-items: center;
  justify-content: center;
  color: var(--ink-faint);
  font-size: 13px;
}

.card-content {
  padding: 1rem;
}

.card-actions {
  display: flex;
  flex-wrap: wrap;
  justify-content: space-between;
  align-items: center;
  gap: 12px;
  margin-top: 1rem;
}

.btn-edit-link {
  color: var(--navy-dark);
  font-weight: 600;
  font-size: 13.5px;
  text-decoration: underline;
  text-underline-offset: 3px;
}

.btn-delete {
  background: #c0392b;
  color: white;
  border: none;
  padding: 8px 14px;
  border-radius: 8px;
  font-size: 13px;
  font-weight: 600;
  cursor: pointer;
  transition: background 0.2s;
}
.btn-delete:hover {
  background: #96281b;
}

/* Same compact sizing as .btn-delete, so a View/Approve/Delete row (New
   Convert submissions) reads as one consistent set of pill buttons rather
   than mixing this row's actions with the larger .btn-save/.btn-cancel
   used on full add/edit forms. */
.btn-approve {
  background: var(--navy);
  color: white;
  border: none;
  padding: 8px 14px;
  border-radius: 8px;
  font-size: 13px;
  font-weight: 600;
  cursor: pointer;
  transition: background 0.2s;
}
.btn-approve:hover {
  background: var(--navy-dark);
}

/* ---------- Hero slide edit page ---------- */
.edit-grid {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 2rem;
  margin-top: 1.5rem;
}
@media (max-width: 800px) {
  .edit-grid {
    grid-template-columns: 1fr;
  }
}
.current-preview img {
  width: 100%;
  border-radius: var(--radius);
  border: 1px solid var(--line);
}
.back-link {
  display: inline-block;
  margin-bottom: 1rem;
  color: var(--navy);
  text-decoration: none;
  font-weight: 600;
}
.back-link:hover {
  color: var(--navy-dark);
}
.form-row {
  display: flex;
  gap: 1rem;
}
.form-row .input-group {
  flex: 1;
}

/* Mobile Toggles */
.menu-btn {
  display: none; /* Hidden on Desktop */
  position: fixed;
  top: 50%;
  transform: translateY(-50%);
  color: white;
  border: 0;
  background: var(--navy);
  padding: 0.7rem 1.1rem;
  border-radius: 12px;
  cursor: pointer;
  z-index: 900;
  font-size: 1.2rem;
  box-shadow: var(--shadow);
}

.left-btn {
  left: 10px;
}

/* When the sidebar has the 'open' class */
.sidebar.open {
  transform: translateX(0);
}

/* Responsive Logic */

/* Tablet: keep the sidebar docked, but narrower, so the content column
   isn't squeezed by a full-width 260px menu. Below 769px it becomes the
   slide-in drawer instead (next block). */
@media (min-width: 769px) and (max-width: 1100px) {
  .content-grid {
    grid-template-columns: 200px 1fr;
  }
  .sidebar {
    width: 200px;
  }
  .sidebar-scroll {
    padding: 1rem 0.5rem;
  }
  .sidebar-header {
    margin: 0 0.75rem 0.75rem;
  }
  .sidebar-menu a {
    padding: 0.55rem 0.75rem;
    font-size: 13px;
  }
  .sidebar-section-label {
    margin: 1rem 0.75rem 0.4rem;
  }
  .main-content {
    padding: 0.75rem;
  }
}

@media (max-width: 768px) {
  .content-grid {
    grid-template-columns: 1fr; /* Stacked on Mobile */
  }

  .main-content {
    /* Desktop pins this to the grid's column 2, alongside the fixed
       sidebar; mobile collapses to a single column, so column 2 doesn't
       exist and must be reset or the browser silently creates an extra
       implicit column instead of stacking full-width. */
    grid-column: 1;
  }

  .menu-btn {
    display: block;
    background: transparent;
    color: var(--ink);
    box-shadow: none;
  }

  .sidebar {
    position: fixed;
    left: 0;
    top: 0;
    height: 100vh;
    height: 100dvh;
    margin: 0;
    transform: translateX(-100%);
    transition: transform 0.3s ease;
    z-index: 100;
    overflow: hidden;
  }

  .sidebar.open {
    transform: translateX(0);
  }

  .overlay {
    display: none;
    position: fixed;
    inset: 0;
    background: rgba(0, 0, 0, 0.5);
    z-index: 90;
  }
  .overlay.active {
    display: block;
  }
}

.perm-table {
  width: 100%;
  border-collapse: collapse;
  margin-top: 8px;
}
.perm-table th,
.perm-table td {
  border: 1px solid var(--border, #ddd);
  padding: 6px 10px;
  text-align: center;
}
.perm-table th:first-child,
.perm-table td:first-child {
  text-align: left;
  text-transform: capitalize;
}

/* Chart.js canvas needs an explicit-height ancestor once
   maintainAspectRatio:false is set — otherwise it has nothing to size
   against. Without this, the canvas fell back to a fixed intrinsic aspect
   ratio (~3.3:1, from its old height="90" attribute with no width), which
   squashed the legend and axis labels into each other on narrow mobile
   widths where the card is much narrower than that ratio expects. */
.chart-container {
  position: relative;
  height: 280px;
}
@media (max-width: 600px) {
  .chart-container {
    height: 220px;
  }
}

.contact-unread-dot {
  display: inline-block;
  width: 8px;
  height: 8px;
  border-radius: 50%;
  background: var(--navy);
  margin-right: 6px;
  flex: none;
}

/* ---------- Click-to-expand row detail dialog ----------
   Shared by Analytics (Top Pages/Referrers), Notifications, Users, and
   Roles — any .entry-list row whose text can be clipped by the
   overflow:hidden/ellipsis rule above gets a pointer cursor here to hint
   it's clickable; the dialog itself is native <dialog>, populated by
   showDetailDialog() in admin_layout.html. */
.entry-list li > span.detail-clickable {
  cursor: pointer;
}
.entry-list li > span.detail-clickable:hover {
  text-decoration: underline;
}

.detail-dialog {
  width: min(480px, 92vw);
  border: none;
  border-radius: 12px;
  padding: 0;
  background: var(--card);
  color: var(--ink);
  box-shadow: var(--shadow);
  /* The site-wide `* { margin: 0 }` reset (web/static/css/styles.css)
     clobbers the UA stylesheet's dialog:modal margin:auto — without
     restoring it here, showModal() pins the dialog to the top-left corner
     instead of centering it in the viewport. */
  margin: auto;
}
.detail-dialog::backdrop {
  background: rgba(0, 0, 0, 0.5);
}
.detail-dialog-header {
  display: flex;
  justify-content: space-between;
  align-items: center;
  padding: 16px 20px;
  border-bottom: 1px solid var(--line);
}
.detail-dialog-header h3 {
  margin: 0;
  font-size: 16px;
  word-break: break-word;
}
.detail-dialog-close {
  background: none;
  border: none;
  color: var(--ink-soft);
  font-size: 22px;
  line-height: 1;
  cursor: pointer;
  padding: 0 4px;
}
.detail-dialog-close:hover {
  color: var(--ink);
}
.detail-dialog-body {
  padding: 16px 20px 20px;
  max-height: 60vh;
  overflow-y: auto;
}
.detail-dialog-row + .detail-dialog-row {
  margin-top: 14px;
}
.detail-dialog-label {
  font-size: 12px;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.03em;
  color: var(--ink-soft);
  margin-bottom: 4px;
}
.detail-dialog-value {
  font-size: 14px;
  word-break: break-word;
  white-space: pre-wrap;
}
