/**
 * Word Snake Game Styles
 *
 * Mobile-first, theme-aware (light/dark via design tokens from main.css).
 * All colors use CSS custom properties — no hardcoded values.
 */

/* ========================================
   Container & Layout
   ======================================== */

.word-snake-container {
    margin: 0 auto;
    max-width: 900px;
}

.word-snake {
    position: relative;
    background: var(--color-bg-card);
    border: 1px solid var(--color-border);
    border-radius: var(--radius-lg, 12px);
    padding: var(--space-4, 1rem);
    box-shadow: var(--shadow-sm, 0 1px 3px rgba(0, 0, 0, 0.1));
}

.ws-card-actions {
    display: flex;
    justify-content: flex-end;
    margin-bottom: var(--space-2, 0.5rem);
}

/* Icon button (help toggles) — shared component pattern */
.btn-icon {
    min-width: var(--favorites-bar-height);
    min-height: var(--favorites-bar-height);
    display: inline-flex;
    align-items: center;
    justify-content: center;
    border-radius: var(--radius-full);
    font-size: var(--font-size-lg);
    font-weight: 600;
    color: var(--color-text-muted);
    background: var(--color-bg-alt);
    border: 1px solid var(--color-border);
    cursor: pointer;
    transition:
        background var(--transition-fast),
        color var(--transition-fast),
        transform var(--transition-fast);
}

.btn-icon:hover {
    background: var(--color-border);
    color: var(--color-text);
}

.btn-icon:focus-visible {
    outline: none;
    box-shadow: var(--focus-ring);
}

.btn-icon:active {
    transform: scale(0.98);
}

/* ========================================
   Difficulty Selector
   ======================================== */

.ws-difficulty-selector {
    display: flex;
    gap: var(--space-2, 0.5rem);
    justify-content: center;
    margin-bottom: var(--space-4, 1rem);
}

.ws-difficulty-btn {
    min-width: 88px;
    min-height: 44px;
    padding: var(--space-2, 0.5rem) var(--space-4, 1rem);
    font-size: var(--font-size-base, 1rem);
    font-weight: 600;
    color: var(--color-text);
    background: var(--color-bg-alt);
    border: 2px solid var(--color-border-dark);
    border-radius: var(--radius-md, 8px);
    cursor: pointer;
    transition: background-color var(--transition-fast), border-color var(--transition-fast);
}

.ws-difficulty-btn:hover {
    background: var(--color-bg-card);
    border-color: var(--color-primary);
}

.ws-difficulty-btn:focus-visible {
    outline: none;
    box-shadow: var(--focus-ring);
}

.ws-difficulty-btn:active {
    transform: scale(0.98);
}

.ws-difficulty-btn.active {
    background: var(--color-primary);
    color: var(--color-text-inverse, #ffffff);
    border-color: var(--color-primary);
}

/* ========================================
   HUD
   ======================================== */

.ws-hud {
    display: flex;
    flex-wrap: wrap;
    gap: var(--space-3, 0.75rem);
    align-items: center;
    justify-content: space-between;
    padding: var(--space-3, 0.75rem);
    margin-bottom: var(--space-4, 1rem);
    background: var(--color-bg-alt);
    border-radius: var(--radius-md, 8px);
}

.ws-hud-label {
    font-size: var(--font-size-sm, 0.875rem);
    color: var(--color-text-muted);
    margin-right: var(--space-1, 0.25rem);
}

.ws-target-word {
    display: flex;
    align-items: center;
    gap: var(--space-2, 0.5rem);
}

.ws-letter-slots {
    display: inline-flex;
    gap: var(--space-1);
    /* Reserve the slot row height before the first word is drawn. The slots stay
       empty until startWord() fills them, which used to grow the HUD row (+6px
       desktop, +15px on the stacked mobile HUD) and push the board down. That
       used to land within 500ms of the Start click (input-excluded); a deferred
       start on a slow bundle can put it outside that window, so it became a
       counted layout shift. Reserving the height keeps the pre-game state
       identical to the already-validated in-play state. */
    font-size: var(--font-size-lg, 1.125rem);
    min-height: 2em;
}

.ws-slot {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 1.75em;
    height: 2em;
    font-size: var(--font-size-lg, 1.125rem);
    font-weight: 700;
    font-family: var(--font-mono, monospace);
    color: var(--color-text-muted);
    background: var(--color-bg-card);
    border: 2px dashed var(--color-border-dark);
    border-radius: var(--radius-sm);
}

.ws-slot-filled {
    color: var(--color-success-text, #047857);
    background: color-mix(in srgb, var(--color-success) 12%, transparent);
    border-style: solid;
    border-color: var(--color-success);
}

.ws-slot-next {
    color: var(--color-primary-text);
    border-style: solid;
    border-color: var(--color-primary);
    box-shadow: inset 0 -3px 0 var(--color-primary);
}

.ws-next-letter {
    display: flex;
    align-items: center;
    gap: var(--space-2, 0.5rem);
}

.ws-next-letter-value {
    font-size: var(--font-size-lg, 1.125rem);
    font-weight: 700;
    color: var(--color-primary-text);
    border-bottom: 3px solid var(--color-primary);
    padding: 0 var(--space-1);
}

/* ========================================
   Wrong-letter cue
   ======================================== */

/* A letter that is not the next one needed stays on the board (tick() only
   consumes correct letters), so on Easy — where it costs no life — and with
   sound off (the default) nothing visible used to happen at all. The script
   puts .ws-wrong-cue on the "next letter" indicator and on the word slot row
   for a moment so the player can see that the letter was not the right one.

   The cue pairs movement (the shake) with colour AND a shape change (the
   outline and the heavier underline), so it never relies on colour alone. It
   is transform/outline/colour/border only: no layout shift, the board is never
   covered, and no game state is touched. */

@keyframes ws-wrong-shake {
    0%, 100% { transform: translateX(0); }
    25% { transform: translateX(-4px); }
    75% { transform: translateX(4px); }
}

.ws-next-letter.ws-wrong-cue,
.ws-letter-slots.ws-wrong-cue {
    animation: ws-wrong-shake 400ms ease-in-out;
}

.ws-next-letter.ws-wrong-cue .ws-next-letter-value {
    color: var(--color-error-text);
    border-bottom-color: var(--color-error);
    outline: 2px solid var(--color-error);
    outline-offset: 2px;
}

/* The slot letter itself keeps its normal colour so it stays readable and does
   not flicker between colours during the cue. The error-coloured border,
   underline and outline carry the non-colour cue instead. */
.ws-letter-slots.ws-wrong-cue .ws-slot-next {
    border-color: var(--color-error);
    box-shadow: inset 0 -3px 0 var(--color-error);
    outline: 2px solid var(--color-error);
    outline-offset: 1px;
}

.ws-stats {
    display: flex;
    gap: var(--space-4, 1rem);
    align-items: center;
}

.ws-stat {
    display: flex;
    align-items: center;
    gap: var(--space-2, 0.5rem);
}

.ws-stat-value {
    font-size: var(--font-size-lg, 1.125rem);
    font-weight: 700;
    color: var(--color-text);
}

/* Lives hearts */
.ws-lives {
    display: inline-flex;
    gap: var(--space-1);
    font-size: var(--font-size-lg, 1.125rem);
}

.ws-heart-full {
    color: var(--color-error);
}

.ws-heart-empty {
    color: var(--color-border-dark);
}

/* ========================================
   Game Board
   ======================================== */

.ws-board-wrapper {
    position: relative;
    width: 100%;
}

/* Reserved grid geometry mirrors setupBoardSize() in word-snake.js (20x15 desktop).
   Declaring it up front lets the board be sized before the script runs, which
   prevents a first-paint layout shift (CLS). The inline styles applied by the
   game script take precedence once it initializes. */
.ws-board {
    display: grid;
    grid-template-columns: repeat(20, 1fr);
    grid-template-rows: repeat(15, 1fr);
    gap: var(--space-1);
    background: var(--color-bg-alt);
    border: 2px solid var(--color-border-dark);
    border-radius: var(--radius-md, 8px);
    padding: var(--space-1);
    aspect-ratio: 20 / 15;
}

.ws-cell {
    position: relative;
    display: flex;
    align-items: center;
    justify-content: center;
    background: var(--color-bg-card);
    border-radius: var(--radius-sm);
    min-height: 0;
    aspect-ratio: 1 / 1;
}

.ws-cell-letter {
    font-size: clamp(0.6rem, 2vw, 1rem);
    font-weight: 700;
    font-family: var(--font-mono, monospace);
    color: var(--color-primary-text);
}

.ws-snake {
    background: var(--color-success);
    border-radius: var(--radius-sm);
}

/* ========================================
   Overlays
   ======================================== */

.ws-overlay {
    position: absolute;
    inset: 0;
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: var(--space-4, 1rem);
    /* Centred so the loading/error message stays optically centred with the
       title and button once it wraps to two or more lines (es/pl at <=375px);
       a single-line message already looked centred because its box shrank to
       the text width. */
    text-align: center;
    background: color-mix(in srgb, var(--color-bg-card) 85%, transparent);
    border-radius: var(--radius-md, 8px);
    z-index: 10;
}

.ws-overlay[hidden] {
    display: none;
}

.ws-overlay-title {
    font-size: var(--font-size-2xl, 1.5rem);
    color: var(--color-text);
    margin: 0;
}

.ws-overlay-word {
    font-size: var(--font-size-xl, 1.25rem);
    font-weight: 700;
    letter-spacing: 0.3em;
    color: var(--color-success-text);
    margin: 0;
}

.ws-overlay-score {
    font-size: var(--font-size-base, 1rem);
    color: var(--color-text);
    margin: 0;
}

/* ========================================
   Buttons & Controls
   ======================================== */

.ws-btn-primary,
.ws-btn-secondary {
    min-height: 44px;
    padding: var(--space-2, 0.5rem) var(--space-6, 1.5rem);
    font-size: var(--font-size-base, 1rem);
    font-weight: 600;
    border-radius: var(--radius-md, 8px);
    cursor: pointer;
    transition: background-color var(--transition-fast), transform var(--transition-fast);
}

.ws-btn-primary {
    color: var(--color-text-inverse, #ffffff);
    background: var(--color-primary);
    border: none;
}

.ws-btn-primary:hover:not(:disabled) {
    background: var(--color-primary-dark);
}

.ws-btn-primary:focus-visible {
    outline: none;
    box-shadow: var(--focus-ring);
}

.ws-btn-primary:active {
    transform: scale(0.98);
}

.ws-btn-secondary {
    color: var(--color-text);
    background: var(--color-bg-alt);
    border: 1px solid var(--color-border-dark);
}

.ws-btn-secondary:hover:not(:disabled) {
    background: var(--color-bg-card);
    border-color: var(--color-primary);
}

.ws-btn-secondary:focus-visible {
    outline: none;
    box-shadow: var(--focus-ring);
}

.ws-btn-secondary:active {
    transform: scale(0.98);
}

/* A deferred start disables the Start button while the word bank loads (and on
   failure), so the state needs its own treatment: without it the button kept
   its full fill, its hover colour and its pointer cursor and was
   indistinguishable from the enabled button. Matches the disabled-button
   convention used across the other apps. */
.ws-btn-primary:disabled,
.ws-btn-secondary:disabled {
    opacity: 0.5;
    cursor: not-allowed;
}

.ws-controls {
    display: flex;
    gap: var(--space-3, 0.75rem);
    justify-content: center;
    margin-top: var(--space-4, 1rem);
}

/* ========================================
   Help panel content (shared .help-panel markup)
   ======================================== */

.help-section {
    margin-bottom: var(--space-6);
}

.help-section:last-child {
    margin-bottom: 0;
}

.help-section h3 {
    margin-bottom: var(--space-4);
    font-size: var(--font-size-base);
    color: var(--color-text);
}

/* main.css resets list markers globally — restore them for help content. */
.help-steps {
    list-style: decimal;
}

.help-list {
    list-style: disc;
}

.help-definitions,
.help-shortcuts {
    margin: 0;
}

.definition-item {
    margin-bottom: var(--space-3);
    padding-left: var(--space-3);
    border-left: 3px solid var(--color-primary);
}

.definition-item:last-child {
    margin-bottom: 0;
}

.definition-item dt {
    margin-bottom: var(--space-1);
    font-weight: 600;
    color: var(--color-text);
}

.definition-item dd {
    margin: 0;
    font-size: var(--font-size-sm);
    color: var(--color-text-muted);
}

.shortcut-item {
    padding: var(--space-2) 0;
    border-bottom: 1px solid var(--color-border);
}

.shortcut-item:last-child {
    border-bottom: none;
}

.shortcut-item dt {
    margin-bottom: var(--space-1);
}

.shortcut-item dd {
    margin: 0;
    font-size: var(--font-size-sm);
    color: var(--color-text-muted);
}

.help-shortcuts kbd {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    min-width: 28px;
    height: 24px;
    padding: 0 var(--space-2);
    font-family: var(--font-mono);
    font-size: var(--font-size-xs);
    font-weight: 600;
    color: var(--color-text);
    background: var(--color-bg-alt);
    border: 1px solid var(--color-border);
    border-radius: var(--radius-sm);
}

/* ========================================
   Touch D-pad (coarse pointers only)
   ======================================== */

.ws-dpad {
    display: none;
    grid-template-columns: repeat(3, 56px);
    grid-template-rows: repeat(2, 56px);
    gap: var(--space-2, 0.5rem);
    justify-content: center;
    margin-top: var(--space-4, 1rem);
}

@media (pointer: coarse) {
    .ws-dpad {
        display: grid;
    }
}

.ws-dpad-btn {
    width: 56px;
    height: 56px;
    font-size: var(--font-size-xl, 1.25rem);
    color: var(--color-text);
    background: var(--color-bg-alt);
    border: 1px solid var(--color-border-dark);
    border-radius: var(--radius-md, 8px);
    cursor: pointer;
    transition:
        background-color var(--transition-fast),
        border-color var(--transition-fast),
        transform var(--transition-fast);
}

.ws-dpad-btn:hover {
    background: var(--color-bg-card);
    border-color: var(--color-primary);
}

.ws-dpad-btn:focus-visible {
    outline: none;
    box-shadow: var(--focus-ring);
}

.ws-dpad-btn:active {
    transform: scale(0.98);
}

.ws-dpad-up { grid-column: 2; grid-row: 1; }
.ws-dpad-left { grid-column: 1; grid-row: 2; }
.ws-dpad-down { grid-column: 2; grid-row: 2; }
.ws-dpad-right { grid-column: 3; grid-row: 2; }

/* ========================================
   Screen-reader-only utility (fallback if main.css lacks it)
   ======================================== */

.sr-only {
    position: absolute;
    width: 1px;
    height: 1px;
    padding: 0;
    margin: -1px;
    overflow: hidden;
    clip: rect(0, 0, 0, 0);
    white-space: nowrap;
    border: 0;
}

/* ========================================
   Responsive: mobile-first adjustments
   ======================================== */

@media (max-width: 768px) {
    /* Matches setupBoardSize() mobile branch (15x12) — see note on .ws-board. */
    .ws-board {
        grid-template-columns: repeat(15, 1fr);
        grid-template-rows: repeat(12, 1fr);
        aspect-ratio: 15 / 12;
    }

    .ws-hud {
        flex-direction: column;
        align-items: stretch;
    }

    .ws-stats {
        justify-content: space-between;
    }

    .ws-target-word,
    .ws-next-letter {
        justify-content: center;
    }
}

/* Narrow phones: let the HUD rows, the difficulty selector and the control
   buttons wrap instead of overflowing the card. Longer localized labels (es/pl)
   and the 5-letter Hard word make these rows wider than a 320-375px card. */
@media (max-width: 480px) {
    .ws-difficulty-selector,
    .ws-controls,
    .ws-target-word,
    .ws-next-letter,
    .ws-stats {
        flex-wrap: wrap;
    }

    .ws-stats {
        row-gap: var(--space-2);
    }
}

/* ========================================
   Reduced motion
   ======================================== */

@media (prefers-reduced-motion: reduce) {
    .ws-difficulty-btn,
    .ws-btn-primary,
    .ws-btn-secondary,
    .ws-dpad-btn {
        transition: none;
    }

    /* The wrong-letter cue keeps its still colour/border/outline change and
       only drops the shake. The script holds it a little longer
       (WRONG_CUE_STILL_MS) because there is no movement to draw the eye. */
    .ws-next-letter.ws-wrong-cue,
    .ws-letter-slots.ws-wrong-cue {
        animation: none;
    }
}
