/* The little that Bootstrap does not already provide.
 *
 * A stylesheet rather than `style="..."` attributes: the CSP has no `unsafe-inline` for styles, so an
 * inline style attribute is blocked by the browser (see base.html).
 */

/* ---------------------------------------------------------------------------
 * The EJS chrome, as classes.
 *
 * Every one of these was a `style="..."` attribute in the EJS templates. They cannot stay inline
 * here — style-src has no `unsafe-inline`, so the browser drops an inline style attribute — but the
 * values are the originals, because the cutover is meant to be invisible.
 * ------------------------------------------------------------------------- */

.portal-navbar {
  background-color: #e8e8e8;
}

.portal-logo {
  width: 200px;
}

/* The fixed 40px bar the EJS pages ended with, plus the room it needs so that it never covers the
 * last row of content — which on the old dashboard it did, hence the 50px spacer div at the bottom
 * of the template. */
.portal-footer {
  height: 40px;
}

.portal-body {
  padding-bottom: 60px;
}

/* The black rule and underlined heading that separated every section of the old dashboard. */
.section-rule {
  border-top: 2px black solid;
}

.section-heading {
  margin-top: 20px;
  margin-bottom: 20px;
  text-decoration: underline;
  text-underline-offset: 15px;
}

/* Straight from Navbar-With-Button-icons.css: the client cards were sized down deliberately, because
 * three of them sit in a row on a laptop and a full-size card title wraps to three lines. */
.card p {
  font-size: 0.8em;
}

h4.card-title {
  font-size: 100%;
}

p.card-text {
  font-size: 75%;
}

.changePayBtn {
  font-size: 75%;
}

.dashAlert {
  font-size: 85%;
}

/* `alert-dismissible` pads only the right, to clear the close button, which pushes centred text off
 * centre by that much. Matching the left padding puts it back. */
.alert-dismissible.text-center {
  padding-left: 3rem;
}

@media (max-width: 1200px) {
  .card p {
    font-size: 75%;
  }
}

/* The old cards were forced to a common height so that a row of them lined up whatever each one had
 * to say. `266.8px` is the measured value the EJS template hardcoded. */
.estimate-card {
  height: 100%;
  min-height: 266.8px;
}

.payment-card {
  height: 100%;
}

/* The "Show/Hide Past Transactions" button changed its own label in dashboard-js. Bootstrap already
 * tracks the state — it puts `.collapsed` on the toggler — so the label follows from CSS and needs no
 * script, which also means it cannot get out of step with the panel it describes. */
#pastTransactionToggle .toggle-show,
#pastTransactionToggle.collapsed .toggle-hide {
  display: none;
}

#pastTransactionToggle.collapsed .toggle-show {
  display: inline;
}

/* R-RAG's fifth state (D-10). Bootstrap 5 has no orange contextual class, and the point of the state
 * is that a declined payment must not look like either the gold "scheduled" or the red "not
 * approved" — those are exactly the two it was indistinguishable from before.
 *
 * #fd7e14 is Bootstrap's own $orange, so it belongs to the same palette as the rest. The colour and
 * the wording are both stated defaults pending UAT (`07` phase 11); this is the one place to change
 * them.
 */
.text-bg-declined {
  color: #fff;
  background-color: #fd7e14;
}

/* The traffic light carries its meaning in a `title` tooltip, so give it the cursor that says so. */
.status-badge[title] {
  cursor: help;
}

/* Sortable column headers. Links, because they are navigation and have to work with HTMX absent — but
 * they should read as table headers rather than as body links. */
.sort-link {
  color: inherit;
  text-decoration: none;
  white-space: nowrap;
}

.sort-link:hover,
.sort-link:focus-visible {
  text-decoration: underline;
}

/* The staff estimate table gets a fixed 80vh pane rather than growing with its row count.
 *
 * Bootstrap has no `80vh` utility — `vh-100` is the only viewport-height class — so this is the one
 * rule that has to exist rather than being spelled in the template.
 *
 * Three parts, and all three are load-bearing:
 *
 *  - the pane is `80vh`, so a page of 5 rows and a page of 50 occupy the same space and the pager
 *    does not walk up and down the screen as you move through it;
 *  - the card is a column flexbox filling the pane, so the pager sits at the bottom edge of the pane
 *    instead of directly under the last row;
 *  - `.table-responsive` takes the leftover height and scrolls it. `min-height: 0` is what makes
 *    that work — a flex item's default `min-height: auto` refuses to shrink below its content, so
 *    without it the table pushes the pane taller than 80vh and nothing scrolls at all.
 */
.estimate-table-pane {
  height: 80vh;
}

/* 80vh is the *preferred* height, not a floor. The chrome around the pane — navbar, heading, toolbar,
 * and the 60px the fixed footer is given — comes to roughly 300px, so a literal 80vh pane pushes the
 * page past the bottom of the window on any normal laptop and the whole document scrolls. That is the
 * opposite of the point: the table was given a fixed height so the page would hold still.
 *
 * So the staff dashboard becomes one viewport tall and the pane is allowed to shrink into whatever
 * the chrome leaves. On a tall window it gets its full 80vh; on a short one it gets less, and either
 * way the document itself does not scroll — only the rows do.
 *
 * `height: 100dvh` after the `100vh` line, not instead of it: `dvh` accounts for mobile browser
 * toolbars that `vh` ignores, and the duplicate declaration is the fallback for engines without it.
 * The body's existing 60px `padding-bottom` is inside that height, because Bootstrap's reboot sets
 * `box-sizing: border-box` — which is exactly the reservation the fixed footer needs. */
.staff-dashboard-fit {
  height: 100vh;
  height: 100dvh;
  display: flex;
  flex-direction: column;
}

.staff-dashboard-fit > main {
  flex: 1 1 auto;
  min-height: 0;
  display: flex;
  flex-direction: column;
}

/* Only the pane may give up height. Without this the heading and the toolbar are shrinkable too —
 * flex items default to `flex-shrink: 1` — and a short window squashes the search box instead of the
 * table. */
.staff-dashboard-fit > main > * {
  flex-shrink: 0;
}

/* A floor rather than `min-height: 0`. The pane is the only shrinkable item here, so on a very short
 * window — or with a wrapped toolbar eating two extra rows — an unbounded shrink collapses the table
 * to nothing and the dashboard looks broken. 10rem still shrinks well below the rows' natural height,
 * which is all `min-height` has to permit for the inner scroll to engage; past that point the
 * document scrolls, which is the right way for this to fail. */
.staff-dashboard-fit > main > .estimate-table-pane {
  flex-shrink: 1;
  min-height: 10rem;
}

.estimate-table-pane > .card {
  height: 100%;
  display: flex;
  flex-direction: column;
}

.estimate-table-pane .table-responsive {
  flex: 1 1 auto;
  min-height: 0;
  overflow-y: auto;
}

/* The header has to stay put once the body scrolls, or the sort links leave the screen and the
 * columns become unreadable a few rows down.
 *
 * On the `th` and not on the `thead`: `position: sticky` on a table section or row is not honoured
 * everywhere, and the cells are the part that has to hold still anyway. They need no background of
 * their own — Bootstrap paints `--bs-table-bg` on every cell, and `.table-light` sets it to #f8f9fa
 * — so the rows scrolling underneath do not show through. */
.estimate-table-pane thead th {
  position: sticky;
  top: 0;
  z-index: 1;
}

/* A `<form>` inside a Bootstrap dropdown item: the button has to fill the item the way an `<a>` does,
 * and Bootstrap only styles `.dropdown-item` elements that are direct children of the menu. */
.dropdown-menu form {
  margin: 0;
}

.dropdown-menu form .dropdown-item {
  border: 0;
  background: none;
  width: 100%;
  text-align: left;
}
