/* wordsearch.css — Word Search portal theme.
 *
 * Scoped under body.wordsearch-portal so it never leaks into the writer
 * platform. Every colour derives from the active CivNode theme tokens
 * (--bg-*, --text-*, --accent) via var() and color-mix() — no hardcoded
 * hex anchors outside the per-volume --ws-accent default fallback.
 *
 * The portal looks at home in midnight, champagne/parchment light themes,
 * and any user-customised palette because it derives rather than overrides.
 *
 * Per-volume accent: JS sets --ws-accent on the .wordsearch-screen wrapper
 * element via inline style when the volume is loaded. Default fallback is
 * the warm rose used by the Alice volume.
 */

body.wordsearch-portal {
  /* Portal token layer — every --ws-* derives from the CivNode palette. */
  --ws-surface:      var(--bg-primary);
  --ws-surface-soft: var(--bg-secondary);
  --ws-paper:        var(--bg-surface);
  --ws-elevated:     var(--bg-elevated);
  --ws-ink:          var(--text-primary);
  --ws-ink-soft:     var(--text-secondary);
  --ws-ink-muted:    var(--text-muted);

  /* Hairlines stay quiet; borders lean on the volume accent. */
  --ws-hairline:     color-mix(in srgb, var(--text-primary) 12%, transparent);
  --ws-hairline-mid: color-mix(in srgb, var(--text-primary) 22%, transparent);

  /* Per-volume accent — overridden by JS inline style on .wordsearch-screen.
     Default: warm rose (Alice). Never reference this hex elsewhere in the
     codebase; always use --ws-accent through var(). */
  --ws-accent:       #C8807A;
  --ws-accent-soft:  color-mix(in srgb, var(--ws-accent) 18%, transparent);
  --ws-accent-faint: color-mix(in srgb, var(--ws-accent) 7%, transparent);

  background: var(--ws-surface);
  color: var(--ws-ink);
}

/* The portal lives inside regular CivNode chrome — the main nav stays so
   users can move between the word search portal and the rest of the site.
   .wordsearch-topbar acts as a section nav below the global one. */
body.wordsearch-portal #main.wordsearch-main {
  margin: 0;
  padding: 0;
  max-width: none;
  background: var(--ws-surface);
  color: var(--ws-ink);
  min-height: 100vh;
}

/* ---- Page shell ---------------------------------------------------------- */

.wordsearch-shell {
  min-height: 100vh;
  display: flex;
  flex-direction: column;
}

.wordsearch-screen {
  /* Volume screens set --ws-accent as an inline style here. */
}

.wordsearch-body {
  max-width: 1080px;
  margin: 0 auto;
  padding: 3rem 2rem 5rem;
  width: 100%;
  box-sizing: border-box;
}

.wordsearch-body--full {
  max-width: none;
  padding: 0;
}

/* ---- Top bar ------------------------------------------------------------- */

.wordsearch-topbar {
  display: flex;
  align-items: center;
  gap: 1.5rem;
  padding: 1rem 2rem;
  border-bottom: 1px solid var(--ws-hairline);
  background: var(--ws-surface);
}

.wordsearch-topbar__brand {
  font-family: var(--font-serif, Georgia, serif);
  font-style: italic;
  font-size: 1.1rem;
  font-weight: 600;
  letter-spacing: 0.01em;
  color: var(--ws-ink);
  text-decoration: none;
}

.wordsearch-topbar__links {
  display: flex;
  gap: 1.25rem;
  margin-left: auto;
}

.wordsearch-topbar__link {
  color: var(--ws-ink-soft);
  text-decoration: none;
  font-size: 0.95rem;
  font-family: var(--font-sans, sans-serif);
  border-bottom: 1px solid transparent;
  padding-bottom: 2px;
  transition: color 120ms ease, border-color 120ms ease;
}

.wordsearch-topbar__link:hover {
  color: var(--ws-ink);
}

.wordsearch-topbar__link.is-active {
  color: var(--ws-ink);
  border-bottom-color: var(--ws-accent);
}

/* ---- Reusable CTA -------------------------------------------------------- */

.ws-cta {
  display: inline-block;
  padding: 0.75rem 1.5rem;
  border: 1px solid var(--ws-accent);
  background: transparent;
  color: var(--ws-accent);
  font-family: var(--font-sans, sans-serif);
  font-size: 0.9rem;
  letter-spacing: 0.04em;
  text-decoration: none;
  cursor: pointer;
  border-radius: var(--radius-sm, 3px);
  transition: background 140ms ease, color 140ms ease;
}

.ws-cta:hover {
  background: var(--ws-accent);
  color: var(--ws-surface);
}

.ws-cta--ghost {
  border-color: var(--ws-hairline-mid);
  color: var(--ws-ink);
}

.ws-cta--ghost:hover {
  background: var(--ws-accent);
  color: var(--ws-surface);
  border-color: var(--ws-accent);
}

/* ---- Loading / error / empty states ------------------------------------- */

.ws-loading,
.ws-error {
  text-align: center;
  padding: 4rem 0;
  color: var(--ws-ink-soft);
  font-family: var(--font-sans, sans-serif);
}

.ws-empty {
  padding: 4rem 0;
  text-align: center;
  color: var(--ws-ink-soft);
}

.ws-empty h2 {
  margin: 0 0 0.75rem;
  color: var(--ws-ink);
  font-family: var(--font-serif, Georgia, serif);
  font-style: italic;
  font-weight: 600;
  font-size: 1.6rem;
}

.ws-empty p {
  margin: 0 0 1.25rem;
  font-size: 1rem;
  line-height: 1.6;
}

.ws-empty__ornament {
  display: block;
  max-width: 120px;
  width: 100%;
  opacity: 0.55;
  margin: 0 auto 1.75rem;
}

.ws-empty__links {
  display: flex;
  justify-content: center;
  gap: 1rem;
  flex-wrap: wrap;
  margin-top: 0.5rem;
}

/* ---- Page chrome --------------------------------------------------------- */

.ws-page__eyebrow {
  font-family: var(--font-sans, sans-serif);
  font-size: 0.7rem;
  letter-spacing: 0.22em;
  text-transform: uppercase;
  color: var(--ws-accent);
  margin: 0 0 0.75rem;
}

.ws-page__title {
  font-family: var(--font-serif, Georgia, serif);
  font-style: italic;
  font-weight: 600;
  font-size: clamp(1.8rem, 3.5vw, 2.6rem);
  letter-spacing: -0.005em;
  margin: 0 0 0.6rem;
  color: var(--ws-ink);
}

.ws-page__lede {
  margin: 0 0 2rem;
  color: var(--ws-ink-soft);
  font-size: 1rem;
  line-height: 1.6;
  max-width: 640px;
}

/* ---- Library card grid --------------------------------------------------- */
/* .wordsearch-card-grid + .wordsearch-card                                   */

.wordsearch-card-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(240px, 1fr));
  gap: 1.5rem;
  margin-top: 2rem;
}

.wordsearch-card {
  display: block;
  text-decoration: none;
  color: inherit;
  background: var(--ws-elevated);
  border: 1px solid var(--ws-hairline);
  border-radius: var(--radius, 6px);
  overflow: hidden;
  transition: border-color 140ms ease, transform 140ms ease, box-shadow 140ms ease;
  box-shadow: var(--shadow-sm);
}

.wordsearch-card:hover {
  border-color: var(--ws-accent);
  transform: translateY(-2px);
  box-shadow: 0 4px 14px color-mix(in srgb, var(--ws-accent) 20%, transparent);
}

.wordsearch-card__cover {
  width: 100%;
  aspect-ratio: 5 / 8;
  object-fit: cover;
  display: block;
}

.wordsearch-card__body {
  padding: 1rem 1.1rem 1.25rem;
}

.wordsearch-card__title {
  font-family: var(--font-serif, Georgia, serif);
  font-style: italic;
  font-weight: 600;
  font-size: 1.05rem;
  margin: 0 0 0.3rem;
  color: var(--ws-ink);
}

.wordsearch-card__meta {
  font-family: var(--font-sans, sans-serif);
  font-size: 0.8rem;
  color: var(--ws-ink-soft);
  margin: 0 0 0.75rem;
  letter-spacing: 0.02em;
}

/* Progress bar — fraction of puzzles solved in this volume. */
.wordsearch-card__progress {
  height: 3px;
  background: var(--ws-hairline);
  border-radius: 999px;
  overflow: hidden;
}

.wordsearch-card__progress-fill {
  height: 100%;
  background: var(--ws-accent);
  border-radius: 999px;
  transition: width 300ms ease;
}

/* Locked variant — volume not yet unlocked by the user. */
.wordsearch-card--locked {
  opacity: 0.55;
  pointer-events: none;
}

.wordsearch-card--locked .wordsearch-card__cover {
  filter: grayscale(0.6);
}

/* ---- Section divider ----------------------------------------------------- */
/* Rendered between easy / medium / hard puzzle bands in the volume page.    */

.wordsearch-section-heading {
  margin: 3rem 0 1rem;
  font-family: var(--font-sans, sans-serif);
  font-size: 0.7rem;
  letter-spacing: 0.24em;
  text-transform: uppercase;
  color: var(--ws-accent);
  font-weight: 600;
  border-top: 1px solid var(--ws-hairline);
  padding-top: 1.5rem;
}

/* ---- Volume cover hero --------------------------------------------------- */

.ws-volume-hero {
  display: grid;
  grid-template-columns: auto 1fr;
  gap: 3rem;
  align-items: start;
  margin: 2rem 0 3rem;
}

@media (max-width: 720px) {
  .ws-volume-hero {
    grid-template-columns: 1fr;
    gap: 1.5rem;
  }
}

.ws-volume-hero__cover {
  width: 220px;
  border-radius: var(--radius, 6px);
  box-shadow: 0 6px 28px color-mix(in srgb, var(--ws-ink) 28%, transparent);
  display: block;
}

@media (max-width: 720px) {
  .ws-volume-hero__cover {
    width: 160px;
    margin: 0 auto;
  }
}

.ws-volume-hero__info {
  display: flex;
  flex-direction: column;
  justify-content: center;
}

.ws-volume-hero__count {
  font-family: var(--font-sans, sans-serif);
  font-size: 0.85rem;
  color: var(--ws-ink-soft);
  margin: 1rem 0 0;
}

/* ---- Puzzle index list --------------------------------------------------- */
/* .wordsearch-puzzle-index                                                   */

.wordsearch-puzzle-index {
  list-style: none;
  padding: 0;
  margin: 0 0 3rem;
}

.wordsearch-puzzle-index__row {
  display: grid;
  grid-template-columns: 3.5rem 1fr auto;
  gap: 0.75rem;
  align-items: baseline;
  padding: 0.6rem 0.6rem;
  border-bottom: 1px solid var(--ws-hairline);
  cursor: pointer;
  outline: none;
  text-decoration: none;
  color: inherit;
  transition: background 120ms ease;
  border-radius: var(--radius-sm, 3px);
}

.wordsearch-puzzle-index__row:hover {
  background: var(--ws-accent-faint);
}

.wordsearch-puzzle-index__num {
  font-family: var(--font-sans, sans-serif);
  font-size: 0.78rem;
  letter-spacing: 0.14em;
  color: var(--ws-ink-muted);
}

.wordsearch-puzzle-index__name {
  font-family: var(--font-serif, Georgia, serif);
  font-style: italic;
  font-size: 1.05rem;
  color: var(--ws-ink);
}

.wordsearch-puzzle-index__band {
  font-family: var(--font-sans, sans-serif);
  font-size: 0.7rem;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--ws-ink-muted);
}

/* ---- Game grid + word list ----------------------------------------------- */
/* .wordsearch-grid + .wordsearch-cell + .wordsearch-stripe                  */
/* .wordsearch-word-list                                                      */

.wordsearch-grid-wrap {
  position: relative;
  display: inline-block;
  overflow: hidden;
  border-radius: 4px;
}

/* Soft volume-cover backdrop. Blurred + dimmed so the grid letters stay
   perfectly readable on top. Toggleable via .wordsearch-grid-wrap--no-bg
   on the wrap. */
.wordsearch-grid-bg {
  position: absolute;
  inset: 0;
  z-index: 0;
  background-size: cover;
  background-position: center;
  background-repeat: no-repeat;
  filter: blur(3px) saturate(0.95);
  opacity: 0.7;
  transform: scale(1.04); /* hides blur halo at the edges */
  pointer-events: none;
  transition: opacity 200ms ease;
}

.wordsearch-grid-wrap--no-bg .wordsearch-grid-bg {
  opacity: 0;
}

.wordsearch-grid {
  position: relative;
  z-index: 1;
  display: grid;
  grid-template-columns: repeat(15, 1fr);
  gap: 0;
  user-select: none;
  touch-action: none;
  border: 2px solid color-mix(in srgb, var(--ws-accent) 55%, transparent);
  background: color-mix(in srgb, var(--ws-paper) 55%, transparent);
}

.wordsearch-grid-wrap--no-bg .wordsearch-grid {
  background: var(--ws-paper);
}

.wordsearch-cell {
  --ws-cell-size: clamp(34px, 4vw, 56px);
  width: var(--ws-cell-size);
  height: var(--ws-cell-size);
  display: flex;
  align-items: center;
  justify-content: center;
  font-family: var(--font-mono, monospace);
  font-size: calc(var(--ws-cell-size) * 0.6);
  font-weight: 700;
  color: var(--ws-ink);
  border-right: 1px solid var(--ws-hairline);
  border-bottom: 1px solid var(--ws-hairline);
  cursor: default;
  transition: background 60ms ease;
}

.wordsearch-cell:nth-child(15n) { border-right: none; }
.wordsearch-cell.is-selected {
  background: var(--ws-accent-soft);
}

/* Stripe: translucent rounded pill laid over found words. Each stripe carries
   its own --stripe-color (set by JS from the harmonic palette) so the grid
   livens up as words come in. Falls back to --ws-accent when --stripe-color
   is unset (e.g. preview stripes during drag). */
.wordsearch-stripe {
  position: absolute;
  pointer-events: none;
  border-radius: 999px;
  background: color-mix(in srgb, var(--stripe-color, var(--ws-accent)) 30%, transparent);
  border: 2px solid color-mix(in srgb, var(--stripe-color, var(--ws-accent)) 65%, transparent);
  transition: opacity 200ms ease;
  z-index: 1;
}

/* Preview stripe — drag-time, always uses --ws-accent (the volume's anchor
   colour) so the user sees a stable preview hue regardless of where the
   final stripe will land in the rotation. */
.wordsearch-stripe--preview {
  background: color-mix(in srgb, var(--ws-accent) 45%, transparent);
  border-color: color-mix(in srgb, var(--ws-accent) 70%, transparent);
  opacity: 0.85;
}

/* Found stripe — opaque, coloured by --stripe-color. */
.wordsearch-stripe--found {
  background: color-mix(in srgb, var(--stripe-color, var(--ws-accent)) 55%, transparent);
  border-color: var(--stripe-color, var(--ws-accent));
  opacity: 1;
}

/* Cell z-index sits above stripes so letters remain readable. */
.wordsearch-cell {
  z-index: 2;
  position: relative;
}

/* Tap-tap touch fallback — first-tap highlight. */
.wordsearch-cell.ws-cell-tap-start {
  background: var(--ws-accent-soft);
  box-shadow: 0 0 0 2px var(--ws-accent);
}

/* ---- Word list panel ---------------------------------------------------- */

.ws-word-list__label {
  font-family: var(--font-sans, sans-serif);
  font-size: 0.7rem;
  letter-spacing: 0.2em;
  text-transform: uppercase;
  color: var(--ws-ink-muted);
  margin: 0 0 0.75rem;
}

.ws-word-list__count {
  font-family: var(--font-sans, sans-serif);
  font-size: 0.78rem;
  color: var(--ws-ink-muted);
  margin: 0.75rem 0 0;
  letter-spacing: 0.04em;
}

/* Word list to the right of (or below, on narrow screens) the grid. */
.wordsearch-word-list {
  list-style: none;
  padding: 0;
  margin: 0;
  display: flex;
  flex-direction: column;
  gap: 0.3rem;
}

.wordsearch-word-list li {
  font-family: var(--font-serif, Georgia, serif);
  font-style: italic;
  font-size: 1.15rem;
  color: var(--ws-ink);
  padding: 0.2rem 0.3rem;
  border-radius: var(--radius-sm, 3px);
  transition: color 160ms ease, text-decoration-color 160ms ease;
}

.wordsearch-word-list .found {
  color: var(--ws-ink-muted);
  text-decoration: line-through;
  text-decoration-color: var(--ws-found-color, var(--ws-accent));
  text-decoration-thickness: 2px;
}

/* ---- Play layout (game screen) ------------------------------------------- */

.ws-play-layout {
  display: grid;
  grid-template-columns: auto 1fr;
  gap: 2.5rem;
  align-items: start;
  margin-top: 2rem;
}

@media (max-width: 820px) {
  .ws-play-layout {
    grid-template-columns: 1fr;
  }
}

.ws-play-layout__meta {
  margin-bottom: 1.5rem;
}

.ws-play-layout__puzzle-name {
  font-family: var(--font-serif, Georgia, serif);
  font-style: italic;
  font-weight: 600;
  font-size: 1.5rem;
  margin: 0 0 0.25rem;
  color: var(--ws-ink);
}

.ws-play-layout__puzzle-meta {
  font-family: var(--font-sans, sans-serif);
  font-size: 0.82rem;
  letter-spacing: 0.06em;
  color: var(--ws-ink-soft);
  margin: 0;
}

/* ---- Placeholder (Phase 5 not yet rendered) ------------------------------ */

.ws-placeholder {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 1rem;
  padding: 4rem 2rem;
  border: 1px dashed var(--ws-hairline-mid);
  border-radius: var(--radius, 6px);
  text-align: center;
  color: var(--ws-ink-muted);
  background: var(--ws-accent-faint);
}

.ws-placeholder p {
  margin: 0;
  font-size: 0.95rem;
  line-height: 1.6;
  max-width: 480px;
}

/* ---- Today hero (home screen) -------------------------------------------- */

.ws-today-hero {
  display: grid;
  grid-template-columns: minmax(300px, 1fr) 1.1fr;
  border-bottom: 1px solid var(--ws-hairline);
}

@media (max-width: 860px) {
  .ws-today-hero {
    grid-template-columns: 1fr;
  }
}

.ws-today-hero__left {
  padding: 4rem 3rem;
  border-right: 1px solid var(--ws-hairline);
  display: flex;
  flex-direction: column;
  justify-content: center;
}

@media (max-width: 860px) {
  .ws-today-hero__left {
    border-right: none;
    border-bottom: 1px solid var(--ws-hairline);
    padding: 3rem 2rem;
  }
}

.ws-today-hero__right {
  padding: 3rem 2.5rem;
  display: flex;
  align-items: center;
  justify-content: center;
  background:
    radial-gradient(ellipse 50% 60% at 50% 50%, color-mix(in srgb, var(--ws-accent) 6%, transparent), transparent 70%),
    var(--ws-surface);
}

.ws-today-hero__title {
  font-family: var(--font-serif, Georgia, serif);
  font-style: italic;
  font-weight: 600;
  font-size: clamp(2rem, 4vw, 3rem);
  line-height: 1.05;
  margin: 0 0 1.25rem;
  color: var(--ws-ink);
}

.ws-today-hero__lede {
  color: var(--ws-ink-soft);
  line-height: 1.65;
  margin: 0 0 2rem;
  max-width: 440px;
  font-size: 1.05rem;
}

/* ---- Grid frame (wraps chrome + grid-wrap) ------------------------------ */

.wordsearch-grid-frame {
  display: inline-flex;
  flex-direction: column;
  gap: 0;
}

/* Chrome row: cover thumb on the left, pips + timer on the right. */
.wordsearch-grid-chrome {
  display: flex;
  align-items: center;
  gap: 0.75rem;
  padding: 0.4rem 0.5rem;
  background: var(--ws-paper);
  border: 2px solid color-mix(in srgb, var(--ws-accent) 55%, transparent);
  border-bottom: 1px solid var(--ws-hairline);
}

/* Centred title slot — auto-shrinks via clamp() and ellipsis if the
   chrome row is tight. flex: 1 1 0 lets the title eat the spare middle
   space; min-width: 0 is required so flex-shrink + ellipsis cooperate. */
.wordsearch-grid-chrome__title {
  flex: 1 1 0;
  min-width: 0;
  text-align: center;
  padding: 0 0.75rem;
}

.wordsearch-grid-chrome__title .ws-play-layout__puzzle-name {
  margin: 0;
  font-family: var(--font-serif, Georgia, serif);
  font-style: italic;
  font-weight: 600;
  font-size: clamp(1rem, 1.4vw, 1.6rem);
  line-height: 1.1;
  color: var(--ws-ink);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.wordsearch-grid-chrome__right {
  display: flex;
  align-items: center;
  gap: 0.75rem;
  flex-shrink: 0;
}

/* ---- Cover thumbnail ---------------------------------------------------- */

.ws-cover-thumb {
  display: block;
  flex-shrink: 0;
  line-height: 0;
  border-radius: var(--radius-sm, 3px);
  overflow: hidden;
  box-shadow: 0 1px 4px color-mix(in srgb, var(--ws-ink) 25%, transparent);
  transition: box-shadow 140ms ease, transform 140ms ease;
}

.ws-cover-thumb:hover {
  transform: translateY(-1px);
  box-shadow: 0 3px 10px color-mix(in srgb, var(--ws-accent) 30%, transparent);
}

.ws-cover-thumb__img {
  display: block;
  width: 38px;
  height: 60px;
  object-fit: cover;
}

/* ---- Difficulty pips ---------------------------------------------------- */

.ws-difficulty-pips {
  display: inline-flex;
  align-items: center;
  gap: 4px;
}

.ws-difficulty-pip {
  width: 7px;
  height: 7px;
  border-radius: 50%;
  border: 1.5px solid color-mix(in srgb, var(--ws-accent) 60%, transparent);
  background: transparent;
  display: inline-block;
  transition: background 200ms ease;
}

.ws-difficulty-pip.is-filled {
  background: var(--ws-accent);
  border-color: var(--ws-accent);
}

/* ---- Timer -------------------------------------------------------------- */

.ws-timer {
  font-family: var(--font-mono, monospace);
  font-size: 0.82rem;
  letter-spacing: 0.06em;
  color: var(--ws-ink-soft);
  min-width: 3.4em;
  text-align: right;
}

/* ---- Leftover-cell tint ------------------------------------------------- */

.wordsearch-cell.leftover-tint {
  background: color-mix(in srgb, var(--ws-accent) 22%, transparent);
  transition: background 200ms ease;
}

/* ---- Quote reveal link -------------------------------------------------- */

.ws-quote-container {
  margin-top: 1rem;
}

.ws-reveal-link {
  display: inline-block;
  font-family: var(--font-serif, Georgia, serif);
  font-style: italic;
  font-size: 0.95rem;
  color: var(--ws-accent);
  text-decoration: underline;
  text-decoration-color: color-mix(in srgb, var(--ws-accent) 45%, transparent);
  text-underline-offset: 3px;
  cursor: pointer;
  transition: text-decoration-color 140ms ease, color 140ms ease;
  padding: 0.25rem 0;
}

.ws-reveal-link:hover {
  color: color-mix(in srgb, var(--ws-accent) 85%, var(--ws-ink));
  text-decoration-color: var(--ws-accent);
}

/* ---- Hidden quote panel ------------------------------------------------- */

.ws-hidden-quote-panel {
  margin: 0;
  border-top: 2px solid var(--ws-accent);
  border-bottom: 2px solid var(--ws-accent);
  background: var(--ws-accent-faint);
  border-radius: var(--radius-sm, 3px);
  animation: ws-quote-in 350ms ease both;
  padding: 1rem 1.25rem 0.75rem;
}

.ws-hidden-quote {
  margin: 0;
  padding: 0.25rem 0;
  font-family: var(--font-serif, Georgia, serif);
  font-style: italic;
  font-size: 1.2rem;
  line-height: 1.7;
  color: var(--ws-ink);
}

.ws-hidden-quote__word {
  cursor: pointer;
  border-radius: 3px;
  padding: 0 2px;
  transition: background 120ms ease, color 120ms ease;
}

.ws-hidden-quote__word:hover {
  background: color-mix(in srgb, var(--ws-accent) 30%, transparent);
}

.ws-hidden-quote__close {
  display: inline-block;
  margin-top: 0.6rem;
  background: transparent;
  border: 1px solid color-mix(in srgb, var(--ws-accent) 50%, transparent);
  color: var(--ws-ink-soft);
  font-family: var(--font-sans, sans-serif);
  font-size: 0.75rem;
  letter-spacing: 0.06em;
  padding: 0.3rem 0.7rem;
  border-radius: var(--radius-sm, 3px);
  cursor: pointer;
  transition: color 120ms ease, border-color 120ms ease, background 120ms ease;
}

.ws-hidden-quote__close:hover {
  color: var(--ws-ink);
  border-color: var(--ws-accent);
  background: color-mix(in srgb, var(--ws-accent) 10%, transparent);
}

@keyframes ws-quote-in {
  from { opacity: 0; transform: translateY(6px); }
  to   { opacity: 1; transform: translateY(0); }
}

/* ---- Reveal mode: hide stripes, paint per-word leftover cells ---------- */

body.wordsearch-quote-revealed .wordsearch-stripe--found {
  display: none;
}

/* When in reveal mode, the soft accent leftover-tint background is replaced
   by per-word vivid colour (set inline by paintQuoteHighlights). */
body.wordsearch-quote-revealed .wordsearch-cell.leftover-tint {
  background: transparent;
}

body.wordsearch-quote-revealed .wordsearch-cell.ws-quote-letter {
  background: var(--ws-quote-bg);
  color: var(--ws-quote-text);
  font-weight: 700;
  transition: background 180ms ease, color 180ms ease, transform 120ms ease;
}

/* Hovering a word in the quote panel pulses the matching cells. */
body.wordsearch-quote-revealed .wordsearch-cell.ws-quote-letter--hover {
  outline: 2px solid var(--ws-quote-text);
  outline-offset: -2px;
  transform: scale(1.08);
  z-index: 3;
  filter: brightness(1.15);
}

/* ---- Drag hint (first-visit affordance) --------------------------------- */

.ws-drag-hint {
  /* Positioned absolutely inside .wordsearch-grid-wrap via JS inline style. */
  filter: drop-shadow(0 1px 3px color-mix(in srgb, var(--ws-accent) 40%, transparent));
}

/* ---- Responsive tweaks --------------------------------------------------- */

@media (max-width: 720px) {
  .wordsearch-body {
    padding: 2rem 1rem 4rem;
  }
  .wordsearch-card-grid {
    grid-template-columns: repeat(auto-fill, minmax(160px, 1fr));
    gap: 1rem;
  }
  .wordsearch-puzzle-index__row {
    grid-template-columns: 2.5rem 1fr auto;
  }
}

/* ---- Redeem form -------------------------------------------------------- */

.ws-redeem-form {
  display: grid;
  grid-template-columns: 1fr auto;
  grid-template-areas:
    "label  label"
    "input  submit"
    "msg    msg";
  gap: 0.6rem 0.75rem;
  max-width: 480px;
  margin-top: 1.5rem;
}

.ws-redeem-form__label {
  grid-area: label;
  font-family: var(--font-sans, sans-serif);
  font-size: 0.7rem;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: var(--ws-ink-muted);
}

.ws-redeem-form__input {
  grid-area: input;
  font-family: var(--font-mono, ui-monospace, monospace);
  font-size: 1.05rem;
  letter-spacing: 0.06em;
  padding: 0.65rem 0.85rem;
  background: var(--ws-elevated);
  border: 1px solid var(--ws-hairline-mid);
  border-radius: var(--radius-sm, 3px);
  color: var(--ws-ink);
  box-sizing: border-box;
}

.ws-redeem-form__input:focus {
  outline: none;
  border-color: var(--ws-accent);
}

.ws-redeem-form .ws-cta {
  grid-area: submit;
  align-self: stretch;
}

.ws-redeem-form__message {
  grid-area: msg;
  margin: 0;
  font-size: 0.9rem;
  min-height: 1.2em;
}

.ws-redeem-form__message.is-ok {
  color: var(--ws-accent);
}

.ws-redeem-form__message.is-error {
  color: var(--error, var(--ws-ink));
}

/* ---- Word-list head row + sort toggle ----------------------------------- */

.ws-word-list__head {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 0.75rem;
  margin: 0 0 0.75rem;
}

.ws-word-list__head .ws-word-list__label {
  margin: 0;
}

.ws-word-list__sort {
  background: transparent;
  border: 1px solid var(--ws-hairline);
  color: var(--ws-ink-soft);
  font-family: var(--font-sans, sans-serif);
  font-size: 0.7rem;
  letter-spacing: 0.08em;
  padding: 0.25rem 0.55rem;
  border-radius: var(--radius-sm, 3px);
  cursor: pointer;
  transition: color 120ms ease, border-color 120ms ease;
}

.ws-word-list__sort:hover {
  color: var(--ws-ink);
  border-color: var(--ws-accent);
}

/* ---- Zen-mode toggle ---------------------------------------------------- */

.ws-zen-toggle,
.ws-backdrop-toggle {
  background: transparent;
  border: 1px solid var(--ws-hairline);
  color: var(--ws-ink-soft);
  font-family: var(--font-sans, sans-serif);
  font-size: 0.7rem;
  letter-spacing: 0.1em;
  padding: 0.3rem 0.7rem;
  border-radius: var(--radius-sm, 3px);
  cursor: pointer;
  margin-left: 0.75rem;
  transition: color 120ms ease, border-color 120ms ease;
}

.ws-zen-toggle:hover,
.ws-backdrop-toggle:hover {
  color: var(--ws-ink);
  border-color: var(--ws-accent);
}

.ws-zen-toggle[aria-pressed="true"],
.ws-backdrop-toggle[aria-pressed="true"] {
  color: var(--ws-accent);
  border-color: var(--ws-accent);
}

/* ---- Zen mode (body class — hides chrome, enlarges puzzle) ------------- */

body.wordsearch-zen #topbar,
body.wordsearch-zen .topbar,
body.wordsearch-zen .wordsearch-topbar,
body.wordsearch-zen .ws-page__eyebrow,
body.wordsearch-zen .ws-play-layout__puzzle-meta,
body.wordsearch-zen .ws-quote-container,
body.wordsearch-zen .ws-hidden-quote-panel,
body.wordsearch-zen .ws-reveal-link {
  display: none !important;
}

body.wordsearch-zen .ws-play-layout__puzzle-name {
  font-size: clamp(1.6rem, 2.6vw, 2.2rem);
  margin: 0.3rem 0;
}

/* Zen-mode cell size: fit the puzzle inside the viewport so the user never
   has to scroll. Take the smaller of:
   - vertical: (viewport height − chrome) / 15 rows
   - horizontal: (viewport width − word list − margins) / 15 cols
   The chrome reservation covers title, grid frame chrome (cover thumb +
   timer row), and a small bottom buffer. The word-list reservation keeps
   room for the side panel without forcing horizontal scroll. */
body.wordsearch-zen .wordsearch-cell {
  --ws-cell-size: min(
    calc((100vh - 240px) / 15),
    calc((100vw - 360px) / 15),
    72px
  );
  font-size: calc(var(--ws-cell-size) * 0.62);
}

body.wordsearch-zen .wordsearch-word-list li {
  font-size: clamp(0.95rem, 1.2vw, 1.25rem);
  padding: 0.2rem 0.4rem;
}

body.wordsearch-zen .ws-word-list__count,
body.wordsearch-zen .ws-word-list__label,
body.wordsearch-zen .ws-word-list__sort {
  font-size: 0.85rem;
}

body.wordsearch-zen .wordsearch-body {
  padding: 0.5rem 1rem;
  max-width: none;
}

body.wordsearch-zen .ws-play-layout {
  gap: 1.25rem;
  margin: 0.5rem auto 0;
  width: fit-content;
  justify-content: center;
}

body.wordsearch-zen .ws-play-layout__meta {
  text-align: center;
  margin-bottom: 0.4rem;
}

body.wordsearch-zen .ws-play-layout__grid {
  display: flex;
  flex-direction: column;
  align-items: center;
}

/* Word list in zen: 2-column layout so a long word list doesn't push the
   grid past the viewport. The wider 320px column accommodates two columns
   at the smaller in-zen font without forcing a scroll bar. */
body.wordsearch-zen .ws-play-layout__words {
  max-width: 320px;
}

body.wordsearch-zen .wordsearch-word-list {
  display: grid;
  grid-template-columns: 1fr 1fr;
  column-gap: 0.75rem;
  row-gap: 0.15rem;
}

body.wordsearch-zen .ws-timer {
  font-size: 1.1rem;
}
