* { box-sizing: border-box; }
body {
  font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
  margin: 0;
  background: #f5f6f8;
  color: #1a1a1a;
}
nav {
  background: #1a2332;
  padding: 12px 20px;
  display: flex;
  gap: 20px;
  align-items: center;
}
nav a { color: #cbd5e1; text-decoration: none; font-size: 14px; }
nav a:hover, nav a.active { color: #fff; font-weight: 600; }
nav .brand { color: #fff; font-weight: 700; margin-right: 20px; }
main { padding: 20px; width: 100%; }
h1 { font-size: 20px; margin: 0 0 16px; }
h2 { font-size: 16px; margin: 24px 0 10px; }

.panel {
  background: #fff;
  border: 1px solid #e2e5ea;
  border-radius: 6px;
  padding: 16px;
  margin-bottom: 16px;
}

.filters { display: flex; flex-wrap: wrap; gap: 10px; align-items: end; margin-bottom: 14px; }
.field { display: flex; flex-direction: column; gap: 4px; max-width: 260px; }
.field label { font-size: 11px; color: #667; text-transform: none; letter-spacing: 0.02em; line-height: 1.4; white-space: normal; }
.field input[type="date"] { width: 150px; }

/* Collapsed-by-default per-column exact-match filters (Browse Data) -- some
   tables have dozens of these, so they live behind a <details> disclosure
   instead of an always-open wall of inputs. */
.filter-columns-wrap { margin-bottom: 14px; }
.filter-columns-wrap summary {
  cursor: pointer;
  font-size: 12px;
  color: #2563eb;
  font-weight: 600;
  padding: 4px 0;
  user-select: none;
}
.filter-columns-wrap summary:hover { text-decoration: underline; }
.filter-columns-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(140px, 1fr));
  gap: 8px 12px;
  margin-top: 10px;
}
.filter-columns-grid .field { max-width: none; width: 100%; }
input, select, button {
  font-size: 13px;
  padding: 6px 10px;
  border: 1px solid #d0d5dd;
  border-radius: 4px;
  background: #fff;
}
button {
  background: #2563eb;
  color: #fff;
  border-color: #2563eb;
  cursor: pointer;
  font-weight: 600;
}
button:hover { background: #1d4ed8; }
button.secondary { background: #fff; color: #2563eb; }
button.secondary:hover { background: #eff6ff; }
button:disabled { opacity: 0.5; cursor: not-allowed; }

table { width: 100%; border-collapse: collapse; font-size: 12px; }
th, td {
  text-align: left;
  padding: 6px 10px;
  border-bottom: 1px solid #eef0f3;
  white-space: nowrap;
  max-width: 240px;
  overflow: hidden;
  text-overflow: ellipsis;
}
th { background: #f8f9fb; position: sticky; top: 0; font-weight: 600; color: #445; }
tr:hover td { background: #f8fafc; }
.table-wrap { overflow-x: auto; max-height: 65vh; overflow-y: auto; border: 1px solid #eef0f3; border-radius: 4px; }

/* Whichever column ends up first (after DataTable's generic reordering, and
   after browse.js prepends an "Ask" link column on some tables) stays put
   while the table scrolls horizontally, instead of disappearing off the
   left edge along with everything else. */
.table-wrap table tr > *:first-child {
  position: sticky;
  left: 0;
  z-index: 2;
  background: #fff;
}
.table-wrap table thead tr > *:first-child {
  z-index: 3; /* above both the sticky header row and the sticky first column */
  background: #f8f9fb;
}
.table-wrap table tbody tr:hover > *:first-child {
  background: #f8fafc;
}

/* Columns blank on every row of the current page (see DataTable's
   computeEmptyColumns) are hidden by default and revealed via the toggle
   button DataTable renders above the table when there are any. */
.table-wrap table td.col-empty,
.table-wrap table th.col-empty {
  display: none;
}
.table-wrap.show-empty-cols table td.col-empty,
.table-wrap.show-empty-cols table th.col-empty {
  display: table-cell;
}
.empty-cols-toggle { margin-bottom: 8px; }
.link-btn {
  background: none;
  border: none;
  padding: 0;
  font-size: 12px;
  color: #2563eb;
  cursor: pointer;
  font-weight: 600;
}
.link-btn:hover { text-decoration: underline; }

a.link { color: #2563eb; text-decoration: none; }
a.link:hover { text-decoration: underline; }

.status { font-size: 11px; padding: 2px 8px; border-radius: 10px; font-weight: 600; }
.status-matched { background: #dcfce7; color: #166534; }
.status-unmatched { background: #fee2e2; color: #991b1b; }
.status-ambiguous { background: #fef3c7; color: #92400e; }
.status-excluded { background: #e5e7eb; color: #374151; }
.status-journaled { background: #dbeafe; color: #1e40af; }
.status-partially_journaled { background: #ede9fe; color: #5b21b6; }
.status-unreconciled { background: #f3f4f6; color: #6b7280; }
.priority-critical { background: #fee2e2; color: #991b1b; }
.priority-high { background: #fef3c7; color: #92400e; }
.priority-medium { background: #dbeafe; color: #1e40af; }
.priority-low { background: #e5e7eb; color: #374151; }

.btn-whatsapp {
  display: inline-block;
  background: #25D366;
  color: #fff;
  padding: 3px 9px;
  border-radius: 4px;
  font-size: 11px;
  font-weight: 600;
  text-decoration: none;
  margin-top: 3px;
}
.btn-whatsapp:hover { background: #1ebe57; }

.chip-row { display: flex; flex-wrap: wrap; gap: 6px; margin-bottom: 12px; }
.chip {
  padding: 8px 14px;
  border-radius: 20px;
  border: 1px solid #d0d5dd;
  background: #fff;
  color: #445;
  font-size: 13px;
  cursor: pointer;
  white-space: nowrap;
}
.chip.active { background: #2563eb; color: #fff; border-color: #2563eb; }

th.sortable { cursor: pointer; user-select: none; }
th.sortable:hover { background: #eef0f3; }
th.sortable .sort-arrow { color: #94a3b8; margin-left: 3px; }
th.sort-active { color: #1d4ed8; background: #eff6ff; }

.tap-copy { cursor: pointer; border-bottom: 1px dotted #94a3b8; }
.tap-copy:hover { color: #2563eb; border-bottom-color: #2563eb; }

/* Maintenance job cards — deliberately NOT a table. A grid of compact
   cards shows more jobs on screen at once than a table ever could (many
   columns per row on desktop, collapses to one per row on a phone), and
   lets each card be scanned at a glance: cabin first (big, top-left),
   priority+type together, description, with the less-urgent fields
   (raised by, booking) tucked behind a native <details> toggle so they
   don't compete for attention. */
.job-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(210px, 1fr));
  gap: 10px;
}
.job-card {
  border: 1px solid #e2e5ea;
  border-radius: 8px;
  padding: 10px 12px;
  background: #fff;
  display: flex;
  flex-direction: column;
  gap: 5px;
}
.job-cabin { font-size: 17px; font-weight: 700; color: #1a2332; }
.job-priority-type { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; }
.job-type { font-size: 12px; color: #556; font-weight: 600; }
.job-description { font-size: 13px; color: #333; line-height: 1.35; }
.job-card-bottom {
  display: flex;
  justify-content: space-between;
  align-items: center;
  margin-top: auto;
  padding-top: 6px;
}
.job-raised-at { font-size: 11px; color: #94a3b8; }
.job-more { font-size: 12px; margin-top: 2px; }
.job-more summary { cursor: pointer; color: #2563eb; list-style: none; }
.job-more summary::-webkit-details-marker { display: none; }
.job-more[open] summary { margin-bottom: 4px; }
.job-more div { color: #556; padding: 1px 0; }
.job-media { display: flex; flex-wrap: wrap; gap: 6px; margin: 6px 0; }
.job-media-thumb { width: 64px; height: 64px; object-fit: cover; border-radius: 4px; border: 1px solid #e2e5ea; }
.job-card-actions { display: flex; gap: 6px; }
.job-edit { margin-top: 8px; padding: 8px; background: #f8fafc; border: 1px solid #e2e5ea; border-radius: 6px; }
.job-edit label { display: block; font-size: 12px; color: #556; margin-bottom: 6px; }
.job-edit input, .job-edit select, .job-edit textarea { width: 100%; box-sizing: border-box; padding: 5px 7px; margin-top: 2px; }
.job-edit-buttons { display: flex; gap: 6px; margin-top: 4px; }
.checkout-soon { color: #b02a37; font-weight: 600; }
.checkout-future { color: #1e7e34; }
.checkout-past { color: #94a3b8; }

/* Mobile responsiveness — below this width, tables with the
   .responsive-table class reflow from a horizontally-scrolling grid
   into stacked cards: each row becomes its own block, each cell shows
   a small label above its value (from the data-label attribute set in
   JS), and the header row is hidden since labels now sit inline. This
   is what actually fixes "too small, need to pinch-zoom and pan" —
   the layout itself changes shape rather than just shrinking. */
/* PORTRAIT ONLY. Landscape deliberately keeps the real table: turning the
   device is the user asking to see the full grid, and the card layout hides
   columns behind one-per-row stacking — which is why the calendar showed only
   booking blobs and never scrolled. .table-wrap supplies the horizontal scroll.
   The PWA manifest was also pinned to portrait-primary, so on an installed app
   landscape never happened at all (fixed 2026-08-18). */
@media (max-width: 760px) and (orientation: portrait) {
  nav { flex-wrap: wrap; gap: 12px 16px; padding: 12px; }
  nav .brand { width: 100%; margin-right: 0; }
  main { padding: 12px; }
  .filters { gap: 8px; }
  .field { max-width: none; width: 100%; }
  .chip-row { gap: 8px; }
  .chip { padding: 10px 16px; font-size: 14px; } /* bigger tap targets */

  .responsive-table thead { display: none; }
  .responsive-table, .responsive-table tbody, .responsive-table tr, .responsive-table td {
    display: block;
    width: 100%;
  }
  .responsive-table { border-collapse: collapse; }
  .responsive-table tr {
    margin-bottom: 14px;
    border: 1px solid #e2e5ea;
    border-radius: 8px;
    padding: 12px;
    background: #fff;
  }
  .responsive-table td {
    border: none;
    padding: 7px 0;
    text-align: left;
    white-space: normal;
    max-width: none;
    overflow: visible;
  }
  .responsive-table td[data-label]::before {
    content: attr(data-label);
    display: block;
    font-size: 10px;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: 0.03em;
    color: #94a3b8;
    margin-bottom: 3px;
  }
  /* Form controls inside a card should use the full card width, not
     the small fixed pixel widths sized for a desktop table column. */
  .responsive-table td textarea,
  .responsive-table td input[type="text"],
  .responsive-table td select {
    width: 100% !important;
  }
  .responsive-table td button { margin: 4px 6px 4px 0; }
}

.pagination { display: flex; gap: 8px; align-items: center; margin-top: 10px; font-size: 13px; }
.msg { padding: 10px; border-radius: 4px; margin: 10px 0; font-size: 13px; }
.msg-error { background: #fee2e2; color: #991b1b; }
.msg-success { background: #dcfce7; color: #166534; }
.msg-info { background: #eff6ff; color: #1e40af; }
pre.csv-preview {
  background: #0f172a; color: #e2e8f0; padding: 12px; border-radius: 4px;
  font-size: 11px; max-height: 300px; overflow: auto; white-space: pre-wrap;
}

/* Shared "ask the diagnostic assistant" chat bubble styling -- used by the
   full-page chat log (ask.html) and the compact inline row panel (Browse
   Data, see .ask-inline-panel below). Kept here rather than duplicated in
   each page's own <style> block. */
.chat-msg { padding: 10px 14px; border-radius: 8px; max-width: 80%; line-height: 1.4; }
.chat-msg.user { background: #2563eb; color: #fff; align-self: flex-end; white-space: pre-wrap; }
.chat-msg.assistant { background: #f3f4f6; color: #1a2332; align-self: flex-start; max-width: 95%; }
.chat-msg.thinking { background: #f3f4f6; color: #94a3b8; align-self: flex-start; font-style: italic; }

.chat-msg.assistant p { margin: 0 0 8px; }
.chat-msg.assistant p:last-child { margin-bottom: 0; }
.chat-msg.assistant ul, .chat-msg.assistant ol { margin: 0 0 8px 18px; padding: 0; }
.chat-msg.assistant code { background: #e5e7eb; padding: 1px 4px; border-radius: 3px; font-size: 12px; }
.chat-msg.assistant pre { background: #1a2332; color: #e5e7eb; padding: 10px; border-radius: 6px; overflow-x: auto; }
.chat-msg.assistant pre code { background: none; padding: 0; }
.chat-msg.assistant table { width: auto; max-width: 100%; border-collapse: collapse; font-size: 12px; margin: 4px 0 8px; }
.chat-msg.assistant th, .chat-msg.assistant td { border: 1px solid #d0d5dd; padding: 5px 9px; text-align: left; white-space: nowrap; }
.chat-msg.assistant th { background: #e9edf2; font-weight: 600; }
.chat-msg.assistant .table-scroll { overflow-x: auto; max-width: 100%; }

.xlsx-export-btn {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  margin-top: 6px;
  padding: 4px 10px;
  font-size: 11px;
  border-radius: 5px;
  border: 1px solid #34a853;
  background: #ecfdf3;
  color: #166534;
  cursor: pointer;
}
.xlsx-export-btn:hover { background: #dcfce7; }

/* Inline "Ask about this row" panel (Browse Data) -- opens as an extra
   table row directly beneath the row it's asking about, rather than
   navigating anywhere, so the table and the answer stay on screen
   together. Only one panel is open at a time (browse.js enforces this). */
.table-wrap table tr.ask-inline-row > td {
  /* Higher specificity than the generic sticky-first-column rule above --
     this row's single colspan-ed cell is technically ":first-child" too,
     but must NOT be pinned like a real first column. */
  position: static;
  background: #fbfcfe;
  padding: 0;
  white-space: normal;
}
.ask-inline-panel {
  padding: 12px 16px;
  display: flex;
  flex-direction: column;
  gap: 8px;
  border-top: 2px solid #2563eb;
  border-bottom: 1px solid #eef0f3;
  max-width: 900px;
  /* The row's own <td> spans every column (colspan), which can be far wider
     than the visible scroll area on a wide table -- e.g. if this was opened
     while scrolled right to see journal_status/amounts. Sticking the panel
     itself to the left edge of the scrollport means the answer always
     appears where your eyes already are, instead of off to the left of a
     4000px-wide row you'd have to scroll back to find. */
  position: sticky;
  left: 0;
}
.ask-inline-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  font-size: 12px;
  color: #445;
}
.ask-inline-actions { display: flex; align-items: center; gap: 14px; }
.ask-inline-refresh { font-size: 11px; }
.ask-inline-cache-note { font-size: 11px; color: #94a3b8; font-weight: normal; cursor: help; }
.ask-inline-close {
  background: none;
  border: none;
  cursor: pointer;
  font-size: 13px;
  color: #667;
  padding: 2px 6px;
}
.ask-inline-close:hover { color: #1a2332; }
.ask-inline-log { display: flex; flex-direction: column; gap: 8px; }
.ask-inline-thinking { font-size: 12px; color: #94a3b8; font-style: italic; }
.ask-inline-followup { display: flex; gap: 8px; }
.ask-inline-followup input { flex: 1; }