/* Battle Barge — Personality & Polish layer
   ================================================================
   Loaded AFTER bb-components.css, BEFORE per-screen CSS. Two jobs:

   1. STATE POLISH (universe-agnostic): pressed states, disabled
      treatment, form errors, placeholder contrast, loading spinner,
      skeletons, empty states. Pure additive — no existing rule is
      redefined, only extended.

   2. UNIVERSE CHARACTER (scoped to html[data-universe]): the shell
      structure stays identical — this is a mid-game companion, so
      function leads — but themed surfaces get a voice:

        HH  "cogitator dataslate" — squared corners, a gold data-rail
            on card tops, targeting-bracket accents, reticle spinner.
        TOW "illuminated ledger"  — double-rule borders, fleur
            ornaments, parchment-warm shadows.

   Everything flows from --bb-* tokens so light theme and universe
   switches keep working. No clip-path on focusable elements (it
   would clip the focus outline).
   ================================================================ */

/* ----------------------------------------------------------------
   Pressed states — tap feedback was completely absent on mobile.
   Transform is user-initiated, instant feedback; no transition so
   it reads as a press, not an animation.
   ---------------------------------------------------------------- */
.bb-btn:active:not(:disabled),
.btn:active:not(:disabled),
.bb-tab:active,
.bb-icon-btn:active,
.bb-splash-option:active,
.roster-card:active,
.campaign-card:active,
.bb-card-interactive:active {
    transform: translateY(1px) scale(0.985);
    filter: brightness(0.94);
}
.bb-btn-primary:active:not(:disabled),
.btn-primary:active:not(:disabled) {
    filter: brightness(0.88);
}

/* ----------------------------------------------------------------
   Disabled — opacity 0.5 alone gutted text contrast. Desaturate and
   hold opacity a touch higher; reads "inert" without going illegible.
   ---------------------------------------------------------------- */
.bb-btn:disabled,
.bb-btn[aria-disabled="true"],
.btn:disabled,
.btn[aria-disabled="true"] {
    opacity: 0.6;
    filter: grayscale(0.5);
}

/* Placeholder contrast: --bb-text-muted sat at the WCAG AA floor.
   Secondary text clears it comfortably in both themes. */
.bb-input::placeholder,
.bb-textarea::placeholder {
    color: var(--bb-text-secondary);
    opacity: 0.8;
}

/* ----------------------------------------------------------------
   Form error state — validation had no visual vocabulary at all.
   Apply .is-error to the .bb-field wrapper; add a .bb-field-error
   <p> for the message.
   ---------------------------------------------------------------- */
.bb-field.is-error .bb-input,
.bb-field.is-error .bb-select,
.bb-field.is-error .bb-textarea {
    border-color: var(--bb-accent-danger);
    box-shadow: 0 0 0 1px var(--bb-accent-danger);
}
.bb-field.is-error .bb-label {
    color: var(--bb-accent-danger);
}
.bb-field-error {
    margin: 0;
    color: var(--bb-accent-danger);
    font-size: var(--bb-text-xs);
    letter-spacing: 0.02em;
}

/* ----------------------------------------------------------------
   Loading — "Loading…" bare text read as a stall. A spun ring says
   "working". HH's ring is a targeting reticle (notched), TOW's a
   simple quill-gold circle.
   ---------------------------------------------------------------- */
.screen-mount-loading::after {
    content: '';
    display: block;
    width: 28px;
    height: 28px;
    margin: var(--bb-space-3) auto 0;
    border: 2px solid color-mix(in srgb, var(--bb-accent-primary) 30%, transparent);
    border-top-color: var(--bb-accent-primary);
    border-radius: 50%;
    animation: bb-spin 0.9s linear infinite;
}
html[data-universe="hh"] .screen-mount-loading::after {
    border-radius: 50%;
    border-style: solid;
    border-right-color: color-mix(in srgb, var(--bb-accent-primary) 30%, transparent);
    border-bottom-color: var(--bb-accent-primary); /* two live arcs = reticle feel */
}
@keyframes bb-spin {
    to { transform: rotate(360deg); }
}

/* Skeleton shimmer utility for screens that want richer loading.  */
.bb-skeleton {
    position: relative;
    overflow: hidden;
    background: var(--bb-bg-elevated);
    border-radius: var(--bb-radius-sm);
    min-height: 1em;
}
.bb-skeleton::after {
    content: '';
    position: absolute;
    inset: 0;
    background: linear-gradient(
        100deg,
        transparent 20%,
        color-mix(in srgb, var(--bb-text-primary) 7%, transparent) 50%,
        transparent 80%);
    animation: bb-shimmer 1.6s ease-in-out infinite;
}
@keyframes bb-shimmer {
    from { transform: translateX(-100%); }
    to   { transform: translateX(100%); }
}

/* ----------------------------------------------------------------
   Empty states — a dashed box of plain text felt abandoned. One
   utility, universe-flavored glyph.
   ---------------------------------------------------------------- */
.bb-empty {
    text-align: center;
    padding: var(--bb-space-8) var(--bb-space-4);
    color: var(--bb-text-muted);
    font-size: var(--bb-text-sm);
}
.bb-empty::before {
    content: '⌖';
    display: block;
    font-size: var(--bb-text-3xl);
    line-height: 1;
    margin-bottom: var(--bb-space-3);
    color: color-mix(in srgb, var(--bb-accent-primary) 55%, transparent);
}
html[data-universe="tow"] .bb-empty::before {
    content: '❖';
}

/* ================================================================
   HORUS HERESY — cogitator dataslate
   ================================================================ */

/* Wordmark: targeting glyph ahead of the title. Every screen carries
   the header, so this one mark does a lot of identity work. */
html[data-universe="hh"] .bb-wordmark > span:first-child::before {
    content: '⌖ ';
    color: var(--bb-accent-primary);
    font-weight: 400;
}

/* Cards become dataslates: squared corners + a gold data-rail along
   the top edge. The rail is a background strip (not border-image,
   which bleeds its gradient onto all four borders) so the existing
   1px border stays clean. */
html[data-universe="hh"] .bb-card,
html[data-universe="hh"] .section,
html[data-universe="hh"] .roster-card,
html[data-universe="hh"] .campaign-card {
    border-radius: var(--bb-radius-sm);
    background:
        linear-gradient(
            90deg,
            var(--bb-accent-primary) 0%,
            color-mix(in srgb, var(--bb-accent-primary) 35%, transparent) 45%,
            transparent 75%) top left / 100% 2px no-repeat,
        var(--bb-bg-surface);
}

/* Buttons: tighter radius + wider tracking — machine-stamped. */
html[data-universe="hh"] .bb-btn,
html[data-universe="hh"] .btn {
    border-radius: 3px;
    letter-spacing: 0.1em;
}

/* Modal titles get a scanline underline. */
html[data-universe="hh"] .bb-modal-header {
    border-bottom: 1px solid var(--bb-border);
    background:
        repeating-linear-gradient(
            0deg,
            transparent 0 3px,
            color-mix(in srgb, var(--bb-accent-primary) 4%, transparent) 3px 4px);
}

/* Active nav tab: a service-light bar across the top of the tab. */
html[data-universe="hh"] .bb-tab[aria-current="page"]::after,
html[data-universe="hh"] .bb-tab.is-active::after {
    content: '';
    position: absolute;
    top: 0;
    left: 50%;
    transform: translateX(-50%);
    width: 28px;
    height: 2px;
    background: var(--bb-accent-primary);
    box-shadow: 0 0 6px color-mix(in srgb, var(--bb-accent-primary) 70%, transparent);
}

/* Splash option: targeting brackets in the corners + faint scanlines.
   Backgrounds only — the element stays a plain focusable button.
   (Unscoped: the splash renders before a universe is picked.) */
.bb-splash-option[data-pick="hh"] {
    background:
        /* corner brackets, top-left + bottom-right */
        linear-gradient(var(--bb-accent-primary), var(--bb-accent-primary)) 0 0 / 14px 2px no-repeat,
        linear-gradient(var(--bb-accent-primary), var(--bb-accent-primary)) 0 0 / 2px 14px no-repeat,
        linear-gradient(var(--bb-accent-primary), var(--bb-accent-primary)) 100% 100% / 14px 2px no-repeat,
        linear-gradient(var(--bb-accent-primary), var(--bb-accent-primary)) 100% 100% / 2px 14px no-repeat,
        /* scanlines */
        repeating-linear-gradient(
            0deg,
            transparent 0 3px,
            rgba(196, 156, 92, 0.05) 3px 4px),
        linear-gradient(140deg, rgba(196, 156, 92, 0.12) 0%, rgba(196, 156, 92, 0) 55%),
        var(--bb-bg-elevated);
    border-radius: 3px;
}

/* ================================================================
   THE OLD WORLD — illuminated ledger
   ================================================================ */

/* Wordmark: fleur ornament. */
html[data-universe="tow"] .bb-wordmark > span:first-child::before {
    content: '⚜ ';
    color: var(--bb-accent-primary);
    font-weight: 400;
}

/* Cards become ledger plates: a double rule via inset ring — no
   layout shift, works over the existing 1px border. Warmer shadow. */
html[data-universe="tow"] .bb-card,
html[data-universe="tow"] .section,
html[data-universe="tow"] .roster-card,
html[data-universe="tow"] .campaign-card {
    box-shadow:
        inset 0 0 0 1px color-mix(in srgb, var(--bb-accent-primary) 14%, transparent),
        var(--bb-shadow-sm);
    border-radius: var(--bb-radius-sm);
}

/* Card titles read as chapter headings: small-caps serif. */
html[data-universe="tow"] .bb-card-title,
html[data-universe="tow"] .section-title,
html[data-universe="tow"] .bb-modal-title {
    font-variant: small-caps;
    letter-spacing: 0.06em;
}

/* Buttons: double-rule inset, like a stamped seal border. */
html[data-universe="tow"] .bb-btn,
html[data-universe="tow"] .btn {
    border-radius: 2px;
    box-shadow: inset 0 0 0 1px color-mix(in srgb, var(--bb-accent-primary) 18%, transparent);
}
html[data-universe="tow"] .bb-btn-primary,
html[data-universe="tow"] .btn-primary {
    box-shadow: inset 0 0 0 1px rgba(0, 0, 0, 0.25);
}

/* Active nav tab: a heraldic diamond above the icon. */
html[data-universe="tow"] .bb-tab[aria-current="page"]::after,
html[data-universe="tow"] .bb-tab.is-active::after {
    content: '';
    position: absolute;
    top: 2px;
    left: 50%;
    width: 6px;
    height: 6px;
    transform: translateX(-50%) rotate(45deg);
    background: var(--bb-accent-primary);
}

/* Splash option: parchment grain + an oversized fleur watermark
   bleeding off the corner. Backgrounds only, still a plain button. */
.bb-splash-option {
    position: relative;
    overflow: hidden;
}
.bb-splash-option[data-pick="tow"]::after {
    content: '⚜';
    position: absolute;
    right: -8px;
    bottom: -14px;
    font-size: 64px;
    line-height: 1;
    color: rgba(199, 154, 90, 0.12);
    pointer-events: none;
}
.bb-splash-option[data-pick="hh"]::after {
    content: '⌖';
    position: absolute;
    right: -6px;
    bottom: -10px;
    font-size: 64px;
    line-height: 1;
    color: rgba(214, 178, 122, 0.10);
    pointer-events: none;
}

/* ----------------------------------------------------------------
   Reduced motion — spinners/skeletons slow to a crawl rather than
   vanish (still signal "working"), presses lose the transform.
   ---------------------------------------------------------------- */
@media (prefers-reduced-motion: reduce) {
    .screen-mount-loading::after { animation-duration: 2.5s; }
    .bb-skeleton::after          { animation-duration: 3s; }
    .bb-btn:active:not(:disabled),
    .btn:active:not(:disabled),
    .bb-tab:active,
    .bb-icon-btn:active,
    .bb-splash-option:active,
    .roster-card:active,
    .campaign-card:active,
    .bb-card-interactive:active {
        transform: none;
    }
}
