/* Modal save dialog: looser spacing on inputs in the left column. */
.save-modal-col .form-group { margin-bottom: 1.25rem; }

/* Summarize-row selects: size each control to its current selection
   (with caret room) and let the input-container shrink so label and
   select sit on the same line. */
.fit-select .shiny-input-container { width: max-content !important; }
.fit-select .selectize-control { width: max-content; min-width: 6em; }
.fit-select .selectize-input { padding-right: 2rem; }

/* Group-values multi-select: constrain to sidebar width (the parent
   .fit-select rules set max-content which blows out for long pills). */
.fit-select .shiny-input-container:has(#group_values) {
  width: 100% !important;
}
.fit-select #group_values + .selectize-control {
  width: 100% !important;
  min-width: 0;
}
.fit-select #group_values + .selectize-control .selectize-input {
  max-width: 100%;
  flex-wrap: wrap;
}

/* Let dropdowns grow wider than the input so options are fully legible. */
.selectize-dropdown { width: auto !important; min-width: 100% !important; }
.selectize-dropdown .option,
.selectize-dropdown .optgroup-header { white-space: nowrap; }

/* Spinner overlays driven by Shiny's global html.shiny-busy class. One per
   tab content area; only the visible tab's overlay actually paints. All three
   overlays use a data-ready handshake (set in each DT's initComplete and, for
   the plot, in plot-sync.js on plotly_afterplot) so they cover the output
   through its first client-side render, which happens after shiny-busy clears. */
#tbl-overlay[data-ready='1'],
#summary-overlay[data-ready='1'],
#plot-overlay[data-ready='1'] { display: none !important; }
html.shiny-busy #tbl-overlay[data-ready='1'],
html.shiny-busy #summary-overlay[data-ready='1'],
html.shiny-busy #plot-overlay[data-ready='1'] { display: flex !important; }
/* Preview renders inside the save-plot modal make Shiny "busy" but the
   main plotly isn't re-rendering — suppress the spinner when a modal is open. */
html.shiny-busy body.modal-open #plot-overlay[data-ready='1'] { display: none !important; }


/* Bottom-align sort arrows when header text wraps to multiple lines.
   DT places ▲/▼ as absolutely-positioned ::before/::after centred in the
   th.  Override to pin them beside the last line of text instead of
   floating mid-cell.  Values use ex (x-height) so they track the font.
   Cap header text to 2 lines so tall labels don't eat 15 % of viewport.
   The Explore tab wraps text in a .th-label <span>; the Summarize tab puts
   text directly in <th>.  Both are covered by the rules below. */
.dt-clamped-header .dataTables_scrollHead th {
  vertical-align: bottom;
  line-height: 1.3;
}
.dt-clamped-header .dataTables_scrollHead th.sorting::before,
.dt-clamped-header .dataTables_scrollHead th.sorting_asc::before,
.dt-clamped-header .dataTables_scrollHead th.sorting_desc::before {
  top: auto !important;
  bottom: calc(0.75em + 1ex + 3px);
}
.dt-clamped-header .dataTables_scrollHead th.sorting::after,
.dt-clamped-header .dataTables_scrollHead th.sorting_asc::after,
.dt-clamped-header .dataTables_scrollHead th.sorting_desc::after {
  top: auto !important;
  bottom: calc(0.75em + 3px);
}
/* Clamp header text to 2 lines. Both tabs wrap text in a .th-label span:
   Explore via its custom header_container, Summarize via headerCallback. */
.dt-clamped-header .dataTables_scrollHead th .th-label {
  display: -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
  overflow: hidden;
}

/* Codebook tooltips on DT column headers can carry a sentence or two;
   default Bootstrap width (~200px) is cramped. */
.tooltip-inner { max-width: 360px; text-align: left; }

/* Navbar layout — bits shared by every width. The desktop (>=1250px) layout is
   in the `min-width: 1250px` block just below; the narrow layout is in the
   `max-width: 1249.98px` block further down. The two regimes are kept fully
   separate so neither bleeds into the other. Moved from app.R tags$style. */
.navbar { position: relative; overflow: visible; }
.navbar > .container-fluid { position: static; overflow: visible; display: flex; flex-wrap: nowrap; align-items: center; }
.navbar-collapse { overflow: visible; }
.navbar .navbar-brand { display: flex; align-items: center; margin: 0; }
/* The brand is a plain SPAN (site name + "Data explorer" subtitle + dataset
   switcher), not a navigation link, so it shouldn't lighten on hover/focus the
   way Bootstrap's .navbar-brand does. Pin the hover/focus color to the resting
   brand color — theme-aware via the BS5 navbar variables. */
.navbar { --bs-navbar-brand-hover-color: var(--bs-navbar-brand-color); }
.navbar .navbar-brand:hover,
.navbar .navbar-brand:focus { color: var(--bs-navbar-brand-color); }
.navbar .form-group { margin-bottom: 0; }

/* Desktop: three zones on one flex row.
     [ brand — natural width ][ tabs — centered in what's left ][ controls ]
   The brand (site name + dataset switcher + Tour) flows at its natural width
   instead of being absolutely positioned, so it reserves real space. The tabs
   and the download controls share the flex-growing .navbar-collapse; an auto
   margin before the first tab and before the controls splits the leftover space
   equally, so the tabs sit dead-center in the gap BETWEEN the brand and the
   controls (not across the whole navbar). Because the controls stay in flow, the
   centering tracks their actual width — the tabs recenter per tab as the download
   bar changes (Explore/Summarize show a format dropdown; Visualize a save btn). */
@media (min-width: 1250px) {
  .navbar .navbar-header { flex: 0 0 auto; }
  .navbar .navbar-brand { margin-left: 0.5rem; }
  .navbar .navbar-collapse { flex: 1 1 auto; }
  .navbar .navbar-nav { width: 100%; align-items: center; }
  .navbar .navbar-nav > .nav-item:first-child { margin-left: auto; }
  .navbar .navbar-nav > .nav-item:last-child { margin-left: auto; margin-right: 0.5rem; display: flex; align-items: center; }
}

/* Navbar download controls: select + button share sm sizing. */
.navbar .btn.btn-sm,
.navbar select.form-control {
  font-size: 0.875rem;
  line-height: 1.5;
  padding: 0.25rem 0.5rem;
  height: auto;
}
.navbar select.form-control {
  padding-right: 2rem; /* room for caret */
}
/* Prevent icon baseline/descender space from inflating button height */
.navbar .btn.btn-sm i { vertical-align: middle; }

/* Never collapse tabs behind a hamburger — Explore / Summarize / Visualize
   stay visible at every width.  Download controls hide on narrow screens.
   bslib uses BS3-compat markup: the toggle is .navbar-toggle (not
   .navbar-toggler) and the wrapper is .navbar-header. */
.navbar-toggle { display: none !important; }
.navbar-collapse { display: flex !important; flex-basis: auto; }

/* Narrow screens (<1250px): brand on the left, tabs pinned to the right, one
   row. The brand may shrink — the site name and the dataset-switcher label
   truncate with an ellipsis — so the tabs (the primary navigation) are never
   pushed off-screen. Tour and the download controls drop out to make room. */
@media (max-width: 1249.98px) {
  /* Brand zone yields space; tabs keep their natural width and never shrink. */
  .navbar .navbar-header { flex: 0 1 auto; min-width: 0; }
  .navbar .navbar-brand { min-width: 0; }
  .navbar .navbar-brand .d-inline-flex { min-width: 0; }
  .navbar .navbar-brand #tour { display: none; }
  /* Truncate the long, variable-width pieces instead of overflowing. Only the
     leaf text nodes get overflow:hidden, so the open switcher menu isn't clipped. */
  .navbar .brand-site-name { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
  /* Switcher: the toggle is a flex row filling the switcher (which floors at
     ~3rem so the button never collapses below its icon + caret — the caret stays
     inside the border). The icon and caret are pinned (flex:0 0 auto); the label
     takes the remaining width and truncates (flex:1 1 0 + ellipsis). Because the
     label flex-grows, any slack from the floor is absorbed by the label (which
     sits before the caret), so there's never dead space past the caret. */
  #dataset-switcher { min-width: 3rem; }
  #dataset-switcher .dropdown-toggle { display: flex; width: 100%; align-items: center; }
  #dataset-switcher .dropdown-toggle > *:not(.ms-1),
  #dataset-switcher .dropdown-toggle::after { flex: 0 0 auto; }
  #dataset-switcher .dropdown-toggle .ms-1 { flex: 1 1 0; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
  /* Tabs: natural width, never shrink, pushed to the right edge. */
  .navbar .navbar-collapse { flex: 0 0 auto; margin-left: auto; }
  .navbar .navbar-nav { width: auto; flex-direction: row; flex-wrap: nowrap; gap: 0.5rem; margin-left: 1rem; }
  .navbar .navbar-nav > .nav-item:last-child { display: none !important; }
}

/* Narrower: drop the "Data explorer (beta)" subtitle to free a line of width. */
@media (max-width: 767.98px) {
  .navbar .navbar-brand .opacity-75 { display: none; }
}

/* Phone: tighten tab spacing so the three tabs keep their full labels. */
@media (max-width: 575.98px) {
  .navbar .navbar-nav { gap: 0.125rem; margin-left: 0.25rem; }
  .navbar .navbar-nav .nav-link { padding-left: 0.25rem; padding-right: 0.25rem; }
}

/* Highlight the active Explore / Summarize / Visualize tab */
.navbar .navbar-nav .nav-link { opacity: 0.65; }
.navbar .navbar-nav .nav-link.active { opacity: 1; }

/* Dataset-switcher dropdown — styled to echo the navbar mega-menus on
   deportationdata.org (their navbar-megamenu.css / custom.scss). The dropdown
   sits inside .navbar-brand (Playfair Display), so the menu first resets to the
   body font for item text. Section headers then opt back into the Playfair
   heading face with a hairline rule beneath — that rule is the section
   separator, so the markup drops the old <hr> dividers. Items take the site's
   smaller size, tighter padding, and muted hover fill. */
#dataset-switcher .dropdown-toggle { font-family: var(--bs-body-font-family); }
/* A little side padding on the panel insets the header hairlines and hover
   fills from the edges, the way the site's mega-menu container padding does. */
.slicer-menu { font-family: var(--bs-body-font-family); padding: 0.4rem 0.45rem; }
/* Section headers: heading face + hairline, mirroring .ddp-mega-col .dropdown-header. */
.slicer-menu .dropdown-header {
  font-family: var(--bs-headings-font-family, "Playfair Display", serif);
  font-size: 1rem;
  font-weight: 600;
  color: #2c3e50;
  text-transform: none;   /* override cosmo's uppercased headers */
  letter-spacing: 0;
  padding: 0.5rem 0.55rem 0.2rem;
  margin: 0.2rem 0 0.4rem;
  border-bottom: 1px solid rgba(0, 0, 0, 0.08);
  white-space: normal;
}
.slicer-menu .dropdown-header:first-child { margin-top: 0; }
/* Items: 0.9rem with the site's muted hover fill (#E6EAEB). */
.slicer-menu .dropdown-item { font-size: 0.9rem; padding: 0.3rem 0.55rem; }
.slicer-menu .dropdown-item:hover,
.slicer-menu .dropdown-item:focus { background-color: #e6eaeb; }
#dataset-switcher .dropdown-menu { z-index: 1050; }

/* Plot save modal preview pane: a centered box matching bslib card chrome. */
.preview-pane {
  min-height: 350px;
  display: flex;
  align-items: center;
  justify-content: center;
  border: 1px solid var(--bs-border-color);
  border-radius: var(--bs-border-radius);
  padding: 0.5rem;
  background: var(--bs-white);
}

/* rintrojs: fix Safari rendering bug where highlight layer is invisible. */
.introjs-tooltipReferenceLayer {
  visibility: visible !important;
}

/* Column-picker: match sidebar font size (bslib sidebar is smaller
   than Bootstrap's default 1rem button/dropdown text). */
.sidebar .bootstrap-select .btn,
.sidebar .bootstrap-select .dropdown-menu { font-size: inherit; }

/* Force the column-picker dropdown to always open downward. handlers.js sets
   data-bs-display="static" on the toggle to bypass Popper entirely. These
   CSS rules are a safety net in case Popper still runs (e.g. race condition
   on init): neutralize the dropup class and top-* placement overrides. */
.bootstrap-select.dropup .dropdown-menu {
  top: 100% !important;
  bottom: auto !important;
}

/* Embed mode (?embed=1, set as a class on <html> by an inline head script
   in app.R): hide the site name in the navbar brand — the page embedding
   the app already provides it — and reclaim its leading margin. */
html.ddp-embed .brand-site-name { display: none; }
html.ddp-embed .brand-site-name + span { margin-left: 0 !important; }

/* Framed mode (app inside an iframe; class set by the head script in app.R):
   the host/viewer chrome floats a round expand/collapse button over the
   top-right corner. Keep the navbar's right-aligned content clear of it. The
   button is cross-origin so its size can't be measured from here — this
   clearance is tuned by eye against the embedded view. --ddp-frame-clearance
   is the single knob; bump it if the host button ever grows again. */
html.ddp-framed { --ddp-frame-clearance: 7rem; }   /* was an ineffective 3.8rem */
/* Desktop: the controls are in flow (auto-margined to the right), so reserve the
   clearance with margin-right; the tabs recenter in the smaller gap. (Narrow
   uses container padding-right below, so scope this to desktop to avoid doubling.) */
@media (min-width: 1250px) {
  html.ddp-framed .navbar .navbar-nav > .nav-item:last-child {
    margin-right: var(--ddp-frame-clearance);
  }
}
@media (max-width: 1249.98px) {
  /* The standalone layout hides the download controls on narrow screens to make
     room for the tabs. But embed mode has a compact brand (site name hidden), so
     there IS room — keep the controls visible and reserve the expand-button
     clearance on the container so the whole right-aligned group (tabs + controls)
     stays clear of the host's corner button. */
  html.ddp-framed .navbar .navbar-nav > .nav-item:last-child { display: flex !important; }
  html.ddp-framed .navbar > .container-fluid {
    padding-right: var(--ddp-frame-clearance);
  }
}
