@import url('open-iconic/font/css/open-iconic-bootstrap.min.css');

html, body {
    font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif;
}

h1:focus {
    outline: none;
}

/* Page-heading spacing, standardized here instead of per-page utility classes so every admin
   page has the same breadcrumb → title → subtitle → section → content rhythm. Scoped to `article`
   (the MainLayout content wrapper) so public/login pages are untouched. */
article h1 {
    margin-bottom: 1.5rem;
}

/* When a lead paragraph (subtitle) follows the title, hug it to the title... */
article h1:has(+ p) {
    margin-bottom: 0.25rem;
}

/* ...and render that subtitle muted + consistently spaced, whether the page marked it text-muted
   or left it a plain <p>. */
article h1 + p {
    color: var(--bs-secondary-color, #6c757d);
    margin-bottom: 1.5rem;
}

/* Section-separator spacing above intra-page <h2>s (was a per-page mt-4). Adjacent-sibling margins
   collapse, so a subtitle (1rem) directly before a section h2 (1.5rem) yields 1.5rem, not 2.5rem. */
article h2 {
    margin-top: 1.5rem;
}

/* <h2> is also used as a card title/header (AllianceCard/GuildCard/overview cards) — no section gap
   inside a card. Higher specificity (0,1,1) than `article h2` (0,0,2), so this wins. */
.card h2 {
    margin-top: 0;
}

a, .btn-link {
    color: #0071c1;
}

.btn-primary {
    color: #fff;
    background-color: #1b6ec2;
    border-color: #1861ac;
}

.content {
    padding-top: 1.1rem;
}

.valid.modified:not([type=checkbox]) {
    outline: 1px solid #26b050;
}

.invalid {
    outline: 1px solid red;
}

.validation-message {
    color: red;
}

/* Bootstrap's grid (row/col-*) only resizes at fixed viewport breakpoints, not based on the
   container's actual available width — a sidebar eating part of the viewport can leave a
   col-xl-3 grid computing "4 columns" that don't actually fit the space left over. This sizes
   off the grid container itself instead: cards never shrink below 250px or grow past 350px,
   and auto-fit (not auto-fill) collapses empty trailing tracks so real cards stretch to fill
   each row evenly instead of leaving a ragged gap. */
.card-grid {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(250px, 350px));
    gap: 1rem;
}

/* The shortcut/overview cards' navy icon glyph and grey subtitle text — shared here instead of a
   repeated inline style on each card. (Not .card-subtitle: that's a Bootstrap class.) */
.card-icon {
    color: rgb(5, 39, 103);
}

.card-subtext {
    color: #5a5a63;
}

/* Opt-in exception: a single card that spans the whole grid width instead of one 250-350px
   track — for a wide element (e.g. a multi-column table) the default track squeezes. Spanning
   1 / -1 works at every track count (full width when 1 track, all tracks when several). */
.card-grid > .card-span-full {
    grid-column: 1 / -1;
}

/* A label and the control it names, inside a SettingsCard.

   The card body is a flex column with gap-3, which spaces every DIRECT child 1rem apart — including
   a label from its own input. Stacked on Bootstrap's own .form-label margin-bottom that reads as
   1.5rem of nothing between "Suffix" and the box you type the suffix into, and it looked like a
   layout bug because it is one.

   Fixed here rather than by wrapping each pair in a div: there were eighteen of them across nine
   editors, and the wrapping has to be remembered every time a card gains a field — it had already
   been reported twice. The negative margin cancels the flex gap for exactly the pairs that should
   hug; flex gap can't be overridden per item any other way. Pairs already wrapped in their own
   element are unaffected, since the label is then no longer a direct child. */
.card-body > .form-label {
    margin-bottom: 0;
}

.card-body > .form-label + * {
    margin-top: -0.5rem;
}

/* Conditional Roles' rule builder. Indentation and the left rule are the only thing conveying
   nesting depth, so an admin can see the shape of the expression they built; ConditionNodeEditor
   renders itself once per level.

   Every width rule below is written as .condition-node .x rather than .x: Bootstrap's .form-select
   sets width:100%, and a bare single-class selector only beats it by load order — which it lost,
   leaving every select stretched across the page. Two classes settle it regardless of order. */
.condition-node {
    /* A rule reads as a short statement, not a full-page banner. */
    max-width: 46rem;
}

.condition-node-nested,
.condition-add-row {
    padding-left: 0.75rem;
}

.condition-node-nested {
    margin-top: 0.5rem;
}

.condition-children {
    margin-left: 0.75rem;
    border-left: 2px solid var(--bs-border-color, #dee2e6);
}

.condition-node .condition-row {
    /* Room to breathe after the operator so it doesn't crowd the operand it applies to. */
    column-gap: 0.75rem;
}

.condition-node .condition-kind-select {
    flex: 0 0 auto;
    width: 9.5rem;
}

.condition-node .condition-operand {
    flex: 0 1 18rem;
    min-width: 0;
}

/* RolePicker wraps its select in a .mb-2, and with align-items:center that half-rem of bottom
   margin is counted into the item's box — so the select itself ends up sitting visibly higher than
   the operator select beside it. !important because Bootstrap's spacing utilities are themselves
   !important; without it this rule loses however specific it is. */
.condition-node .condition-operand > div {
    margin-bottom: 0 !important;
}

/* RolePicker renders a plain .form-select, but everything beside it in the row is form-select-sm /
   btn-sm, so the two controls came out at different heights. These are Bootstrap's own
   .form-select-sm metrics applied to the picker's inner select — padding-right is left alone, since
   that is what makes room for the dropdown arrow. Done here rather than by adding a size parameter
   to RolePicker, which is shared by a dozen editors that have no such need. */
.condition-node .condition-operand .form-select {
    padding-top: 0.25rem;
    padding-bottom: 0.25rem;
    padding-left: 0.5rem;
    font-size: 0.875rem;
    border-radius: var(--bs-border-radius-sm);
}

.condition-name-input {
    max-width: 24rem;
}

/* QuickGrid intentionally renders extra empty <tr>/<td> elements on a paginated grid's
   last page to keep a stable row count/height across pages (documented behavior, see
   https://github.com/dotnet/aspnetcore/issues/59096 and /issues/57199) — it explicitly
   leaves the styling of those placeholder rows to the app. Can't target them via
   :empty — the placeholder <td>s aren't actually childless (likely whitespace), so
   :empty silently fails to match. QuickGrid does mark every REAL data row with an
   aria-rowindex attribute (accessibility metadata) that placeholder rows lack — that's
   the reliable signal (see the aria-rowindex workaround in aspnetcore#57199's comments).
   Not display: none — keeps the placeholder rows' layout space, the actual point of the
   feature. border-bottom-style: hidden clears the row's bottom border: with Bootstrap's
   border-collapse, that border is a *shared* edge with the real row above it, and
   "hidden" always wins in the CSS border-conflict resolution regardless of which side
   declares it. --col-gap: 0 clears the column-spacing custom property QuickGrid's theme
   CSS defines (normally 1rem) — scoped to this selector, it only cascades to cells
   inside these specific (invisible) rows, so real rows' column spacing is untouched. */
.quickgrid tbody tr:not([aria-rowindex]) {
    border-bottom-style: hidden;
    --col-gap: 0;
}

/* Alliance emblem picker — a static-SSR radio grid on the STFC alliance Create/Edit pages.
   Selection highlight is pure CSS (:has(:checked)) so it updates on click with no interactive
   circuit; the native radios post the chosen index (or empty = None) with the form. */
.emblem-picker {
    display: flex;
    flex-wrap: wrap;
    gap: 0.5rem;
    max-width: 640px;
}
.emblem-tile {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 60px;
    height: 60px;
    padding: 6px;
    border: 2px solid #dee2e6;
    border-radius: 8px;
    cursor: pointer;
    background: #fff;
    margin: 0;
}
.emblem-tile:hover {
    border-color: #adb5bd;
}
.emblem-tile:has(input:checked) {
    border-color: rgb(5, 39, 103);
    box-shadow: 0 0 0 2px rgba(5, 39, 103, 0.2);
}
.emblem-tile-none {
    color: #6c757d;
    font-size: 0.72rem;
    font-weight: 600;
    text-transform: uppercase;
}

/* "Powered by {source}" attribution credit (PoweredBy.razor) — a Bootstrap info alert on admin
   pages/editors backed by third-party data. The alert styles colour/typography; this just adds a
   top gap so it sits as a footer credit and keeps it compact. */
.powered-by {
    margin-top: 2rem;
    font-size: 0.875rem;
}

/* The operand typeahead's results, floating over whatever follows the row rather than pushing the
   rest of the tree down while someone is searching. */
.condition-search-results {
    position: absolute;
    z-index: 5;
    top: 100%;
    left: 0;
    right: 0;
    max-height: 16rem;
    overflow-y: auto;
    background: var(--bs-body-bg, #fff);
    border: 1px solid var(--bs-border-color, #dee2e6);
    border-radius: var(--bs-border-radius-sm);
    box-shadow: 0 0.25rem 0.5rem rgba(0, 0, 0, 0.1);
}

.condition-search-result {
    display: block;
    width: 100%;
    padding: 0.25rem 0.5rem;
    border: 0;
    background: none;
    text-align: left;
    font-size: 0.875rem;
}

.condition-search-result:hover,
.condition-search-result:focus {
    background: var(--bs-secondary-bg, #e9ecef);
}

/* Expandable rule rows: the chevron column stays narrow, and the detail row drops the top border so
   it reads as part of the row above rather than as a row of its own. */
.condition-expand-col {
    width: 2rem;
}

.condition-expand {
    padding: 0;
    text-decoration: none;
}

.condition-detail-row > td {
    border-top: 0;
    padding-top: 0;
}

.condition-summary,
.condition-summary-children {
    margin-bottom: 0;
}

.condition-summary-children {
    margin-left: 1rem;
    padding-left: 0.75rem;
    border-left: 2px solid var(--bs-border-color, #dee2e6);
}
