/* ============================================================
   CASE HERO — WORD SEARCH
   Intro on top, a full-width puzzle band below, meta row last.
   Grid size comes from --wsh-cols/rows (defaults below; override inline on .wsh per case).
============================================================ */

.wsh .cs-header__hook {
  margin-bottom: 0;
}

.wsh .cs-meta {
  margin-top: var(--space-64);
}

/* No frame: the puzzle spans the content width, aligned with the title and meta row */
.wsh__game {
  position: relative;
  margin-top: var(--space-48);
}

/* On short, wide screens the width-driven grid would outgrow the viewport: cap the puzzle so
   the grid plus the nav and the chip row (--wsh-reserve) fit in one screen */
@media (min-width: 769px) {
  .wsh__game {
    max-width: calc((100svh - var(--wsh-reserve, 224px)) * var(--wsh-cols) / var(--wsh-rows));
  }
}

/* Styled by .section-tag, like the section tags below */
.wsh__kicker {
  display: block;
  margin-bottom: var(--space-24);
}

.wsh__count {
  font-size: var(--size-body-sm);
  color: var(--accent-primary);
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
}

/* ---------- Grid ---------- */
/* Grid size lives only here, so the box is reserved before JS runs and JS builds the same grid
   (it reads the resolved --cols/--rows). A case can override it inline on .wsh, e.g.
   style="--wsh-cols: 20; --wsh-rows-mobile: 14". */
.wsh {
  --wsh-cols: 24;
  --wsh-rows: 7;
  --wsh-cols-mobile: 12;
  --wsh-rows-mobile: 12;
}

.wsh__grid {
  --cols: var(--wsh-cols);
  --rows: var(--wsh-rows);
  position: relative;
  display: grid;
  grid-template-columns: repeat(var(--cols), 1fr);
  aspect-ratio: var(--cols) / var(--rows);
  container-type: inline-size;
  touch-action: pan-y; /* vertical swipes still scroll the page; taps and sideways drags reveal */
  cursor: crosshair;
  user-select: none;
}

.wsh__cell {
  position: relative;
  z-index: 1;
  display: flex;
  align-items: center;
  justify-content: center;
  font-family: var(--font-display);
  font-weight: 700;
  font-size: calc(100cqw / var(--cols) * 0.62);
  line-height: 1;
  color: var(--accent-primary);
  transition: color 0.15s ease-out, opacity 0.15s ease-out;
}

.wsh__cell.is-word.is-lit {
  color: var(--text-primary);
  opacity: 1 !important; /* beats the random inline opacity */
}

.wsh__capsule {
  position: absolute;
  border: 1.5px solid var(--accent-primary);
  background: var(--accent-subtle);
  border-radius: var(--radius-control);
  pointer-events: none;
  animation: wsh-capsule 0.35s ease-out both;
}

@keyframes wsh-capsule {
  from { opacity: 0; transform: scale(0.92); }
  to   { opacity: 1; transform: scale(1); }
}

/* ---------- Balloon ---------- */
.wsh__balloon {
  position: absolute;
  z-index: 3;
  width: min(340px, 90%);
  padding: var(--space-16) var(--space-20);
  border: 1px solid var(--accent-muted);
  border-radius: var(--radius-surface);
  background: var(--background-primary);
  box-shadow: 0 12px 32px rgba(0, 0, 0, 0.45);
  pointer-events: none;
  opacity: 0;
  transform: translateY(6px);
  transition: opacity 0.25s ease-out, transform 0.25s ease-out;
}

.wsh__balloon.is-visible {
  opacity: 1;
  transform: none;
}

.wsh__balloon-cat {
  margin-bottom: var(--space-4);
  font-size: var(--size-label);
  font-weight: 500;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--accent-primary);
}

.wsh__balloon-text {
  font-size: var(--size-body-sm);
  line-height: 1.5;
  color: var(--text-primary);
}

/* ---------- Row: count, word chips, reveal ---------- */
/* The list's box is dissolved so chips, count, and reveal share one wrapping row:
   when chips wrap, Reveal all follows the last chip. role="list" keeps the semantics. */
.wsh__row {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--space-8) var(--space-16); /* 16px apart, so unpadded blanks don't merge into one line */
  margin-top: var(--space-24);
}

.wsh__legend {
  display: contents;
  list-style: none;
}

.wsh__chip {
  padding: var(--space-4) var(--space-12);
  border: 1px solid var(--background-divider);
  border-radius: var(--radius-control);
  font-family: var(--font-display);
  font-weight: 700;
  font-size: 14px;
  letter-spacing: 0.08em;
  color: var(--text-ghost);
  transition: background-color 0.2s ease, border-color 0.2s ease;
}

/* Not found yet: no outline, no pointer, and no side padding, so the blanks sit flush with the
   count and keep the row's 16px spacing. Vertical padding and border stay, so the row height
   holds when a word is found; only the chip's width grows. */
.wsh__item:not(.is-found) .wsh__chip {
  padding-inline: 0;
  border-color: transparent;
  border-inline-width: 0;
  cursor: default;
}

.wsh__item.is-found .wsh__chip {
  border-color: var(--accent-muted);
  color: var(--accent-primary);
}

.wsh__item.is-found .wsh__chip:hover,
.wsh__item.is-found .wsh__chip:focus-visible {
  background: var(--accent-subtle);
}

.wsh__item.is-found .wsh__term-blank { display: none; }

/* Category, caption, and not-yet-found terms stay readable to assistive tech only */
.wsh__cat,
.wsh__caption {
  position: absolute;
  width: 1px;
  height: 1px;
  overflow: hidden;
  clip: rect(0, 0, 0, 0);
  white-space: nowrap;
}

/* With scripting on, show the playable state from the first paint so nothing shifts when JS runs */
@media (scripting: enabled) {
  .wsh__item:not(.is-found) .wsh__term-text {
    position: absolute;
    width: 1px;
    height: 1px;
    overflow: hidden;
    clip: rect(0, 0, 0, 0);
    white-space: nowrap;
  }
}

.wsh__reveal {
  font-size: var(--size-body-sm);
  color: var(--text-ghost);
  text-decoration: underline;
  text-underline-offset: 3px;
  white-space: nowrap;
}

.wsh__reveal:hover { color: var(--text-primary); }
.wsh__reveal[hidden] { display: none; }

/* Without JS the puzzle can't run: show the legend as plain text instead */
@media (scripting: none) {
  .wsh__grid,
  .wsh__count,
  .wsh__reveal,
  .wsh__term-blank {
    display: none;
  }
}

@media (max-width: 768px) {
  .wsh__grid {
    --cols: var(--wsh-cols-mobile);
    --rows: var(--wsh-rows-mobile);
  }

  /* Chips first; count and reveal side by side on a line below (the empty break line adds
     one more 8px gap, so that line sits 16px under the chips) */
  .wsh__row::before {
    content: '';
    flex-basis: 100%;
    order: 1;
  }

  .wsh__count { order: 2; }
  .wsh__reveal { order: 3; }
}

@media (prefers-reduced-motion: reduce) {
  .wsh__cell,
  .wsh__capsule,
  .wsh__balloon,
  .wsh__chip {
    transition: none;
    animation: none;
  }
}
