/* Battle Barge (TOW) — the markup nothing ever styled
   ================================================================
   Story 14.5, Task 2a.

   The audit that opened this story diffed every class TOW's screen
   modules emit against every selector in bb/, hh/ and 40k/. On the
   play path — home, setup, scenarios, battle, magic, tools, history —
   161 distinct classes come out of those modules. 29 were already
   covered by the shell and 27 more by TOW's own stylesheets once the
   shell linked them. The remaining 105 had no rule anywhere, in any
   file, ever. Ten of those ride on an element carrying a styled class
   so they merely look wrong; the other 102 sit on elements where
   nothing at all is styled and render as raw text in document order.

   The cause is drift, not omission: TOW's JavaScript kept being
   written while its CSS stopped. screens/magic.css is the clearest
   case — 109 well-made lines that cover almost none of what magic.js
   now emits, because it was written for an older version of that
   screen. Nothing rendered it, so nothing complained.

   Everything here is scoped to html[data-universe="tow"]. Several of
   these names (.stat-card, .spell-card, .ref-table, .badge) are
   generic enough to collide with a future shell component, and this
   file must never be the reason an HH screen changes.

   Tokens come from bb-tokens.css: the shared legacy aliases plus the
   TOW-scoped block added by this story.
   ================================================================ */


/* ----------------------------------------------------------------
   Primitives ported from the component files the shell does not link

   cards.css, forms.css, modals.css and typography.css are all
   superseded by bb-components.css for their main selectors, but each
   carries a handful of names the shell has no equivalent for. Those
   are lifted here rather than linking a file whose .card and .btn
   rules would take over every universe.
   ---------------------------------------------------------------- */

html[data-universe="tow"] .text-gold { color: var(--color-gold); }

html[data-universe="tow"] .card-row {
    display: flex;
    align-items: baseline;
    justify-content: space-between;
    gap: var(--space-sm);
    font-size: var(--text-sm);
    color: var(--color-text-secondary);
}

html[data-universe="tow"] .badge {
    display: inline-block;
    padding: 2px var(--space-sm);
    border-radius: var(--radius-sm);
    border: 1px solid var(--color-border-light);
    background-color: var(--color-surface-raised);
    color: var(--color-text-secondary);
    font-size: var(--text-xs);
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: 0.08em;
    line-height: 1.6;
    white-space: nowrap;
}
html[data-universe="tow"] .badge-active {
    border-color: var(--color-success);
    color: var(--color-success);
}
html[data-universe="tow"] .badge-win {
    border-color: var(--color-success);
    color: var(--color-success);
}
html[data-universe="tow"] .badge-draw {
    border-color: var(--color-iron);
    color: var(--color-text-secondary);
}
html[data-universe="tow"] .badge-loss {
    border-color: var(--color-error);
    color: var(--color-error);
}
html[data-universe="tow"] .badge-journal {
    border-color: var(--color-gold-dark);
    color: var(--color-gold);
}

html[data-universe="tow"] .radio-group {
    display: flex;
    flex-wrap: wrap;
    gap: var(--space-sm);
}
html[data-universe="tow"] .radio-label,
html[data-universe="tow"] .checkbox-label {
    display: inline-flex;
    align-items: center;
    gap: var(--space-xs);
    min-height: var(--touch-min);
    padding: var(--space-xs) var(--space-sm);
    font-size: var(--text-sm);
    color: var(--color-text-primary);
    cursor: pointer;
}
html[data-universe="tow"] .radio-label input,
html[data-universe="tow"] .checkbox-label input {
    accent-color: var(--color-gold);
    width: var(--control-box);
    height: var(--control-box);
    flex: none;
}

html[data-universe="tow"] .modal-content {
    padding: var(--space-md);
    display: flex;
    flex-direction: column;
    gap: var(--space-md);
}


/* ----------------------------------------------------------------
   End-of-battle dialog

   The dialog itself is constructed in screens/battle.js and reuses
   the shell's .modal / .modal-header / .form-* chrome. This is the
   one wrapper that has no shell equivalent.
   ---------------------------------------------------------------- */

html[data-universe="tow"] .end-battle-scores {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(140px, 1fr));
    gap: var(--space-md);
    margin-bottom: var(--space-md);
}


/* ----------------------------------------------------------------
   Scenario picker and detail  (screens/scenarios.js)

   screens/scenarios.css styles the CARD — including .selected, whose
   absence is why "you can't select a scenario, none are clickable"
   was reported when the click handler had always worked. It does not
   style the detail panel below the list, which is all of this.
   ---------------------------------------------------------------- */

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

html[data-universe="tow"] .scenario-desc {
    font-size: var(--text-sm);
    color: var(--color-text-secondary);
    line-height: 1.6;
    margin: 0 0 var(--space-sm);
}

html[data-universe="tow"] .scenario-round-info {
    font-size: var(--text-xs);
    color: var(--color-text-muted);
    text-transform: uppercase;
    letter-spacing: 0.08em;
    font-weight: 700;
}

html[data-universe="tow"] .scenario-detail-card {
    padding: var(--space-md);
    background-color: var(--color-surface-raised);
    border: 1px solid var(--color-border);
    border-left: 3px solid var(--color-border-light);
    border-radius: var(--radius-md);
    margin-bottom: var(--space-sm);
}
/* Victory conditions are what players argue about; give them the gold. */
html[data-universe="tow"] .scenario-detail-card.scenario-victory {
    border-left-color: var(--color-gold);
}

html[data-universe="tow"] .scenario-detail-label {
    display: block;
    font-size: var(--text-xs);
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: 0.1em;
    color: var(--color-gold);
    margin-bottom: var(--space-xs);
}

html[data-universe="tow"] .scenario-detail-text {
    font-size: var(--text-sm);
    color: var(--color-text-secondary);
    line-height: 1.65;
}

html[data-universe="tow"] .scenario-type-badge {
    display: inline-block;
    padding: 2px var(--space-sm);
    border-radius: var(--radius-sm);
    border: 1px solid var(--color-border-light);
    font-size: var(--text-xs);
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: 0.08em;
    white-space: nowrap;
    color: var(--color-text-secondary);
}
html[data-universe="tow"] .badge-pitched {
    border-color: var(--color-forest-green);
    color: #7fb069;
}
html[data-universe="tow"] .badge-matched {
    border-color: var(--color-gold-dark);
    color: var(--color-gold);
}
html[data-universe="tow"] .badge-custom {
    border-color: var(--color-info);
    color: var(--color-info);
}


/* ----------------------------------------------------------------
   Active spells on the battle dashboard  (screens/battle.js)

   Four classes — the whole of what the battle screen was missing.
   ---------------------------------------------------------------- */

/* The strip needs a heading that reads as one.
   It was a bare `<span>` above a list of bordered rows, so "Castable now"
   floated between the score panel and the spells with nothing tying it to
   either — field-reported 2026-08-14 as "castable section is good, but
   could use some help standing out a little more". Same shell as the score
   panel and the clock, so it reads as a section of the battle screen
   rather than a caption that got loose. */
html[data-universe="tow"] .active-spells-panel {
    background-color: var(--color-surface);
    border: 1px solid var(--color-border);
    border-radius: var(--radius-lg);
    padding: var(--space-sm) var(--space-md) var(--space-xs);
    margin-bottom: var(--space-md);
}

html[data-universe="tow"] .active-spells-header {
    display: flex;
    align-items: center;
    gap: var(--space-sm);
    margin-bottom: var(--space-sm);
    font-size: var(--text-xs);
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: 0.12em;
    color: var(--color-gold);
}

/* A rule to the right of the label, so the heading spans the panel. */
html[data-universe="tow"] .active-spells-header::after {
    content: "";
    flex: 1;
    height: 1px;
    background-color: var(--color-border);
}

/* Wraps. Three inline pieces with `white-space: nowrap` on two of them
   could not fit a 390pt phone, and `justify-content: space-between` pushed
   the wizard's name off the right edge rather than under the spell it
   belongs to. */
html[data-universe="tow"] .active-spell-item {
    display: flex;
    flex-wrap: wrap;
    align-items: baseline;
    gap: 2px var(--space-sm);
    padding: var(--space-sm);
    background-color: var(--color-surface-raised);
    border: 1px solid var(--color-border);
    border-left: 2px solid var(--color-gold-dark);
    border-radius: var(--radius-sm);
    margin-bottom: var(--space-xs);
}

html[data-universe="tow"] .active-spell-name {
    font-size: var(--text-sm);
    font-weight: 600;
    color: var(--color-text-primary);
    flex: 1 1 100%;
}

html[data-universe="tow"] .active-spell-wizard,
html[data-universe="tow"] .active-spell-meta {
    font-size: var(--text-xs);
    color: var(--color-text-muted);
    white-space: normal;
    overflow-wrap: anywhere;
}


/* ----------------------------------------------------------------
   In effect  (screens/magic.js `_renderInEffect`)

   What is standing on the table right now, above what could be cast.
   Louder than the castable strip on purpose: these are the effects
   changing every roll, and the players need to see them without going
   looking. Requested 2026-08-14.
   ---------------------------------------------------------------- */

html[data-universe="tow"] .in-effect-panel {
    background-color: var(--color-surface);
    border: 1px solid var(--color-gold-dark);
    border-radius: var(--radius-lg);
    padding: var(--space-sm) var(--space-md) var(--space-xs);
    margin-bottom: var(--space-md);
}

html[data-universe="tow"] .in-effect-header {
    display: flex;
    align-items: center;
    gap: var(--space-sm);
    margin-bottom: var(--space-sm);
    font-size: var(--text-xs);
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: 0.12em;
    color: var(--color-gold);
}

html[data-universe="tow"] .in-effect-header::after {
    content: "";
    flex: 1;
    height: 1px;
    background-color: var(--color-gold-dark);
}

html[data-universe="tow"] .in-effect-item {
    padding: var(--space-sm);
    background-color: var(--color-surface-raised);
    border: 1px solid var(--color-border);
    border-left: 3px solid var(--color-border);
    border-radius: var(--radius-sm);
    margin-bottom: var(--space-xs);
}

/* Whose spell it is, at a glance and not by reading the name. */
html[data-universe="tow"] .in-effect-item.is-mine {
    border-left-color: var(--color-gold);
}

html[data-universe="tow"] .in-effect-item.is-theirs {
    border-left-color: var(--color-error);
}

/* Wraps, for the same reason `.active-spell-item` above does: three
   inline pieces, two of them nowrap, do not fit a 390pt phone once a team
   is called something like "The Warriors of the Frozen North". Caught in
   review — this panel had repeated the pattern that was fixed next door. */
html[data-universe="tow"] .in-effect-row {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 2px var(--space-sm);
}

html[data-universe="tow"] .in-effect-name {
    font-size: var(--text-sm);
    font-weight: 700;
    color: var(--color-text-primary);
    flex: 1 1 auto;
    min-width: 0;
    overflow-wrap: anywhere;
}

html[data-universe="tow"] .in-effect-who {
    font-size: var(--text-xs);
    color: var(--color-text-secondary);
    /* A flex item's automatic minimum is its min-content width, so a
       nowrap name with no `min-width: 0` cannot shrink and pushes the End
       button off the edge. */
    min-width: 0;
    white-space: normal;
    overflow-wrap: anywhere;
}

html[data-universe="tow"] .in-effect-end {
    flex: 0 0 auto;
    min-height: 32px;
}

html[data-universe="tow"] .in-effect-until {
    display: block;
    margin-top: 2px;
    font-size: var(--text-xs);
    color: var(--color-text-muted);
}

html[data-universe="tow"] .in-effect-text {
    margin: var(--space-xs) 0 0;
    font-size: var(--text-xs);
    line-height: 1.35;
    color: var(--color-text-secondary);
}

/* Type / casting value / range / duration, one labelled row each.
   `minmax(0, 1fr)` on the value column so a long duration phrase wraps
   inside the dialog instead of widening it past the phone. */
html[data-universe="tow"] .spell-facts {
    display: grid;
    grid-template-columns: auto minmax(0, 1fr);
    gap: 0.15rem var(--space-md);
    margin: 0 0 var(--space-sm);
    padding: var(--space-sm);
    border: 1px solid var(--color-border);
    border-radius: var(--radius-sm);
}

html[data-universe="tow"] .spell-facts dt {
    font-size: var(--text-xs);
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: 0.08em;
    color: var(--color-text-muted);
    white-space: nowrap;
}

html[data-universe="tow"] .spell-facts dd {
    margin: 0;
    font-size: var(--text-sm);
    line-height: 1.3;
    color: var(--color-text-primary);
    overflow-wrap: break-word;
}

/* The spell's own words in the cast and dispel dialogs. */
html[data-universe="tow"] .cast-result-text {
    margin: var(--space-xs) 0 var(--space-sm);
    padding: var(--space-sm);
    border-left: 2px solid var(--color-gold-dark);
    background-color: var(--color-surface-raised);
    border-radius: var(--radius-sm);
    font-size: var(--text-sm);
    line-height: 1.4;
    color: var(--color-text-secondary);
}


/* ----------------------------------------------------------------
   The magic panel and its fold

   The panel lives in the battle screen because casting happens several
   times a turn, mid-phase, and making the player leave the score to do
   it is wrong. It folds when nothing is castable so it does not own the
   screen during the three phases where it has nothing to say.

   The fold is driven entirely by `magic-active`, which
   refreshMagicPanel already sets from the battle's castable categories
   (magic.js:42-46). That call has run since the module was written and
   has never had a rule attached. No new logic decides this; the class
   simply gained a meaning.
   ---------------------------------------------------------------- */

html[data-universe="tow"] .magic-panel {
    background-color: var(--color-surface);
    border: 1px solid var(--color-border);
    border-radius: var(--radius-md);
    margin-bottom: var(--space-md);
    overflow: hidden;
}
html[data-universe="tow"] .magic-panel.magic-active {
    border-color: var(--color-gold-dark);
}

html[data-universe="tow"] .magic-panel-header {
    padding: var(--space-sm) var(--space-md);
    background-color: var(--color-surface-raised);
    border-bottom: 1px solid var(--color-border);
}

html[data-universe="tow"] .magic-panel-title {
    margin: 0;
    font-size: var(--text-sm);
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: 0.12em;
    color: var(--color-gold);
}

html[data-universe="tow"] .castable-indicator {
    padding: var(--space-sm) var(--space-md);
    font-size: var(--text-sm);
    line-height: 1.5;
}
html[data-universe="tow"] .castable-indicator.active {
    color: var(--color-text-primary);
    background-color: color-mix(in srgb, var(--color-gold) 10%, transparent);
    border-bottom: 1px solid var(--color-border);
}
html[data-universe="tow"] .castable-indicator.inactive {
    color: var(--color-text-muted);
}
html[data-universe="tow"] .castable-indicator strong { color: var(--color-gold-light); }

html[data-universe="tow"] .magic-panel-body {
    padding: var(--space-md);
    display: flex;
    flex-direction: column;
    gap: var(--space-md);
}

/* THE FOLD. Nothing castable: the casting form goes away and the panel
   collapses to the indicator plus anything still in play — which stays,
   because a Remains in Play spell is live whether or not you can cast
   right now.

   THE CAST LOG STAYS TOO, and it did not.

   `#dispel-section` is the log — every spell either player has cast this
   battle — and folding it away with the spellbook made it visible only
   during a casting sub-phase. Two consequences, both found in review on
   2026-08-14. Advance out of the magic phase and the log vanishes, which
   also takes the correction dialog with it: the only way to fix a
   mistapped result is to tap the entry, and the entry is gone the moment
   the phase moves on. And on a FINISHED battle `magic-active` is off by
   definition (`status !== 'active'`), so the log disappeared from the
   record — while `_lockDownIfFinished` deliberately keeps the panel
   visible with the comment "the cast log is part of the record". The CSS
   was hiding exactly the thing the JS was preserving, and with no
   Remains in Play card the rule below then collapsed the whole body to
   an empty gold heading reading "Magic". */
html[data-universe="tow"] .magic-panel:not(.magic-active) #magic-spellbook,
html[data-universe="tow"] .magic-panel:not(.magic-active) #btn-add-spell {
    display: none;
}
html[data-universe="tow"] .magic-panel:not(.magic-active)
    .magic-panel-body:not(:has(.rip-card)):not(:has(.spell-entry)) {
    display: none;
}

/* ----------------------------------------------------------------
   Remains in Play — first in the panel and deliberately loud.

   These spells are on the table affecting every turn until something
   dispels them, which outranks a spellbook consulted a few times a
   phase. The section hides itself entirely when empty (`hidden` from
   `_renderRipDashboard`) rather than spending the panel's best strip
   reporting that there is nothing to report.
   ---------------------------------------------------------------- */

html[data-universe="tow"] .magic-section-rip {
    margin-bottom: var(--space-lg);
    padding: var(--space-sm) var(--space-md) var(--space-md);
    border: 1px solid var(--color-gold);
    border-radius: var(--radius-md);
    background-color: rgba(255, 255, 255, 0.04);
}

html[data-universe="tow"] .magic-section-rip .magic-section-title {
    color: var(--color-gold);
    letter-spacing: 0.08em;
}

html[data-universe="tow"] .magic-section-rip[hidden] {
    display: none;
}

/* Adding a spell mid-battle is rare and never urgent — last, and quiet. */
html[data-universe="tow"] .magic-add-spell {
    display: block;
    margin: var(--space-lg) auto 0;
    opacity: 0.75;
    font-size: var(--text-sm);
}

html[data-universe="tow"] .magic-add-spell:hover {
    opacity: 1;
}

/* ----------------------------------------------------------------
   The spellbook

   Modelled on HH's reactions list: the things you can do are on screen
   as a list, and you tap the one you did. The player already told the
   app their wizards and spells during setup; the in-battle job is to
   record what happened, not to re-collect the army list.
   ---------------------------------------------------------------- */

html[data-universe="tow"] .magic-spellbook {
    display: flex;
    flex-direction: column;
    gap: var(--space-md);
}

html[data-universe="tow"] .spellbook-wizard {
    display: flex;
    flex-direction: column;
    gap: var(--space-xs);
}

html[data-universe="tow"] .spellbook-wizard-head {
    display: flex;
    align-items: baseline;
    flex-wrap: wrap;
    gap: var(--space-xs) var(--space-sm);
    padding-bottom: var(--space-xs);
    border-bottom: 1px solid var(--color-border);
}

/* Whose wizard this is, spelled out. The list runs both armies down one
   column, and a highlight on the active player's name is a fact about
   the turn, not about ownership — so on the opponent's turn every one of
   your own wizards was the unmarked ones. */
html[data-universe="tow"] .spellbook-wizard-owner {
    margin-right: auto;
    padding: 0.05em 0.45em;
    border: 1px solid var(--color-border-light);
    border-radius: var(--radius-sm, 3px);
    font-size: var(--text-xs);
    color: var(--color-text-secondary);
}

html[data-universe="tow"] .spellbook-wizard.is-active-player .spellbook-wizard-owner {
    border-color: var(--color-gold-dark, var(--color-gold));
    color: var(--color-gold);
}

/* One attempt per SPELL per round, marked on the spell rather than on the
   wizard. A level 4 may attempt all four of the spells they know; what
   they may not do is attempt the same one twice. Corrected 2026-08-14. */
html[data-universe="tow"] .spellbook-spell-spent {
    margin-left: auto;
    padding: 0.05em 0.4em;
    border-radius: var(--radius-sm, 3px);
    border: 1px solid var(--color-border-light);
    font-size: var(--text-xs);
    letter-spacing: 0.06em;
    text-transform: uppercase;
    color: var(--color-text-muted);
    white-space: nowrap;
}

/* And WHICH of the two players on that side, in a 2v2. The chip above
   carries the team; this one carries the person. Filled rather than
   outlined so the two do not read as one long label. */
html[data-universe="tow"] .spellbook-wizard-player {
    padding: 0.05em 0.45em;
    border-radius: var(--radius-sm, 3px);
    background-color: var(--color-surface-raised);
    border: 1px solid var(--color-border);
    font-size: var(--text-xs);
    font-weight: 600;
    color: var(--color-text-primary);
    white-space: nowrap;
}

/* One attempt per wizard per turn — said on the wizard, not only in the
   dialog you reach by tapping past it. */
html[data-universe="tow"] .spellbook-wizard-spent {
    font-size: var(--text-xs);
    letter-spacing: 0.06em;
    text-transform: uppercase;
    color: var(--color-text-muted);
}

html[data-universe="tow"] .spellbook-spell.is-spent {
    opacity: 0.45;
}

html[data-universe="tow"] .spellbook-wizard-name {
    font-size: var(--text-sm);
    font-weight: 700;
    letter-spacing: 0.06em;
    text-transform: uppercase;
    color: var(--color-text-secondary);
}
/* Whose turn it is, at a glance. */
html[data-universe="tow"] .spellbook-wizard.is-active-player .spellbook-wizard-name {
    color: var(--color-gold);
}

html[data-universe="tow"] .spellbook-wizard-meta {
    font-size: var(--text-xs);
    color: var(--color-text-muted);
}

html[data-universe="tow"] .spellbook-spell {
    display: grid;
    grid-template-columns: 1fr auto;
    grid-template-areas: "name cv" "cat cv";
    gap: 0 var(--space-sm);
    width: 100%;
    min-height: var(--touch-min);
    padding: var(--space-sm) var(--space-md);
    text-align: left;
    background-color: var(--color-surface-raised);
    border: 1px solid var(--color-border);
    border-left: 3px solid var(--color-border-light);
    border-radius: var(--radius-sm);
    color: var(--color-text-primary);
    font-family: inherit;
    cursor: pointer;
    transition: border-color var(--transition-fast), background-color var(--transition-fast);
}
html[data-universe="tow"] .spellbook-spell:hover {
    background-color: var(--color-surface-hover);
}

/* Castable in the current sub-phase. */
html[data-universe="tow"] .spellbook-spell.is-castable {
    border-left-color: var(--color-gold);
}

/* Not normally castable now — dimmed, NOT disabled. An item or a scenario
   can always produce a cast the phase rules do not predict, and a tracker
   that refuses the tap makes the game unrecordable. */
html[data-universe="tow"] .spellbook-spell.is-offphase {
    opacity: 0.55;
}
html[data-universe="tow"] .spellbook-spell.is-offphase:hover {
    opacity: 1;
}

html[data-universe="tow"] .spellbook-spell-name {
    grid-area: name;
    font-size: var(--text-base);
}
html[data-universe="tow"] .spellbook-spell-cat {
    grid-area: cat;
    font-size: var(--text-xs);
    text-transform: uppercase;
    letter-spacing: 0.08em;
    color: var(--color-text-muted);
}
html[data-universe="tow"] .spellbook-spell-cv {
    grid-area: cv;
    align-self: center;
    font-family: 'Courier New', monospace;
    font-size: var(--text-sm);
    color: var(--color-gold-light);
    font-variant-numeric: tabular-nums;
    white-space: nowrap;
}

/* Result prompt — one tap per outcome, no dropdown. */
html[data-universe="tow"] .cast-result-sub {
    margin: 0 0 var(--space-md);
    font-size: var(--text-sm);
    color: var(--color-text-secondary);
}

/* Casting out of phase. Loud enough to stop a thumb, not a refusal. */
html[data-universe="tow"] .cast-result-warning {
    margin: 0 0 var(--space-md);
    padding: var(--space-sm) var(--space-md);
    border-left: 3px solid var(--color-warning, var(--color-gold));
    border-radius: var(--radius-sm);
    background-color: rgba(255, 255, 255, 0.04);
    font-size: var(--text-sm);
    font-weight: 600;
    color: var(--color-warning, var(--color-gold));
}

/* Remains in Play when the spell decides it, not the player. */
html[data-universe="tow"] .cast-result-rip.is-automatic {
    margin: 0 0 var(--space-md);
    font-size: var(--text-sm);
    color: var(--color-text-secondary);
}

html[data-universe="tow"] .cast-result-buttons {
    display: grid;
    /* `minmax(0, …)` so a track can shrink below its content instead of
       forcing the modal wider than the phone. */
    grid-template-columns: repeat(auto-fit, minmax(min(9rem, 100%), 1fr));
    gap: var(--space-sm);
}

/* The four outcomes, one tap each.
   "PERFECT INVOCATION" is twice the width of "FAILED" and was overflowing
   its box on a phone — field-reported 2026-08-15. The label wraps onto two
   lines now rather than escaping, which is why the vertical padding and
   the tighter line-height are here: `.btn` centres a single line with
   `min-height` alone and has no room for a second. */
html[data-universe="tow"] .cast-result-btn {
    min-height: var(--touch-min);
    height: auto;
    padding: var(--space-xs) var(--space-sm);
    border: 1px solid var(--color-border-light);
    background-color: var(--color-surface-raised);
    color: var(--color-text-primary);
    white-space: normal;
    overflow-wrap: break-word;
    text-align: center;
    line-height: 1.15;
    font-size: var(--text-xs);
    letter-spacing: 0.03em;
}
html[data-universe="tow"] .cast-result-btn.cast-result-ok {
    border-color: var(--color-success);
    color: var(--color-success);
}
html[data-universe="tow"] .cast-result-btn.cast-result-bad {
    border-color: var(--color-error);
    color: var(--color-error);
}

html[data-universe="tow"] .cast-result-rip {
    margin-top: var(--space-md);
    padding-top: var(--space-md);
    border-top: 1px solid var(--color-border);
}

html[data-universe="tow"] .magic-section-title {
    margin: 0 0 var(--space-xs);
    font-size: var(--text-xs);
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: 0.1em;
    color: var(--color-text-muted);
}

/* Three sections, three boundaries.
   The spellbook had no heading of its own and sat between Remains in
   Play's and the log's, so it belonged visually to whichever one you had
   just read — "very confusing in its current iteration", 2026-08-13. Each
   section is now bounded and says what it is and what it is for. */
html[data-universe="tow"] .magic-section-hint {
    margin: 0 0 var(--space-sm);
    font-size: var(--text-xs);
    color: var(--color-text-muted);
}

html[data-universe="tow"] .magic-section-spellbook,
html[data-universe="tow"] .magic-section-log {
    margin-top: var(--space-lg);
    padding-top: var(--space-md);
    border-top: 2px solid var(--color-border);
}

/* Remains in Play hides itself when there is nothing on the table, and
   then the spellbook is the first thing in the panel — a divider above
   it separates it from the panel's own heading, which is not a boundary
   that needs drawing. */
html[data-universe="tow"] .magic-section-rip[hidden] + .magic-section-spellbook {
    margin-top: 0;
    padding-top: 0;
    border-top: 0;
}

/* The log is a record, not a control surface. Recessed so a thumb going
   for a spell does not land in it. */
html[data-universe="tow"] .magic-section-log {
    padding: var(--space-md);
    border: 1px solid var(--color-border);
    border-radius: var(--radius-md);
    background-color: rgba(0, 0, 0, 0.14);
}

html[data-universe="tow"] .magic-section-log .spell-log {
    max-height: 22rem;
    overflow-y: auto;
}

/* Tap the miscast you rolled — the rows are buttons now, so they have to
   read as one without becoming louder than the table itself. */
html[data-universe="tow"] .miscast-row {
    display: block;
    width: 100%;
    text-align: left;
    background: none;
    color: inherit;
    font-family: inherit;
    cursor: pointer;
}

html[data-universe="tow"] .miscast-row:hover {
    background-color: rgba(255, 255, 255, 0.05);
}

html[data-universe="tow"] .miscast-row.is-rolled {
    background-color: rgba(201, 168, 76, 0.14);
    box-shadow: inset 3px 0 0 0 var(--color-gold);
}

/* The one-cast-per-wizard gate: the rule, then the way past it. */
html[data-universe="tow"] .cast-result-gate {
    margin: var(--space-md) 0;
    padding: var(--space-sm);
    border: 1px solid var(--color-border);
    border-radius: var(--radius-sm);
    text-align: center;
}

html[data-universe="tow"] .rip-add-row {
    display: grid;
    grid-template-columns: 1fr 1fr auto auto;
    gap: var(--space-sm);
    margin-bottom: var(--space-sm);
}
@media (max-width: 560px) {
    html[data-universe="tow"] .rip-add-row {
        grid-template-columns: 1fr 1fr;
    }
}

/* Cast log entries — screens/magic.css styles .spell-entry and its
   result variants; these are the pieces it predates. */
html[data-universe="tow"] .spell-log:empty::after {
    content: 'No spells cast yet.';
    color: var(--color-text-muted);
    font-size: var(--text-sm);
}


/* ----------------------------------------------------------------
   Magic  (screens/magic.js)

   Live state — the cast log and Remains in Play — renders in the
   battle screen's magic panel. The lore reference and miscast table
   render in the shared Reference drawer. Both are styled here because
   both are magic.js's markup; where each is mounted is Task 3's
   business, not the stylesheet's.
   ---------------------------------------------------------------- */

/* Remains in Play */
html[data-universe="tow"] .rip-card {
    padding: var(--space-sm);
    background-color: var(--color-surface-raised);
    border: 1px solid var(--color-border);
    border-left: 2px solid var(--color-gold-dark);
    border-radius: var(--radius-sm);
    margin-bottom: var(--space-xs);
}
/* Owner is the thing you need at a glance: whose spell is still up. */
html[data-universe="tow"] .rip-card.rip-opponent {
    border-left-color: var(--color-error);
}

html[data-universe="tow"] .rip-card-header {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: var(--space-sm);
}

html[data-universe="tow"] .rip-card-name {
    font-size: var(--text-sm);
    font-weight: 600;
    color: var(--color-text-primary);
}

html[data-universe="tow"] .rip-card-meta {
    display: flex;
    flex-wrap: wrap;
    gap: var(--space-sm);
    margin-top: 2px;
    font-size: var(--text-xs);
    color: var(--color-text-muted);
}

/* Spell cards — shared with tools.js, which emits the same class
   names for the same concepts. Written once on purpose. */
html[data-universe="tow"] .spell-card {
    padding: var(--space-sm) var(--space-md);
    background-color: var(--color-surface-raised);
    border: 1px solid var(--color-border);
    border-radius: var(--radius-sm);
    margin-bottom: var(--space-xs);
}

html[data-universe="tow"] .spell-card-header {
    display: flex;
    align-items: baseline;
    gap: var(--space-sm);
}

html[data-universe="tow"] .spell-card-name {
    flex: 1;
    font-size: var(--text-base);
    color: var(--color-text-primary);
}

html[data-universe="tow"] .spell-num {
    flex: none;
    min-width: 1.6em;
    padding: 0 var(--space-xs);
    text-align: center;
    font-family: 'Courier New', monospace;
    font-size: var(--text-xs);
    color: var(--color-gold-dark);
    border: 1px solid var(--color-border-light);
    border-radius: var(--radius-sm);
}
/* A lore's signature spell is always available to its wizards, so it
   reads differently from the numbered ones you roll for. */
html[data-universe="tow"] .spell-sig {
    background-color: var(--color-gold);
    border-color: var(--color-gold);
    color: var(--color-bg, #0d0b08);
    font-weight: 700;
}

html[data-universe="tow"] .spell-card-cv,
html[data-universe="tow"] .spell-card-range {
    flex: none;
    font-family: 'Courier New', monospace;
    font-size: var(--text-sm);
    color: var(--color-gold-light);
    font-variant-numeric: tabular-nums;
}

html[data-universe="tow"] .spell-card-category,
html[data-universe="tow"] .spell-card-meta {
    font-size: var(--text-xs);
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: 0.08em;
    color: var(--color-text-secondary);
}

html[data-universe="tow"] .spell-card-text {
    font-size: var(--text-sm);
    color: var(--color-text-secondary);
    line-height: 1.6;
    margin: var(--space-xs) 0 0;
}

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

/* Remains in Play is the property that changes how you play around a
   spell, so it is called out rather than left in the body text. */
html[data-universe="tow"] .spell-card-rip {
    display: inline-block;
    padding: 0 var(--space-xs);
    border: 1px solid var(--color-gold-dark);
    border-radius: var(--radius-sm);
    font-size: var(--text-xs);
    font-weight: 700;
    letter-spacing: 0.08em;
    text-transform: uppercase;
    color: var(--color-gold);
}

/* Lore reference */
html[data-universe="tow"] .lore-attribute,
html[data-universe="tow"] .lore-ref-attribute {
    padding: var(--space-sm) var(--space-md);
    background-color: var(--color-surface-raised);
    border-left: 3px solid var(--color-gold);
    border-radius: var(--radius-sm);
    font-size: var(--text-sm);
    color: var(--color-text-secondary);
    line-height: 1.6;
    margin-bottom: var(--space-md);
}

html[data-universe="tow"] .lore-ref-spells {
    display: flex;
    flex-direction: column;
    gap: var(--space-xs);
}

html[data-universe="tow"] .lore-ref-spell {
    padding: var(--space-sm) var(--space-md);
    background-color: var(--color-surface-raised);
    border: 1px solid var(--color-border);
    border-radius: var(--radius-sm);
}

html[data-universe="tow"] .lore-ref-spell-header {
    display: flex;
    align-items: baseline;
    gap: var(--space-sm);
}

html[data-universe="tow"] .lore-ref-spell-name {
    flex: 1;
    font-size: var(--text-base);
    color: var(--color-text-primary);
}

html[data-universe="tow"] .lore-ref-spell-desc {
    font-size: var(--text-sm);
    color: var(--color-text-secondary);
    line-height: 1.6;
    margin: var(--space-xs) 0 0;
}

/* Miscast table — a lookup you read under pressure, so the roll
   column is fixed-width and the whole row is scannable. */
/* `.miscast-table` is a stack of divs. `.ref-table` is deliberately NOT
   in this rule — tools.js renders it as a real <table>, and display:flex
   on a table element destroys its layout. It is styled as a table under
   the .ref-grid wrapper further up. */
html[data-universe="tow"] .miscast-table {
    display: flex;
    flex-direction: column;
    border: 1px solid var(--color-border);
    border-radius: var(--radius-md);
    overflow: hidden;
}

html[data-universe="tow"] .miscast-row {
    display: grid;
    grid-template-columns: 4.5em 1fr;
    gap: var(--space-sm);
    padding: var(--space-sm) var(--space-md);
    border-top: 1px solid var(--color-border);
    background-color: var(--color-surface);
}
html[data-universe="tow"] .miscast-row:first-child { border-top: 0; }

html[data-universe="tow"] .miscast-roll {
    font-family: 'Courier New', monospace;
    font-size: var(--text-sm);
    font-weight: 700;
    color: var(--color-error);
    font-variant-numeric: tabular-nums;
}

html[data-universe="tow"] .miscast-result {
    font-size: var(--text-sm);
    font-weight: 600;
    color: var(--color-text-primary);
}

html[data-universe="tow"] .miscast-body {
    font-size: var(--text-sm);
    color: var(--color-text-secondary);
    line-height: 1.6;
}


/* ----------------------------------------------------------------
   Tools screen chrome

   The More-drawer entry is gated the same way the Reference tab is
   gated to 40k (see bb/css/reference-drawer.css): hidden by default,
   revealed by the universe attribute. Unlike everything else in this
   file the gate itself must NOT be scoped to TOW — the default-hidden
   half has to apply in every universe or the entry shows everywhere.
   ---------------------------------------------------------------- */

/* `.bb-more-item-tools` gated the More-drawer entry to The Old World.
   Tools became a bottom-bar tab in every universe on 2026-08-16 and the
   drawer entry was removed, so the rule has nothing left to hide. */

html[data-universe="tow"] .tools-tabs { margin-bottom: var(--space-md); }

html[data-universe="tow"] .tool-panel { display: none; }
html[data-universe="tow"] .tool-panel.active {
    display: flex;
    flex-direction: column;
    gap: var(--space-md);
}

/* ----------------------------------------------------------------
   Rules reference — weapons, unit types, formations, misfire tables.
   Added 2026-08-16.

   Read standing up, one-handed, mid-phase, with dice in the other hand.
   So: the citation is always on the right of the heading where the eye
   can find it without reading the rule, the stat line is a grid of three
   labelled cells rather than a sentence, and the book's Note — which is
   the half that gets misplayed — is set apart rather than run on.
   ---------------------------------------------------------------- */

/* Which tab you are on.
   ----------------------------------------------------------------
   The shell paints a selected pill from `[aria-selected="true"]` or
   `.is-active` (bb-layout.css). `initToolsScreen` and the sub-tab binder
   both toggle plain `.active`, which nothing has ever styled — so the
   open tab looked exactly like the eight closed ones and the only way to
   tell was the panel below. The gold ring in earlier screenshots was
   `:focus-visible` from the tap that got you there, and it vanished on
   the next tap elsewhere.

   Styled here rather than renamed in the JS: `.active` is the contract
   the tab handler, the panels and the tests all share, and the ids in
   this screen fail silently when they drift. */
html[data-universe="tow"] .tools-tab.active,
html[data-universe="tow"] .ref-subtab.active {
    color: var(--bb-bg-base);
    background: var(--bb-accent-primary);
    border-color: var(--bb-accent-primary);
}

html[data-universe="tow"] .ref-subtabs {
    padding-left: 0;
    padding-right: 0;
    background: none;
    border-bottom: none;
}

html[data-universe="tow"] .ref-pane { display: none; }
html[data-universe="tow"] .ref-pane.active {
    display: flex;
    flex-direction: column;
    gap: var(--space-md);
}

html[data-universe="tow"] .ref-group {
    display: flex;
    flex-direction: column;
    gap: var(--space-sm);
}

html[data-universe="tow"] .ref-group-head,
html[data-universe="tow"] .ref-entry-head {
    display: flex;
    align-items: baseline;
    justify-content: space-between;
    gap: var(--space-sm);
}

html[data-universe="tow"] .ref-group-name {
    margin: 0;
    color: var(--color-gold);
    font-size: var(--text-lg);
}

html[data-universe="tow"] .ref-entry-name {
    margin: 0;
    color: var(--color-text-primary);
    font-size: var(--text-base);
}

/* The page citation. Small, dim, and never wrapped away from its
   heading — it is what settles the argument. */
html[data-universe="tow"] .ref-page {
    flex: none;
    color: var(--color-text-muted);
    font-size: var(--text-xs);
    white-space: nowrap;
}

html[data-universe="tow"] .ref-blurb,
html[data-universe="tow"] .ref-text {
    margin: 0;
    color: var(--color-text-secondary);
    font-size: var(--text-sm);
    line-height: 1.5;
}

html[data-universe="tow"] .ref-entry {
    display: flex;
    flex-direction: column;
    gap: var(--space-xs);
    padding: var(--space-sm);
    background: var(--color-surface-raised);
    border: 1px solid var(--color-border);
    border-radius: var(--radius-md);
}

/* Stat cells. `auto-fit` rather than a fixed three, because the unit-type
   rows carry "As starting Wounds" in the third cell. Weapon profiles are
   always three — a variant's name sits above the row, not in it. */
html[data-universe="tow"] .ref-profile {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(90px, 1fr));
    gap: var(--space-xs);
    margin: 0;
}

html[data-universe="tow"] .ref-profile dt {
    grid-row: 1;
}

html[data-universe="tow"] .ref-profile dd {
    grid-row: 2;
}

/* The armour tables WRAP rather than sharing one two-row grid: maximum
   armour value has five entries, which needed 450px and pushed War
   Machine off the right edge of a 390px phone. */
html[data-universe="tow"] .ref-armour {
    display: flex;
    flex-wrap: wrap;
    gap: var(--space-xs) var(--space-md);
    margin: 0;
}

html[data-universe="tow"] .ref-armour-cell {
    min-width: 84px;
}

html[data-universe="tow"] .ref-profile dt,
html[data-universe="tow"] .ref-armour dt {
    color: var(--color-text-muted);
    font-size: var(--text-xs);
    text-transform: uppercase;
    letter-spacing: 0.06em;
}

html[data-universe="tow"] .ref-profile dd,
html[data-universe="tow"] .ref-armour dd {
    margin: 0;
    color: var(--color-text-primary);
    font-family: 'Courier New', monospace;
    font-size: var(--text-base);
}

html[data-universe="tow"] .ref-profile-label {
    margin: 0;
    color: var(--color-gold-light);
    font-family: inherit;
    font-size: var(--text-sm);
    font-weight: 600;
}

html[data-universe="tow"] .ref-rules {
    margin: 0;
    color: var(--color-gold-dark);
    font-size: var(--text-xs);
    text-transform: uppercase;
    letter-spacing: 0.06em;
}

html[data-universe="tow"] .ref-note {
    margin: 0;
    padding-left: var(--space-sm);
    border-left: 2px solid var(--color-gold-dark);
    color: var(--color-text-secondary);
    font-size: var(--text-sm);
    line-height: 1.5;
}

/* Misfire rows. The D6 result is the thing being looked for, so it gets
   its own column and does not have to be read out of a sentence. */
html[data-universe="tow"] .ref-misfire-row {
    display: flex;
    gap: var(--space-sm);
    padding: var(--space-sm);
    background: var(--color-surface-raised);
    border: 1px solid var(--color-border);
    border-radius: var(--radius-md);
}

html[data-universe="tow"] .ref-misfire-roll {
    flex: none;
    min-width: 3ch;
    color: var(--color-gold);
    font-family: 'Courier New', monospace;
    font-size: var(--text-lg);
    text-align: center;
}

html[data-universe="tow"] .ref-misfire-result {
    display: block;
    color: var(--color-text-primary);
    font-size: var(--text-base);
}

/* A stat line and the special rules that belong to it, kept together so a
   two-profile weapon (brace of pistols, cannon) cannot have its rules read
   against the wrong row. */
html[data-universe="tow"] .ref-profile-block {
    display: flex;
    flex-direction: column;
    gap: var(--space-xs);
}

html[data-universe="tow"] .ref-special {
    margin: 0;
    color: var(--color-text-secondary);
    font-size: var(--text-sm);
    line-height: 1.5;
}

html[data-universe="tow"] .ref-special strong {
    color: var(--color-text-muted);
    font-size: var(--text-xs);
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: 0.06em;
}

html[data-universe="tow"] .tools-section-title {
    margin: 0;
    font-size: var(--text-sm);
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: 0.12em;
    color: var(--color-gold);
}

html[data-universe="tow"] .tools-filter-row {
    display: flex;
    align-items: center;
    gap: var(--space-md);
    flex-wrap: wrap;
}

/* Combat calculator. Two sides side by side where there is room, and
   stacked on a phone — you are entering one side at a time anyway. */
html[data-universe="tow"] .cc-sides {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(240px, 1fr));
    gap: var(--space-md);
}

html[data-universe="tow"] .cc-side {
    padding: var(--space-md);
    background-color: var(--color-surface);
    border: 1px solid var(--color-border);
    border-radius: var(--radius-md);
}

html[data-universe="tow"] .cc-side-title {
    display: flex;
    align-items: baseline;
    justify-content: space-between;
    gap: var(--space-sm);
    margin: 0 0 var(--space-sm);
    font-size: var(--text-base);
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: 0.1em;
    color: var(--color-text-secondary);
}

/* The running total is the number you actually watch while typing. */
html[data-universe="tow"] .cc-total {
    font-family: 'Courier New', monospace;
    font-size: var(--text-2xl);
    font-weight: 700;
    color: var(--color-gold);
    font-variant-numeric: tabular-nums;
}

html[data-universe="tow"] .cc-fields {
    display: grid;
    gap: var(--space-sm);
}

html[data-universe="tow"] .cc-field {
    display: grid;
    grid-template-columns: 1fr 5.5em;
    align-items: center;
    gap: var(--space-sm);
    font-size: var(--text-sm);
    color: var(--color-text-secondary);
}
html[data-universe="tow"] .cc-field input { text-align: right; }

html[data-universe="tow"] .cc-checks {
    display: flex;
    flex-wrap: wrap;
    gap: var(--space-xs) var(--space-sm);
    margin-top: var(--space-sm);
    padding-top: var(--space-sm);
    border-top: 1px solid var(--color-border);
}

html[data-universe="tow"] .cc-result:empty { display: none; }

html[data-universe="tow"] .cc-break-section {
    padding: var(--space-md);
    background-color: var(--color-surface);
    border: 1px solid var(--color-gold-dark);
    border-radius: var(--radius-md);
    display: flex;
    flex-direction: column;
    gap: var(--space-sm);
}

/* Reference grids. The charts are wide by nature, so they scroll inside
   their own container rather than pushing the page sideways. */
html[data-universe="tow"] .ref-grid {
    overflow-x: auto;
    border: 1px solid var(--color-border);
    border-radius: var(--radius-md);
}

html[data-universe="tow"] .ref-grid table {
    border-collapse: collapse;
    width: 100%;
    min-width: 30rem;
    font-size: var(--text-sm);
    font-variant-numeric: tabular-nums;
}

html[data-universe="tow"] .ref-grid th,
html[data-universe="tow"] .ref-grid td {
    padding: var(--space-xs) var(--space-sm);
    text-align: center;
    border: 1px solid var(--color-border);
    color: var(--color-text-secondary);
}

html[data-universe="tow"] .ref-grid th {
    background-color: var(--color-surface-raised);
    color: var(--color-text-primary);
    font-weight: 700;
}

/* _bindTableHighlight marks the cell you tapped plus its row and column
   headers, so you can find a crossing on a phone without losing it. */
html[data-universe="tow"] .ref-grid td { cursor: pointer; }
html[data-universe="tow"] .ref-grid .highlight {
    background-color: color-mix(in srgb, var(--color-gold) 22%, transparent);
    color: var(--color-text-primary);
    font-weight: 700;
}

html[data-universe="tow"] .ref-modifiers {
    font-size: var(--text-sm);
    color: var(--color-text-secondary);
    line-height: 1.6;
}

html[data-universe="tow"] .spellcard-list {
    display: flex;
    flex-direction: column;
    gap: var(--space-xs);
}


/* ----------------------------------------------------------------
   Tools — combat resolution and break tests  (screens/tools.js)

   The screen with the most unstyled markup in the app: 35 classes,
   none of which has ever had a rule. screens/tools.css is a comment
   header and nothing else.
   ---------------------------------------------------------------- */

html[data-universe="tow"] .combat-winner,
html[data-universe="tow"] .combat-draw {
    padding: var(--space-md);
    border-radius: var(--radius-md);
    text-align: center;
    font-size: var(--text-lg);
    font-weight: 700;
    border: 1px solid var(--color-border-light);
    background-color: var(--color-surface-raised);
}
html[data-universe="tow"] .combat-winner { color: var(--color-gold); border-color: var(--color-gold-dark); }
html[data-universe="tow"] .combat-draw   { color: var(--color-text-secondary); }

html[data-universe="tow"] .break-result {
    padding: var(--space-md);
    border-radius: var(--radius-md);
    border: 1px solid var(--color-border);
    background-color: var(--color-surface-raised);
    margin-top: var(--space-sm);
}

html[data-universe="tow"] .break-ld-display {
    font-family: 'Courier New', monospace;
    font-size: var(--text-2xl);
    font-weight: 700;
    color: var(--color-gold);
    font-variant-numeric: tabular-nums;
    text-align: center;
}

html[data-universe="tow"] .break-thresholds {
    display: flex;
    flex-direction: column;
    gap: 1px;
    margin-top: var(--space-sm);
    background-color: var(--color-border);
    border-radius: var(--radius-sm);
    overflow: hidden;
}

html[data-universe="tow"] .break-threshold {
    display: flex;
    align-items: baseline;
    justify-content: space-between;
    gap: var(--space-sm);
    padding: var(--space-xs) var(--space-sm);
    background-color: var(--color-surface);
    font-size: var(--text-sm);
    color: var(--color-text-secondary);
}

html[data-universe="tow"] .break-threshold-roll {
    font-family: 'Courier New', monospace;
    font-weight: 700;
    font-variant-numeric: tabular-nums;
    color: var(--color-text-primary);
}

/* Outcome severity, worst to best. Colour carries the reading so the
   result is legible across a table. */
html[data-universe="tow"] .break-gives-ground { color: var(--color-warning); font-weight: 700; }
html[data-universe="tow"] .break-falls-back   { color: #e08a3c;              font-weight: 700; }
html[data-universe="tow"] .break-flees        { color: var(--color-error);   font-weight: 700; }
html[data-universe="tow"] .break-impossible   { color: var(--color-text-muted); }

/* Roll difficulty, used on the casting and break tables alike.
   Written with the .ref-grid descendant so these beat
   `html[data-universe="tow"] .ref-grid td`, which is one class-level
   token heavier than a bare `.roll-easy` would be. Without the extra
   token the chart renders in flat secondary text and the whole point of
   the shading is lost. */
html[data-universe="tow"] .roll-easy,
html[data-universe="tow"] .ref-grid td.roll-easy       { color: var(--color-success); }
html[data-universe="tow"] .roll-mid,
html[data-universe="tow"] .ref-grid td.roll-mid        { color: var(--color-warning); }
html[data-universe="tow"] .roll-hard,
html[data-universe="tow"] .ref-grid td.roll-hard       { color: #e08a3c; }
html[data-universe="tow"] .roll-impossible,
html[data-universe="tow"] .ref-grid td.roll-impossible { color: var(--color-text-muted); text-decoration: line-through; }

/* The same five bands the framework's charts use, at the specificity this
   file needs to reach a `.ref-grid td`.

   `roll-easy` / `roll-mid` / `roll-hard` above still style the MODIFIER
   tables — "-1 for long range" is a good/neutral/bad judgement, not a
   number on a die. The charts moved to the framework's per-roll bands on
   2026-08-28 (`rollBandClass` in
   static/bb/js/reference/reference-table.js) so a 4+ is the same colour in
   both games. The colours themselves are in bb-tokens.css and are
   deliberately not universe-scoped.

   These MUST be written with the `.ref-grid td` descendant, for the reason
   the block above says: a bare `.bb-ref-roll-4` is one class-level token
   lighter than `html[data-universe="tow"] .ref-grid td`, so the whole
   chart would render in flat secondary text and lose the point. */
html[data-universe="tow"] .bb-ref-roll-2,
html[data-universe="tow"] .ref-grid td.bb-ref-roll-2 { color: var(--bb-roll-2); }
html[data-universe="tow"] .bb-ref-roll-3,
html[data-universe="tow"] .ref-grid td.bb-ref-roll-3 { color: var(--bb-roll-3); }
html[data-universe="tow"] .bb-ref-roll-4,
html[data-universe="tow"] .ref-grid td.bb-ref-roll-4 { color: var(--bb-roll-4); }
html[data-universe="tow"] .bb-ref-roll-5,
html[data-universe="tow"] .ref-grid td.bb-ref-roll-5 { color: var(--bb-roll-5); font-weight: 600; }
html[data-universe="tow"] .bb-ref-roll-6,
html[data-universe="tow"] .ref-grid td.bb-ref-roll-6 { color: var(--bb-roll-6); font-weight: 600; }

/* Written as `.ref-grid th.corner-cell` so it outweighs
   `html[data-universe="tow"] .ref-grid th`, which sets a primary text
   colour one class-level token heavier than a bare `.corner-cell`. Same
   trap as the .roll-* rules above. */
html[data-universe="tow"] .ref-grid th.corner-cell,
html[data-universe="tow"] .corner-cell {
    color: var(--color-text-muted);
    font-size: var(--text-xs);
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: 0.08em;
}

html[data-universe="tow"] .highlight {
    background-color: color-mix(in srgb, var(--color-gold) 18%, transparent);
    border-radius: var(--radius-sm);
}

/* Phase guide — the checklist of what happens in the current phase. */
html[data-universe="tow"] .phase-guide-section {
    padding: var(--space-md);
    background-color: var(--color-surface);
    border: 1px solid var(--color-border);
    border-radius: var(--radius-md);
    margin-bottom: var(--space-sm);
}
html[data-universe="tow"] .phase-guide-section.active-guide {
    border-color: var(--color-gold-dark);
    background-color: var(--color-surface-raised);
}

html[data-universe="tow"] .phase-guide-summary {
    font-size: var(--text-sm);
    color: var(--color-text-secondary);
    line-height: 1.6;
    margin-bottom: var(--space-sm);
}

html[data-universe="tow"] .phase-guide-checklist {
    display: flex;
    flex-direction: column;
    gap: var(--space-xs);
    margin: 0;
    padding: 0;
    list-style: none;
}

html[data-universe="tow"] .phase-guide-step {
    display: flex;
    gap: var(--space-sm);
    font-size: var(--text-sm);
    color: var(--color-text-secondary);
    line-height: 1.55;
}
html[data-universe="tow"] .phase-guide-step::before {
    content: '';
    flex: none;
    width: 6px;
    height: 6px;
    margin-top: 0.55em;
    border-radius: 50%;
    background-color: var(--color-gold-dark);
}


/* ----------------------------------------------------------------
   Setup wizard extras  (screens/setup.js)

   The wizard's own chrome is shell-styled; these are the Old World
   specific parts — declaring wizards and their spells, and pasting in
   an army list.
   ---------------------------------------------------------------- */

html[data-universe="tow"] .wizard-player-block,
html[data-universe="tow"] .import-player-block {
    padding: var(--space-md);
    background-color: var(--color-surface);
    border: 1px solid var(--color-border);
    border-radius: var(--radius-md);
    margin-bottom: var(--space-md);
}

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

html[data-universe="tow"] .wizard-row-config {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(120px, 1fr));
    gap: var(--space-sm);
}

html[data-universe="tow"] .wizard-spells-list {
    display: flex;
    flex-direction: column;
    gap: var(--space-xs);
    margin-top: var(--space-sm);
    padding-top: var(--space-sm);
    border-top: 1px solid var(--color-border);
}

html[data-universe="tow"] .spell-checkbox {
    display: flex;
    align-items: baseline;
    gap: var(--space-sm);
    padding: var(--space-xs) var(--space-sm);
    min-height: var(--touch-min);
    border-radius: var(--radius-sm);
    cursor: pointer;
}
html[data-universe="tow"] .spell-checkbox:hover {
    background-color: var(--color-surface-hover);
}

html[data-universe="tow"] .spell-pick-label {
    display: flex;
    align-items: baseline;
    gap: var(--space-sm);
    flex: 1;
    font-size: var(--text-sm);
    cursor: pointer;
}
html[data-universe="tow"] .spell-pick-name { flex: 1; color: var(--color-text-primary); }
html[data-universe="tow"] .spell-pick-cv {
    font-family: 'Courier New', monospace;
    color: var(--color-gold-light);
    font-variant-numeric: tabular-nums;
}
/* Running spell count. Goes amber rather than red when a wizard knows more
   than their level: that is legal with the right item, so it is a flag to
   look at, not an error to fix. */
html[data-universe="tow"] .spell-count-hint {
    margin: 0 0 var(--space-xs);
    font-size: var(--text-xs);
    color: var(--color-text-secondary);
}
html[data-universe="tow"] .spell-count-hint.spell-count-over {
    color: var(--color-warning);
    font-weight: 600;
}

html[data-universe="tow"] .spell-pick-cat {
    font-size: var(--text-xs);
    text-transform: uppercase;
    letter-spacing: 0.08em;
    color: var(--color-text-muted);
}

html[data-universe="tow"] .import-section {
    padding: var(--space-md);
    background-color: var(--color-surface);
    border: 1px solid var(--color-border);
    border-radius: var(--radius-md);
}

html[data-universe="tow"] .import-row {
    display: flex;
    align-items: center;
    gap: var(--space-sm);
    flex-wrap: wrap;
}

html[data-universe="tow"] .import-label {
    font-size: var(--text-sm);
    font-weight: 600;
    color: var(--color-text-primary);
}

html[data-universe="tow"] .import-done {
    font-size: var(--text-sm);
    font-weight: 700;
    color: var(--color-success);
}

html[data-universe="tow"] .paste-modal {
    display: flex;
    flex-direction: column;
    gap: var(--space-md);
}

html[data-universe="tow"] .paste-modal-actions {
    display: flex;
    justify-content: flex-end;
    gap: var(--space-sm);
}


/* ----------------------------------------------------------------
   History and stats  (screens/history.js)
   ---------------------------------------------------------------- */

html[data-universe="tow"] .stats-cards {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(96px, 1fr));
    gap: var(--space-sm);
    margin-bottom: var(--space-md);
}

html[data-universe="tow"] .stat-card {
    padding: var(--space-md) var(--space-sm);
    background-color: var(--color-surface-raised);
    border: 1px solid var(--color-border);
    border-radius: var(--radius-md);
    text-align: center;
}

html[data-universe="tow"] .stat-value {
    display: block;
    font-size: var(--text-2xl);
    font-weight: 700;
    line-height: 1.1;
    color: var(--color-gold);
    font-variant-numeric: tabular-nums;
}
html[data-universe="tow"] .stat-win  .stat-value,
html[data-universe="tow"] .stat-card.stat-win  { color: var(--color-success); }
html[data-universe="tow"] .stat-loss .stat-value,
html[data-universe="tow"] .stat-card.stat-loss { color: var(--color-error); }
html[data-universe="tow"] .stat-draw .stat-value,
html[data-universe="tow"] .stat-card.stat-draw { color: var(--color-text-secondary); }

html[data-universe="tow"] .stat-label {
    display: block;
    margin-top: var(--space-xs);
    font-size: var(--text-xs);
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: 0.09em;
    color: var(--color-text-muted);
}

html[data-universe="tow"] .stats-table {
    display: flex;
    flex-direction: column;
    gap: var(--space-xs);
}

html[data-universe="tow"] .stats-row {
    display: grid;
    grid-template-columns: 1fr auto auto;
    align-items: center;
    gap: var(--space-sm);
    padding: var(--space-sm);
    background-color: var(--color-surface);
    border: 1px solid var(--color-border);
    border-radius: var(--radius-sm);
}

html[data-universe="tow"] .stats-row-name {
    font-size: var(--text-sm);
    color: var(--color-text-primary);
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

html[data-universe="tow"] .stats-row-record,
html[data-universe="tow"] .stats-row-wr {
    font-family: 'Courier New', monospace;
    font-size: var(--text-sm);
    color: var(--color-text-secondary);
    font-variant-numeric: tabular-nums;
    white-space: nowrap;
}

/* Win-rate bar. Spans the full row beneath the figures so the shape
   of a record reads before the numbers do. */
html[data-universe="tow"] .stats-row-bar {
    grid-column: 1 / -1;
    height: 4px;
    border-radius: 2px;
    background-color: var(--color-surface-hover);
    overflow: hidden;
}

html[data-universe="tow"] .stats-row-fill {
    display: block;
    height: 100%;
    background-color: var(--color-gold);
}

html[data-universe="tow"] .stats-mini-list {
    display: flex;
    flex-wrap: wrap;
    gap: var(--space-xs) var(--space-md);
}

html[data-universe="tow"] .stats-mini-item {
    font-size: var(--text-xs);
    color: var(--color-text-muted);
}

html[data-universe="tow"] .roster-panel {
    padding: var(--space-md);
    background-color: var(--color-surface);
    border: 1px solid var(--color-border);
    border-radius: var(--radius-md);
}


/* ----------------------------------------------------------------
   Reduced motion — nothing here animates, but the transitions
   inherited from the linked TOW component files do.
   ---------------------------------------------------------------- */

@media (prefers-reduced-motion: reduce) {
    html[data-universe="tow"] * {
        transition-duration: 0.01ms !important;
        animation-duration: 0.01ms !important;
    }
}


/* ================================================================
   End-of-game victory point calculator

   Most Old World points are scored after the dice are down. The score
   row on the dashboard tracks objectives claimed DURING the game;
   this is the reckoning.

   Every band share and bonus value is rendered next to its own
   control on purpose — the rules differ by event pack, and a number
   the player can see is a number the player can catch.
   ================================================================ */

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

html[data-universe="tow"] .vp-unit-rows {
    display: flex;
    flex-direction: column;
    gap: var(--space-sm);
    margin-bottom: var(--space-sm);
}

html[data-universe="tow"] .vp-unit-row {
    display: grid;
    grid-template-columns: minmax(0, 1.6fr) minmax(64px, 0.7fr) minmax(0, 1.8fr) auto auto;
    gap: var(--space-xs);
    align-items: center;
}

/* On a phone the five columns become two rows rather than five slivers.
   A points field you cannot read is a points field you mistype. */
@media (max-width: 560px) {
    html[data-universe="tow"] .vp-unit-row {
        grid-template-columns: minmax(0, 1fr) minmax(64px, auto) auto;
        grid-template-areas:
            "name   points remove"
            "band   band   value";
    }
    html[data-universe="tow"] .vp-unit-name { grid-area: name; }
    html[data-universe="tow"] .vp-unit-points { grid-area: points; }
    html[data-universe="tow"] .vp-unit-band { grid-area: band; }
    html[data-universe="tow"] .vp-unit-value { grid-area: value; }
    html[data-universe="tow"] .vp-unit-remove { grid-area: remove; }
}

html[data-universe="tow"] .vp-unit-value {
    min-width: 3.5ch;
    text-align: right;
    font-weight: 700;
    font-variant-numeric: tabular-nums;
    color: var(--color-gold);
}

html[data-universe="tow"] .vp-empty {
    margin: 0;
    font-size: var(--text-sm);
}

html[data-universe="tow"] .vp-bonus-rows {
    display: flex;
    flex-direction: column;
    gap: var(--space-sm);
}

/* Three columns, not four: control, what it is, what it is worth. The
   fourth used to be an editable amount per bonus and is gone — see
   screens/vp-calculator.js::total. */
html[data-universe="tow"] .vp-bonus-row {
    display: grid;
    grid-template-columns: auto minmax(0, 1fr) auto;
    gap: var(--space-sm);
    align-items: center;
}

html[data-universe="tow"] .vp-bonus-count {
    min-width: 0;
    text-align: center;
    font-variant-numeric: tabular-nums;
}

html[data-universe="tow"] .vp-bonus-toggle {
    width: 20px;
    height: 20px;
}

html[data-universe="tow"] .vp-bonus-worth {
    font-size: var(--text-sm);
    color: var(--color-text-muted);
    font-variant-numeric: tabular-nums;
    white-space: nowrap;
}

html[data-universe="tow"] .vp-total-row {
    display: flex;
    align-items: baseline;
    justify-content: space-between;
    margin-top: var(--space-md);
    padding-top: var(--space-sm);
    border-top: 1px solid var(--color-border);
}

html[data-universe="tow"] .vp-total-label {
    font-size: var(--text-sm);
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: 0.1em;
    color: var(--color-text-secondary);
}

html[data-universe="tow"] .vp-total-value {
    font-size: var(--text-3xl);
    font-weight: 700;
    line-height: 1;
    font-variant-numeric: tabular-nums;
    color: var(--color-gold);
}

html[data-universe="tow"] .vp-apply-row {
    display: flex;
    flex-wrap: wrap;
    gap: var(--space-sm);
    margin-top: var(--space-md);
}

html[data-universe="tow"] .vp-apply-row .btn {
    flex: 1 1 auto;
    min-height: 44px;
}

html[data-universe="tow"] .vp-rules-note {
    margin: var(--space-md) 0 0;
    font-size: var(--text-xs);
    color: var(--color-text-muted);
}


/* ----------------------------------------------------------------
   The inline phase guide

   The checklist for the sub-phase you are standing in, directly under
   the tracker. Collapsed by default: it costs one line when you do
   not want it and answers the question when you do.

   In Break Tests & Pursuit this is the combat resolution reference,
   which is the whole reason it moved out of a tab on another screen.
   ---------------------------------------------------------------- */

html[data-universe="tow"] .phase-guide-inline {
    margin-bottom: var(--space-md);
    border: 1px solid var(--color-border);
    border-radius: var(--radius-md);
    background-color: var(--color-surface);
}

html[data-universe="tow"] .phase-guide-inline[hidden] {
    display: none;
}

html[data-universe="tow"] .phase-guide-inline-summary {
    min-height: 40px;
    display: flex;
    align-items: center;
    padding: var(--space-xs) var(--space-md);
    font-size: var(--text-sm);
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: 0.08em;
    color: var(--color-gold);
    cursor: pointer;
}

html[data-universe="tow"] .phase-guide-inline-body {
    padding: 0 var(--space-md) var(--space-md);
}

html[data-universe="tow"] .phase-guide-inline-summary-text {
    margin: 0 0 var(--space-sm);
    font-size: var(--text-sm);
    color: var(--color-text-secondary);
}

html[data-universe="tow"] .phase-guide-inline .phase-guide-checklist {
    margin: 0;
    padding-left: 1.25rem;
    font-size: var(--text-sm);
    color: var(--color-text-secondary);
    line-height: 1.7;
}

html[data-universe="tow"] .phase-guide-inline .phase-guide-checklist li + li {
    margin-top: var(--space-xs);
}

/* The other player's wizards, on the other player's turn.
   Dimmed like a wizard who has already had its attempt — the same signal
   for the same meaning, "this is here, it is not yours right now" — and
   gated the same way rather than blocked. Requested 2026-08-13. */
html[data-universe="tow"] .spellbook-spell.is-offturn {
    opacity: 0.45;
}

html[data-universe="tow"] .spellbook-wizard:not(.is-active-player) .spellbook-wizard-name {
    opacity: 0.7;
}
