/* =========================================================================
   Sentle - sequential sentence-guessing game
   SENTLE REDESIGN - see masterprompt.md for
   the full design rationale (§2 covers the palette/type/signature-element
   reasoning behind everything below).

   Mobile-first throughout: base rules target narrow viewports first,
   since content clipping on <480px is a documented, recurring bug class
   elsewhere on the site (masterprompt §1.4) that this must not repeat.
   Every tile/gap dimension below is a clamp(), not a fixed px value.

   Restraint note: this file spends its one deliberate visual risk on
   the word-lock "stamp" moment and the end-of-game cascade (§2.3). The
   tile flip and invalid-guess shake are both quick and functional, on
   purpose -- not everything needs to be a moment.
   ========================================================================= */

#sentle-root {
  /* ---- Base tokens ---------------------------------------------------
     --sentle-indigo / --sentle-brass are the two deliberate accent
     choices (masterprompt §2.2). --sentle-correct / --sentle-present
     stay close to Wordle convention on purpose -- this is the one place
     where matching expectation beats novelty. The light-mode ink and
     the real sitewide #F8F9FC anchor (from quizthespire.com's
     theme-color meta tag) are what the whole palette is built from.
     ---------------------------------------------------------------- */
  --sentle-indigo: #3F3AA6;
  --sentle-brass: #C08A3E;
  --sentle-correct: #2F9E63;
  --sentle-present: #D9A441;
  --sentle-absent-light: #8B8FA3;
  --sentle-absent-dark: #454759;
  --sentle-ink-light: #1C1E2A;
  --sentle-ink-dark: #E7E8F2;

  /* Theme-resolved aliases -- every rule below reads these, never the
     raw light/dark values above, so light/dark switching only ever
     needs to happen here and in the two override blocks right below. */
  --sentle-fg: var(--sentle-ink-light);
  --sentle-absent-tile: var(--sentle-absent-light);
  --sentle-tile-empty-border: color-mix(in srgb, var(--sentle-ink-light) 25%, transparent);
  --sentle-border: color-mix(in srgb, var(--sentle-ink-light) 12%, transparent);

  --sentle-border-radius: 8px;
  --sentle-tile-gap: clamp(4px, 1.2vw, 8px);
  --sentle-tile-size: clamp(2.1rem, 8vw, 3.4rem);
  --sentle-font-ui: "Manrope", -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif;
  --sentle-font-tile: "IBM Plex Mono", ui-monospace, "SFMono-Regular", Menlo, monospace;

  font-family: var(--sentle-font-ui);
  color: var(--sentle-fg);
  max-width: 640px;
  margin-inline: auto;
  padding-inline: clamp(12px, 4vw, 24px);
}

#sentle-root,
#sentle-root *,
#sentle-root *::before,
#sentle-root *::after {
  box-sizing: border-box;
}

@media (prefers-color-scheme: dark) {
  #sentle-root {
    --sentle-fg: var(--sentle-ink-dark);
    --sentle-absent-tile: var(--sentle-absent-dark);
    --sentle-tile-empty-border: color-mix(in srgb, var(--sentle-ink-dark) 30%, transparent);
    --sentle-border: color-mix(in srgb, var(--sentle-ink-dark) 16%, transparent);
  }
}

/* Mirrors the block above for a site that toggles a [data-theme]
   attribute rather than relying only on the OS-level setting -- Sentle
   should follow whichever the rest of quizthespire.com actually uses.
   Harmless to keep both; only one will ever apply at a time. */
[data-theme="dark"] #sentle-root {
  --sentle-fg: var(--sentle-ink-dark);
  --sentle-absent-tile: var(--sentle-absent-dark);
  --sentle-tile-empty-border: color-mix(in srgb, var(--sentle-ink-dark) 30%, transparent);
  --sentle-border: color-mix(in srgb, var(--sentle-ink-dark) 16%, transparent);
}

/* -------------------------------------------------------------------
   Sentence banner -- the signature element (masterprompt §2.3). Word
   groups sit on a shared baseline like type set on a line: solved
   words sit flush on the rule, the active word's attempt history
   stacks upward above its position, and unreached words are empty
   outlines already holding their place and length in line.
   ------------------------------------------------------------------- */

.sentle-banner {
  display: flex;
  flex-wrap: wrap;
  align-items: flex-end;
  gap: clamp(6px, 2vw, 14px);
  padding-block: 24px 16px;
  border-bottom: 2px solid var(--sentle-border);
  margin-bottom: 20px;
  transition: border-color 400ms ease;
}

.sentle-banner.is-complete {
  border-bottom-color: var(--sentle-brass);
}

.sentle-word-group {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
}

.sentle-word-rows {
  display: flex;
  flex-direction: column-reverse; /* newest attempt row nearest the baseline */
  gap: var(--sentle-tile-gap);
}

.sentle-tile-row {
  display: flex;
  gap: var(--sentle-tile-gap);
}

/* Active word's current (unsubmitted) draft gets a touch of emphasis
   so it's unambiguous where typing is going, especially useful once
   a word has a couple of past-attempt rows stacked above it. The
   draft row is always the LAST DOM child (game.js appends past
   attempts first, draft last) -- :last-child here, deliberately not
   :first-child, since column-reverse changes paint order but not
   which element these pseudo-classes match. */
.sentle-word-group.is-active .sentle-tile-row:last-child .sentle-tile.is-empty,
.sentle-word-group.is-active .sentle-tile-row:last-child .sentle-tile.is-filled {
  border-color: var(--sentle-indigo);
}

/* -------------------------------------------------------------------
   Tiles
   ------------------------------------------------------------------- */

.sentle-tile {
  width: var(--sentle-tile-size);
  height: var(--sentle-tile-size);
  display: flex;
  align-items: center;
  justify-content: center;
  font-family: var(--sentle-font-tile);
  font-size: calc(var(--sentle-tile-size) * 0.42);
  font-weight: 600;
  text-transform: uppercase;
  line-height: 1;
  border-radius: calc(var(--sentle-border-radius) * 0.6);
  border: 2px solid var(--sentle-tile-empty-border);
  background: transparent;
  color: var(--sentle-fg);
}

.sentle-tile.is-filled {
  border-color: color-mix(in srgb, var(--sentle-fg) 55%, transparent);
}

.sentle-tile.is-correct {
  background: var(--sentle-correct);
  border-color: var(--sentle-correct);
  color: white;
}

.sentle-tile.is-present {
  background: var(--sentle-present);
  border-color: var(--sentle-present);
  color: white;
}

.sentle-tile.is-absent {
  background: var(--sentle-absent-tile);
  border-color: var(--sentle-absent-tile);
  color: white;
}

/* Auto-revealed (attempts exhausted), not solved -- deliberately NOT
   solid green. It says plainly that this word was given, not earned
   (masterprompt §2.4). */
.sentle-tile.is-revealed {
  background: transparent;
  border-color: var(--sentle-brass);
  border-style: dashed;
  color: var(--sentle-brass);
}

/* -------------------------------------------------------------------
   Animation: reveal flip
   Triggered only on the specific row game.js just judged (via the
   transient .is-revealing class it adds and removes itself) -- never
   tied to the persistent state classes above, so it can't replay on
   an unrelated re-render. Staggered left to right, capped at 8 tiles
   which covers every word in the current bank.
   ------------------------------------------------------------------- */

.sentle-tile.is-revealing {
  animation: sentle-flip 420ms ease both;
}

.sentle-tile-row .sentle-tile.is-revealing:nth-child(1) { animation-delay: 0ms; }
.sentle-tile-row .sentle-tile.is-revealing:nth-child(2) { animation-delay: 90ms; }
.sentle-tile-row .sentle-tile.is-revealing:nth-child(3) { animation-delay: 180ms; }
.sentle-tile-row .sentle-tile.is-revealing:nth-child(4) { animation-delay: 270ms; }
.sentle-tile-row .sentle-tile.is-revealing:nth-child(5) { animation-delay: 360ms; }
.sentle-tile-row .sentle-tile.is-revealing:nth-child(6) { animation-delay: 450ms; }
.sentle-tile-row .sentle-tile.is-revealing:nth-child(7) { animation-delay: 540ms; }
.sentle-tile-row .sentle-tile.is-revealing:nth-child(8) { animation-delay: 630ms; }

@keyframes sentle-flip {
  0%   { transform: rotateX(0deg); }
  50%  { transform: rotateX(90deg); }
  100% { transform: rotateX(0deg); }
}

/* -------------------------------------------------------------------
   Animation: lock-in stamp -- the signature moment (masterprompt
   §2.3). A brief scale + brass glow-ring when a word settles onto
   the baseline. Also driven by a transient class game.js adds/removes
   itself, for the same replay-safety reason as the flip above.
   ------------------------------------------------------------------- */

.sentle-word-group.is-locking-in {
  animation: sentle-lock-in 560ms cubic-bezier(0.34, 1.56, 0.64, 1);
}

@keyframes sentle-lock-in {
  0%   { transform: scale(1); }
  35%  { transform: scale(1.08); filter: drop-shadow(0 0 6px color-mix(in srgb, var(--sentle-brass) 65%, transparent)); }
  100% { transform: scale(1); filter: drop-shadow(0 0 0 transparent); }
}

/* -------------------------------------------------------------------
   Animation: invalid-guess shake
   ------------------------------------------------------------------- */

.sentle-word-group.is-shaking {
  animation: sentle-shake 480ms ease;
}

@keyframes sentle-shake {
  10%, 90%      { transform: translateX(-1px); }
  20%, 80%      { transform: translateX(2px); }
  30%, 50%, 70% { transform: translateX(-4px); }
  40%, 60%      { transform: translateX(4px); }
}

/* -------------------------------------------------------------------
   Animation: completion cascade -- the one other deliberate moment.
   Each word settles in with a short stagger once the whole sentence
   is done; everything else in this file stays quick and functional
   by comparison, on purpose.
   ------------------------------------------------------------------- */

.sentle-banner.is-complete .sentle-word-group {
  animation: sentle-settle 380ms ease both;
}

.sentle-banner.is-complete .sentle-word-group:nth-child(1) { animation-delay: 0ms; }
.sentle-banner.is-complete .sentle-word-group:nth-child(2) { animation-delay: 70ms; }
.sentle-banner.is-complete .sentle-word-group:nth-child(3) { animation-delay: 140ms; }
.sentle-banner.is-complete .sentle-word-group:nth-child(4) { animation-delay: 210ms; }
.sentle-banner.is-complete .sentle-word-group:nth-child(5) { animation-delay: 280ms; }
.sentle-banner.is-complete .sentle-word-group:nth-child(6) { animation-delay: 350ms; }
.sentle-banner.is-complete .sentle-word-group:nth-child(7) { animation-delay: 420ms; }
.sentle-banner.is-complete .sentle-word-group:nth-child(8) { animation-delay: 490ms; }

@keyframes sentle-settle {
  0%   { opacity: 0.4; transform: translateY(6px); }
  100% { opacity: 1;   transform: translateY(0); }
}

/* -------------------------------------------------------------------
   Active-word hint panel
   ------------------------------------------------------------------- */

.sentle-active-panel {
  margin-bottom: 18px;
}

.sentle-hint-tags {
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
  margin-bottom: 6px;
}

.sentle-tag {
  font-size: 0.72rem;
  font-weight: 600;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  padding: 3px 8px;
  border-radius: 999px;
}

.sentle-tag--pos {
  background: color-mix(in srgb, var(--sentle-indigo) 14%, transparent);
  color: var(--sentle-indigo);
}

.sentle-tag--hint {
  background: color-mix(in srgb, var(--sentle-brass) 16%, transparent);
  color: var(--sentle-brass);
}

.sentle-attempts {
  font-size: 0.85rem;
  color: color-mix(in srgb, var(--sentle-fg) 65%, transparent);
  margin: 0;
}

/* -------------------------------------------------------------------
   Keyboard
   ------------------------------------------------------------------- */

.sentle-keyboard {
  display: flex;
  flex-direction: column;
  gap: 6px;
  margin-top: 20px;
}

.sentle-keyboard-row {
  display: flex;
  justify-content: center;
  gap: 5px;
}

.sentle-key {
  font-family: var(--sentle-font-ui);
  font-weight: 600;
  font-size: 0.8rem;
  border: none;
  border-radius: 6px;
  background: color-mix(in srgb, var(--sentle-fg) 10%, transparent);
  color: var(--sentle-fg);
  min-width: clamp(24px, 8vw, 40px);
  max-width: 44px;
  height: 46px;
  flex: 1;
  display: flex;
  align-items: center;
  justify-content: center;
  cursor: pointer;
  transition: background 140ms ease, transform 140ms ease;
}

.sentle-key.is-wide {
  max-width: 62px;
  font-size: 0.68rem;
}

.sentle-key:active {
  transform: scale(0.92);
}

.sentle-key.is-correct { background: var(--sentle-correct); color: white; }
.sentle-key.is-present { background: var(--sentle-present); color: white; }
.sentle-key.is-absent  { background: var(--sentle-absent-tile); color: white; }

/* -------------------------------------------------------------------
   Completion panel, loading & error states
   ------------------------------------------------------------------- */

.sentle-completion {
  margin-top: 24px;
  padding: 16px;
  border-radius: var(--sentle-border-radius);
  background: color-mix(in srgb, var(--sentle-brass) 8%, transparent);
  text-align: center;
}

.sentle-share-preview {
  font-family: var(--sentle-font-tile);
  font-size: 0.9rem;
  white-space: pre;
  overflow-x: auto;
  margin: 10px 0;
}

.sentle-share-button {
  font-family: var(--sentle-font-ui);
  font-weight: 600;
  background: var(--sentle-indigo);
  color: white;
  border: none;
  border-radius: 999px;
  padding: 10px 20px;
  cursor: pointer;
}

.sentle-loading,
.sentle-error {
  padding: 40px 0;
  text-align: center;
  color: color-mix(in srgb, var(--sentle-fg) 65%, transparent);
}

/* -------------------------------------------------------------------
   Accessibility
   ------------------------------------------------------------------- */

.visually-hidden {
  position: absolute;
  width: 1px;
  height: 1px;
  padding: 0;
  margin: -1px;
  overflow: hidden;
  clip: rect(0, 0, 0, 0);
  white-space: nowrap;
  border: 0;
}

#sentle-root button:focus-visible {
  outline: 3px solid var(--sentle-indigo);
  outline-offset: 2px;
}

@media (prefers-reduced-motion: reduce) {
  #sentle-root *,
  #sentle-root *::before,
  #sentle-root *::after {
    animation-duration: 0.001ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.001ms !important;
  }
}

/* -------------------------------------------------------------------
   Larger screens -- mobile-first base above already carries most of
   the responsive weight via clamp(), so this is a light enhancement
   pass, not a second layout.
   ------------------------------------------------------------------- */

@media (min-width: 640px) {
  .sentle-keyboard-row {
    gap: 6px;
  }
  .sentle-key {
    height: 52px;
  }
}
