/* Battle Barge (TOW) — Magic Screen */

/* ===== Castable Categories Indicator ===== */

html[data-universe="tow"] .castable-indicator {
    text-align: center;
    padding: var(--space-sm) var(--space-md);
    border-radius: var(--radius-md);
    margin-bottom: var(--space-md);
    font-size: var(--text-sm);
    background-color: var(--color-surface);
    border: 1px solid var(--color-border);
}

html[data-universe="tow"] .castable-indicator.active {
    border-color: var(--color-gold-dark);
    background-color: rgba(201, 168, 76, 0.08);
}

html[data-universe="tow"] .castable-indicator.inactive {
    border-color: var(--color-border);
    color: var(--color-text-muted);
}


/* ===== Magic Panel ===== */

html[data-universe="tow"] .magic-panel {
    transition: border-color var(--transition-base);
}

html[data-universe="tow"] .magic-panel.magic-active {
    border-left: 4px solid var(--color-gold);
    padding-left: var(--space-md);
}

html[data-universe="tow"] .spell-casting-form {
    background-color: var(--color-surface);
    border: 1px solid var(--color-border);
    border-radius: var(--radius-lg);
    padding: var(--space-md);
    margin-top: var(--space-lg);
    margin-bottom: var(--space-lg);
}

html[data-universe="tow"] .spell-log-section {
    margin-top: var(--space-lg);
}

html[data-universe="tow"] .spell-entry {
    padding: var(--space-sm) var(--space-md);
    border-radius: var(--radius-md);
    margin-bottom: var(--space-sm);
    border-left: 4px solid var(--color-border);
    background-color: var(--color-surface);
}

html[data-universe="tow"] .spell-entry.spell-success {
    border-left-color: var(--color-success);
}

html[data-universe="tow"] .spell-entry.spell-perfect {
    border-left-color: var(--color-gold);
    background-color: rgba(201, 168, 76, 0.08);
}

html[data-universe="tow"] .spell-entry.spell-miscast {
    border-left-color: var(--color-error);
    background-color: rgba(196, 30, 58, 0.08);
}

html[data-universe="tow"] .spell-entry.spell-failed {
    border-left-color: var(--color-text-muted);
    opacity: 0.7;
}

/* Your own casts, in a log both players now read.
   Deliberately an inset marker rather than another border colour: the left
   border already carries the RESULT, and a second meaning on the same edge
   would make a miscast of yours and a success of theirs argue about which
   colour wins. */
html[data-universe="tow"] .spell-entry.spell-entry-mine {
    box-shadow: inset 3px 0 0 0 var(--color-gold);
}

/* Correctable entries. The whole row is the target — a small pencil on a
   phone at a games table is a miss waiting to happen — so it needs to look
   pressable without competing with the result colour on the left edge. */
html[data-universe="tow"] .spell-entry-editable {
    cursor: pointer;
    position: relative;
    padding-right: var(--space-lg);
}

html[data-universe="tow"] .spell-entry-editable::after {
    content: '\270E';
    position: absolute;
    top: var(--space-sm);
    right: var(--space-sm);
    font-size: var(--text-sm);
    color: var(--color-text-muted);
}

html[data-universe="tow"] .spell-entry-editable:hover,
html[data-universe="tow"] .spell-entry-editable:focus-visible {
    background-color: var(--color-surface-hover);
    outline: none;
}

html[data-universe="tow"] .spell-entry-editable:focus-visible {
    box-shadow: 0 0 0 2px var(--color-gold);
}

/* A dispelled cast still shows its casting result — the spell WAS cast,
   it was stopped afterwards — so the two facts sit side by side rather
   than one overwriting the other. */
html[data-universe="tow"] .spell-entry-dispelled {
    font-weight: 700;
    color: #93c5fd;
    text-transform: uppercase;
    font-size: var(--text-xs);
    letter-spacing: 0.06em;
}

html[data-universe="tow"] .spell-entry-header {
    display: flex;
    justify-content: space-between;
    align-items: center;
    gap: var(--space-sm);
    flex-wrap: wrap;
    margin-bottom: var(--space-xs);
}

html[data-universe="tow"] .spell-entry-result {
    font-size: var(--text-sm);
    color: var(--color-text-secondary);
    display: flex;
    align-items: center;
    gap: var(--space-sm);
    flex-wrap: wrap;
}

html[data-universe="tow"] .spell-result-text {
    font-weight: 700;
}

html[data-universe="tow"] .spell-success .spell-result-text { color: #4ade80; }
html[data-universe="tow"] .spell-perfect .spell-result-text { color: var(--color-gold); }
html[data-universe="tow"] .spell-miscast .spell-result-text { color: #f87171; }
html[data-universe="tow"] .spell-failed .spell-result-text { color: var(--color-text-muted); }

/* Miscast detail line */
html[data-universe="tow"] .spell-miscast-detail {
    font-size: var(--text-xs);
    color: #f87171;
    margin-top: var(--space-xs);
    padding-top: var(--space-xs);
    border-top: 1px solid rgba(196, 30, 58, 0.2);
}

/* ===== End-of-battle reckoning =====
   One player per column, inside the end dialog.

   The two columns used to split at 720px, which is where the dialog is
   only just wide enough for one of them. Each unit row is four controls
   across — points, what happened, worth, remove — so halving the width
   crushed the middle one to a few characters. Field-reported 2026-08-13:
   "The final reckoning is a squished mess... I could not see this
   dropdown to change the value for reduced, fleeing, etc."

   Two things had to change together, and neither alone would have done
   it: the split now waits until there is genuinely room for two of these
   columns, and the row itself stacks rather than compressing. */

html[data-universe="tow"] .end-scoring {
    display: grid;
    grid-template-columns: 1fr;
    gap: var(--space-lg);
    margin-top: var(--space-md);
    padding-top: var(--space-md);
    border-top: 1px solid var(--color-border);
}

/* Side by side only where BOTH columns still fit a unit row on one line.
   The split was at 1024px viewport, which is not the same measurement:
   the dialog is capped at 920px and padded, so each column landed around
   430px and the row inside it broke back to its stacked layout — two
   narrow stacks side by side, which is what "still a LITTLE squished"
   describes (2026-08-13). 1280 gives each column ~560px, comfortably
   past the 560px the row needs. */
@media (min-width: 1280px) {
    html[data-universe="tow"] .end-scoring {
        grid-template-columns: 1fr 1fr;
    }
}

/* The bonus rows carry a long label between a control and a value, and
   they were the other half of the crush — "Enemy Battle Standard Bearer
   slain, fled off, or fleeing" wrapped to three lines against a 50 that
   had nowhere to sit. */
html[data-universe="tow"] .end-scoring-bonus {
    padding: var(--space-xs) 0;
    line-height: 1.35;
}

/* Each player's reckoning as its own bounded block. Two lists of unit
   rows running together down one narrow dialog is the other half of what
   "squished" meant — nothing said where one player's tally ended. */
html[data-universe="tow"] .end-scoring-col {
    padding: var(--space-sm);
    border: 1px solid var(--color-border);
    border-radius: var(--radius-md, 6px);
    background: rgba(0, 0, 0, 0.12);
}

html[data-universe="tow"] .end-scoring-title {
    font-size: var(--text-sm);
    color: var(--color-gold);
    margin: 0 0 var(--space-xs);
}

html[data-universe="tow"] .end-scoring-help {
    margin: 0 0 var(--space-xs);
}

/* One unit, stacked, so the dropdown is always full width and always
   legible. It was `5rem | 1fr | auto | auto` on one line at every width,
   and inside a half-width column on a phone the 1fr — the dropdown that
   decides whether a unit is worth 100% or 50% of its points — was the
   part that gave. That control is the entire arithmetic of the reckoning;
   it does not get to be the one that shrinks.

   Back to a single line at 560px, where there is room for all four. */
html[data-universe="tow"] .end-scoring-row {
    display: grid;
    grid-template-columns: minmax(0, 1fr) auto;
    grid-template-areas:
        "pts   drop"
        "band  band"
        "worth worth";
    gap: var(--space-xs);
    align-items: center;
    margin-bottom: var(--space-sm);
    padding: var(--space-xs);
    border: 1px solid var(--color-border);
    border-radius: var(--radius-sm, 3px);
}

html[data-universe="tow"] .end-scoring-points { grid-area: pts; }
html[data-universe="tow"] .end-scoring-band   { grid-area: band; width: 100%; }
html[data-universe="tow"] .end-scoring-drop   { grid-area: drop; }
html[data-universe="tow"] .end-scoring-row .end-scoring-worth {
    grid-area: worth;
    text-align: right;
}

@media (min-width: 560px) {
    html[data-universe="tow"] .end-scoring-row {
        grid-template-columns: minmax(0, 5.5rem) minmax(0, 1fr) auto auto;
        grid-template-areas: "pts band worth drop";
        padding: 0;
        border: 0;
        margin-bottom: var(--space-xs);
    }
    html[data-universe="tow"] .end-scoring-row .end-scoring-worth {
        text-align: left;
    }
}

html[data-universe="tow"] .end-scoring-bonus {
    display: grid;
    grid-template-columns: auto minmax(0, 1fr) auto;
    gap: var(--space-xs);
    align-items: center;
    margin-top: var(--space-xs);
    font-size: var(--text-sm);
}

html[data-universe="tow"] .end-scoring-count {
    max-width: 3.5rem;
}

html[data-universe="tow"] .end-scoring-worth {
    color: var(--color-gold);
    font-size: var(--text-sm);
    white-space: nowrap;
}

html[data-universe="tow"] .end-scoring-total {
    margin-top: var(--space-sm);
    padding-top: var(--space-xs);
    border-top: 1px solid var(--color-border);
    font-size: var(--text-sm);
    color: var(--color-text-secondary);
}

html[data-universe="tow"] .end-scoring-add {
    margin-top: var(--space-xs);
}

/* The numbered steps down the reckoning dialog. The parts were all there
   and the order was backwards, so a player opened it and could not tell
   which box produced which number. Numbering them is cheaper than a help
   paragraph nobody reads at a table. */
html[data-universe="tow"] .end-scoring-step {
    font-family: var(--bb-font-display, inherit);
    font-size: var(--text-sm);
    letter-spacing: 0.08em;
    text-transform: uppercase;
    color: var(--color-gold);
    margin: var(--space-md) 0 var(--space-xs);
}

html[data-universe="tow"] .end-scoring-step:first-child {
    margin-top: 0;
}

html[data-universe="tow"] .end-scoring-inplay-row {
    display: flex;
    justify-content: space-between;
    gap: var(--space-sm);
    padding: var(--space-xs) 0;
    border-bottom: 1px solid var(--color-border);
    font-size: var(--text-sm);
}

/* ===== Wizard declaration ===== */

html[data-universe="tow"] .wizard-setup {
    display: grid;
    grid-template-columns: 1fr;
    gap: var(--space-md);
}

@media (min-width: 720px) {
    html[data-universe="tow"] .wizard-setup {
        grid-template-columns: 1fr 1fr;
    }
}

html[data-universe="tow"] .wizard-setup-title {
    font-size: var(--text-sm);
    color: var(--color-gold);
    margin: 0 0 var(--space-xs);
}

html[data-universe="tow"] .wizard-setup-card {
    border: 1px solid var(--color-border);
    border-radius: var(--radius-md);
    padding: var(--space-sm);
    margin-bottom: var(--space-sm);
}

/* "Belongs to" — only rendered in a 2v2, where a side has two players in
   it and the column heading can only name the team. */
html[data-universe="tow"] .wizard-setup-owner {
    margin-top: var(--space-xs);
}

html[data-universe="tow"] .wizard-setup-owner .form-help {
    margin: 0 0 2px;
}

html[data-universe="tow"] .wizard-setup-row {
    display: grid;
    grid-template-columns: minmax(0, 1fr) auto auto;
    gap: var(--space-xs);
    align-items: center;
}

html[data-universe="tow"] .wizard-setup-level {
    max-width: 7rem;
}

html[data-universe="tow"] .wizard-setup-chips {
    display: flex;
    flex-wrap: wrap;
    gap: var(--space-xs);
    margin-top: var(--space-xs);
}

html[data-universe="tow"] .wizard-setup-chip {
    border: 1px solid var(--color-gold);
    color: var(--color-gold);
}

html[data-universe="tow"] .wizard-setup-spells {
    margin-top: var(--space-sm);
}

html[data-universe="tow"] .wizard-setup-spell {
    display: grid;
    grid-template-columns: auto minmax(0, 1fr);
    gap: var(--space-xs);
    align-items: center;
    font-size: var(--text-sm);
    margin-top: var(--space-xs);
}

html[data-universe="tow"] .wizard-setup-known {
    margin-top: var(--space-sm);
    padding-top: var(--space-xs);
    border-top: 1px solid var(--color-border);
    font-size: var(--text-sm);
    color: var(--color-text-secondary);
}

/* One block per lore on the wizard: its own roll, its own picker, its own
   signature spells. Rolling one lore must not look like it touched
   another, so each is visibly boxed. */
html[data-universe="tow"] .wizard-setup-lore-block {
    margin-top: var(--space-sm);
    padding: var(--space-sm);
    border: 1px solid var(--color-border);
    border-radius: var(--radius-sm, 4px);
}

html[data-universe="tow"] .wizard-setup-lore-name {
    margin: 0 0 var(--space-xs);
    font-size: var(--text-sm);
    color: var(--color-gold);
}

html[data-universe="tow"] .wizard-setup-rolled {
    display: flex;
    flex-wrap: wrap;
    gap: var(--space-xs);
    margin-bottom: var(--space-xs);
}

html[data-universe="tow"] .wizard-setup-pick {
    margin-top: var(--space-xs);
    width: 100%;
}

/* ===== Room to work =====

   Every dialog in this universe was capped at 480px by
   components/modals.css — Horus Heresy caps its at 600 — and the two
   widest forms in the app open into it: the end-of-battle reckoning,
   which is two players' unit tallies side by side, and Declare Wizards,
   which is a lore block per lore per wizard. So they were squeezed into
   the narrowest dialog in either universe, at every screen size, which
   is exactly what "the final reckoning is a squished mess... This is
   what it looks like regardless of screen size" describes
   (field-reported 2026-08-13).

   Capped by viewport as well as by pixels so a phone still gets its
   margins. */
html[data-universe="tow"] .end-battle-modal,
html[data-universe="tow"] .wizard-setup-modal {
    max-width: min(920px, calc(100vw - 2 * var(--space-md)));
}

html[data-universe="tow"] .result-agreement-modal {
    max-width: min(520px, calc(100vw - 2 * var(--space-md)));
}

/* The agreed result, as both players see it before it is recorded. */
html[data-universe="tow"] .result-agreement-scores {
    margin: var(--space-md) 0;
}

html[data-universe="tow"] .result-agreement-row {
    display: flex;
    justify-content: space-between;
    gap: var(--space-sm);
    padding: var(--space-sm) 0;
    border-bottom: 1px solid var(--color-border);
}

html[data-universe="tow"] .result-agreement-verdict {
    margin: 0;
    font-family: var(--bb-font-display, inherit);
    font-size: var(--text-lg);
    letter-spacing: 0.06em;
    text-transform: uppercase;
    color: var(--color-gold);
    text-align: center;
}

/* Whose wizard, on the wizard. */
html[data-universe="tow"] .wizard-setup-seat {
    margin-left: var(--space-xs);
    font-size: var(--text-xs, 0.75rem);
    letter-spacing: 0.08em;
    text-transform: uppercase;
    color: var(--color-text-secondary);
}

/* -- Seat picker (2v2) -------------------------------------------------
   The table seen from above: two sides, two chairs each. Teammates sit
   together because the pairing IS the authority model — seats 1 and 3
   share the host's controls, 2 and 4 share the guest's — and a player who
   misreads which side they are on gets the wrong half of the game. */
.seat-picker-modal { max-width: min(560px, calc(100vw - 2 * var(--space-md))); }

/* Who you are, above where you sit. Asked here because this is the only
   moment the app has a fourth player's attention — setup runs on the
   host's phone and can only ever know about the host. */
.seat-identity {
    display: grid;
    gap: var(--space-sm);
    margin-bottom: var(--space-md);
    padding-bottom: var(--space-md);
    border-bottom: 1px solid var(--border-color, #4a4238);
}
.seat-identity .form-group { margin-bottom: 0; }

.seat-table {
    display: grid;
    gap: var(--space-md);
    margin-top: var(--space-md);
}
.seat-side {
    border: 2px solid var(--border-color, #4a4238);
    border-radius: 8px;
    padding: var(--space-sm);
}
/* Named as well as positioned. A games hall is dark and a projector is
   worse; a team told apart only by border colour is a team told apart by
   nothing. */
.seat-side-title {
    margin: 0 0 var(--space-sm);
    font-size: 0.85rem;
    letter-spacing: 0.08em;
    text-transform: uppercase;
    color: var(--text-muted, #9a8f80);
}
.seat-side-1 { border-color: var(--accent-gold, #c9a227); }
.seat-side-2 { border-color: var(--accent-blue, #4a7fb5); }

.seat-row {
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: var(--space-sm);
}
.seat-chair {
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: 2px;
    /* Tapped by someone standing at a table holding dice. */
    min-height: 72px;
    padding: var(--space-sm);
    border: 1px solid var(--border-color, #4a4238);
    border-radius: 6px;
    background: var(--bg-elevated, #241f1a);
    color: var(--text-primary, #e8dfd0);
    cursor: pointer;
    font: inherit;
}
.seat-chair:hover:not(:disabled),
.seat-chair:focus-visible:not(:disabled) {
    border-color: var(--accent-gold, #c9a227);
    outline: none;
}
.seat-chair-slot {
    font-size: 0.75rem;
    letter-spacing: 0.06em;
    text-transform: uppercase;
    color: var(--text-muted, #9a8f80);
}
.seat-chair-who { font-weight: 600; }
.seat-chair.is-taken {
    opacity: 0.5;
    cursor: not-allowed;
}

@media (min-width: 480px) {
    .seat-table { grid-template-columns: 1fr 1fr; }
}
