/* ============================================================================
 * LexiLab Word Search Maker - grid stylesheet
 * ----------------------------------------------------------------------------
 * Extracted verbatim from word-search-maker/index.html on 2026-08-15
 * (solve-mode spec, phase P1a). Every rule here styles markup that
 * word-search-maker/render.js emits and nothing else - the two files are a
 * pair, and a page that loads one without the other renders an unstyled or
 * unpopulated grid.
 *
 * The word bank travels with the grid rather than staying in the page,
 * because renderBank() moved to render.js: in a word search the list IS the
 * puzzle, so the play page needs both or neither.
 *
 * Editor chrome, panels, buttons, the empty state, the save panel and the
 * print page furniture stay in the page's own <style> block.
 *
 * Palette tokens come from /assets/theme.css. Nothing here hardcodes a colour
 * except inside @media print, where the sheet is deliberately forced to black
 * on white - including the answer-key rings, which would otherwise half-tone
 * into a grey smudge on a monochrome classroom printer.
 *
 * NOTE FOR THE TEST SUITE: rules here are pinned by SOURCE-TEXT assertions in
 * scripts/test-wordsearch-page.mjs rather than by computed style, because
 * jsdom cannot resolve CSS custom properties. Those assertions read THIS file.
 * If a rule moves out of here, move its assertion with it in the same commit -
 * a check pointed at a file that no longer contains what it is checking passes
 * while asserting nothing.
 * ========================================================================== */

/* --- Grid -------------------------------------------------------
 * A word search grid is dense and rectangular, unlike a crossword's
 * sparse one, and conventionally has NO ruling at all - just letters
 * in a regular array. That is the default here, and it is also why
 * this tool sidesteps the entire class of bug the Crossword Maker
 * spent four rounds on: with no lines there is nothing for two DOM
 * elements to disagree about.
 *
 * When lines ARE switched on, they follow the rule that history
 * established rather than re-deriving it: one absolutely-positioned
 * element per line, positioned with calc(var(--cell) * N), never a
 * border on the cells themselves. See CLAUDE.md.
 * -------------------------------------------------------------- */
.ws-grid {
    display: grid;
    gap: 0;
    justify-content: center;
    margin: 0 auto;
    /* fit-content and position:relative are both load-bearing for the
     * absolutely-positioned children (.ws-gridline, .ws-ring): their
     * coordinates are computed from this box's own top-left corner,
     * so any centering slack between the box and its tracks would
     * offset every overlay by that slack. */
    width: fit-content;
    position: relative;
}
.ws-cell {
    width: var(--cell, 30px);
    height: var(--cell, 30px);
    position: relative;
}
.ws-letter {
    position: absolute;
    inset: 0;
    display: flex;
    align-items: center;
    justify-content: center;
    font-family: Fraunces, Georgia, serif;
    font-size: calc(var(--cell, 30px) * 0.56);
    color: var(--tile-ink);
    line-height: 1;
}
.dark .ws-letter { color: var(--text); }

.ws-gridline {
    position: absolute;
    background: var(--border);
    pointer-events: none;
}
.ws-grid-framed { outline: 1px solid var(--border); }

/* The answer-key marker. ONE rotated capsule per hidden word,
 * absolutely positioned and sized from the word's own row/col/dir/
 * length - no cell map, no neighbour lookup, nothing to resolve
 * against another word. Two words crossing simply overlap on screen
 * with nothing to fight over, which is the whole point: this is the
 * same conclusion the Crossword Maker reached after four rounds of
 * per-cell-border bugs, applied from the start rather than
 * rediscovered. See entryRingStyle(). */
.ws-ring {
    position: absolute;
    border: 2px solid var(--accent-orange);
    border-radius: 999px;
    pointer-events: none;
    transform-origin: 50% 50%;
}

/* On the answer key the filler drops back so the ringed words read at
 * a glance. Applied to the KEY grid only, never the puzzle grid. */
.ws-grid-key .ws-letter { color: var(--text-faint); }
.ws-grid-key .ws-cell-word .ws-letter { color: var(--text); font-weight: 600; }
.dark .ws-grid-key .ws-cell-word .ws-letter { color: var(--text); }

.ws-gridwrap { overflow-x: auto; padding: 0.5rem 0 1rem; }

/* --- Word bank --------------------------------------------------
 * NOT optional the way a crossword's is. In a word search the word
 * list IS the puzzle - without it the student has nothing to look
 * for - so it is on by default and the toggle is inverted into a
 * "hide it" challenge mode. */
.ws-bank {
    border-top: 1px solid var(--border);
    padding-top: 0.9rem;
    margin-top: 0.25rem;
}
/* --text-muted: at 12px, --text-faint measures 3.58:1 in light and 3.63:1
   in dark, under the 4.5:1 floor. This rule serves the Maker's word bank
   too - the same failure was sitting there unnoticed, because P3's pass
   measured the Maker's other text and not this heading. */
.ws-bank h3 {
    font-size: 12px;
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: 0.08em;
    color: var(--text-muted);
    margin-bottom: 0.6rem;
}
.ws-bank-list {
    display: flex;
    flex-wrap: wrap;
    gap: 0.4rem;
}
.ws-bank-word {
    border: 1px solid var(--border);
    border-radius: 8px;
    padding: 0.3rem 0.6rem;
    font-size: 13px;
    color: var(--text);
    background: var(--bg);
    letter-spacing: 0.04em;
}
.ws-bank-word.ws-bank-hover {
    border-color: var(--accent-orange);
    color: var(--accent-soft-ink);
    background: var(--accent-soft);
}

/* --- Solve mode (/word-search-play/) -----------------------------
 * Added 2026-08-15 for phase P2 of docs/solve-mode-spec.md. These
 * rules layer onto the grid markup render.js already emits; render.js
 * itself is UNCHANGED by P2 and the Maker never adds .ws-grid-solve,
 * so nothing here can reach the Maker or the printed sheet.
 *
 * They live here, next to the rules they layer on, for the same
 * reason the crossword's solve-mode cell states live in
 * crossword-maker/grid.css rather than in the shell: the shell owns
 * no grid.
 *
 * TWO-CLASS SELECTORS throughout, per the cascade rule P1b
 * established. `.ws-cell-sel` alone is (0,1,0) and would lose
 * silently to any two-class grid rule while every classList
 * assertion in the suite kept passing - which is exactly how the
 * .cm-cell-filler bug got as far as it did.
 * ---------------------------------------------------------------- */

.ws-grid-solve {
    /* WITHOUT THIS THE PAGE IS UNUSABLE ON A PHONE: the browser
     * treats a drag across the grid as a scroll gesture and steals
     * every pointermove after the first. One declaration, and the
     * whole touch story comes free from pointer events. */
    touch-action: none;

    /* A drag across letters is a text selection by default, so the
     * grid fills with blue highlight and the pointerup lands on a
     * selection rather than a cell. */
    user-select: none;
    -webkit-user-select: none;

    cursor: crosshair;
    outline: none;
}
/* Removing the outline without a focus-visible replacement strands
 * keyboard users - the same pairing the crossword's solve grid has. */
.ws-grid-solve:focus-visible {
    box-shadow: 0 0 0 3px var(--ring);
    border-radius: 3px;
}

/* The cells under the live drag. background-COLOR, never the
 * `background` shorthand: the shorthand resets background-image, and
 * a later state that draws one would then survive only by source
 * order. Same trap as the crossword's cursor tint. */
.ws-cell.ws-cell-sel { background-color: var(--accent-soft); }

/* The keyboard cursor. inset box-shadow rather than a border,
 * because a border would change the cell's box and shift every
 * letter after it by a pixel - the geometry rule this whole file
 * exists to respect. */
.ws-cell.ws-cell-cursor { box-shadow: inset 0 0 0 2px var(--accent-orange); }

/* The live drag previews the ring it is about to become - same
 * entryRingStyle() geometry, dashed so it reads as provisional.
 * FORM, not colour: the palette's only strong accent is already
 * carrying the found ring, and dark mode collapses the rest. */
.ws-ring.ws-ring-live {
    border-style: dashed;
    border-width: 2px;
}

/* A revealed word reads as not-the-solver's, so a teacher looking
 * over a shoulder can tell at a glance which ones were found and
 * which were given. Again form first - dashed and muted - because
 * colour alone does not survive dark mode. */
.ws-ring.ws-ring-revealed {
    border-style: dashed;
    border-color: var(--text-faint);
}

.ws-bank-word.ws-bank-found {
    text-decoration: line-through;
    opacity: 0.55;
    border-color: var(--accent-orange);
}
.ws-bank-word.ws-bank-revealed {
    text-decoration: line-through;
    opacity: 0.55;
    border-style: dashed;
}

/* --- Print ---------------------------------------------------------
 * Only the grid's and word bank's own print rules live here. The
 * sheet's page setup (@page, the forced-light palette override,
 * .ws-print-page spacing) stays in the page: worksheet furniture,
 * not grid rendering.
 * ------------------------------------------------------------------ */
@media print {
    .ws-grid { break-inside: avoid; page-break-inside: avoid; }
    .ws-gridwrap { overflow: visible; padding: 0 0 6mm; }

    .ws-letter { color: #000000; }
    .ws-gridline { background: #000000; }
    .ws-grid-framed { outline: 0.4mm solid #000000; }

    /* The answer key rings print black rather than orange: most
       classroom printers are monochrome, and an orange ring
       half-tones into a grey smudge over the letter it is meant to
       highlight. */
    .ws-ring { border-color: #000000; border-width: 0.5mm; }
    .ws-grid-key .ws-letter { color: #888888; }
    .ws-grid-key .ws-cell-word .ws-letter { color: #000000; font-weight: 700; }

    .ws-bank { border-top: 0.3mm solid #000000; }
    .ws-bank-word {
        border: 0.3mm solid #000000;
        background: #FFFFFF;
        color: #000000;
        font-size: 10.5pt;
    }
    .ws-bank h3 { color: #000000; font-size: 9pt; }
}
