/*
   Components: buttons, badges and pills, form fields, tabs, username combobox.
   Tokens only (css/tokens.css). Usage and rules: docs/ai/components.md.
*/

/* ---------- Buttons ---------- */
/* Hierarchy: .btn-primary (one per area of a page), .btn-secondary, .btn-danger, .bj-btn-ghost, .btn-link.
   Bootstrap's .btn-* colours come from tokens.css. */

.btn {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: var(--bj-space-2);
    min-height: var(--bj-target);
    padding: var(--bj-space-2) var(--bj-space-4);
    line-height: var(--bj-leading-tight);
}

.btn > i {
    font-size: 1.25em;
    flex: none;
}

.btn-sm {
    min-height: 36px;
    padding: var(--bj-space-1) var(--bj-space-3);
    font-size: var(--bj-text-sm);
}

.btn-lg {
    min-height: 52px;
    padding: var(--bj-space-3) var(--bj-space-5);
    font-size: var(--bj-text-lg);
}

/* Small buttons still get a full touch target on touch screens. */
@media (pointer: coarse) {
    .btn-sm {
        min-height: var(--bj-target);
    }
}

.bj-btn-ghost {
    --bs-btn-color: var(--bj-text);
    --bs-btn-bg: transparent;
    --bs-btn-border-color: transparent;
    --bs-btn-hover-color: var(--bj-text);
    --bs-btn-hover-bg: var(--bj-surface-raised);
    --bs-btn-hover-border-color: transparent;
    --bs-btn-active-color: var(--bj-text);
    --bs-btn-active-bg: var(--bj-border);
    --bs-btn-active-border-color: transparent;
    --bs-btn-disabled-color: var(--bj-text-subtle);
    --bs-btn-disabled-bg: transparent;
    --bs-btn-disabled-border-color: transparent;
}

/* Icon-only button: must have aria-label or a visually hidden text. */
.bj-btn-icon {
    width: var(--bj-target);
    padding: 0;
}

.bj-btn-icon > i {
    font-size: 1.375rem;
}

.bj-btn-block {
    width: 100%;
}

/* Full width on phones, natural width from tablets: the usual choice for a page's main action. */
@media (max-width: 575.98px) {
    .bj-btn-block-phone {
        width: 100%;
    }
}

/* Disabled, and waiting for a cooldown, look the same for every variant: a flat muted outline with
   muted text and no hover effect. The reason is written next to the button (bj-btn-note). */
[data-bs-theme="dark"] .btn:disabled,
[data-bs-theme="dark"] .btn.disabled,
[data-bs-theme="dark"] fieldset:disabled .btn {
    --bs-btn-disabled-color: var(--bj-text-subtle);
    --bs-btn-disabled-bg: var(--bj-surface);
    --bs-btn-disabled-border-color: var(--bj-border);
    --bs-btn-disabled-opacity: 1;
    border-style: dashed;
    box-shadow: none;
    cursor: not-allowed;
    pointer-events: auto;
}

[data-bs-theme="dark"] .btn-link:disabled,
[data-bs-theme="dark"] .btn-link.disabled {
    --bs-btn-disabled-bg: transparent;
    --bs-btn-disabled-border-color: transparent;
    text-decoration: none;
}

/* A disabled button says why (ButtonStateTagHelper: disabled-reason, cooldown-seconds). */
.bj-btn-wrap {
    display: inline-flex;
    flex-direction: column;
    align-items: stretch;
    gap: var(--bj-space-1);
    max-width: 100%;
}

.bj-btn-note {
    display: flex;
    align-items: flex-start;
    gap: 6px;
    color: var(--bj-text-muted);
    font-size: var(--bj-text-sm);
    line-height: var(--bj-leading-tight);
}

.bj-btn-note > i {
    flex: none;
    font-size: 1.125rem;
}

.bj-btn-note[hidden] {
    display: none;
}

/* Loading state: set by js/components.js when the button's form is submitted. */
.btn.is-loading {
    position: relative;
    pointer-events: none;
}

.btn.is-loading::before {
    content: "";
    width: 1em;
    height: 1em;
    border: 2px solid currentColor;
    border-right-color: transparent;
    border-radius: 50%;
    animation: bj-spin 0.7s linear infinite;
}

@keyframes bj-spin {
    to { transform: rotate(360deg); }
}

/* A form that holds only a button inside a button row: the button lays out as one of the row's items. */
.bj-inline-form {
    display: contents;
}

.bj-button-row {
    display: flex;
    flex-wrap: wrap;
    align-items: flex-start;
    gap: var(--bj-space-2) var(--bj-space-3);
}

/* ---------- Badges and pills ---------- */

.bj-pill {
    display: inline-flex;
    align-items: center;
    gap: 4px;
    min-height: 24px;
    padding: 2px var(--bj-space-2);
    border: 1px solid transparent;
    border-radius: var(--bj-radius-pill);
    font-size: var(--bj-text-xs);
    font-weight: 600;
    line-height: 1.2;
    white-space: nowrap;
    vertical-align: middle;
}

.bj-pill > i {
    font-size: 0.875rem;
}

.bj-pill--neutral { background: var(--bj-surface-raised); border-color: var(--bj-border); color: var(--bj-text-muted); }
.bj-pill--accent { background: var(--bj-accent-soft); color: var(--bj-accent); }
.bj-pill--money,
.bj-pill--warning { background: var(--bj-warning-soft); color: var(--bj-warning); }
.bj-pill--respect { background: var(--bj-respect-soft); color: var(--bj-respect); }
.bj-pill--danger { background: var(--bj-danger-soft); color: var(--bj-danger); }
.bj-pill--info { background: var(--bj-info-soft); color: var(--bj-info); }

/* Online dot: <icon name="@Icons.Circle" weight="fill" class="bj-dot bj-dot--online" label="Online" /> */
.bj-dot {
    font-size: 0.625rem;
    color: var(--bj-text-subtle);
}

.bj-dot--online {
    color: var(--bj-success);
}

/* ---------- Form field ---------- */

.bj-field {
    display: flex;
    flex-direction: column;
    gap: 6px;
    margin-bottom: var(--bj-space-4);
    min-width: 0;
}

.bj-field-label {
    color: var(--bj-text);
    font-size: var(--bj-text-sm);
    font-weight: 600;
}

.bj-field-required {
    margin-left: 2px;
    color: var(--bj-danger);
}

.bj-field-control .form-control,
.bj-field-control .form-select {
    min-height: var(--bj-target);
}

.bj-field-control textarea.form-control {
    min-height: 6rem;
}

.bj-field-help {
    margin: 0;
    color: var(--bj-text-muted);
    font-size: var(--bj-text-sm);
}

/* Live "12 / 250" under a field with a maximum length: <field counter="250">. */
.bj-field-counter {
    margin: 0;
    color: var(--bj-text-muted);
    font-size: var(--bj-text-sm);
    text-align: right;
}

.bj-field-counter--full {
    color: var(--bj-warning);
    font-weight: 600;
}

.bj-field-error,
.bj-field .field-validation-error {
    display: flex;
    align-items: flex-start;
    gap: 6px;
    margin: 0;
    color: var(--bj-danger);
    font-size: var(--bj-text-sm);
    font-weight: 600;
}

.bj-field--invalid .form-control,
.bj-field--invalid .form-select,
.bj-field .input-validation-error {
    border-color: var(--bj-danger);
}

/* Money amounts: numeric keypad, right aligned, currency after the field. */
.bj-input-affix {
    display: flex;
    align-items: stretch;
    width: 100%;
    max-width: 22rem;
}

.bj-input-affix .form-control {
    text-align: right;
    font-variant-numeric: tabular-nums;
    border-top-right-radius: 0;
    border-bottom-right-radius: 0;
}

.bj-input-affix .form-control:only-child {
    border-radius: var(--bj-radius-sm);
}

.bj-input-suffix {
    display: inline-flex;
    align-items: center;
    padding: 0 var(--bj-space-3);
    border: 1px solid var(--bj-border-control);
    border-left: 0;
    border-radius: 0 var(--bj-radius-sm) var(--bj-radius-sm) 0;
    background: var(--bj-surface);
    color: var(--bj-text-muted);
    font-size: var(--bj-text-sm);
}

/* ---------- Tabs ---------- */

.bj-tabs-scroll {
    overflow-x: auto;
    scrollbar-width: thin;
    border-bottom: 1px solid var(--bj-border);
    /* Fade at the right edge hints that there are more tabs. */
    mask-image: linear-gradient(to right, #000 calc(100% - 32px), transparent);
}

.bj-tabs-scroll.is-at-end,
.bj-tabs-scroll:not(.is-scrollable) {
    mask-image: none;
}

.bj-tabs-list {
    display: flex;
    flex-wrap: nowrap;
    gap: var(--bj-space-1);
    margin: 0;
    padding: 0;
    list-style: none;
}

.bj-tab {
    display: inline-flex;
    align-items: center;
    gap: var(--bj-space-2);
    min-height: var(--bj-target);
    padding: var(--bj-space-2) var(--bj-space-3);
    border: 0;
    border-bottom: 3px solid transparent;
    background: transparent;
    color: var(--bj-text-muted);
    font-size: var(--bj-text-sm);
    font-weight: 600;
    white-space: nowrap;
}

.bj-tab > i {
    font-size: 1.125rem;
}

.bj-tab:hover {
    color: var(--bj-text);
}

.bj-tab.active {
    border-bottom-color: var(--bj-accent);
    color: var(--bj-accent);
}

.bj-tabs-content {
    padding-top: var(--bj-space-4);
}

.bj-tabs-content > .tab-pane:focus-visible {
    outline-offset: 4px;
}

/* ---------- Username combobox (js/components.js) ---------- */

.bj-combobox {
    position: relative;
    flex: 1 1 auto;
    min-width: 0;
}

.bj-combobox-list {
    position: absolute;
    top: calc(100% + 4px);
    left: 0;
    right: 0;
    z-index: 1100;
    margin: 0;
    padding: var(--bj-space-1);
    max-height: min(50vh, 320px);
    overflow-y: auto;
    list-style: none;
    border: 1px solid var(--bj-border);
    border-radius: var(--bj-radius-sm);
    background: var(--bj-surface-raised);
    box-shadow: var(--bj-shadow-overlay);
}

.bj-combobox-list[hidden] {
    display: none;
}

.bj-combobox-option {
    display: flex;
    align-items: center;
    min-height: var(--bj-target);
    padding: var(--bj-space-2) var(--bj-space-3);
    border-radius: var(--bj-radius-sm);
    color: var(--bj-text);
    font-size: var(--bj-text-sm);
    cursor: pointer;
}

.bj-combobox-option[aria-selected="true"],
.bj-combobox-option:hover {
    background: var(--bj-accent-soft);
    color: var(--bj-accent);
}

.bj-combobox-empty {
    padding: var(--bj-space-2) var(--bj-space-3);
    color: var(--bj-text-muted);
    font-size: var(--bj-text-sm);
}

/* ---------- Turnstile ---------- */

/* <turnstile form="...">: Cloudflare's widget (65 px high, as wide as the form, at least 300 px). The space is
   kept while the script loads, so the button does not jump. */
.bj-turnstile {
    min-height: 65px;
    margin: 0 0 var(--bj-space-4);
}

.bj-form-narrow {
    max-width: 28rem;
}

/* A short input for a few characters (a colour code). */
.bj-input-short {
    max-width: 8rem;
}

/* Why another player cannot be attacked now (the profile, attack-protection.md, part 5). */
.bj-attack-reason {
    display: flex;
    gap: var(--bj-space-2);
    margin: var(--bj-space-3) 0 0;
    color: var(--bj-text-muted);
}
