/* Fallback slots, used only if the shared shell hands back fewer than it names. */
.game-flag .flag-slot + .flag-slot {
  margin-top: 1rem;
}

.game-flag .flag-play {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 1rem;
}

.game-flag .flag-stage {
  position: relative;
  width: 100%;
  max-width: 34rem;
  aspect-ratio: 4 / 3;
  border-radius: var(--r-lg);
  overflow: hidden;
  background: var(--md-surface-container-lowest);
  box-shadow: var(--e2);
  isolation: isolate;
}

.game-flag .flag-stage::after {
  content: '';
  position: absolute;
  inset: 0;
  z-index: 3;
  pointer-events: none;
  border-radius: inherit;
  box-shadow: inset 0 0 0 1px var(--md-outline-variant);
}

.game-flag .flag-frame {
  position: absolute;
  inset: 0;
  z-index: 1;
}

.game-flag .flag-img {
  display: block;
  width: 100%;
  height: 100%;
  object-fit: contain;
  user-select: none;
  transition: filter var(--dur-long) var(--ease-emph);
}

.game-flag .flag-stage[data-grey='1'] .flag-img {
  filter: grayscale(1) contrast(1.06);
}

.game-flag .flag-stage[data-broken='1'] .flag-frame {
  background:
    repeating-linear-gradient(
      135deg,
      var(--md-surface-container-low) 0 12px,
      var(--md-surface-container-normal) 12px 24px
    );
}

.game-flag .flag-frame.is-won {
  animation: flag-reveal var(--dur-long) var(--ease-spring) both;
}

@keyframes flag-reveal {
  from { transform: scale(0.9); opacity: 0.35; }
  60%  { transform: scale(1.015); opacity: 1; }
  to   { transform: none; opacity: 1; }
}

/* Tiles */

.game-flag .flag-tiles {
  position: absolute;
  inset: 0;
  z-index: 2;
  display: grid;
  gap: 2px;
  grid-template-columns: repeat(var(--flag-cols, 3), 1fr);
  grid-template-rows: repeat(var(--flag-rows, 3), 1fr);
  padding: 2px;
}

.game-flag .flag-tile {
  border-radius: calc(var(--r-xs) / 2);
  background:
    linear-gradient(
      150deg,
      color-mix(in oklab, var(--md-surface-container-highest) 88%, var(--md-primary)),
      var(--md-surface-container-high)
    );
  box-shadow: inset 0 0 0 1px color-mix(in oklab, var(--md-outline) 28%, transparent);
  transform-origin: 50% 50%;
  transition:
    opacity var(--dur-med) var(--ease-emph),
    transform var(--dur-med) var(--ease-emph);
}

.game-flag .flag-tile.is-gone {
  opacity: 0;
  transform: scale(0.55) rotate(-7deg);
}

.game-flag .flag-tile.no-anim {
  transition: none;
  transition-delay: 0s;
}

/* Counter and hint chips */

.game-flag .flag-meta {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: center;
  gap: 0.5rem 1rem;
  width: 100%;
  max-width: 34rem;
}

.game-flag .flag-counter {
  display: flex;
  align-items: center;
  gap: 0.625rem;
}

.game-flag .flag-pips {
  display: flex;
  gap: 0.3125rem;
}

.game-flag .flag-pip {
  width: 0.75rem;
  height: 0.75rem;
  border-radius: var(--r-full);
  box-shadow: inset 0 0 0 2px var(--md-outline);
}

.game-flag .flag-pip[data-state='wrong'] {
  border-radius: calc(var(--r-xs) / 2);
  background: var(--md-error);
  box-shadow: none;
}

.game-flag .flag-pip[data-state='right'] {
  background: var(--md-primary);
  box-shadow: none;
}

.game-flag .flag-pips-label {
  font-size: 0.8125rem;
  color: var(--md-on-surface-variant);
}

.game-flag .flag-chips {
  display: flex;
  flex-wrap: wrap;
  gap: 0.5rem;
}

.game-flag .flag-chip {
  display: inline-flex;
  align-items: center;
  gap: 0.375rem;
  font-size: 0.8125rem;
}

/* app.css may outline .chip with either a border or an inset shadow; clear both
   so the tonal fill reads as one solid chip either way. */
.game-flag .flag-chip.is-hint {
  background: var(--md-tertiary-container);
  color: var(--md-on-tertiary-container);
  border-color: transparent;
  box-shadow: none;
}

.game-flag .flag-chip.is-warn {
  background: var(--md-error-container);
  color: var(--md-on-error-container);
  border-color: transparent;
  box-shadow: none;
}

/* Guess list */

.game-flag .flag-side {
  display: flex;
  flex-direction: column;
  gap: 0.75rem;
}

.game-flag .flag-side-title {
  display: flex;
  align-items: center;
  gap: 0.5rem;
  margin: 0;
  font-size: 0.9375rem;
  font-weight: 600;
  letter-spacing: 0.02em;
  text-transform: uppercase;
  color: var(--md-on-surface-variant);
}

.game-flag .flag-guesses {
  display: flex;
  flex-direction: column;
  gap: 0.5rem;
  margin: 0;
  padding: 0;
  list-style: none;
}

.game-flag .flag-guess {
  display: grid;
  grid-template-columns: 1.5rem minmax(0, 1fr);
  align-items: center;
  gap: 0.5rem;
}

.game-flag .flag-guess.is-new {
  animation: flag-row-in var(--dur-med) var(--ease-emph) both;
}

.game-flag .flag-guess > :not(.flag-guess-no) {
  min-width: 0;
}

@keyframes flag-row-in {
  from { opacity: 0; transform: translateY(-0.375rem); }
  to   { opacity: 1; transform: none; }
}

.game-flag .flag-guess-no {
  font-size: 0.8125rem;
  text-align: center;
  color: var(--md-on-surface-variant);
}

.game-flag .flag-withheld {
  grid-column: 2;
  display: flex;
  align-items: center;
  gap: 0.375rem;
  margin: 0;
  padding: 0 0.25rem;
  font-size: 0.75rem;
  color: var(--md-on-surface-variant);
}

.game-flag .flag-empty {
  display: flex;
  align-items: center;
  gap: 0.75rem;
  padding: 1rem;
  border: 1px dashed var(--md-outline-variant);
  border-radius: var(--r-md);
  color: var(--md-on-surface-variant);
}

.game-flag .flag-empty p {
  margin: 0;
  font-size: 0.875rem;
}

.game-flag .flag-empty-icon {
  flex: none;
  font-size: 1.5rem;
  opacity: 0.7;
}

/* Footer: input, bonus round, result */

.game-flag .flag-footer {
  display: flex;
  flex-direction: column;
  gap: 0.375rem;
}

.game-flag .flag-alert {
  display: flex;
  align-items: center;
  gap: 0.375rem;
  margin: 0;
  padding: 0 0.25rem;
  font-size: 0.8125rem;
  color: var(--md-error);
}

/* Must follow the rule above: equal specificity, so the later one wins. */
.game-flag .flag-alert:empty {
  display: none;
}

.game-flag .flag-done {
  display: flex;
  flex-direction: column;
  gap: 1rem;
  padding: 1rem;
  border-radius: var(--r-lg);
}

/* tabindex="-1": focus is moved here when the guess field it replaced held it. */
.game-flag .flag-done:focus-visible {
  outline: 2px solid var(--md-primary);
  outline-offset: 2px;
}

.game-flag .flag-done-head {
  display: flex;
  align-items: flex-start;
  gap: 0.75rem;
}

.game-flag .flag-done-icon {
  flex: none;
  font-size: 1.75rem;
  color: var(--md-primary);
}

.game-flag .flag-done[data-state='lost'] .flag-done-icon {
  color: var(--md-error);
}

.game-flag .flag-done-text {
  display: flex;
  flex-direction: column;
  gap: 0.125rem;
  min-width: 0;
}

.game-flag .flag-done-text p {
  margin: 0;
}

.game-flag .flag-done-title {
  font-family: var(--font-display, inherit);
  font-size: 1.125rem;
  font-weight: 600;
}

.game-flag .flag-done-bonus {
  margin-top: 0.25rem;
  font-size: 0.8125rem;
  color: var(--md-on-surface-variant);
}

.game-flag .flag-done-actions,
.game-flag .flag-bonus-actions {
  display: flex;
  flex-wrap: wrap;
  gap: 0.5rem;
}

.game-flag .flag-bonus {
  display: flex;
  flex-direction: column;
  gap: 0.875rem;
  padding: 1rem;
  border-radius: var(--r-lg);
  background: var(--md-tertiary-container);
  color: var(--md-on-tertiary-container);
  animation: flag-bonus-in var(--dur-med) var(--ease-spring) both;
}

@keyframes flag-bonus-in {
  from { opacity: 0; transform: translateY(0.75rem) scale(0.98); }
  to   { opacity: 1; transform: none; }
}

.game-flag .flag-bonus-head {
  display: flex;
  align-items: flex-start;
  gap: 0.75rem;
}

.game-flag .flag-bonus-icon {
  flex: none;
  font-size: 1.75rem;
}

.game-flag .flag-bonus-title {
  margin: 0 0 0.125rem;
  font-family: var(--font-display, inherit);
  font-size: 1.0625rem;
  font-weight: 600;
}

/* app.css's .muted is on-surface-variant, which is wrong over a tertiary card.
   Use the matching on-container role at full opacity — fading it below 100%
   would drop this body text under the 4.5:1 bar. */
.game-flag .flag-bonus .muted {
  margin: 0;
  color: var(--md-on-tertiary-container);
}

.game-flag .flag-bonus-actions {
  justify-content: flex-end;
}

.game-flag .flag-bonus-out {
  display: flex;
  align-items: center;
  gap: 0.375rem;
  margin: 0;
  font-size: 0.875rem;
  font-weight: 500;
}

/* Must follow the rule above: equal specificity, so the later one wins. */
.game-flag .flag-bonus-out:empty {
  display: none;
}

/* The card behind this is --md-tertiary-container, so the outcome line carries
   its own container/on-container pair rather than putting --md-error on a
   surface that pair was never contrast-checked against. */
.game-flag .flag-bonus-out[data-state] {
  padding: 0.5rem 0.75rem;
  border-radius: var(--r-sm);
}

.game-flag .flag-bonus-out[data-state='right'] {
  background: var(--md-primary-container);
  color: var(--md-on-primary-container);
}

.game-flag .flag-bonus-out[data-state='wrong'] {
  background: var(--md-error-container);
  color: var(--md-on-error-container);
}

/* Capital autocomplete */

.game-flag .flag-cap {
  display: flex;
  flex-direction: column;
  gap: 0.25rem;
}

.game-flag .flag-cap-label {
  padding-left: 0.25rem;
  font-size: 0.75rem;
  font-weight: 500;
  letter-spacing: 0.02em;
}

.game-flag .flag-cap-wrap {
  position: relative;
  display: flex;
  align-items: center;
  gap: 0.5rem;
  padding: 0 0.875rem;
  border-radius: var(--r-full);
  background: var(--md-surface);
  color: var(--md-on-surface);
  box-shadow: inset 0 0 0 1px var(--md-outline);
}

.game-flag .flag-cap-wrap:focus-within {
  box-shadow: inset 0 0 0 2px var(--md-primary);
}

.game-flag .flag-cap-wrap:has(.flag-cap-input:focus-visible) {
  outline: 2px solid var(--md-primary);
  outline-offset: 2px;
}

.game-flag .flag-cap-icon {
  flex: none;
  font-size: 1.25rem;
  color: var(--md-on-surface-variant);
}

.game-flag .flag-cap-input {
  flex: 1;
  min-width: 0;
  min-height: 48px;
  border: 0;
  background: none;
  color: inherit;
  font: inherit;
  outline: none;
}

.game-flag .flag-cap[data-locked='1'] .flag-cap-wrap {
  opacity: 0.7;
}

.game-flag .flag-cap-list {
  position: absolute;
  z-index: 5;
  left: 0;
  right: 0;
  bottom: calc(100% + 0.375rem);
  max-height: 15rem;
  margin: 0;
  padding: 0.375rem;
  overflow-y: auto;
  list-style: none;
  border-radius: var(--r-md);
  background: var(--md-surface-container-high);
  color: var(--md-on-surface);
  box-shadow: var(--e3);
}

.game-flag .flag-cap-option {
  display: flex;
  align-items: center;
  min-height: 48px;
  padding: 0 0.75rem;
  border-radius: var(--r-sm);
  cursor: pointer;
}

.game-flag .flag-cap-option:hover {
  background: color-mix(in oklab, var(--md-on-surface) 8%, transparent);
}

.game-flag .flag-cap-option[aria-selected='true'] {
  background: var(--md-secondary-container);
  color: var(--md-on-secondary-container);
}

/* Help dialog + boot states */

.game-flag.flag-help {
  display: flex;
  flex-direction: column;
  gap: 0.75rem;
}

.game-flag.flag-help p {
  margin: 0;
}

.game-flag .flag-help-list {
  display: flex;
  flex-direction: column;
  gap: 0.375rem;
  margin: 0;
  padding: 0.75rem 1rem;
  border-radius: var(--r-md);
  background: var(--md-surface-container-high);
  list-style: none;
  font-size: 0.875rem;
}

.game-flag.flag-boot {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 1rem;
  padding: 2rem 1rem;
  text-align: center;
}

.game-flag.flag-error .flag-error-icon {
  font-size: 2.5rem;
  color: var(--md-error);
}

.game-flag.flag-error h2 {
  margin: 0;
  font-size: 1.125rem;
}

@media (min-width: 60rem) {
  .game-flag .flag-stage,
  .game-flag .flag-meta {
    max-width: 38rem;
  }
}

/* Motion: the in-app setting and the OS setting both cut every transform. */

.game-flag[data-motion='reduced'] .flag-tile {
  transition: none;
  transition-delay: 0s;
}

/* visibility, not display: grid auto-placement must keep every cell in place. */
.game-flag[data-motion='reduced'] .flag-tile.is-gone {
  visibility: hidden;
  opacity: 0;
  transform: none;
}

/* Match .is-new / .is-won exactly: a bare .flag-guess would lose the
   specificity tie against .flag-guess.is-new and the row would still animate. */
.game-flag[data-motion='reduced'] .flag-frame.is-won,
.game-flag[data-motion='reduced'] .flag-guess.is-new,
.game-flag[data-motion='reduced'] .flag-bonus {
  animation: none;
}

.game-flag[data-motion='reduced'] .flag-img {
  transition: none;
}

@media (prefers-reduced-motion: reduce) {
  .game-flag .flag-tile {
    transition: none;
    transition-delay: 0s;
  }

  .game-flag .flag-tile.is-gone {
    visibility: hidden;
    opacity: 0;
    transform: none;
  }

  /* A media query adds no specificity, so this must match .is-new class for
     class or the row-in animation would win the tie and still play. */
  .game-flag .flag-frame.is-won,
  .game-flag .flag-guess.is-new,
  .game-flag .flag-bonus {
    animation: none;
  }

  .game-flag .flag-img {
    transition: none;
  }
}
