/* ==========================================================================
   Chessboard Battle
   Layout: grid for the macro regions, flexbox inside them, per STANDARDS.md.
   Tablet-first: the console below the board is sized for a tablet held in
   landscape, then re-stacks for phones and widens for desktop.

   The whole overlay is pointer-transparent except the lobby. The board is
   driven entirely by the keyboard, so nothing here should ever intercept a
   click that belongs to the canvas beneath it.
   ========================================================================== */

.battle-root {
    position: absolute;
    inset: 0;
    z-index: 30;
    display: grid;
    grid-template-areas: "stack";
    background: radial-gradient(circle at 50% 0%, rgba(120, 90, 220, .18), transparent 55%), #05060d;
    color: var(--text-primary);
    overflow: hidden;
}

.battle-root.hidden { display: none; }

/* All three share one grid cell and are explicitly stacked.
   WHY: the stage has to be positioned for the WebGL canvas to fill it, and a
   positioned element paints above a static sibling regardless of DOM order —
   so without these z-indexes the canvas hides the entire HUD. */
.battle-stage,
.battle-overlay,
.battle-lobby {
    grid-area: stack;
    position: relative;
    min-width: 0;
    min-height: 0;
}

.battle-stage { z-index: 0; }
.battle-overlay { z-index: 1; }
.battle-lobby { z-index: 2; }

/* -- The three.js surface ------------------------------------------------- */

.battle-stage { overflow: hidden; }
.battle-canvas { display: block; width: 100%; height: 100%; }

/* -- Overlay macro-grid ---------------------------------------------------
   Six rows: enemy towers, top bar, banner, spacer, own towers, console.     */

.battle-overlay {
    display: grid;
    grid-template-rows: auto auto auto minmax(0, 1fr) auto auto;
    grid-template-areas:
        "enemy"
        "top"
        "banner"
        "space"
        "own"
        "console";
    gap: .4rem;
    padding: 3.9rem .8rem .8rem;
    pointer-events: none;
}

.battle-overlay-idle { opacity: .18; filter: saturate(.4); }

/* -- Tower health rows ---------------------------------------------------- */

.battle-enemy-towers,
.battle-own-towers {
    display: flex;
    gap: .5rem;
    justify-content: center;
}

.battle-enemy-towers { grid-area: enemy; }
.battle-own-towers { grid-area: own; }

.battle-tower {
    flex: 1 1 0;
    max-width: 13rem;
    display: flex;
    flex-direction: column;
    gap: .18rem;
    padding: .3rem .5rem;
    border: 1px solid rgba(140, 160, 220, .22);
    border-radius: 6px;
    background: rgba(6, 10, 22, .78);
}

.battle-tower-label {
    font-size: .58rem;
    letter-spacing: .14em;
    color: var(--text-secondary);
}

.battle-tower-track {
    display: block;
    height: 6px;
    border-radius: 3px;
    background: rgba(255, 255, 255, .1);
    overflow: hidden;
}

.battle-tower-track i {
    display: block;
    height: 100%;
    width: 100%;
    background: linear-gradient(90deg, var(--accent-green), var(--accent-cyan));
    transition: width .18s linear;
}

/* A shielded base is the rule players most often forget, so it is stated
   outright rather than implied by a colour. */
.battle-tower.is-shielded { border-color: rgba(255, 238, 0, .45); }
.battle-tower.is-shielded .battle-tower-label::after {
    content: " · SHIELDED";
    color: var(--accent-yellow);
}
.battle-tower.is-shielded .battle-tower-track i {
    background: linear-gradient(90deg, #6b6f8a, #9aa0c4);
}

.battle-tower.is-down { opacity: .4; border-style: dashed; }
.battle-tower.is-down .battle-tower-label::after { content: " · DOWN"; color: var(--accent-red); }

/* -- Top bar -------------------------------------------------------------- */

.battle-topbar {
    grid-area: top;
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: .8rem;
    padding: .35rem .7rem;
    border: 1px solid rgba(140, 160, 220, .2);
    border-radius: 8px;
    background: rgba(6, 10, 22, .8);
}

.battle-round b { display: block; font: 800 .9rem var(--font-display); color: var(--accent-cyan); }
.battle-round span { display: block; font-size: .58rem; letter-spacing: .12em; color: var(--text-secondary); }

.battle-clock {
    font: 900 1.9rem var(--font-display);
    color: var(--text-primary);
    font-variant-numeric: tabular-nums;
}
.battle-clock.is-urgent { color: var(--accent-red); animation: battlePulse .5s ease-in-out infinite alternate; }

@keyframes battlePulse { from { opacity: .55; } to { opacity: 1; } }

/* The match clock sits beside the phase clock but deliberately smaller: the
   phase timer is what you act on, the match timer is what you plan around. */
.battle-match {
    display: flex;
    align-items: baseline;
    gap: .35rem;
    font-size: .6rem;
    letter-spacing: .1em;
    color: var(--text-secondary);
}
.battle-match b { font-size: .85rem; color: var(--text-primary); font-variant-numeric: tabular-nums; }
.battle-match b.is-urgent { color: var(--accent-red); animation: battlePulse .5s ease-in-out infinite alternate; }
.battle-match-label { opacity: .7; }

/* Tower tally: the match is decided on this if the clock runs out. */
.battle-tower-count {
    padding: .05rem .35rem;
    border-radius: 3px;
    background: rgba(255, 255, 255, .08);
    font-weight: 800;
    font-variant-numeric: tabular-nums;
}
.battle-tower-count.is-ahead { color: var(--accent-green); }
.battle-tower-count.is-behind { color: var(--accent-red); }

.battle-link { display: flex; align-items: center; gap: .4rem; font-size: .65rem; letter-spacing: .1em; }

.battle-link-dot {
    width: 9px;
    height: 9px;
    border-radius: 50%;
    background: var(--text-dim);
}
/* Link state is a dot rather than words: it must be readable without being
   read, because the player's attention is on the prompt. */
.battle-link-dot.is-local { background: var(--accent-purple); }
.battle-link-dot.is-live { background: var(--accent-green); }
.battle-link-dot.is-connecting { background: var(--accent-yellow); }
.battle-link-dot.is-degraded { background: var(--accent-orange); animation: battlePulse .4s infinite alternate; }
.battle-link-dot.is-closed { background: var(--accent-red); }

/* -- Centre banner -------------------------------------------------------- */

.battle-banner {
    grid-area: banner;
    justify-self: center;
    padding: .4rem 1.2rem;
    border-radius: 999px;
    font: 900 1.1rem var(--font-display);
    letter-spacing: .18em;
    opacity: 0;
    transform: translateY(-6px);
    transition: opacity var(--transition-med), transform var(--transition-med);
}
.battle-banner.is-visible { opacity: 1; transform: translateY(0); }
.battle-banner.is-good { color: var(--accent-green); background: rgba(0, 255, 136, .12); }
.battle-banner.is-bad { color: var(--accent-red); background: rgba(255, 34, 68, .14); }
.battle-banner.is-warn { color: var(--accent-yellow); background: rgba(255, 238, 0, .12); }
.battle-banner.is-urgent { color: var(--accent-magenta); background: rgba(255, 0, 170, .14); }

/* -- Typing console -------------------------------------------------------
   The one region that must never be crowded out: everything the player reads
   while typing lives here, in a fixed reading order.                        */

.battle-console {
    grid-area: console;
    display: flex;
    flex-direction: column;
    gap: .45rem;
    padding: .6rem .7rem .7rem;
    border: 1px solid rgba(140, 160, 220, .25);
    border-radius: 10px;
    background: rgba(4, 7, 16, .92);
}

.battle-step {
    font-size: .62rem;
    letter-spacing: .16em;
    color: var(--accent-yellow);
}

/* Board orientation toggle. Deliberately quiet: it belongs to the window, not
   to the game, and must never compete with a lane or a piece for attention. */
.battle-orient {
    /* The overlay as a whole is pointer-events:none so clicks fall through to
       the board and nothing competes with the keyboard. This is one of the two
       things in it you are actually meant to click, so it opts back in. */
    pointer-events: auto;
    flex: 0 0 auto;
    white-space: nowrap;
    font: inherit;
    font-size: .52rem;
    letter-spacing: .12em;
    padding: .2rem .5rem;
    color: var(--text-secondary);
    background: rgba(255, 255, 255, .04);
    border: 1px solid rgba(255, 255, 255, .14);
    border-radius: 3px;
    cursor: pointer;
    transition: color .15s ease, border-color .15s ease, background .15s ease;
}
.battle-orient:hover {
    color: var(--accent-cyan);
    border-color: rgba(0, 240, 255, .45);
    background: rgba(0, 240, 255, .08);
}
.battle-orient.is-horizontal { color: var(--accent-cyan); border-color: rgba(0, 240, 255, .35); }

.battle-roster,
.battle-lanes { display: flex; gap: .45rem; }

/* Six pieces do not fit one comfortable row below tablet width, so the roster
   wraps into two rows of three rather than shrinking every card past reading
   size. flex-basis 30% is what forces the 3 + 3 break. */
.battle-roster { flex-wrap: wrap; }
.battle-card { flex: 1 1 14%; min-width: 8.5rem; }

.battle-card,
.battle-lane {
    flex: 1 1 0;
    min-width: 0;
    display: flex;
    flex-direction: column;
    align-items: flex-start;
    gap: .12rem;
    padding: .45rem .5rem;
    border: 1px solid rgba(140, 160, 220, .22);
    border-radius: 8px;
    background: rgba(10, 14, 28, .9);
    color: inherit;
    font-family: var(--font-main);
    text-align: left;
    cursor: default;
    transition: border-color var(--transition-fast), opacity var(--transition-fast);
}

.battle-card-glyph { font-size: 1.1rem; line-height: 1; }
.battle-card-name { font-size: .58rem; letter-spacing: .12em; color: var(--text-secondary); }

.battle-card-role { font-size: .5rem; letter-spacing: .1em; }
.battle-role-attack { color: var(--accent-magenta); }
.battle-role-guard { color: var(--accent-cyan); }

/* The prompt is the largest text in the interface, because it is the only
   text the player is actually reading during a fight. */
.battle-card-word,
.battle-lane-word {
    width: 100%;
    font: 800 1rem var(--font-display);
    letter-spacing: .04em;
    overflow-wrap: anywhere;
}

/* Typed characters are dimmed and the remainder stays bright, so the eye
   tracks forward through the word instead of re-reading it. */
.battle-card-word b,
.battle-lane-word b { color: var(--accent-green); opacity: .55; font-weight: 800; }

.battle-card-hint {
    font-size: .55rem;
    color: var(--text-dim);
    font-style: italic;
    overflow-wrap: anywhere;
}

/* The stat line and the special sit under the prompt, deliberately quieter
   than it: they are reference material the player consults between rounds,
   not something to read while a word is being typed. */
.battle-card-stats {
    font-size: .5rem;
    letter-spacing: .04em;
    color: var(--text-dim);
    font-variant-numeric: tabular-nums;
}

.battle-card-special {
    font-size: .52rem;
    line-height: 1.35;
    color: var(--accent-purple);
    overflow-wrap: anywhere;
}

.battle-card-cooldown { font-size: .58rem; color: var(--accent-orange); font-variant-numeric: tabular-nums; }

.battle-card.is-locked { opacity: .32; }
.battle-card.is-live,
.battle-lane.is-live { border-color: rgba(0, 240, 255, .55); }
.battle-card.is-selected { border-color: var(--accent-magenta); background: rgba(255, 0, 170, .1); }

/* A lane word is readable but clearly inactive until a piece is in hand. */
.battle-lane:not(.is-live) .battle-lane-word { opacity: .45; }
.battle-lane-name { font-size: .58rem; letter-spacing: .14em; color: var(--text-secondary); }
.battle-lane-slot { font-size: .52rem; letter-spacing: .1em; color: var(--accent-cyan); }
.battle-lane.is-full { opacity: .35; }
.battle-lane.is-full .battle-lane-slot { color: var(--accent-red); }

/* The only lane that can reach an exposed base. Marked hard, because nothing
   on the board itself explains why pieces sent elsewhere ignore it. */
.battle-lane.is-assault { border-color: var(--accent-yellow); background: rgba(255, 238, 0, .07); }
.battle-lane.is-assault .battle-lane-slot { color: var(--accent-yellow); font-weight: 800; }

.battle-buffer {
    display: flex;
    align-items: center;
    gap: .1rem;
    min-height: 1.5rem;
    padding: .2rem .5rem;
    border-radius: 6px;
    background: rgba(0, 0, 0, .45);
    font: 800 1.05rem var(--font-display);
    letter-spacing: .12em;
    color: var(--accent-green);
}

.battle-caret {
    display: inline-block;
    width: .55rem;
    height: 1.05rem;
    background: var(--accent-green);
    animation: battlePulse .5s steps(2, end) infinite alternate;
}

/* A mistype has to be felt instantly, before the player reads any message. */
.battle-root.is-fumbled .battle-buffer { background: rgba(255, 34, 68, .3); color: var(--accent-red); }
.battle-root.is-fumbled .battle-caret { background: var(--accent-red); }

.battle-meters {
    display: flex;
    flex-wrap: wrap;
    gap: .9rem;
    font-size: .58rem;
    letter-spacing: .1em;
    color: var(--text-secondary);
}
.battle-meters b { color: var(--text-primary); font-variant-numeric: tabular-nums; }
.battle-hintline { color: var(--accent-orange); }

/* -- Lobby ---------------------------------------------------------------- */

.battle-lobby {
    display: grid;
    place-items: center;
    padding: 1rem;
    background: rgba(3, 5, 12, .86);
    pointer-events: auto;
}
.battle-lobby.hidden { display: none; }

.battle-lobby-card {
    display: flex;
    flex-direction: column;
    gap: .75rem;
    width: min(100%, 32rem);
    padding: 1.4rem;
    border: 1px solid rgba(140, 160, 220, .3);
    border-radius: 12px;
    background: rgba(8, 12, 26, .96);
    text-align: center;
}

.battle-lobby-card h2 { font: 900 1.4rem var(--font-display); letter-spacing: .18em; color: var(--accent-cyan); }
.battle-lobby-copy { font-size: .72rem; line-height: 1.6; color: var(--text-secondary); }

.battle-lobby-actions { display: flex; flex-direction: column; gap: .5rem; }

.battle-button {
    padding: .6rem .9rem;
    border: 1px solid rgba(0, 240, 255, .45);
    border-radius: 8px;
    background: rgba(0, 240, 255, .08);
    color: var(--text-primary);
    font: 800 .78rem var(--font-display);
    letter-spacing: .14em;
    cursor: pointer;
    transition: background var(--transition-fast), border-color var(--transition-fast);
}
.battle-button:hover,
.battle-button:focus-visible { background: rgba(0, 240, 255, .2); border-color: var(--accent-cyan); }

.battle-button-quiet { border-color: rgba(140, 160, 220, .3); background: transparent; }

.battle-join { display: flex; gap: .5rem; }
.battle-join input {
    flex: 1 1 auto;
    min-width: 0;
    padding: .6rem .8rem;
    border: 1px solid rgba(140, 160, 220, .35);
    border-radius: 8px;
    background: rgba(0, 0, 0, .4);
    color: var(--text-primary);
    font: 800 .95rem var(--font-display);
    letter-spacing: .3em;
    text-align: center;
    text-transform: uppercase;
}
.battle-join .battle-button { flex: 0 0 auto; }

.battle-code {
    padding: .7rem;
    border: 1px dashed rgba(0, 240, 255, .5);
    border-radius: 8px;
    font: 900 2.2rem var(--font-display);
    letter-spacing: .4em;
    color: var(--accent-cyan);
    text-indent: .4em;
}

.battle-lobby-status { min-height: 1.1rem; font-size: .68rem; color: var(--accent-yellow); }

/* -- Responsive shifts ----------------------------------------------------
   Only the grid regions move; components keep their flex behaviour.        */

/* Phones: the five-card roster cannot fit one row, so it wraps and the
   hints are dropped rather than shrunk into illegibility. */
@media (max-width: 620px) {
    .battle-overlay { padding: 3.4rem .5rem .5rem; gap: .3rem; }
    .battle-card { flex: 1 1 30%; min-width: 6rem; }
    .battle-card-hint,
    .battle-card-special,
    .battle-card-stats { display: none; }
    .battle-card-word, .battle-lane-word { font-size: .85rem; }
    .battle-clock { font-size: 1.4rem; }
    .battle-match-label { display: none; }
    .battle-topbar { gap: .4rem; }
    .battle-tower-label { font-size: .5rem; }
    .battle-meters { gap: .55rem; }
}

/* Short landscape (a phone turned sideways) has no vertical room for the
   banner row, so it overlaps the board instead of claiming its own band. */
@media (max-height: 560px) {
    .battle-overlay { grid-template-rows: auto auto 0 minmax(0, 1fr) auto auto; }
    .battle-banner { position: relative; z-index: 5; }
    .battle-card-hint,
    .battle-card-special { display: none; }
}

@media (min-width: 1024px) {
    .battle-overlay { padding: 4.2rem 1.6rem 1rem; }
    .battle-console { padding: .8rem 1rem 1rem; }
    .battle-card-word, .battle-lane-word { font-size: 1.15rem; }
}

/* Motion is decorative here; the state is always also carried by colour and
   text, so removing it costs the player nothing. */
@media (prefers-reduced-motion: reduce) {
    .battle-clock.is-urgent,
    .battle-caret,
    .battle-link-dot.is-degraded { animation: none; }
    .battle-banner { transition: none; }
}
