/* ============================================================================
   Puzzles — board + answer loop.
   Tokens only (tokens.css). Mobile-first; breakpoints are --bp-* values.
   Prefix pz- so the board can be dropped into Home, Battle Lab or Deck View
   without colliding with those pages' classes.
   ========================================================================= */

.pz-page {
    max-width: var(--page-max-width);
    margin: 0 auto;
    padding: var(--space-6) var(--space-4) var(--space-16);
}

.pz-intro {
    display: flex;
    flex-direction: column;
    gap: var(--space-2);
    margin-bottom: var(--space-6);
}

.pz-intro__title {
    font-family: var(--font-display);
    font-size: var(--font-size-3xl);
    font-weight: 700;
    margin: 0;
}

.pz-intro__lede {
    color: var(--text-muted);
    font-size: var(--font-size-base);
    margin: 0;
    max-width: 60ch;
}

/* ── Header ───────────────────────────────────────────────────────────── */

.pz-header {
    display: flex;
    flex-wrap: wrap;
    gap: var(--space-3);
    align-items: baseline;
    justify-content: space-between;
    margin-bottom: var(--space-3);
}

.pz-header__eyebrow {
    font-size: var(--font-size-xs);
    letter-spacing: 0.12em;
    text-transform: uppercase;
    color: var(--text-faint);
    font-weight: 600;
    margin: 0;
}

.pz-header__aside {
    display: flex;
    align-items: center;
    gap: var(--space-3);
}

.pz-header__score {
    font-size: var(--font-size-sm);
    color: var(--text-muted);
    font-variant-numeric: tabular-nums;
    margin: 0;
}

/* Quiet on purpose: it has to be findable from any position and compete with
   none of them. */
.pz-feedback-open {
    display: inline-flex;
    align-items: center;
    gap: var(--space-1);
    background: none;
    border: none;
    padding: var(--space-1) var(--space-2);
    border-radius: var(--radius-sm);
    color: var(--text-muted);
    font: inherit;
    font-size: var(--font-size-sm);
    cursor: pointer;
}

.pz-feedback-open:hover {
    color: var(--text);
    background: var(--surface-700);
}

.pz-feedback-open:focus-visible {
    outline: 2px solid var(--brand);
    outline-offset: 2px;
}

.pz-feedback-open .material-symbols-outlined {
    font-size: var(--font-size-lg);
}

/* ── Board ────────────────────────────────────────────────────────────── */

.pz-board {
    background: var(--surface-900);
    border: 1px solid var(--surface-500);
    border-radius: var(--radius-lg);
    overflow: hidden;
}

.pz-side {
    display: grid;
    grid-template-columns: 1fr;
    gap: var(--space-3);
    /* The stat row hangs below its card and the board clips overflow. */
    padding: var(--space-4) var(--space-4) var(--space-8);
    align-items: start;
}

.pz-side + .pz-side {
    border-top: 1px solid var(--surface-500);
}

.pz-side--you {
    background: var(--brand-soft);
}

.pz-side__meta {
    display: flex;
    flex-direction: column;
    gap: var(--space-2);
}

.pz-side__who {
    font-size: var(--font-size-xs);
    letter-spacing: 0.12em;
    text-transform: uppercase;
    font-weight: 700;
    color: var(--text-muted);
}

.pz-side--you .pz-side__who {
    color: var(--brand);
}

.pz-shields {
    display: flex;
    gap: var(--space-1);
}

.pz-pip {
    width: 15px;
    height: 21px;
    border-radius: var(--radius-sm);
    background: var(--brand);
}

.pz-side--opp .pz-pip {
    background: var(--surface-300);
}

.pz-pip.is-gone {
    background: transparent;
    border: 1px solid var(--surface-500);
}

.pz-shields.is-linked .pz-pip {
    box-shadow: 0 0 0 2px var(--brand);
}

.pz-side__alarm {
    color: var(--status-danger);
    font-weight: 700;
    font-size: var(--font-size-xs);
    letter-spacing: 0.08em;
    text-transform: uppercase;
}

.pz-side__counts {
    display: flex;
    gap: var(--space-4);
    font-size: var(--font-size-xs);
    color: var(--text-muted);
    font-variant-numeric: tabular-nums;
}

.pz-count__label {
    margin-right: var(--space-1);
}

.pz-count__value {
    color: var(--text);
}

/* ── Base ─────────────────────────────────────────────────────────────── */

/* The Base sits in front of the shields and takes battle damage first, so it
   is drawn as a card next to them rather than folded into the counts row. */
.pz-basezone {
    display: flex;
    align-items: center;
    gap: var(--space-2);
}

.pz-basezone__label,
.pz-basezone__empty {
    font-size: var(--font-size-xs);
    color: var(--text-faint);
}

.pz-basezone__label {
    letter-spacing: 0.1em;
    text-transform: uppercase;
}

.pz-base {
    position: relative;
    width: 46px;
    height: 64px;
    border-radius: var(--radius-sm);
    background: var(--surface-700);
    border: 1px solid var(--surface-500);
}

.pz-base__art {
    width: 100%;
    height: 100%;
    object-fit: cover;
    border-radius: var(--radius-sm);
    display: block;
}

/* The starting EX Base has no printed card, so there is no art to load. */
.pz-base__placeholder {
    width: 100%;
    height: 100%;
    border-radius: var(--radius-sm);
    background: var(--gradient-surface-dark);
    border: 1px dashed var(--surface-400);
    display: flex;
    align-items: center;
    justify-content: center;
    padding: var(--space-1);
    text-align: center;
    font-size: 9px;
    font-weight: 600;
    line-height: 1.2;
    color: var(--text-muted);
}

/* Kept inside the card, unlike a unit's: the base sits in a tight meta column
   where a hanging stat row would collide with the shield pips. */
.pz-base__stats {
    position: absolute;
    left: 0;
    right: 0;
    bottom: 2px;
    display: flex;
    justify-content: center;
    font-size: var(--font-size-xs);
    font-weight: 700;
    font-variant-numeric: tabular-nums;
}

.pz-base.is-linked {
    outline: 3px solid var(--brand);
    outline-offset: 3px;
}

/* ── Units ────────────────────────────────────────────────────────────── */

.pz-field {
    display: flex;
    flex-wrap: wrap;
    gap: var(--space-2);
    min-height: 128px;
}

.pz-field__empty {
    color: var(--text-faint);
    font-size: var(--font-size-sm);
    align-self: center;
}

.pz-slot {
    width: 128px;
    height: 128px;
    display: flex;
    align-items: center;
    justify-content: center;
}

.pz-unit {
    width: 82px;
    height: 114px;
    position: relative;
    border-radius: var(--radius-sm);
    background: var(--surface-700);
    border: 1px solid var(--surface-500);
}

.pz-unit__art,
.pz-unit__pilot {
    width: 100%;
    height: 100%;
    object-fit: cover;
    border-radius: var(--radius-sm);
    display: block;
}

.pz-unit__art {
    position: relative;
    z-index: 1;
}

/* Tokens are made by card effects, so they have no printed card to show. */
.pz-unit__token {
    position: relative;
    z-index: 1;
    width: 100%;
    height: 100%;
    border-radius: var(--radius-sm);
    background: var(--gradient-surface-dark);
    border: 1px dashed var(--surface-400);
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: var(--space-1);
    padding: var(--space-2);
    text-align: center;
}

.pz-unit__token-kind {
    font-size: 9px;
    letter-spacing: 0.1em;
    text-transform: uppercase;
    color: var(--text-faint);
}

.pz-unit__token-name {
    font-size: var(--font-size-xs);
    font-weight: 600;
    color: var(--text-muted);
    line-height: 1.2;
}

/* A paired Pilot sits under its Unit on a real table, and the Unit's AP/HP
   already fold the Pilot's numbers in — drawing the Unit alone shows a stat
   line its own card art contradicts. */
.pz-unit__pilot {
    position: absolute;
    z-index: 0;
    left: -14px;
    top: -7px;
    filter: brightness(0.62) saturate(0.7);
    box-shadow: var(--shadow-md);
}

.pz-unit--rested {
    transform: rotate(90deg);
}

.pz-unit--rested .pz-unit__art {
    filter: saturate(0.55) brightness(0.72);
}

.pz-unit--rested .pz-unit__pilot {
    filter: brightness(0.45) saturate(0.5);
}

.pz-unit__stats {
    position: absolute;
    z-index: 2;
    left: -3px;
    right: -3px;
    bottom: -9px;
    display: flex;
    justify-content: center;
    gap: var(--space-1);
    font-size: var(--font-size-xs);
    font-weight: 700;
    font-variant-numeric: tabular-nums;
}

.pz-unit--rested .pz-unit__stats {
    transform: rotate(-90deg);
    transform-origin: center;
    left: 0;
    right: 0;
    bottom: 50px;
}

.pz-stat {
    background: var(--surface-950);
    border: 1px solid var(--surface-500);
    border-radius: var(--radius-sm);
    padding: 3px 5px;
}

.pz-stat--ap {
    color: var(--status-warn);
}

.pz-stat--hp {
    color: var(--status-ok);
}

.pz-stat--hp.is-hurt {
    color: var(--status-danger);
}

.pz-stat--pilot {
    color: var(--brand);
    text-transform: uppercase;
    letter-spacing: 0.06em;
}

.pz-unit__tag {
    position: absolute;
    z-index: 2;
    top: -9px;
    left: 50%;
    transform: translateX(-50%);
    font-size: 9px;
    font-weight: 700;
    letter-spacing: 0.1em;
    text-transform: uppercase;
    padding: 3px 6px;
    border-radius: var(--radius-sm);
    white-space: nowrap;
    background: var(--brand);
    color: var(--surface-950);
}

.pz-unit--rested .pz-unit__tag {
    transform: translateX(-50%) rotate(-90deg);
}

.pz-unit--attacker {
    outline: 2px solid var(--brand);
    outline-offset: 3px;
}

.pz-unit--target {
    outline: 1px dashed var(--surface-400);
    outline-offset: 3px;
}

.pz-unit--linked {
    outline: 3px solid var(--brand);
    outline-offset: 3px;
}

.pz-unit--linked .pz-unit__art {
    filter: none;
}

.pz-unit--answer {
    outline: 3px solid var(--status-ok);
    outline-offset: 3px;
}

.pz-unit--wrong {
    outline: 3px solid var(--status-danger);
    outline-offset: 3px;
}

/* Inside the forgiveness band: worse than the best line, but not a blunder,
   and not drawn as one. */
.pz-unit--close {
    outline: 3px solid var(--status-warn);
    outline-offset: 3px;
}

/* ── Enlarged card ────────────────────────────────────────────────────── */

/* Every drawn card is a button that opens this. At 82-116px the art is a
   recogniser, not a readable card, and Block/Command positions turn on the
   printed text. */
.pz-zoom {
    position: fixed;
    inset: 0;
    z-index: 1000;
    background: rgb(0 0 0 / 0.72);
    display: flex;
    align-items: center;
    justify-content: center;
    padding: var(--space-4);
}

.pz-zoom__panel {
    position: relative;
    max-width: min(96vw, 900px);
    max-height: 92vh;
    overflow-y: auto;
    background: var(--surface-900);
    border: 1px solid var(--surface-500);
    border-radius: var(--radius-lg);
    padding: var(--space-6) var(--space-4) var(--space-4);
    box-shadow: var(--shadow-lg);
}

.pz-zoom__panel:focus-visible,
.pz-zoom__close:focus-visible {
    outline: 2px solid var(--brand);
    outline-offset: 2px;
}

.pz-zoom__close {
    position: absolute;
    top: var(--space-2);
    right: var(--space-2);
    width: 40px;
    height: 40px;
    display: flex;
    align-items: center;
    justify-content: center;
    border: none;
    border-radius: 50%;
    background: var(--surface-700);
    color: var(--text);
    cursor: pointer;
}

.pz-zoom__cards {
    display: flex;
    flex-wrap: wrap;
    gap: var(--space-4);
    justify-content: center;
}

.pz-zoom__card {
    margin: 0;
    display: flex;
    flex-direction: column;
    gap: var(--space-2);
    align-items: center;
}

.pz-zoom__art {
    display: block;
    width: auto;
    max-width: 100%;
    /* Tall enough to read printed text, short enough to leave the caption in
       view on a phone in landscape. */
    max-height: 66vh;
    border-radius: var(--radius-md);
}

.pz-zoom__placeholder {
    width: 240px;
    height: 335px;
    border-radius: var(--radius-md);
    background: var(--gradient-surface-dark);
    border: 1px dashed var(--surface-400);
    display: flex;
    align-items: center;
    justify-content: center;
    padding: var(--space-3);
    text-align: center;
    font-weight: 600;
    color: var(--text-muted);
}

.pz-zoom__caption {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: var(--space-1);
    text-align: center;
}

.pz-zoom__name {
    font-weight: 700;
}

.pz-zoom__detail {
    font-size: var(--font-size-sm);
    color: var(--text-muted);
    font-variant-numeric: tabular-nums;
}

/* Every card advertises that it opens. */
.pz-unit[role="button"],
.pz-base[role="button"],
.pz-hand__card[role="button"] {
    cursor: zoom-in;
}

.pz-unit:focus-visible,
.pz-base:focus-visible,
.pz-hand__card:focus-visible {
    outline: 2px solid var(--brand);
    outline-offset: 3px;
}

/* ── Trash ────────────────────────────────────────────────────────────── */

/* A public zone, so it is on the board for both players. Collapsed by default
   with the count in the summary: the count is what card conditions turn on
   ("10 or more cards in your trash"), the contents matter less often, and two
   open piles would push the actual board off a phone screen. */
/* Its own row under the field rather than a slot in the 168px meta column:
   collapsed it costs one line either way, and expanded it needs the full width
   or a 20-card pile scrolls two thumbnails at a time. */
.pz-trash {
    grid-column: 1 / -1;
    font-size: var(--font-size-xs);
}

.pz-trash__summary {
    display: flex;
    align-items: center;
    gap: var(--space-2);
    cursor: pointer;
    color: var(--text-muted);
    list-style: none;
    width: fit-content;
    padding: var(--space-1) var(--space-2);
    border: 1px solid var(--surface-500);
    border-radius: var(--radius-sm);
}

.pz-trash__summary::-webkit-details-marker {
    display: none;
}

.pz-trash__summary::after {
    content: 'expand_more';
    font-family: 'Material Symbols Outlined';
    font-size: 16px;
    line-height: 1;
}

.pz-trash[open] .pz-trash__summary::after {
    content: 'expand_less';
}

.pz-trash__summary:focus-visible {
    outline: 2px solid var(--brand);
    outline-offset: 2px;
}

.pz-trash__label {
    letter-spacing: 0.1em;
    text-transform: uppercase;
}

.pz-trash__count {
    color: var(--text);
    font-variant-numeric: tabular-nums;
}

.pz-trash__empty {
    margin: var(--space-2) 0 0;
    color: var(--text-faint);
}

.pz-trash__cards {
    display: flex;
    flex-wrap: wrap;
    gap: var(--space-2);
    margin-top: var(--space-2);
    /* Long piles stay inside the side rather than stretching the board. */
    max-height: 220px;
    overflow-y: auto;
}

.pz-trash__card {
    position: relative;
    width: 52px;
    height: 72px;
    border-radius: var(--radius-sm);
    background: var(--surface-700);
    border: 1px solid var(--surface-500);
}

.pz-trash__card[role="button"] {
    cursor: zoom-in;
}

.pz-trash__card:focus-visible {
    outline: 2px solid var(--brand);
    outline-offset: 3px;
}

.pz-trash__art {
    width: 100%;
    height: 100%;
    object-fit: cover;
    border-radius: var(--radius-sm);
    display: block;
}

.pz-trash__placeholder {
    width: 100%;
    height: 100%;
    border-radius: var(--radius-sm);
    background: var(--gradient-surface-dark);
    border: 1px dashed var(--surface-400);
    display: flex;
    align-items: center;
    justify-content: center;
    padding: 2px;
    text-align: center;
    font-size: 8px;
    font-weight: 600;
    line-height: 1.2;
    color: var(--text-muted);
}

/* Copies are collapsed into one thumbnail, so the multiplier is the only thing
   telling a player how deep the pile really is on that card. */
.pz-trash__x {
    position: absolute;
    right: -4px;
    bottom: -4px;
    min-width: 18px;
    height: 18px;
    padding: 0 3px;
    border-radius: var(--radius-sm);
    background: var(--surface-950);
    border: 1px solid var(--surface-400);
    color: var(--text);
    font-size: 10px;
    font-weight: 700;
    font-variant-numeric: tabular-nums;
    display: flex;
    align-items: center;
    justify-content: center;
}

/* ── What is hidden ───────────────────────────────────────────────────── */

.pz-legend {
    display: flex;
    align-items: center;
    gap: var(--space-2);
    margin: var(--space-2) 0 0;
    font-size: var(--font-size-xs);
    color: var(--text-faint);
}

.pz-legend__icon {
    font-size: 16px;
    line-height: 1;
}

/* ── Hand ─────────────────────────────────────────────────────────────── */

/* Sits under your field, spanning the side, because every one of these
   decisions is read between the two: what is on the board, and what you still
   hold to follow it up with. */
.pz-hand {
    grid-column: 1 / -1;
    display: flex;
    flex-direction: column;
    gap: var(--space-2);
    margin-top: var(--space-3);
    padding-top: var(--space-3);
    border-top: 1px dashed var(--surface-500);
}

.pz-hand__label {
    font-size: var(--font-size-xs);
    letter-spacing: 0.12em;
    text-transform: uppercase;
    font-weight: 700;
    color: var(--text-muted);
}

.pz-hand__cards {
    display: flex;
    flex-wrap: wrap;
    gap: var(--space-2);
}

.pz-hand__card {
    position: relative;
    width: 92px;
    height: 128px;
    border-radius: var(--radius-sm);
    background: var(--surface-700);
    border: 1px solid var(--surface-500);
}

/* Playable, queued, locked. Turn puzzles make the hand a control surface — the
   one-move board leaves these off, so an unadorned hand still renders as before.
   Colour is never the only signal: playable lifts, queued keeps the checkmark
   badge below, locked dims. */
/* The attribute selector above sets `zoom-in`, because on the ONE-MOVE board a
   hand card is only ever something you open. Here a click plays it, so this has
   to out-specify that rule rather than merely follow it. */
.pz-hand__card--playable,
.pz-hand__card--playable[role="button"] {
    cursor: pointer;
    border-color: var(--brand);
}

.pz-hand__card--playable:hover {
    transform: translateY(-3px);
    transition: transform 0.12s ease;
}

.pz-hand__card--queued {
    outline: 2px solid var(--brand);
    outline-offset: 2px;
}

.pz-hand__card--queued::after {
    content: "✓";
    position: absolute;
    top: 2px;
    left: 4px;
    font-size: var(--font-size-sm);
    font-weight: 700;
    color: var(--brand);
    text-shadow: 0 0 3px #000;
}

/* A Pilot is attached, not played, so it reads differently from a queued
   deploy: pairable is a click away, armed is waiting for the Unit you pick
   next, and target marks the queued deploy it may land on. Each carries a shape
   or a badge as well as a colour — the queued checkmark above is the pattern. */
.pz-hand__card--pairable,
.pz-hand__card--pairable[role="button"] {
    cursor: pointer;
    border-color: var(--status-warn);
    border-style: dashed;
}

.pz-hand__card--pairable:hover {
    transform: translateY(-3px);
    transition: transform 0.12s ease;
}

.pz-hand__card--armed {
    outline: 2px dashed var(--status-warn);
    outline-offset: 2px;
}

.pz-hand__card--armed::before {
    content: "→";
    position: absolute;
    top: 2px;
    right: 4px;
    font-size: var(--font-size-sm);
    font-weight: 700;
    color: var(--status-warn);
    text-shadow: 0 0 3px #000;
}

.pz-hand__card--target {
    cursor: pointer;
    outline: 2px solid var(--status-ok);
    outline-offset: 2px;
}

.pz-hand__card--locked {
    opacity: 0.45;
}

/* Why a card is locked, on the card. The tooltip carries the same text, but a
   tooltip is not an answer on touch and not an answer at a glance — and the
   commonest reason (resource LEVEL) is a number printed nowhere on the board. */
.pz-hand__why {
    position: absolute;
    left: 0;
    right: 0;
    bottom: 0;
    padding: 2px 3px;
    background: rgba(0, 0, 0, 0.78);
    color: var(--text);
    font-size: 9px;
    line-height: 1.15;
    text-align: center;
    border-radius: 0 0 var(--radius-sm) var(--radius-sm);
}

.pz-hand__art {
    width: 100%;
    height: 100%;
    object-fit: cover;
    border-radius: var(--radius-sm);
    display: block;
}

.pz-hand__placeholder {
    width: 100%;
    height: 100%;
    border-radius: var(--radius-sm);
    background: var(--gradient-surface-dark);
    border: 1px dashed var(--surface-400);
    display: flex;
    align-items: center;
    justify-content: center;
    padding: var(--space-1);
    text-align: center;
    font-size: var(--font-size-xs);
    font-weight: 600;
    line-height: 1.2;
    color: var(--text-muted);
}

/* The cost is the constraint the whole decision turns on, so it is drawn
   rather than left to the card art a player may not be able to read. */
.pz-hand__cost {
    position: absolute;
    top: -6px;
    left: -6px;
    min-width: 20px;
    height: 20px;
    padding: 0 var(--space-1);
    border-radius: 50%;
    background: var(--surface-950);
    border: 1px solid var(--surface-400);
    color: var(--text);
    font-size: var(--font-size-xs);
    font-weight: 700;
    font-variant-numeric: tabular-nums;
    display: flex;
    align-items: center;
    justify-content: center;
}

.pz-hand__card.is-linked {
    outline: 3px solid var(--brand);
    outline-offset: 3px;
}

/* ── Question and options ─────────────────────────────────────────────── */

.pz-ask {
    margin: var(--space-5) 0 var(--space-3);
    font-size: var(--font-size-lg);
}

.pz-ask b {
    color: var(--brand);
}

.pz-options {
    display: grid;
    gap: var(--space-2);
}

.pz-option {
    display: grid;
    grid-template-columns: 1fr auto;
    align-items: center;
    gap: var(--space-4);
    /* Primary control: stays a comfortable touch target on phones. */
    min-height: 52px;
    background: var(--surface-700);
    border: 1px solid var(--surface-500);
    border-radius: var(--radius-md);
    padding: var(--space-3) var(--space-4);
    cursor: pointer;
    text-align: left;
    width: 100%;
    color: var(--text);
    font: inherit;
    position: relative;
    overflow: hidden;
}

.pz-option:hover:not([aria-disabled="true"]) {
    background: var(--surface-600);
}

.pz-option:focus-visible {
    outline: 2px solid var(--brand);
    outline-offset: 2px;
}

.pz-option[aria-disabled="true"] {
    cursor: default;
}

.pz-option__name {
    font-weight: 600;
    z-index: 1;
}

.pz-option__flag {
    color: var(--text-muted);
    font-size: var(--font-size-xs);
    font-weight: 400;
    margin-left: var(--space-2);
}

/* What the move does on the board. Sits under the option name as a second
   line, so the list reads as a comparison rather than four percentages. */
.pz-option__chip {
    display: block;
    margin-top: 2px;
    font-weight: 400;
    font-size: var(--font-size-xs);
    color: var(--text-muted);
}

.pz-option__rate {
    font-weight: 700;
    font-variant-numeric: tabular-nums;
    z-index: 1;
}

.pz-option__rate--locked {
    color: var(--text-faint);
    display: inline-flex;
    align-items: center;
}

.pz-option__rate--locked .material-symbols-outlined {
    font-size: var(--font-size-base);
}

.pz-option__bar {
    position: absolute;
    inset: 0 auto 0 0;
    width: 0;
    background: var(--brand-soft);
}

/* WHAT THE ENGINE DID, under the option that did it. Only block puzzles carry
   one — attack and command options are mined without a log and leave the stream
   with the move to turn+block.

   Indented and un-bordered on purpose: it is a footnote to the button above it,
   not a second control. Giving it a card of its own made the option list read as
   twice as many choices as it offers. */
.pz-option__log {
    margin: calc(var(--space-1) * -1) 0 var(--space-1) var(--space-4);
    padding-left: var(--space-3);
    border-left: 2px solid var(--border);
}

.pz-option__log--answer {
    border-left-color: var(--status-ok);
}

.pz-option__log-list {
    margin: 0;
    padding-left: var(--space-4);
}

.pz-option__log-list li {
    font-size: var(--font-size-sm);
    color: var(--text-muted);
    padding: 1px 0;
}

.pz-options.is-revealed .pz-option--answer {
    border-color: var(--status-ok);
}

.pz-options.is-revealed .pz-option--answer .pz-option__rate {
    color: var(--status-ok);
}

.pz-options.is-revealed .pz-option--wrong {
    border-color: var(--status-danger);
}

.pz-options.is-revealed .pz-option--wrong .pz-option__rate {
    color: var(--status-danger);
}

.pz-options.is-revealed .pz-option--close {
    border-color: var(--status-warn);
}

.pz-options.is-revealed .pz-option--close .pz-option__rate {
    color: var(--status-warn);
}

@media (prefers-reduced-motion: no-preference) {
    .pz-option__bar {
        transition: width 0.5s cubic-bezier(0.22, 0.61, 0.36, 1);
    }
}

/* ── Verdict, status, empty ───────────────────────────────────────────── */

.pz-verdict {
    margin-top: var(--space-4);
    padding: var(--space-4);
    border-radius: var(--radius-md);
    background: var(--surface-800);
    border: 1px solid var(--surface-500);
}

.pz-verdict--ok {
    border-left: 4px solid var(--status-ok);
}

.pz-verdict--no {
    border-left: 4px solid var(--status-danger);
}

.pz-verdict--close {
    border-left: 4px solid var(--status-warn);
}

.pz-verdict__head {
    display: flex;
    align-items: center;
    gap: var(--space-2);
    font-weight: 700;
    font-size: var(--font-size-lg);
    margin: 0 0 var(--space-2);
}

.pz-verdict--ok .pz-verdict__icon {
    color: var(--status-ok);
}

.pz-verdict--no .pz-verdict__icon {
    color: var(--status-danger);
}

.pz-verdict--close .pz-verdict__icon {
    color: var(--status-warn);
}

/* The one sentence saying what changed on the board. Reads ahead of the
   percentages, which is the order a player asks the question in. */
.pz-verdict__why {
    margin: 0 0 var(--space-2);
    font-weight: 600;
}

.pz-verdict__detail {
    margin: 0 0 var(--space-2);
}

.pz-verdict__cost {
    color: var(--status-danger);
}

/* What other players picked. Muted: it is context, not the lesson. */
.pz-verdict__crowd {
    color: var(--text-muted);
    font-size: var(--font-size-sm);
    margin: 0 0 var(--space-2);
}

.pz-verdict__note {
    color: var(--text-faint);
    font-size: var(--font-size-xs);
    margin: 0 0 var(--space-3);
}

.pz-verdict__streak {
    display: flex;
    align-items: center;
    gap: var(--space-1);
    font-size: var(--font-size-sm);
    font-weight: 600;
    color: var(--status-warn);
    margin: 0 0 var(--space-4);
}

.pz-verdict__streak-icon {
    font-size: var(--font-size-lg);
}

.pz-verdict__actions {
    display: flex;
    flex-wrap: wrap;
    gap: var(--space-2);
}

.pz-status {
    margin-top: var(--space-3);
    color: var(--text-muted);
    font-size: var(--font-size-sm);
    /* The copy-link confirmation carries a full URL. */
    overflow-wrap: anywhere;
}

.pz-status--ok {
    color: var(--status-ok);
}

.pz-status--error {
    color: var(--status-danger);
}

.pz-empty {
    padding: var(--space-8);
    text-align: center;
    color: var(--text-muted);
    background: var(--surface-900);
    border: 1px solid var(--surface-500);
    border-radius: var(--radius-lg);
}

/* ── Archetype filter (T2) ────────────────────────────────────────────────
   Not .filter-select-compact: that component is built for the light filter
   bars (hardcoded px, --neutral-* tokens, white ground) and would read as a
   foreign object on the board's dark surface. */

.pz-filter {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: var(--space-2) var(--space-3);
    margin-top: var(--space-6);
    padding-top: var(--space-4);
    border-top: 1px solid var(--surface-500);
}

.pz-filter__label {
    font-size: var(--font-size-sm);
    font-weight: 600;
    color: var(--text-muted);
}

.pz-filter__select {
    /* Comfortable touch target: this is a control, not a caption. */
    min-height: 44px;
    padding: var(--space-2) var(--space-3);
    background: var(--surface-700);
    border: 1px solid var(--surface-500);
    border-radius: var(--radius-md);
    color: var(--text);
    font: inherit;
    font-size: var(--font-size-sm);
    cursor: pointer;
    max-width: 100%;
}

.pz-filter__select:focus-visible {
    outline: 2px solid var(--brand);
    outline-offset: 2px;
}

.pz-filter__select:disabled {
    cursor: not-allowed;
    color: var(--text-faint);
}

.pz-filter__gate {
    display: inline-flex;
    align-items: center;
    gap: var(--space-2);
    font-size: var(--font-size-sm);
    color: var(--text-muted);
    text-decoration: none;
}

.pz-filter__gate:hover { text-decoration: underline; }

.pz-filter__gate:focus-visible {
    outline: 2px solid var(--brand);
    outline-offset: 2px;
    border-radius: var(--radius-sm);
}

/* ── Feedback modal ───────────────────────────────────────────────────────
   Shell (.modal / .modal-content / .modal-actions) is the shared component in
   components.css; only the fields are local, because the shared form controls
   (.form-control) are the light-theme legacy set and read as a foreign object
   on this surface — the same reason .pz-filter__select exists. */

.pz-feedback__ref {
    margin: 0;
    font-size: var(--font-size-sm);
    color: var(--text-muted);
}

.pz-feedback__ref code {
    color: var(--text);
    font-size: var(--font-size-sm);
}

.pz-feedback__field > label {
    display: block;
    font-size: var(--font-size-sm);
    font-weight: 600;
    color: var(--text);
    margin-bottom: var(--space-2);
}

.pz-feedback__hint {
    font-weight: 400;
    color: var(--text-muted);
}

.pz-feedback__input {
    width: 100%;
    min-height: 44px;
    padding: var(--space-2) var(--space-3);
    background: var(--surface-700);
    border: 1px solid var(--surface-500);
    border-radius: var(--radius-md);
    color: var(--text);
    font: inherit;
    font-size: var(--font-size-sm);
    resize: vertical;
}

.pz-feedback__input::placeholder { color: var(--text-faint); }

.pz-feedback__input:focus-visible {
    outline: 2px solid var(--brand);
    outline-offset: 2px;
}

.pz-feedback__status {
    margin: 0;
    font-size: var(--font-size-sm);
    color: var(--text-muted);
}

.pz-feedback__status--error { color: var(--status-danger); }

/* ── Home card ────────────────────────────────────────────────────────── */

.pz-home {
    display: flex;
    flex-direction: column;
    gap: var(--space-3);
}

.pz-home__meta {
    display: flex;
    flex-wrap: wrap;
    gap: var(--space-2) var(--space-4);
    font-size: var(--font-size-sm);
    color: var(--text-muted);
}

/* ── Solved: the collapsed strip ──────────────────────────────────────────
   Home carries a playable board only while it is actionable. Once this browser
   has answered today's position the section shrinks to one line (#24 §8.1a),
   which is what keeps it from being a permanent eighth section. */

.pz-home-section.is-collapsed {
    padding: var(--space-5) 0;
}

.pz-home-section.is-collapsed .pz-home-section__head {
    display: none;
}

.pz-solved {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: var(--space-2) var(--space-3);
    padding: var(--space-3) var(--space-4);
    border-radius: var(--radius-md);
    background: var(--surface-800);
    border: 1px solid var(--surface-500);
    font-size: var(--font-size-sm);
}

/* The border colour is a second signal only — the icon and the words in
   .pz-solved__text carry the result on their own (#24 §6). */
.pz-solved--ok { border-left: 4px solid var(--status-ok); }
.pz-solved--no { border-left: 4px solid var(--status-danger); }
.pz-solved--close { border-left: 4px solid var(--status-warn); }
.pz-solved--ok .pz-solved__icon { color: var(--status-ok); }
.pz-solved--no .pz-solved__icon { color: var(--status-danger); }
.pz-solved--close .pz-solved__icon { color: var(--status-warn); }

.pz-solved__text {
    color: var(--text-muted);
}

.pz-solved__text b {
    color: var(--text);
}

.pz-solved__streak {
    display: inline-flex;
    align-items: center;
    gap: var(--space-1);
    color: var(--status-warn);
    font-weight: 600;
}

.pz-solved__streak-icon {
    font-size: var(--font-size-base);
}

.pz-solved__next {
    display: inline-flex;
    align-items: center;
    gap: var(--space-1);
    margin-left: auto;
    /* Stays a real touch target on phones, where it is the only control here. */
    min-height: 44px;
    color: var(--brand);
    font-weight: 600;
    text-decoration: none;
}

.pz-solved__next:hover { text-decoration: underline; }

.pz-solved__next:focus-visible {
    outline: 2px solid var(--brand);
    outline-offset: 2px;
    border-radius: var(--radius-sm);
}

.pz-solved__next .material-symbols-outlined {
    font-size: 1.1em;
}

/* ── Desktop ──────────────────────────────────────────────────────────── */

@media (min-width: 768px) {
    .pz-side {
        grid-template-columns: 168px 1fr;
        gap: var(--space-5);
    }

    .pz-slot {
        width: 160px;
        height: 160px;
    }

    .pz-unit {
        width: 104px;
        height: 145px;
    }

    .pz-unit__pilot {
        left: -16px;
        top: -8px;
    }

    .pz-base {
        width: 58px;
        height: 81px;
    }

    .pz-unit--rested .pz-unit__stats {
        bottom: 66px;
    }

    .pz-hand__card {
        width: 116px;
        height: 162px;
    }

    .pz-page {
        padding: var(--space-8) var(--space-6) var(--space-20);
    }
}

/* ── Turn puzzles ─────────────────────────────────────────────────────────
   The whole-turn format: an objective, a line you build, and the engine's own
   narration of what it did. Reuses every pz-* class above on purpose — one
   board, two question shapes. */

.tz-goal {
    display: flex;
    align-items: center;
    gap: var(--space-2);
    padding: var(--space-3) var(--space-4);
    margin-bottom: var(--space-3);
    border-radius: var(--radius-md);
    background: var(--surface-700);
    border-left: 4px solid var(--brand);
    font-size: var(--font-size-lg);
}

.pz-unit--clickable {
    cursor: pointer;
}

.pz-unit--clickable:hover,
.pz-unit--clickable:focus-visible {
    outline: 2px solid var(--brand);
    outline-offset: 2px;
}

/* A legal target for the unit currently selected. */
.pz-unit--target {
    outline: 3px dashed var(--brand);
    outline-offset: 3px;
}

.tz-line {
    margin: var(--space-4) 0;
    padding: var(--space-3) var(--space-4);
    border: 1px dashed var(--surface-500);
    border-radius: var(--radius-md);
}

.tz-line__label {
    display: block;
    font-weight: 600;
    margin-bottom: var(--space-2);
}

.tz-line__empty {
    color: var(--text-muted);
}

.tz-line__steps {
    margin: 0;
    padding-left: var(--space-5);
}

.tz-line__step {
    padding: 2px 0;
}

.tz-line__remove {
    margin-left: var(--space-2);
    background: none;
    border: none;
    color: var(--text-muted);
    cursor: pointer;
    font-size: var(--font-size-base);
}

.tz-line__remove:hover {
    color: var(--status-danger);
}

/* Steps the engine refused. Sits at the TOP of the reveal, before any
   comparison, because everything below it describes the turn that was actually
   played and this is where the two can differ. */
.tz-dropped {
    margin: var(--space-3) 0;
    padding: var(--space-3);
    border-left: 3px solid var(--status-warning, #e0a33a);
    border-radius: var(--radius-sm);
    background: var(--surface-700);
}

.tz-dropped__head {
    margin: 0;
    font-weight: 600;
}

.tz-dropped__list {
    margin: var(--space-2) 0;
    padding-left: var(--space-5);
    font-size: var(--font-size-sm);
}

.tz-dropped__foot {
    margin: 0;
    color: var(--text-muted);
    font-size: var(--font-size-sm);
}

.tz-compare {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(220px, 1fr));
    gap: var(--space-3);
    margin: var(--space-3) 0;
}

.tz-compare__col {
    padding: var(--space-3);
    border-radius: var(--radius-md);
    background: var(--surface-700);
}

.tz-compare__row {
    display: flex;
    justify-content: space-between;
    gap: var(--space-3);
    font-size: var(--font-size-sm);
    color: var(--text-muted);
    padding: 1px 0;
}

.tz-compare__row b {
    color: var(--text);
    font-variant-numeric: tabular-nums;
}

.tz-log {
    margin: var(--space-2) 0 0;
    padding-left: var(--space-5);
}

.tz-log__line {
    font-size: var(--font-size-sm);
    color: var(--text-muted);
    padding: 1px 0;
}

/* WHERE TWO TURNS SPLIT. Replaces the pair of logs the reveal used to print
   side by side, which asked the player to diff nine lines by eye — and which is
   why the outcome table above it got read as the reason the line was worse. The
   table cannot carry that claim: fitted against the measured win rate it picks
   the better of two turns 58% of the time. This is exact instead. */
.tz-split {
    margin: var(--space-3) 0;
    padding: var(--space-3) var(--space-4);
    border-radius: var(--radius-md);
    background: var(--surface-700);
}

.tz-split__head {
    margin: 0 0 var(--space-2);
    font-weight: 600;
}

.tz-split__list {
    margin: 0;
    padding: 0;
    list-style: none;
}

.tz-split__line {
    display: flex;
    gap: var(--space-2);
    align-items: baseline;
    font-size: var(--font-size-sm);
    padding: 2px 0;
}

/* Shared steps stay quiet: they are the part the player got right, and drawing
   them at the same weight as the divergence buries the one line that matters. */
.tz-split__line--same .tz-split__text {
    color: var(--text-muted);
}

.tz-split__line--yours .tz-split__text {
    color: var(--status-danger);
}

.tz-split__line--theirs .tz-split__text {
    color: var(--status-ok);
}

/* A word, not a colour alone — the two sides must be tellable apart without
   seeing colour at all. */
.tz-split__who {
    flex: none;
    min-width: 3.5em;
    font-size: var(--font-size-xs);
    text-transform: uppercase;
    letter-spacing: .04em;
    opacity: .75;
}

.tz-split__line--yours .tz-split__who {
    color: var(--status-danger);
}

.tz-split__line--theirs .tz-split__who {
    color: var(--status-ok);
}

.tz-split__mark {
    margin: var(--space-2) 0;
    padding-top: var(--space-2);
    border-top: 1px dashed var(--border);
    font-size: var(--font-size-xs);
    color: var(--text-muted);
}

/* The running account of the turn being played, not an explanation after it.
   Never collapsed: a draw, a block and a destroyed unit are named here and
   nowhere else, and the whole point of playing a step at a time is reading them
   before the next decision. */
.tz-log__box {
    margin: var(--space-3) 0;
    padding: var(--space-3) var(--space-4);
    border-radius: var(--radius-md);
    background: var(--surface-700);
}

/* What happened since the last step. The list only ever grows, so without this
   a player who just attacked has to find their own attack in a wall of text. */
.tz-log__line.is-new {
    color: var(--text);
    font-weight: 600;
}

/* A question a CARD asked. Sits between the board and the plan because it
   BLOCKS both: nothing else on the page does anything until it is answered, and
   a question that looked like one more optional control would read as a board
   that had stopped responding. */
.tz-ask {
    margin: var(--space-3) 0;
    padding: var(--space-3) var(--space-4);
    border: 1px solid var(--accent, #6ea8fe);
    border-radius: var(--radius-md);
    background: var(--surface-700);
}

.tz-ask__head {
    margin: 0 0 var(--space-2);
    font-weight: 600;
}

.tz-ask__options {
    display: flex;
    flex-wrap: wrap;
    gap: var(--space-3);
    align-items: flex-start;
}

.tz-ask__option {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: var(--space-1);
    padding: var(--space-1);
    border: 2px solid transparent;
    border-radius: var(--radius-sm);
    cursor: pointer;
    max-width: 140px;
}

.tz-ask__option:hover,
.tz-ask__option:focus-visible {
    border-color: var(--accent, #6ea8fe);
}

.tz-ask__option.is-picked {
    border-color: var(--status-success, #4caf76);
}

/* An option with no card behind it — "rest" or "attack" for a Support unit. */
.tz-ask__word {
    display: inline-block;
    padding: var(--space-2) var(--space-4);
    border-radius: var(--radius-sm);
    background: var(--surface-500);
    font-weight: 600;
}

.tz-ask__label,
.tz-ask__note {
    font-size: var(--font-size-sm);
    color: var(--text-muted);
    text-align: center;
}

.tz-ask__note {
    margin: var(--space-2) 0 0;
}

/* What the player controls, and what the simulator plays for them. Quiet but
   present: the board is a contract, and an unstated exception reads as a bug. */
.tz-scope {
    margin: 0 0 var(--space-3);
    color: var(--text-muted);
    font-size: var(--font-size-sm);
}

/* Which matchup and which turn this position came from. */
.tz-meta {
    margin: 0 0 var(--space-3);
    color: var(--text-muted);
    font-size: var(--font-size-sm);
}

/* The opponent's life: base in front, shields behind. This is the click target
   for "attack the player" — the same gesture as attacking a unit, aimed at the
   thing being attacked, instead of a button elsewhere on the page. */
.tz-life {
    display: flex;
    align-items: center;
    gap: var(--space-2);
    padding: var(--space-1) var(--space-2);
    border-radius: var(--radius-sm);
    border: 1px solid transparent;
}

.tz-life--target {
    cursor: pointer;
    border-color: var(--brand);
    border-style: dashed;
}

.tz-life--target:hover,
.tz-life--target:focus-visible {
    outline: 2px solid var(--brand);
    outline-offset: 2px;
}

/* Hover-to-read. Fixed and pointer-transparent: it appears beside the card you
   are reading and must never sit between you and the next click, because you
   read a card in the middle of building a line, not instead of it. */
.tz-zoom {
    position: fixed;
    z-index: 1000;
    display: none;
    gap: var(--space-2);
    padding: var(--space-2);
    border-radius: var(--radius-md);
    background: var(--surface-900);
    border: 1px solid var(--surface-500);
    box-shadow: 0 12px 32px rgb(0 0 0 / 45%);
    pointer-events: none;
}

.tz-zoom.is-open {
    display: flex;
}

.tz-zoom__art {
    width: 260px;
    height: auto;
    border-radius: var(--radius-sm);
    display: block;
}

@media (prefers-reduced-motion: no-preference) {
    .tz-zoom.is-open {
        animation: tz-zoom-in 0.12s ease-out;
    }

    @keyframes tz-zoom-in {
        from { opacity: 0; }
        to   { opacity: 1; }
    }
}

/* 【Activate･Main】 abilities and <Support> rests, as steps the player takes.
   Both used to be the simulator's decisions, made silently mid-turn — and a
   Main ability usually costs resting the Unit, so it could take the attacker
   the player had just chosen off the table.

   A row of its own rather than a click on the unit: clicking a unit already
   means "attack with this", and one gesture cannot mean two things. */
.tz-abilities {
    margin: var(--space-3) 0;
    padding: var(--space-3) var(--space-4);
    border-radius: var(--radius-md);
    background: var(--surface-700);
}

.tz-abilities__row {
    display: flex;
    flex-wrap: wrap;
    gap: var(--space-2);
}

/* 44px so the control is reachable on a touch screen, where this row matters
   most: the board's other affordances lean on hover, and this one cannot. */
.tz-abilities__btn {
    min-height: 44px;
}
