/* OrcaPlanner shared UI shell — layout + theme.
   Loaded by templates/base.html on every page. Bootstrap 5 provides the
   component baseline; this file adds the shell layout and the design tokens.

   Palette (slate + one blue accent — keep it consistent everywhere):
     top bar (chrome)  dark slate #1e293b, text #cbd5e1 — the status bar
     left nav          soft cool grey-blue #eef2f7 — a calm sidebar tone
     main panel        WHITE #ffffff canvas + white cards (bordered/shadowed)
     accent            #3b82f6 (active nav, primary highlights)
     headings          #1e293b

   Button system (toolbars & cards) — every page uses this one scheme:
     · all toolbar buttons : `btn btn-sm` + variant, Title Case labels
     · primary action      : btn-primary — max ONE per toolbar/card
                             (create / run / solve / save-new, e.g.
                             "+ New Shipment", "▶ Solve Day Plan")
     · neutral actions     : btn-outline-secondary (view links, refresh,
                             secondary nav)
     · template download   : btn-outline-secondary, glyph 📄
     · import / upload     : btn-outline-secondary, glyph ⬆ (Validate and
                             commit-Import in import flows too — no accent)
     · export / download   : btn-outline-success, glyph ⬇ (Excel/JSON
                             exports, route exports, db download)
     · destructive         : btn-outline-danger, glyph 🗑 or ✕
     · save existing data  : btn-success solid (e.g. "💾 Save Changes")
     · modal footers       : btn-primary Save + btn-secondary Cancel
   Toolbar order: primary first, then the template/import/export cluster,
   destructive actions last — clusters separated by <div class="vr mx-1">;
   filter controls stay to the right.
*/

:root {
  --op-font: "Segoe UI", system-ui, -apple-system, "Helvetica Neue", Arial, sans-serif;

  /* dark chrome — TOP BAR ONLY */
  --op-chrome-bg: #1e293b;
  --op-chrome-bg-deep: #172033;
  --op-chrome-border: #334155;
  --op-chrome-fg: #cbd5e1;
  --op-chrome-fg-dim: #94a3b8;
  --op-chrome-fg-bright: #f8fafc;

  /* left nav — soft cool grey-blue, calmer than the white content area */
  --op-nav-bg: #eef2f7;
  --op-nav-ctx-bg: #e6ecf4;
  --op-nav-fg: #475569;
  --op-nav-fg-dim: #64748b;
  --op-nav-fg-strong: #1e293b;
  --op-nav-hover: #e2e8f0;
  --op-nav-active-bg: #dbeafe;
  --op-nav-active-fg: #1d4ed8;
  --op-nav-border: #dbe2ec;

  --op-accent: #3b82f6;
  --op-accent-soft: rgba(59, 130, 246, .16);

  --op-main-bg: #ffffff;
  --op-card-border: #e2e8f0;

  --op-nav-width: 210px;
  --op-topbar-height: 38px;
  --op-props-width: 320px;
}

html, body { height: 100%; }

body.app-body {
  margin: 0;
  font-family: var(--op-font);
  font-size: 0.82rem;
  background: var(--op-main-bg);
  overflow: hidden;
}

/* ── Grid shell ─────────────────────────────────────────────────────────── */
.app-shell {
  display: grid;
  height: 100vh;
  grid-template-rows: var(--op-topbar-height) 1fr;
  grid-template-columns: var(--op-nav-width) 1fr;
  grid-template-areas:
    "topbar topbar"
    "nav    main";
}
.app-shell.nav-collapsed { grid-template-columns: 0 1fr; }
.app-shell.nav-collapsed #app-nav { display: none; }

/* ── Top bar — lean status-bar style, same chrome as the nav ────────────── */
#app-topbar {
  grid-area: topbar;
  display: flex;
  align-items: center;
  gap: .65rem;
  padding: 0 .65rem 0 .4rem;
  background: var(--op-chrome-bg);
  border-bottom: 1px solid var(--op-chrome-border);
  color: var(--op-chrome-fg);
  z-index: 1040;
}
#app-topbar .brand {
  display: flex; align-items: center; gap: .45rem;
  font-family: var(--op-font);
  font-weight: 600; font-size: .85rem; letter-spacing: .01em;
  color: var(--op-chrome-fg-bright);
  white-space: nowrap;
}
#app-topbar .brand img { height: 18px; }

/* ── Light top bar (app_config.json → ui.topbar_theme = "light") ──────────
 * White chrome that fits the red FINSA logo, with a thin brand-red accent
 * under the bar. The --op-chrome-* overrides are scoped to #app-topbar ONLY:
 * the same variables also style dark table headers in the main content
 * (.table-dark, datatable sort affordances), which must stay dark. */
body.topbar-light #app-topbar {
  --op-chrome-bg: #ffffff;
  --op-chrome-bg-deep: #f1f5f9;
  --op-chrome-border: #dfe5ee;
  --op-chrome-fg: #475569;
  --op-chrome-fg-dim: #7c8aa0;
  --op-chrome-fg-bright: #1e293b;
  border-bottom: 2px solid #e30613;    /* FINSA brand red */
}
body.topbar-light #app-topbar .brand { gap: .9rem; }   /* wider logo–title gap */
body.topbar-light #app-topbar .brand img { height: 21px; }
body.topbar-light #app-topbar .brand-title { font-weight: 500; color: #475569; }

/* Gasóleos San Marcos (firefighting) uses the light top bar too, with its own
   brand-red accent instead of the FINSA red. */
body.topbar-light.mod-fire #app-topbar { border-bottom-color: #aa1e14; }  /* GSM red */
body.topbar-light.mod-fire #app-topbar .brand img { height: 23px; }        /* GSM wordmark reads a touch larger */

/* ── Deployment module gating (server-rendered body class) ─────────────────
 * app_config.json module flags become body classes on every page
 * (base.html: mod-finsa when finsa_trailer_modes, mod-fire when firefighting).
 * Hiding gated CONTENT here — in the render-blocking stylesheet — means it is
 * never painted, so there is NO flash of elements that later get hidden. Nav
 * SECTIONS are gated separately (not even emitted server-side; see base.html).
 * `.finsa-only` / `.firefighting-only` keep their inline `display:none` default
 * and are revealed by page JS, which preserves each element's real display
 * type (flex/grid/…), so they are intentionally NOT handled here. */
body.mod-finsa .finsa-hide { display: none !important; }

/* chrome icon buttons (nav toggle, sync): borderless, quiet */
.chrome-btn {
  border: 0; background: transparent;
  color: var(--op-chrome-fg-dim);
  border-radius: .375rem;
  padding: .15rem .45rem;
  font-size: .95rem; line-height: 1.2;
}
.chrome-btn:hover { background: var(--op-chrome-border); color: var(--op-chrome-fg-bright); }

#topbar-context { display: flex; align-items: center; gap: .5rem; flex: 1 1 auto; min-width: 0; }
#topbar-status  { display: flex; align-items: center; gap: .3rem; white-space: nowrap; }
/* Signed-in user chip (local auth only — base.html omits it otherwise). */
.topbar-user {
  font-size: .74rem;
  color: var(--op-chrome-fg-dim);
  max-width: 11rem;
  overflow: hidden;
  text-overflow: ellipsis;
  padding-left: .35rem;
}

/* Bootstrap controls placed inside the dark top bar adapt automatically */
#app-topbar .page-title { font-size: .82rem; font-weight: 600; color: var(--op-chrome-fg-bright); margin: 0; }
#app-topbar .form-control, #app-topbar .form-select {
  background: var(--op-chrome-bg-deep);
  border-color: var(--op-chrome-border);
  color: var(--op-chrome-fg-bright);
  font-size: .75rem;
  padding-top: .12rem; padding-bottom: .12rem;
}
#app-topbar .form-control::placeholder { color: var(--op-chrome-fg-dim); }
#app-topbar .form-label, #app-topbar label { color: var(--op-chrome-fg-dim); margin: 0; font-size: .72rem; }
#app-topbar .btn-outline-secondary, #app-topbar .btn-outline-primary, #app-topbar .btn-light {
  --bs-btn-color: var(--op-chrome-fg);
  --bs-btn-border-color: var(--op-chrome-border);
  --bs-btn-bg: transparent;
  --bs-btn-hover-bg: var(--op-chrome-border);
  --bs-btn-hover-color: var(--op-chrome-fg-bright);
  --bs-btn-hover-border-color: var(--op-chrome-border);
  padding-top: .1rem; padding-bottom: .1rem; font-size: .75rem;
}
#app-topbar a { color: var(--op-chrome-fg); }
#app-topbar .text-muted { color: var(--op-chrome-fg-dim) !important; }

/* connection status chips */
.conn-chip {
  display: inline-flex; align-items: center; gap: .25rem;
  font-size: .6rem; font-weight: 600; letter-spacing: .04em;
  padding: .08rem .4rem; border-radius: 999px;
  border: 1px solid var(--op-chrome-border);
  color: var(--op-chrome-fg-dim);
  cursor: default; user-select: none;
}
.conn-chip .dot { width: .45rem; height: .45rem; border-radius: 50%; background: #64748b; }
.conn-chip.ok .dot   { background: #22c55e; }
.conn-chip.down .dot { background: #ef4444; }

/* ── Left nav (soft grey-blue, calmer than the white content area) ───────── */
#app-nav {
  grid-area: nav;
  position: relative;
  display: flex; flex-direction: column;
  background: var(--op-nav-bg);
  border-right: 1px solid var(--op-nav-border);
  overflow-y: auto;
  min-height: 0;
}

/* drag handle on the nav's right edge (width persisted via ui_settings) */
#nav-resizer {
  position: absolute; top: 0; right: 0;
  width: 5px; height: 100%;
  cursor: col-resize;
  z-index: 10;
}
#nav-resizer:hover, body.nav-resizing #nav-resizer { background: var(--op-accent-soft); }
body.nav-resizing { cursor: col-resize; user-select: none; }
body.nav-resizing #app-main-wrap { pointer-events: none; }  /* maps must not eat the drag */
#app-nav .nav-sections { padding: .45rem .4rem; display: flex; flex-direction: column; gap: 1px; }
#app-nav .nav-btn {
  display: flex; align-items: center; gap: .55rem;
  padding: .4rem .6rem;
  border: 0; border-radius: .375rem;
  background: transparent; color: var(--op-nav-fg);
  font-family: var(--op-font);
  font-size: .79rem; text-align: left; text-decoration: none;
  white-space: nowrap;
}
#app-nav .nav-btn:hover  { background: var(--op-nav-hover); color: var(--op-nav-fg-strong); }
#app-nav .nav-btn.active {
  background: var(--op-nav-active-bg);
  color: var(--op-nav-active-fg);
  font-weight: 600;
  box-shadow: inset 2px 0 0 var(--op-accent);
}
#app-nav .nav-btn .ico { width: 1.2rem; text-align: center; flex: 0 0 auto; }

#nav-context {
  border-top: 1px solid var(--op-nav-border);
  background: var(--op-nav-ctx-bg);
  padding: .6rem .55rem;
  color: var(--op-nav-fg);
  overflow-y: auto;
  flex: 1 1 auto;
  min-height: 0;
}
#nav-context:empty { display: none; }
#nav-context .ctx-title {
  font-size: .64rem; font-weight: 700; text-transform: uppercase;
  letter-spacing: .06em; color: var(--op-nav-fg-dim); margin-bottom: .4rem;
}

/* ── Main panel + properties panel ──────────────────────────────────────── */
#app-main-wrap {
  grid-area: main;
  display: flex;
  min-width: 0; min-height: 0;
  overflow: hidden;
}
#app-main {
  flex: 1 1 auto;
  min-width: 0;
  overflow-y: auto;
  padding: 1rem;
}
#app-main.no-pad { padding: 0; }   /* map-like full-bleed pages */

#app-props {
  flex: 0 0 var(--op-props-width);
  border-left: 1px solid var(--op-card-border);
  background: #fff;
  overflow-y: auto;
  padding: .75rem;
}
#app-props[hidden] { display: none; }

/* ── Alerts / toasts ────────────────────────────────────────────────────── */
#alert-zone {
  position: fixed;
  top: calc(var(--op-topbar-height) + 8px);
  right: 12px;
  z-index: 2000;
  max-width: 440px;
}

/* ── Shared content conventions ─────────────────────────────────────────── */
/* Cards sit on the white canvas, so a soft default shadow keeps white-on-white
   readable even without the Bootstrap .shadow-sm utility (which still wins). */
.card {
  border-color: var(--op-card-border);
  box-shadow: 0 1px 2px rgba(15, 23, 42, .04), 0 1px 3px rgba(15, 23, 42, .06);
}
.card-header { background: #f8fafc; }

.table th, .table td { vertical-align: middle; }
th small { display: block; font-weight: 400; color: #94a3b8; font-size: .65rem; }
.status-badge { font-size: .65rem; text-transform: uppercase; letter-spacing: .04em; }

/* dark table headers restyled to the chrome palette */
.table-dark { --bs-table-bg: var(--op-chrome-bg); --bs-table-border-color: var(--op-chrome-border); }

.nav-tabs { border-bottom-color: var(--op-card-border); }
.nav-tabs .nav-link { font-size: .8rem; padding: .35rem .85rem; color: #475569; }
.nav-tabs .nav-link:hover { color: #1e293b; }
.nav-tabs .nav-link.active { font-weight: 600; color: var(--op-accent); }

.btn-primary {
  --bs-btn-bg: var(--op-accent); --bs-btn-border-color: var(--op-accent);
  --bs-btn-hover-bg: #2563eb;   --bs-btn-hover-border-color: #2563eb;
  --bs-btn-active-bg: #1d4ed8;  --bs-btn-active-border-color: #1d4ed8;
}
.btn-outline-primary {
  --bs-btn-color: var(--op-accent); --bs-btn-border-color: #93c5fd;
  --bs-btn-hover-bg: var(--op-accent); --bs-btn-hover-border-color: var(--op-accent);
}

.page-title { font-size: 1rem; font-weight: 600; margin: 0; }

/* Collapsible card pattern (settings & panels): chevron button in header */
.card-collapse-btn {
  border: 0; background: transparent; color: #64748b;
  font-size: .8rem; padding: 0 .25rem; line-height: 1;
}
.card-collapse-btn:hover { color: #1e293b; }

/* ── DataTable component (static/js/datatable.js) ───────────────────────────
   Header sort carets + funnel filter popovers + filter chips + pager. */
.dt-table th.dt-th { white-space: nowrap; }
.dt-th-inner { display: inline-flex; align-items: center; gap: .3rem; vertical-align: middle; }
.dt-th-label small { display: block; }   /* keep the sub-label under the title */
th.dt-sortable { cursor: pointer; user-select: none; }

/* stacked ▲/▼ carets — always in the layout (no jumps), faint until hover,
   accent-blue when that direction is the active sort */
.dt-sort { display: inline-flex; flex-direction: column; line-height: 0; gap: 1px; }
.dt-sort .dt-s {
  display: block; padding: 0 1px; cursor: pointer;
  color: var(--op-chrome-fg-dim); opacity: .28;
  transition: opacity .12s ease, color .12s ease;
}
.dt-table th:hover .dt-s { opacity: .7; }
.dt-sort .dt-s:hover { opacity: 1; color: var(--op-chrome-fg-bright); }
.dt-sort .dt-s.active { color: var(--op-accent); opacity: 1; }
.dt-table th:hover .dt-s.active { opacity: 1; }

/* funnel filter button — quiet until hover; accent + dot when a filter is on */
.dt-filterbtn {
  position: relative; border: 0; background: transparent;
  padding: 1px 2px; line-height: 0; border-radius: .25rem;
  color: var(--op-chrome-fg-dim); opacity: .35;
  transition: opacity .12s ease, color .12s ease;
}
.dt-table th:hover .dt-filterbtn { opacity: 1; }
.dt-filterbtn:hover { color: var(--op-chrome-fg-bright); background: var(--op-chrome-border); }
.dt-filterbtn.dt-on { opacity: 1; color: var(--op-accent); }
.dt-filterbtn.dt-on::after {
  content: ''; position: absolute; top: -1px; right: -1px;
  width: 5px; height: 5px; border-radius: 50%;
  background: var(--op-accent); box-shadow: 0 0 0 1.5px var(--op-chrome-bg);
}

/* anchored filter popover (appended to <body>) */
.dt-popover {
  position: fixed; z-index: 3000; min-width: 210px; max-width: 280px;
  background: #fff; border: 1px solid var(--op-card-border);
  border-radius: .45rem; padding: .55rem .6rem;
  box-shadow: 0 8px 22px rgba(15, 23, 42, .16);
  font-size: .78rem;
}
.dt-popover .dt-pop-title {
  font-size: .64rem; font-weight: 700; text-transform: uppercase;
  letter-spacing: .05em; color: #64748b; margin-bottom: .4rem;
}
.dt-popover .dt-pop-clear { padding: .1rem .5rem; font-size: .72rem; }

/* active-filter summary chips above the table */
.dt-chips { display: flex; flex-wrap: wrap; gap: .35rem; margin-bottom: .5rem; }
.dt-chip {
  display: inline-flex; align-items: center; gap: .35rem;
  font-size: .7rem; padding: .12rem .5rem; border-radius: 999px;
  background: var(--op-accent-soft); border: 1px solid #bfdbfe; color: #1d4ed8;
}
.dt-chip button {
  border: 0; background: none; color: inherit; padding: 0;
  line-height: 1; font-size: .72rem; opacity: .7;
}
.dt-chip button:hover { opacity: 1; }

/* toolbar / pager — compact, muted borders to match the canvas */
.dt-toolbar .dt-count { letter-spacing: .01em; }
.dt-persize { border-color: var(--op-card-border); }
.dt-pager .page-link {
  color: #475569; border-color: var(--op-card-border);
  padding: .12rem .5rem; font-size: .74rem;
}
.dt-pager .page-item.active .page-link {
  background: var(--op-accent); border-color: var(--op-accent); color: #fff;
}
.dt-pager .page-item.disabled .page-link { color: #cbd5e1; }
