/* hax-lexigon.css — Lexigon play surface styling per LexigonDesign/docs/design.md §11.
   Loaded via @Assets cache-busting from App.razor.

   v1 chunk D.4.a — view-only board, rack, score panel, move history. Interactive layer (drag,
   click-to-place, blank-tile picker) lands in chunk D.4.b/c with additional .lexigon-board-cell
   modifier classes (.is-selectable, .is-target, .is-invalid).

   Mobile-first per design.md §11.1: ~380px portrait baseline, each board cell ~50px so the
   accessible-target threshold is met without zoom. The 7×7 grid + 5-tile rack + score panel
   stack vertically and don't need media queries to scale up — the board centers within its
   container's max-width and the rack inherits the same width.

   Premium-square cues use both background color and a glyph hint (2L / 3L / 2W / 3W) per
   §11.1's "color cue + glyph hint (not relying on color alone)" — survives colorblind viewers
   and the operator preference [[feedback-color-never-sole-indicator]]. */

.lexigon-play {
    display: flex;
    flex-direction: column;
    gap: 16px;
    max-width: 460px;
    margin: 0 auto;
    padding: 12px 8px;
}

.lexigon-play-pregame,
.lexigon-play-terminal,
.lexigon-play-game {
    display: flex;
    flex-direction: column;
    gap: 12px;
}

.lexigon-play-pregame-actions {
    display: flex;
    flex-wrap: wrap;
    gap: 8px;
}

.lexigon-play-header {
    display: flex;
    flex-direction: column;
    gap: 8px;
}

.lexigon-play-scores {
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: 8px;
}

.lexigon-play-score-tile {
    background: var(--mud-palette-surface);
    border: 1px solid var(--mud-palette-divider);
    border-radius: 8px;
    padding: 8px 12px;
    text-align: center;
}

.lexigon-play-score-tile.is-active {
    border-color: var(--mud-palette-primary);
    box-shadow: 0 0 0 2px var(--mud-palette-primary-hover);
}

.lexigon-play-score-name {
    font-size: 0.85rem;
    color: var(--mud-palette-text-secondary);
}

.lexigon-play-score-value {
    font-size: 1.6rem;
    font-weight: 700;
    line-height: 1.2;
}

.lexigon-play-status {
    display: flex;
    justify-content: space-between;
    align-items: center;
    flex-wrap: wrap;
    gap: 8px;
}

.lexigon-play-status-badge {
    font-weight: 600;
    padding: 4px 10px;
    border-radius: 999px;
    font-size: 0.9rem;
}

.lexigon-play-status-badge.turn-you {
    background: var(--mud-palette-primary);
    color: var(--mud-palette-primary-text);
}

.lexigon-play-status-badge.turn-opp {
    background: var(--mud-palette-surface);
    border: 1px solid var(--mud-palette-divider);
    color: var(--mud-palette-text-secondary);
}

.lexigon-play-status-badge.win {
    background: var(--mud-palette-success);
    color: var(--mud-palette-success-text);
}

.lexigon-play-status-badge.loss {
    background: var(--mud-palette-surface);
    border: 1px solid var(--mud-palette-divider);
    color: var(--mud-palette-text-secondary);
}

.lexigon-play-meta {
    font-size: 0.8rem;
    color: var(--mud-palette-text-secondary);
}

.lexigon-play-decisive {
    font-style: italic;
    color: var(--mud-palette-text-secondary);
}

/* 7×7 board grid. */
.lexigon-board {
    display: flex;
    flex-direction: column;
    gap: 2px;
    background: var(--mud-palette-divider);
    padding: 2px;
    border-radius: 6px;
}

.lexigon-board-row {
    display: grid;
    grid-template-columns: repeat(7, 1fr);
    gap: 2px;
    /* clip any subpixel overflow — defense-in-depth against the 2026-06-01 row-2
       overflow bug where webkit let min-content from premium-square glyphs push a
       row past the board frame on narrow iPhone viewports. */
    overflow: hidden;
}

.lexigon-board-cell {
    /* box-sizing: border-box so .has-tile's padding lives INSIDE the grid track instead of
       expanding the cell's rendered size — without this, the 1px padding extends the cell
       2px wider than its track and eats both grid gaps on adjacent placed-tile cells, so
       consecutive tiles visually touch (UAT regression noticed 2026-05-31 after the 05-30
       tan-empty-cell palette change made the gap visible). */
    box-sizing: border-box;
    /* min-width:0 / min-height:0 overrides the grid-item default of min-width:auto
       (== min-content). Without this, premium-square glyph cells ("3L"/"3W") can demand
       more space than their 1fr track allocates, and webkit lets the row overflow rather
       than shrinking the cells — caused the 2026-06-01 row-2-overflow bug on narrow iPhone
       viewports after orientation change. */
    min-width: 0;
    min-height: 0;
    aspect-ratio: 1 / 1;
    background: #e8d5a8;                /* light tan empty-cell field — operator palette 2026-05-30 */
    border-radius: 3px;
    display: flex;
    align-items: center;
    justify-content: center;
    font-size: 0.75rem;
    font-weight: 700;
    color: #4a3823;                     /* warm brown for any text against tan */
    user-select: none;
    position: relative;
    /* Container queries — the placed tile's letter + point sizing scales off THIS cell's
       inline size (cqi) instead of a fixed rem, so mobile (~50px cells) and desktop (~65px
       cells) both render the letter at the same proportion. Operator 2026-05-30 squish fix. */
    container-type: inline-size;
}

/* Premium palette — all shades of green per operator design 2026-05-30. Intensity ladder
   preserved: DL (lightest) → TL (deeper letter) and DW (light) → TW (deepest). */
.lexigon-board-cell.is-dl { background: #c8e6c9; color: #1b5e20; }   /* pale sage */
.lexigon-board-cell.is-tl { background: #2e7d32; color: #fff; }      /* medium emerald */
.lexigon-board-cell.is-dw { background: #a5d6a7; color: #1b5e20; }   /* spring green */
.lexigon-board-cell.is-tw { background: #1b5e20; color: #fff; }      /* deep forest */

.lexigon-board-cell.is-start {
    background: linear-gradient(135deg, #a5d6a7, #81c784);
    color: #1b5e20;
}

.lexigon-board-cell.is-last-move {
    outline: 2px solid var(--mud-palette-warning);
    outline-offset: -2px;
}

.lexigon-board-cell.has-tile {
    background: transparent;
    color: inherit;
    padding: 1px;
}

.lexigon-board-cell.is-click-target {
    cursor: pointer;
}

.lexigon-board-cell.is-click-target:hover {
    outline: 2px dashed var(--mud-palette-primary);
    outline-offset: -2px;
}

.lexigon-board-cell.is-staged {
    outline: 2px solid var(--mud-palette-primary);
    outline-offset: -2px;
}

.lexigon-board-cell.is-staged .lexigon-tile {
    background: linear-gradient(180deg, #fff8e0, #f0e0a8);
    border-color: var(--mud-palette-primary);
}

.lexigon-board-start-mark {
    font-size: 1.4rem;
    opacity: 0.6;
}

.lexigon-board-premium-glyph {
    font-size: 0.65rem;
    letter-spacing: 0.5px;
}

/* Tile glyph — used both on the board (placed tiles) and in the rack. The width:100% on .lexigon-tile
   inside a board cell makes it fill the cell; in the rack the .lexigon-rack-tile wrapper sizes it. */
.lexigon-tile {
    /* box-sizing: border-box so the 1px border is included in the 100% width/height — without
       it the tile renders 2px larger than its parent cell's content area, contributing to the
       2026-05-31 board-gap eating regression (see .lexigon-board-cell note). */
    box-sizing: border-box;
    width: 100%;
    height: 100%;
    background: linear-gradient(180deg, #fdf6e3, #f5ecd3);
    border: 1px solid #c9b89a;
    border-radius: 3px;
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    color: #2a2a2a;
    font-family: "Segoe UI", system-ui, sans-serif;
    position: relative;
    box-shadow: 0 1px 0 rgba(0, 0, 0, 0.08);
}

.lexigon-tile.is-blank {
    background: linear-gradient(180deg, #fffefa, #f4eed8);
    font-style: italic;
}

.lexigon-tile-letter {
    /* 55% of the containing cell's inline size — scales naturally between mobile + desktop.
       The rack-scoped override below uses an explicit rem since rack tiles are uniform. */
    font-size: 55cqi;
    font-weight: 700;
    line-height: 1;
}

.lexigon-tile-points {
    font-size: 20cqi;                   /* ~22% of cell — keeps the subscript readable but not crowding the letter */
    font-weight: 700;
    position: absolute;
    bottom: 2px;
    right: 3px;
    color: #000;                        /* black — operator 2026-05-30; was mud-palette-text-secondary which renders near-invisible on the cream tile */
}

/* Rack — 5 fixed slots whether filled or not so the layout doesn't reflow as the rack drains.
   width:100% added 2026-05-30 — without it the grid shrink-wraps to its inner content (button
   intrinsic size), collapsing rack tiles to ~25px squares. The max-width caps things on desktop;
   tightened from 320px → 240px per operator 2026-05-30 (rack tiles read about one size smaller
   than board-placed tiles, mirroring real Scrabble-tile-in-rack proportions). */
/* The rack and its shuffle, side by side. Wraps rather than squeezing: on a narrow phone the
   button drops under the rack instead of stealing width from the tiles. */
.lexigon-rack-row {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    justify-content: center;
    gap: 0.5rem;
}

.lexigon-rack {
    display: grid;
    grid-template-columns: repeat(5, 1fr);
    gap: 4px;
    width: 100%;
    max-width: 240px;
    margin: 0 auto;
}

/* Deliberately quiet (operator 2026-08-29): borderless, dimmed until you go near it. It sits beside
   six action buttons that all end or commit a turn, and this one only rearranges what you are
   looking at — it should not compete with them for attention. Icon-only, so the accessible name
   lives on the button's aria-label. */
.lexigon-rack-shuffle {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    flex: none;
    padding: 0.35rem;
    border: none;
    border-radius: 6px;
    background: transparent;
    color: var(--mud-palette-text-secondary);
    cursor: pointer;
    opacity: 0.65;
    transition: opacity 120ms ease, color 120ms ease;
}

.lexigon-rack-shuffle:hover:not([disabled]),
.lexigon-rack-shuffle:focus-visible {
    opacity: 1;
    color: var(--mud-palette-primary);
}

.lexigon-rack-shuffle[disabled] {
    opacity: 0.25;
    cursor: default;
}

/* Tap target stays finger-sized even though the glyph is small (§iOS: 44px is the floor). */
@media (hover: none) {
    .lexigon-rack-shuffle {
        padding: 0.65rem;
        opacity: 0.8;
    }
}

/* Scope the letter + point-value font sizes inside the rack to the smaller rack-tile footprint.
   Board-placed tiles use container-query sizing (55cqi / 20cqi) off their cell; the rack uses
   absolute rems because rack tiles share one rack-wide width and don't need to scale per-tile. */
.lexigon-rack .lexigon-tile-letter {
    font-size: 1.6rem;
}

.lexigon-rack .lexigon-tile-points {
    font-size: 0.55rem;
}

.lexigon-rack-tile {
    aspect-ratio: 1 / 1;
    border-radius: 4px;
    padding: 0;
    border: none;
    background: none;
    /* Container — the rack-tile itself is the sizing base when the tile lives outside .lexigon-rack
       (e.g. the Exchange overlay's tile picker). Without this, the base .lexigon-tile-letter cqi
       falls back to viewport units and renders the letter ~3x the tile size. Operator 2026-05-30. */
    container-type: inline-size;
}

.lexigon-rack-tile.is-empty {
    background: var(--mud-palette-divider);
    opacity: 0.4;
}

.lexigon-rack-tile.is-view-only .lexigon-tile {
    opacity: 0.85;
}

.lexigon-rack-tile.is-clickable {
    cursor: pointer;
}

.lexigon-rack-tile.is-clickable[disabled] {
    cursor: default;
    opacity: 0.4;
}

.lexigon-rack-tile.is-clickable .lexigon-tile {
    transition: transform 80ms ease-out, box-shadow 80ms ease-out;
}

.lexigon-rack-tile.is-clickable:hover:not([disabled]) .lexigon-tile {
    transform: translateY(-2px);
    box-shadow: 0 4px 6px rgba(0, 0, 0, 0.15);
}

.lexigon-rack-tile.is-selected .lexigon-tile {
    /* Strong "this tile is armed" signal — operator 2026-05-30. Was a 3px lift + thin primary
       ring that read as a subtle hover state, not a selection. Now: bigger lift, mint-green
       tint replacing the cream face, thicker primary ring + deeper shadow. The letter (#2a2a2a)
       stays readable against the tint. */
    transform: translateY(-6px);
    background: linear-gradient(180deg, #b8ecc8, #8fdca0);
    border-color: var(--mud-palette-primary);
    box-shadow: 0 0 0 3px var(--mud-palette-primary), 0 6px 10px rgba(0, 0, 0, 0.3);
}

.lexigon-rack-tile.is-staged .lexigon-tile {
    opacity: 0.35;
}

.lexigon-play-submit-error {
    grid-column: 1 / -1;
    width: 100%;
}

/* Actions strip + history. */
.lexigon-play-actions {
    display: flex;
    justify-content: center;
    gap: 8px;
    flex-wrap: wrap;
}

.lexigon-play-history {
    background: var(--mud-palette-surface);
    border: 1px solid var(--mud-palette-divider);
    border-radius: 6px;
    padding: 8px 12px;
}

.lexigon-play-history-empty {
    text-align: center;
    color: var(--mud-palette-text-secondary);
    font-style: italic;
}

.lexigon-play-history > summary {
    cursor: pointer;
    font-weight: 600;
    color: var(--mud-palette-text-primary);
}

/* HAX-00006: once the list outgrows max-height the scrollbar arrives INSIDE the padding box, so
   with padding:0 the scores and the per-word breakdown sat flush against it. The gutter keeps
   that space reserved whether or not the bar is showing, so the rows don't shift sideways the
   moment a match gets long enough to scroll. */

.lexigon-play-history-list {
    margin: 8px 0 0 0;
    padding: 0 10px 0 2px;
    list-style: none;
    max-height: 200px;
    overflow-y: auto;
    scrollbar-gutter: stable;
}

.lexigon-play-history-entry {
    display: grid;
    grid-template-columns: auto 1fr auto auto;
    gap: 8px;
    padding: 4px 0;
    border-bottom: 1px solid var(--mud-palette-divider);
    font-size: 0.85rem;
}

.lexigon-play-history-entry:last-child {
    border-bottom: none;
}

.lexigon-play-history-num {
    color: var(--mud-palette-text-secondary);
}

.lexigon-play-history-who {
    font-weight: 600;
}

.lexigon-play-history-score {
    color: var(--mud-palette-primary);
    font-weight: 600;
}

/* The end-of-game rack settlement (operator 2026-08-29). Sits at the top of the reversed list,
   which is where it happened - after the last move. Marked off with a rule above rather than a
   colour, so it reads as a different KIND of row and not just an emphasised one. */
.lexigon-play-history-entry.is-endgame {
    border-top: 1px solid var(--mud-palette-divider);
    border-bottom: none;
}

.lexigon-play-history-entry.is-endgame + .lexigon-play-history-entry:not(.is-endgame) {
    border-top: 1px solid var(--mud-palette-divider);
}

/* The minus sign is what says "deduction"; the colour only reinforces it. */
.lexigon-play-history-score.is-penalty {
    color: var(--mud-palette-warning);
}

/* HAX-00009: the power a turn spent, as a chip left of the word. Takes the same deep violet as the
   armed-power bar so "a power was involved" is one colour across the surface, rather than the
   history inventing its own. Sits inline with the play text and never wraps mid-name — a chip that
   breaks across two lines stops reading as a chip. */

.lexigon-play-history-power {
    display: inline-block;
    margin-right: 0.4rem;
    padding: 0.05rem 0.4rem;
    border-radius: 4px;
    background: #2A0E45;
    border: 1px solid #4C1D95;              /* violet-900 — matches .lexigon-power-bar */
    color: #E879F9;                         /* fuchsia-400 — matches the bar's power name */
    font-size: 0.72rem;
    font-weight: 600;
    white-space: nowrap;
    vertical-align: baseline;
}

/* Per-word arithmetic under a multi-word play (HAX-00002). Spans from the player-name column to
   the end so it reads as a continuation of the line above rather than a new entry, and wraps
   instead of stretching the grid — a 4-word play on a phone would otherwise force a horizontal
   scrollbar onto the whole history list. */

.lexigon-play-history-breakdown {
    grid-column: 2 / -1;
    text-align: right;
    color: var(--mud-palette-text-secondary);
    font-size: 0.78rem;
    line-height: 1.45;
    overflow-wrap: anywhere;
}

/* Action-menu overlays — blank-tile picker, exchange picker, pass + resign confirms.
   Full-viewport backdrop centered over the play surface; the inner card stops click
   propagation so taps inside don't dismiss. Bottom-sheet style on small viewports for
   thumb-reach finger affordance per design.md §11.1. */

.lexigon-overlay {
    position: fixed;
    inset: 0;
    background: rgba(0, 0, 0, 0.45);
    display: flex;
    align-items: center;
    justify-content: center;
    z-index: 1000;
    padding: 16px;
}

.lexigon-overlay-card {
    background: var(--mud-palette-background);
    color: var(--mud-palette-text-primary);
    border-radius: 10px;
    padding: 16px;
    max-width: 360px;
    width: 100%;
    display: flex;
    flex-direction: column;
    gap: 8px;
    box-shadow: 0 8px 24px rgba(0, 0, 0, 0.3);
}

.lexigon-overlay-hint {
    color: var(--mud-palette-text-secondary);
}

.lexigon-overlay-actions {
    display: flex;
    justify-content: flex-end;
    gap: 8px;
    margin-top: 8px;
}

.lexigon-blank-picker-grid {
    display: grid;
    grid-template-columns: repeat(7, 1fr);
    gap: 6px;
    margin-top: 8px;
}

.lexigon-blank-picker-letter {
    aspect-ratio: 1 / 1;
    border: 1px solid var(--mud-palette-divider);
    background: var(--mud-palette-surface);
    color: var(--mud-palette-text-primary);
    font-size: 1.1rem;
    font-weight: 700;
    border-radius: 4px;
    cursor: pointer;
}

.lexigon-blank-picker-letter:hover {
    background: var(--mud-palette-primary);
    color: var(--mud-palette-primary-text);
    border-color: var(--mud-palette-primary);
}

.lexigon-exchange-row {
    display: grid;
    grid-template-columns: repeat(5, 1fr);
    gap: 6px;
    margin-top: 8px;
}

/* Force End panel — Dev/Staging-only per design.md §14.1. Visually fenced from the live play
   controls so the operator's eye reads the pipeline-test affordance separately from real-play
   actions and never confuses it with a regular Resign. */

.lexigon-force-end-panel {
    margin-top: 12px;
    padding: 12px;
    background: var(--mud-palette-surface);
    border: 1px dashed var(--mud-palette-warning);
    border-radius: 8px;
    display: flex;
    flex-direction: column;
    gap: 8px;
}

.lexigon-force-end-header {
    display: flex;
    align-items: center;
    gap: 8px;
}

.lexigon-force-end-pill {
    background: var(--mud-palette-warning);
    color: var(--mud-palette-warning-text);
    font-size: 0.7rem;
    font-weight: 700;
    padding: 2px 8px;
    border-radius: 999px;
    letter-spacing: 0.05em;
    text-transform: uppercase;
}

.lexigon-force-end-title {
    font-weight: 600;
    color: var(--mud-palette-text-primary);
}

.lexigon-force-end-hint,
.lexigon-force-end-followup {
    margin: 0;
    font-size: 0.8rem;
    color: var(--mud-palette-text-secondary);
}

.lexigon-force-end-buttons {
    display: flex;
    gap: 8px;
    flex-wrap: wrap;
}

/* Stats cards CSS — used by LexigonStatsComponent. */
.lexigon-stats {
    display: flex;
    flex-direction: column;
    gap: 12px;
}

.lexigon-stats-grid {
    display: flex;
    flex-direction: column;
    gap: 16px;
}

.lexigon-stats-event-title {
    margin: 0 0 8px 0;
    font-size: 1.05rem;
    font-weight: 600;
}

.lexigon-stats-stats {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(120px, 1fr));
    gap: 8px;
    margin: 0 0 12px 0;
    padding: 0;
}

.lexigon-stats-stats > div {
    background: var(--mud-palette-surface);
    border: 1px solid var(--mud-palette-divider);
    border-radius: 6px;
    padding: 8px 12px;
}

.lexigon-stats-stats dt {
    margin: 0;
    font-size: 0.75rem;
    color: var(--mud-palette-text-secondary);
    text-transform: uppercase;
    letter-spacing: 0.05em;
}

.lexigon-stats-stats dd {
    margin: 2px 0 0 0;
    font-size: 1.3rem;
    font-weight: 700;
}

.lexigon-stats-scoring dd {
    color: var(--mud-palette-primary);
}

.lexigon-stats-empty {
    color: var(--mud-palette-text-secondary);
    font-style: italic;
    text-align: center;
}

/* ============================================================================
   Lexigon Prime — the Power Point layer (LexigonPrimeDesign/docs/design.md §8)
   Nothing here renders on Classic; the component gates every element on IsPrime.
   ============================================================================ */

/* Quadruple premiums exist only after Tile Bump raises a square. They continue the
   existing green intensity ladder rather than introducing a new hue — a 4W is a
   louder 3W, not a different kind of square. */
.lexigon-board-cell.is-ql { background: #1b5e20; color: #fff; }
.lexigon-board-cell.is-qw { background: #0b3d0f; color: #fff; }

/* A bumped square carries a corner notch as well as its raised "4W" glyph, so the
   upgrade is legible without relying on the shade difference alone. */
.lexigon-board-cell.is-bumped::after {
    content: "▲";
    position: absolute;
    top: 1px;
    right: 2px;
    font-size: 0.5rem;
    line-height: 1;
    color: currentColor;
    opacity: 0.85;
}

/* Squares Tile Bump can legally take while it's armed. */
.lexigon-board-cell.is-bump-target {
    outline: 2px dashed var(--mud-palette-primary);
    outline-offset: -2px;
    cursor: pointer;
}

/* LexHelp's answer — one square, pulsing, no word attached. */
/* LexHelp's answer. Purple, and it repaints the square rather than outlining it (operator
   2026-08-20): the first cut was a lime outline, which is a green edge on a green-and-tan board —
   and worse, it pulsed to TRANSPARENT, so half of every cycle the one square the player paid to be
   shown wasn't marked at all. It now stays fully marked and the pulse only varies the glow. */
.lexigon-board-cell.is-lexhelp-hint {
    background: #D8B4FE;                    /* purple-300 — replaces the tan, so it reads at a glance */
    color: #3B0764;                         /* purple-950 — keeps a premium glyph legible on it */
    outline: 3px solid #A855F7;             /* purple-500 */
    outline-offset: -3px;
    animation: lexigon-hint-pulse 1.4s ease-in-out infinite;
}

@keyframes lexigon-hint-pulse {
    0%, 100% { box-shadow: 0 0 5px 1px rgba(168, 85, 247, 0.55); }
    50%      { box-shadow: 0 0 14px 4px rgba(168, 85, 247, 0.95); }
}

/* Reduced motion still gets a fully-marked square — the glow just doesn't breathe. */
@media (prefers-reduced-motion: reduce) {
    .lexigon-board-cell.is-lexhelp-hint {
        box-shadow: 0 0 10px 2px rgba(168, 85, 247, 0.8);
    }
}

@media (prefers-reduced-motion: reduce) {
    .lexigon-board-cell.is-lexhelp-hint { animation: none; }
}

/* Rack tiles picked to go back to the bag under Rack Refresh. */
.lexigon-rack-tile.is-returning .lexigon-tile {
    opacity: 0.55;
    outline: 2px dashed var(--mud-palette-warning);
    outline-offset: -2px;
}

/* The Power Bank bar — persistent, directly under the board. */
/* The bank bar takes the armed-power bar's deep-violet panel (operator 2026-08-29). The two are the
   only Power-Point chrome on the surface — one says what you HAVE, one says what you are SPENDING —
   so wearing different clothes made them read as unrelated widgets. Metrics are `.lexigon-power-bar`
   verbatim; keep them in step if either moves. */
.lexigon-power-bank {
    display: flex;
    align-items: center;
    flex-wrap: wrap;
    gap: 0.6rem;
    margin-top: 0.5rem;
    padding: 0.6rem 0.8rem;
    border: 1px solid #4C1D95;              /* violet-900 - present but not a drawn line */
    border-radius: 6px;
    background: #2A0E45;                    /* deep violet, darker than the page */
    font-weight: 600;
}

.lexigon-power-pips {
    display: inline-flex;
    gap: 0.15rem;
    font-size: 0.95rem;
    line-height: 1;
}

.lexigon-power-pip.is-filled { color: var(--mud-palette-primary); }
.lexigon-power-pip.is-empty  { color: var(--mud-palette-text-disabled); }

/* On the violet panel the page's emerald and grey both go muddy, so the pips take the bar's own
   accent. Scoped to the bank: the same pip markup also draws the powers modal's head, which sits on
   the green overlay card and still wants the default pair. */
.lexigon-power-bank .lexigon-power-pip.is-filled { color: #E879F9; }                     /* fuchsia-400 */
.lexigon-power-bank .lexigon-power-pip.is-empty  { color: rgba(233, 213, 255, 0.38); }   /* purple-200, dimmed */

/* The pips are shape + colour; the count is the text that carries the same fact,
   because colour is never the sole status indicator. */
.lexigon-power-label {
    font-size: 0.8rem;
    font-weight: 600;
    color: #F5F3FF;                         /* violet-50, matching the bar's prompt */
    margin-right: auto;
}

/* Powers is the bank's one control, so it takes the panel's light purple rather than the emerald
   the page uses elsewhere - the same move the armed bar makes with Cancel. */
.lexigon-power-bank .mud-button-root.mud-button-outlined:not([disabled]) {
    color: #E9D5FF;                         /* purple-200 */
    border-color: #6D28D9;                  /* violet-700 */
    font-weight: 600;
}

.lexigon-power-bank .mud-button-root.mud-button-outlined:not([disabled]):hover {
    background: rgba(233, 213, 255, 0.08);
    border-color: #A855F7;                  /* purple-500 */
}

.lexigon-power-bank .mud-button-root.mud-button-outlined[disabled] {
    color: rgba(233, 213, 255, 0.35);
    border-color: rgba(109, 40, 217, 0.45);
}

/* The description bar — above the board (HAX-00008, operator mock 2026-08-27).
   A filled deep-violet panel: the armed power's name in bright fuchsia, the prompt in near-white,
   Cancel on the right in light purple.

   This IS the treatment that was tried and walked back on 2026-08-20 — but it lands now for a
   reason that did not hold then. The earlier version borrowed the page's own violet at low
   contrast, so it competed with a green board on the same footing and read as clutter. This one
   goes DARKER than the page rather than brighter, which reads as a distinct surface — the board
   stays the loud thing while the bar is unmistakably its own object. The lesson from the first
   attempt still stands; it was about contrast direction, not about filling the panel. */

/* Geometry is ArmadaOne's `.armadaone-banner` verbatim — same padding, radius, border weight and
   type weight — because the operator's mock was that bar recoloured, not a new shape. Only the
   palette differs: ArmadaOne fills near-black navy against a deep-space page, Lexigon fills deep
   violet against a green one. Keeping the metrics identical means the two disciplines' armed-power
   surfaces read as the same component wearing different colours, which is what they are. */

.lexigon-power-bar {
    display: flex;
    align-items: center;
    flex-wrap: wrap;
    gap: 0.6rem;
    margin-bottom: 0.5rem;
    padding: 0.6rem 0.8rem;
    background: #2A0E45;                    /* deep violet, darker than the page */
    border: 1px solid #4C1D95;              /* violet-900 — present but not a drawn line */
    border-radius: 6px;
    font-weight: 600;
}

/* Cancel is part of the bar's copy, so it takes the same light purple rather than the emerald the
   page uses for text buttons elsewhere. */
.lexigon-power-bar .mud-button-root.mud-button-text {
    color: #E9D5FF;                         /* purple-200 */
    font-weight: 600;
}

.lexigon-power-bar-name {
    font-size: 0.8rem;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: 0.06em;
    color: #E879F9;                        /* fuchsia-400 — the accent that carries the panel */
}

/* Near-white, not purple: the prompt is the instruction the player has to act on, so it gets the
   highest contrast in the bar. The name beside it is the label, and labels can afford colour. */
.lexigon-power-bar-prompt {
    font-size: 0.9rem;
    color: #F5F3FF;                        /* violet-50 */
    margin-right: auto;
}

/* The powers modal — rides the shared .lexigon-overlay scrim.

   HAX-00010: rebuilt to ArmadaOne's Command Powers shape (operator 2026-08-27) — titled head with
   the bank on the right, a deck of glyph + name + cost + blurb rows, full-width Cancel. Metrics are
   `.armadaone-modal` and `.armadaone-power` verbatim; only the palette differs, the same way the
   armed-power bar does. Two disciplines, one component, different clothes. */

.lexigon-powers-card {
    width: 100%;
    max-width: 24rem;
    max-height: calc(100dvh - 2rem);
    overflow-y: auto;
    padding: 0.9rem;
    display: flex;
    flex-direction: column;
    gap: 0.75rem;
    box-shadow: 0 10px 44px rgba(0, 0, 0, 0.7);
}

.lexigon-powers-head {
    display: flex;
    align-items: center;
    justify-content: space-between;

    /* Holds the gap the cut hint line used to open up (operator 2026-08-29 — "remove the text but
       keep the spacing"). Without it the card's 0.75rem flex gap puts the first power row directly
       under the title and the head stops reading as a header. */
    margin-bottom: 0.5rem;
}

.lexigon-powers-title {
    font-weight: 700;
    letter-spacing: 0.5px;
}

.lexigon-powers-bank {
    letter-spacing: 2px;
}

/* Full-width, matching .armadaone-modal-cancel — the last thing in the sheet, and the one control
   that is always available. */
.lexigon-powers-cancel {
    width: 100%;
    padding: 0.5rem 0.9rem;
    border: 1px solid var(--mud-palette-divider);
    border-radius: 6px;
    background: var(--mud-palette-surface);
    color: inherit;
    font: inherit;
    font-weight: 600;
    cursor: pointer;
}

.lexigon-powers-cancel:hover:not([disabled]) {
    border-color: #A855F7;                  /* purple-500 */
}

.lexigon-powers-list {
    display: flex;
    flex-direction: column;
    gap: 0.4rem;
}

/* Row is now glyph + body, so the column stack moved down one level into -body. */
.lexigon-power-row {
    display: flex;
    flex-direction: row;
    align-items: flex-start;
    gap: 0.7rem;
    width: 100%;
    text-align: left;
    padding: 0.6rem;
    border: 1px solid var(--mud-palette-divider);
    border-radius: 6px;
    background: var(--mud-palette-surface);
    color: inherit;
    font: inherit;
    cursor: pointer;
}

.lexigon-power-row-glyph {
    display: block;
    flex-shrink: 0;
    line-height: 0;
}

.lexigon-glyph {
    width: 2rem;
    height: 2rem;
    display: block;
}

.lexigon-power-row-body {
    display: flex;
    flex-direction: column;
    align-items: flex-start;
    gap: 0.2rem;
    min-width: 0;
    flex: 1;
}

.lexigon-power-row:hover:not([disabled]) {
    border-color: var(--mud-palette-primary);
}

/* Unaffordable powers stay visible so a player can see what they're saving toward. */
.lexigon-power-row.is-unaffordable {
    opacity: 0.45;
    cursor: not-allowed;
}

.lexigon-power-row-head {
    display: flex;
    align-items: baseline;
    gap: 0.5rem;
}

.lexigon-power-row-name {
    font-weight: 700;
    font-size: 0.9rem;
}

.lexigon-power-row-cost {
    font-size: 0.75rem;
    font-weight: 700;
    color: var(--mud-palette-primary);
    white-space: nowrap;
}

.lexigon-power-row-desc {
    font-size: 0.78rem;
    color: var(--mud-palette-text-secondary);
}

/* Why a power row is greyed out — "you can't afford it" and "it has nothing to do"
   are different facts and the player can only act on one of them. */
.lexigon-power-row-blocked {
    font-size: 0.72rem;
    font-style: italic;
    color: var(--mud-palette-warning);
}

/* HAX-00007: the irreversibility clause on a power that pays out the instant it is armed.
   Amber rather than the purple used elsewhere in this modal — it is a caution, not chrome, and it
   has to survive being read past. Never colour alone: the sentence says "no takebacks" outright. */

.lexigon-power-row-warning {
    font-size: 0.72rem;
    font-weight: 600;
    color: var(--mud-palette-warning);
}

/* Its counterpart on the description bar, standing where Cancel would otherwise be. */

.lexigon-power-bar-locked {
    font-size: 0.78rem;
    font-weight: 600;
    color: var(--mud-palette-warning);
    white-space: nowrap;
}

/* A refused word — informational, not a failure (operator 2026-08-16). ORANGE from 2026-08-27:
   the notice has to say "that placement didn't take" at a glance, and both earlier colours were
   too quiet to do it — indigo (2026-08-20) went flat against a green page, and the purple that
   replaced it separated cleanly but still read as decoration rather than as a stop.

   Orange, specifically NOT the theme's warning amber. That distinction was the whole point of
   moving off yellow in the first place: amber has to keep meaning "something actually broke", and
   a word the dictionary declines is an ordinary part of playing. Since `d959c0f` the two live on
   different surfaces anyway — a refused word is caught client-side and shown inline here, while a
   real failure is still the warning snackbar — so orange can be loud without borrowing amber's
   meaning. Hardcoded like the board palette above: one module's message colour is not a platform
   token. */
.lexigon-play-placement-notice.mud-alert {
    margin-bottom: 0.5rem;
    background: rgba(249, 115, 22, 0.18);   /* orange-500 wash over the dark page ground */
    border-color: #F97316;                  /* orange-500 */
}

/* Light orange on the dark wash — comfortably past AA, and never relying on the colour alone to
   carry the meaning, since the sentence itself names the words that failed. */
.lexigon-play-placement-notice.mud-alert,
.lexigon-play-placement-notice .mud-alert-message,
.lexigon-play-placement-notice .mud-alert-icon .mud-icon-root {
    color: #FFEDD5;                          /* orange-100 */
}

/* Second section inside the dev panel — needs a rule above it so the Power Point controls read
   as their own thing rather than more Force End buttons. */
.lexigon-dev-bank-header {
    margin-top: 0.75rem;
    padding-top: 0.75rem;
    border-top: 1px solid var(--mud-palette-divider);
}

/* Turn notices sit directly above the board (operator 2026-08-20) rather than under the action
   strip, which on a phone is below the fold — a player retyping a word never saw the line telling
   them why the last one bounced. */
.lexigon-play-submit-error {
    margin-bottom: 0.5rem;
}
