/*
 * This is a manifest file that'll be compiled into application.css.
 *
 * With Propshaft, assets are served efficiently without preprocessing steps. You can still include
 * application-wide styles in this file, but keep in mind that CSS precedence will follow the standard
 * cascading order, meaning styles declared later in the document or manifest will override earlier ones,
 * depending on specificity.
 *
 * Consider organizing styles into separate files for maintainability.
 */

/*
 *= require_tree .
 *= require_self
 */

body {
  font-family: sans-serif;
  margin: 0;
}

header {
  background-color: #f1f3f5; /* Between admin and main toolbar colors */
  color: #212529; /* Reset text color for light background */
  padding: 1rem;
  display: flex;
  flex-wrap: wrap;
  justify-content: space-between;
  align-items: center;
  width: 100%;
  box-sizing: border-box;
}

header .logo a {
  font-size: 1.5em;
  font-weight: bold;
  color: #333;
  text-decoration: none;
}

header nav {
  display: flex;
  flex-wrap: wrap;
  gap: 1rem;
}

header nav > a, header nav > form input[type="submit"] {
  color: #333;
  text-decoration: none;
  font-size: 1em;
  background: none;
  border: none;
  cursor: pointer;
  font-family: sans-serif;
}

header nav > a:hover, header nav > form input[type="submit"]:hover {
  text-decoration: underline;
}

/* Native <details> dropdown - no JS needed for the toggle. */
.user-menu > summary {
  list-style: none;
  cursor: pointer;
}

.user-menu > summary::-webkit-details-marker {
  display: none;
}

.user-menu > .dropdown-menu {
  display: none;
}

.user-menu[open] > .dropdown-menu {
  display: block;
  right: 0;
  left: auto;
  margin-top: 0.25rem;
}

.user-menu li form.button_to {
  margin: 0;
}

.user-menu .dropdown-item {
  width: 100%;
  text-align: left;
}

main {
  padding: 1rem 2rem;
}

@media (max-width: 576px) {
  main {
    padding: 1rem;
  }
}

/* Empty spacer footer (see layouts/application.html.erb) reserving room for
   the fixed-position Messages/Feedback buttons - both sit at bottom: 1.5rem
   with a default .btn height, so 5rem clears them with a little to spare.
   Without this, a page whose own last control (pagination, Back/Save, ...)
   ends near the bottom of a short page, or when scrolled to the end of a
   long one, sits directly under those fixed buttons. */
.floating-widget-spacer {
  height: 5rem;
}

.toolbar {
  padding: 0.5rem 1rem;
  width: 100%;
  box-sizing: border-box;
  border-bottom: 1px solid #dee2e6;
  clear: both;
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 1rem;
}

.toolbar-main {
  background-color: #f8f9fa; /* Slightly lighter gray */
}

.toolbar-title {
  font-weight: bold;
}

.toolbar a {
  text-decoration: none;
}

.toolbar-dropdown-toggle {
  background: none;
  border: none;
  padding: 0;
  margin: 0;
  color: var(--bs-link-color, #0d6efd);
  font-size: 1em;
  font-family: inherit;
  cursor: pointer;
}

.toolbar-dropdown-toggle:hover {
  text-decoration: underline;
}

.breadcrumbs {
  padding: 0.5rem 1rem;
  width: 100%;
  box-sizing: border-box;
  border-bottom: 1px solid #dee2e6;
  background-color: #ffffff;
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 0.5rem;
  font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
  font-size: 0.8rem;
  color: #6c757d;
}

.breadcrumbs a {
  text-decoration: none;
}

.breadcrumb-separator {
  color: #adb5bd;
}

.breadcrumb-current {
  color: #6c757d;
}

/* Sortable data grids (see grid_controller.js) */
th[data-grid-sort-type] {
  cursor: pointer;
  white-space: nowrap;
}

th[data-grid-sort-type]:hover {
  background-color: #e9ecef;
}

.grid-sort-indicator {
  font-size: 0.75em;
}

[data-sort-field] {
  cursor: pointer;
  user-select: none;
  white-space: nowrap;
}

[data-sort-field]:hover {
  background-color: #e9ecef;
}

/* React DashboardGrid: sortable headers get a pointer + hover so the sort
   affordance is discoverable (the old grid_controller rules above only match
   its data attributes, which the React grid doesn't use). */
.dashboard-grid th[role="button"] {
  cursor: pointer;
  white-space: nowrap;
}

.dashboard-grid th[role="button"]:hover {
  background-color: #e9ecef;
}

/* DashboardGrid: freeze a column to the left while the table scrolls
   horizontally inside .table-responsive (e.g. the By Member name column). The
   cell needs an opaque base background so scrolled content doesn't show
   through; Bootstrap's striping is an inset box-shadow (not background-color),
   so it still paints on top and frozen body cells stay striped in step with
   their row. Header cells keep their own .table-light background. */
.dashboard-grid-sticky-col {
  position: sticky;
  left: 0;
  z-index: 1;
}

.dashboard-grid tbody .dashboard-grid-sticky-col {
  background-color: var(--bs-body-bg);
}

.dashboard-grid thead .dashboard-grid-sticky-col {
  z-index: 2;
}

/* Flex-based grid rows (divs standing in for table rows) - stripe and
   highlight the same way .table-striped would for an actual <table>. */
.flex-grid-row:nth-child(even) {
  background-color: rgba(0, 0, 0, 0.03);
}

.flex-grid-row:hover {
  background-color: rgba(0, 0, 0, 0.06);
}

/* Icon-only action buttons (IconButtonHelper / BiIcon - the only bi-* usage in
   the app): render the glyph a size up from btn-sm's 0.875rem text so the icons
   read clearly in the grids' Actions columns. */
.btn .bi {
  font-size: 1.1rem;
  vertical-align: -0.125em;
}

/* Button color/emphasis semantics - two classes combine on the same element
   (e.g. class="btn btn-normal btn-solid"):
     - color:    .btn-destructive (red)  = a destructive action
                 .btn-informational (yellow) = an informational/needs-review action
                 .btn-normal (green) = a normal/default action
     - emphasis: .btn-solid = emphasised, .btn-outline = understated (fills
                 solid on hover, matching Bootstrap's own outline buttons) */
.btn-destructive.btn-solid {
  color: #fff;
  background-color: var(--bs-danger);
  border-color: var(--bs-danger);
}

.btn-destructive.btn-solid:hover {
  background-color: #bb2d3b;
  border-color: #b02a37;
}

.btn-destructive.btn-outline {
  color: var(--bs-danger);
  background-color: transparent;
  border-color: var(--bs-danger);
}

.btn-destructive.btn-outline:hover {
  color: #fff;
  background-color: var(--bs-danger);
  border-color: var(--bs-danger);
}

.btn-informational.btn-solid {
  color: #000;
  background-color: var(--bs-warning);
  border-color: var(--bs-warning);
}

.btn-informational.btn-solid:hover {
  background-color: #ffca2c;
  border-color: #ffc720;
}

.btn-informational.btn-outline {
  color: var(--bs-warning);
  background-color: transparent;
  border-color: var(--bs-warning);
}

.btn-informational.btn-outline:hover {
  color: #000;
  background-color: var(--bs-warning);
  border-color: var(--bs-warning);
}

.btn-normal.btn-solid {
  color: #fff;
  background-color: var(--bs-success);
  border-color: var(--bs-success);
}

.btn-normal.btn-solid:hover {
  background-color: #157347;
  border-color: #146c43;
}

.btn-normal.btn-outline {
  color: var(--bs-success);
  background-color: transparent;
  border-color: var(--bs-success);
}

.btn-normal.btn-outline:hover {
  color: #fff;
  background-color: var(--bs-success);
  border-color: var(--bs-success);
}

/* Alliance-member picker dropdowns in the score import grid - a standard
   width so every DDL in a row lines up regardless of option text length. */
.alliance_member {
  width: 100%;
  max-width: 300px;
}

/* Bordered key/value and stat grids (event planning's CharacterCard context
   section, TeamColumn's running totals) - a CSS grid with a `gap` the size
   of the desired line, colored via the container's own background, with
   each cell painting over it in the surrounding surface's color. Cheaper
   than bordering every cell and sidesteps doubled-up borders on shared
   edges. Callers just set `gridTemplateColumns` and drop <span>s in. */
.context-grid {
  display: grid;
  gap: 1px;
  background-color: var(--bs-border-color);
  border: 1px solid var(--bs-border-color);
  border-radius: var(--bs-border-radius-sm);
  overflow: hidden;
}

.context-grid > * {
  background-color: var(--bs-body-bg);
  padding: 0.125rem 0.375rem;
}

/* EventHeaderCard's "row" variant (events/index, event_plans/index): the
   title+badges block gets a fixed width so every row's fields start at the
   same offset, but only once flex-md-row actually lays the card out
   horizontally (matching Bootstrap's own md breakpoint). `flex-basis`
   follows the flex container's main axis, which flex-md-row flips from
   vertical to horizontal at md - applying a fixed 16rem basis unconditionally
   made this block 16rem *tall* instead of wide once the card stacked below
   that breakpoint. Widened from 16rem to 19rem (2026-10-28): at 16rem, a
   title's protected 10rem (see EventHeaderCard.tsx) left a long badge only
   ~5.5rem to work with before truncating hard - too aggressive. 19rem gives
   the badge ~8.5rem instead (50%+ more) while the date stays fully visible. */
@media (min-width: 768px) {
  .event-header-row-title {
    flex: 0 0 19rem;
  }
}

/* A badge inside the row-title block (EventHeaderCard.tsx wraps it in a
   shrinkable flex item with minWidth: 0) needs to shrink and truncate itself
   rather than just getting clipped by the wrapper: a plain overflow:hidden on
   the wrapper clips the pill's own background/corner with a hard edge and no
   "…", since text-overflow:ellipsis can't reach inside a nested inline-block.
   Constraining the badge itself to the wrapper's width (max-width: 100%, a
   definite size from flex) lets it ellipsize its own text within the pill. */
.event-header-row-title .badge {
  display: inline-block;
  max-width: 100%;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  vertical-align: middle;
}

/* EventHeaderCard row-variant fields (every card grid), at every width: show
   the label and value on one line - label left, value right - wrapping the
   value to its own line only when the two don't fit side by side. Previously
   this one-line layout was mobile-only (below md); at md+ the label sat above
   the value with the value truncated to one line, which kept columns aligned
   but made every row tall even for short values (reported on alliances#show's
   Members list, 2026-10-28). A field that does wrap now stands slightly taller
   than its row-mates - an acceptable trade for shorter rows overall.

   Below md, a field is the only thing on its line (the card has stacked into
   a column), so pushing the value to the far right edge reads fine. At md+,
   several fields share one row as side-by-side columns (flex-basis 0 each -
   see .event-header-row-title's comment) - stretching label-to-value across
   the *whole* column there put the value flush against the next field's
   label with no visual gap, reading as if it belonged to that label instead
   of its own (reported 2026-10-28). So at md+ the value sits with a small
   fixed gap right after its own label instead of being pushed to the column
   edge; a field whose column declares `text-md-end` (numeric columns - see
   EventHeaderField's `align` prop) pins that label+value pair to the end of
   its column instead, same as before. */
.event-header-field {
  display: flex;
  justify-content: space-between;
  flex-wrap: wrap;
  column-gap: 0.75rem;
}
.event-header-field-label {
  flex: 0 0 auto;
}
.event-header-field-value {
  min-width: 0;
  text-align: right;
  overflow-wrap: anywhere;
}
@media (min-width: 768px) {
  .event-header-field {
    justify-content: flex-start;
    column-gap: 0.4rem;
  }
  .event-header-field.text-md-end {
    justify-content: flex-end;
  }
  .event-header-field-value {
    text-align: left;
  }
}

/* Event planning's Team board menu embeds full button components (AddTeamButton,
   SavePlanButton, etc.) rather than plain .dropdown-item rows, so their .btn
   sizes to its own label by default - keep them all a consistent width instead.
   Scoped to .btn so it doesn't touch the plain .dropdown-item entries (Collapse,
   Hide Details, ...) other menus use. */
.dropdown-menu .btn {
  width: 100%;
}

/* Google Picker (Drive attach) renders its own dialog + backdrop straight
   into <body> at a fixed z-index of 1000/1001. That sits BELOW Bootstrap's
   modal (backdrop 1050, dialog 1055), so when the Drive picker is opened from
   inside a modal (Bulk Update Characters, image attach, ...) the file picker
   lands behind the modal and is unreachable. Lift both picker layers above
   any Bootstrap modal so it's always clickable regardless of what opened it. */
.picker-dialog-bg {
  z-index: 2000 !important;
}

.picker-dialog {
  z-index: 2001 !important;
}