/* Review cards: card chrome, graded reveals, the grading scale, choice and
   map exercises, and the study session sidebar. */

.card-header {
  display: flex;
  justify-content: space-between;
  align-items: center;
  min-height: 3rem;
}

.card--row,
.word--row,
.fact--row,
.clip--row {
  border-radius: 0.5rem;
  border: 1px solid var(--bs-border-color);
  transition: all 0.3s;
}

.card--row:hover,
.word--row:hover,
.fact--row:hover,
.clip--row:hover {
  background-color: color-mix(in srgb, var(--bs-emphasis-color) 3%, transparent);
  scale: 1.01;
  box-shadow: 0 0.25rem 0.5rem color-mix(in srgb, var(--bs-emphasis-color) 5%, transparent);
}

.card--shown-on-revealed {
  display: none;
}

.card--revealed,
.card:has(.card--reveal:checked) {
  display: flex;

  .card--shown-on-revealed {
    display: flex;
    flex-direction: column;
  }

  .card--hidden-on-revealed {
    display: none;
  }
}

.card--front,
.card--back {
  min-height: 10rem;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 1rem 4rem;
  font-size: 1.25rem;
}

.card--back .card--shown-on-revealed {
  align-items: center;
  text-align: center;
}

/* Graded free-type reveals (steelman, use-in-sentence, pairs): the back is
   reading matter, not a flashcard answer: left-aligned prose, the learner's
   words set off as a quote. */
.card--back-prose {
  font-size: 1.05rem;
  padding: 1.5rem 2.5rem;
}

.card--back-prose .card--shown-on-revealed {
  align-items: stretch;
  text-align: start;
  gap: 1rem;
  width: 100%;
}

.card--kicker {
  font-family: var(--display);
  font-weight: 600;
  font-size: 0.68rem;
  letter-spacing: 0.09em;
  text-transform: uppercase;
  color: var(--muted);
  margin-bottom: 0.35rem;
}

.card--given {
  margin: 0;
  padding: 0.75rem 1rem;
  background-color: color-mix(in srgb, var(--wash) 42%, var(--card));
  border-left: 3px solid var(--accent);
  border-radius: 0 0.5rem 0.5rem 0;
  font-style: italic;
}

.card--given .card--kicker {
  font-style: normal;
}

.card--model:not(:first-child) {
  border-top: 1px solid var(--line);
  padding-top: 1rem;
}

/* Quantity answers ride the stage (stage.css) at card scale. */
.card--stage {
  font-size: clamp(1.25rem, 3vw, 1.75rem);
}

/* Skipping is saying the words: a quiet text button, not an icon. */
.card--idk {
  background: none;
  border: none;
  padding: 0.45rem 0;
  font-family: var(--display);
  font-weight: 600;
  color: var(--muted);
  text-decoration: underline dotted;
  text-underline-offset: 0.25em;
}

.card--idk:hover {
  color: var(--ink);
}

/* The grading scale is a filling circle (○ ◐ ●): a material question, not a
   traffic light. Shape carries the meaning; the accent carries the brand. */
.card--review-buttons {
  form {
    flex-grow: 1;
  }

  .btn {
    --bs-btn-border-radius: 1.25rem;
    width: 100%;
    min-height: 5.5rem;
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    background-color: var(--card);
    border: 1.5px solid var(--line);
    transition: border-color 0.2s, background-color 0.2s;
  }

  .btn:hover,
  .btn:focus-visible {
    background-color: var(--wash);
    border-color: var(--accent);
  }

  .grade-glyph {
    font-size: 2.8rem;
    line-height: 1;
    color: var(--accent);
    transition: transform 0.2s;
  }

  .btn:hover .grade-glyph,
  .btn:focus-visible .grade-glyph {
    transform: scale(1.12);
  }

}

/* Loading dots: the maturity dots take turns filling while something is
   worth waiting for (shared/_loading_dots). Drawn geometry rather than
   text glyphs, so the trio renders the same in every font stack. The
   Bootstrap .spinner-border remains the right wait for tight corners. */
.loading-dots span {
  display: inline-block;
  width: 1.2rem;
  height: 1.2rem;
  margin: 0 0.25rem;
  border: 2.5px solid var(--accent);
  border-radius: 50%;
  animation: grading-pulse 1.2s ease-in-out infinite;
}

.loading-dots .curing {
  background: linear-gradient(90deg, var(--accent) 50%, transparent 50%);
}

.loading-dots .stone {
  background: var(--accent);
}

.loading-dots span:nth-child(2) {
  animation-delay: 0.2s;
}

.loading-dots span:nth-child(3) {
  animation-delay: 0.4s;
}

@keyframes grading-pulse {
  0%, 100% {
    opacity: 0.25;
    transform: translateY(0);
  }

  50% {
    opacity: 1;
    transform: translateY(-0.2rem);
  }
}

/* Grading wait: the dots plus a rotating message, centered in the card */
.card--grading {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 0.25rem;
  padding: 1rem 0;
}

.card--grading-message {
  color: var(--bs-secondary-color);
}

@media (prefers-reduced-motion: reduce) {
  .card--review-buttons .grade-glyph {
    transition: none;
  }

  .card--review-buttons .btn:hover .grade-glyph,
  .card--review-buttons .btn:focus-visible .grade-glyph {
    transform: none;
  }

  .loading-dots span {
    animation: none;
  }
}

/* Maturity state rendered as a glyph (history lists, summaries); the
   grading-scale glyphs wear plain accent, with no data-maturity to read */
.maturity-glyph {
  color: var(--maturity, var(--accent));
}

/* Study session sidebar */
.study-session--sidebar {
  position: sticky;
  top: 1rem;
}

.study-session--review-history {
  max-height: 24rem;
  overflow-y: auto;
}

.study-session--hotkey-hints {
  color: var(--bs-secondary-color);
  font-size: 0.8rem;
}

.study-session--hotkey-hints kbd {
  font-size: 0.8rem;
  font-family: inherit;
  font-weight: 600;
  padding: 0.15rem 0.45rem;
  border-radius: 0.25rem;
  border: 1px solid var(--bs-border-color);
  background-color: var(--bs-body-bg);
  color: var(--bs-body-color);
  box-shadow: 0 1px 0 var(--bs-border-color);
}

/* Choice card: stacked option rows, label on the left, confidence picks on
   the right. Picking an answer and rating sureness is one gesture. */
.choice-options {
  display: flex;
  flex-direction: column;
  gap: 0.6rem;
}

.choice-option {
  display: flex;
  align-items: center;
  gap: 0.8rem;
  border: 1px solid var(--line);
  border-radius: 0.8rem;
  padding: 0.7rem 0.9rem;
  transition: border-color 0.2s, background-color 0.2s;
}

.choice-option-label {
  font-family: var(--display);
  font-weight: 650;
  font-size: 1.05rem;
  flex: 1;
}

.choice-mark {
  font-family: var(--display);
  font-weight: 700;
}

.choice-confidence {
  display: flex;
  gap: 0.4rem;
}

.choice-btn {
  width: 2.6rem;
  height: 2.6rem;
  padding: 0;
  border: 1px solid var(--line);
  border-radius: 999px;
  background: none;
  display: grid;
  place-items: center;
  font-size: 1.1rem;
  line-height: 1;
  color: var(--accent);
  cursor: pointer;
  transition: transform 0.18s cubic-bezier(0.34, 1.56, 0.64, 1),
              border-color 0.2s,
              background-color 0.2s;
}

.choice-btn:hover {
  border-color: var(--accent);
  background-color: var(--wash);
  transform: scale(1.12);
}

/* Revealed choice states: the verdict wears moss when correct and rose when
   wrong, stated once for option rows and map pins alike */
.choice-option--correct,
.choice-map-pin--correct {
  --verdict: var(--moss);
  --verdict-wash: var(--moss-wash);
}

.choice-option--wrong,
.choice-map-pin--wrong {
  --verdict: var(--rose);
  --verdict-wash: var(--rose-wash);
}

.choice-option--correct,
.choice-option--wrong {
  border-color: var(--verdict);
  background-color: var(--verdict-wash);
}

.choice-option--correct {
  animation: choiceCorrectIn 0.4s ease-out;
}

.choice-option--correct .choice-mark,
.choice-option--wrong .choice-mark {
  color: var(--verdict);
}

.choice-option--shake {
  animation: choiceShake 0.4s ease-out;
}

@keyframes choiceCorrectIn {
  0% { transform: scale(1); }
  50% { transform: scale(1.03); }
  100% { transform: scale(1); }
}

@keyframes choiceShake {
  0%, 100% { transform: translateX(0); }
  20% { transform: translateX(-6px); }
  40% { transform: translateX(6px); }
  60% { transform: translateX(-4px); }
  80% { transform: translateX(4px); }
}

/* Choice map pins */
.choice-map-pin {
  cursor: pointer;
  width: 34px;
  height: 34px;
  border-radius: 50%;
  display: flex;
  align-items: center;
  justify-content: center;
  font-weight: 700;
  font-size: 1rem;
  background-color: var(--bs-body-bg);
  color: var(--bs-body-color);
  border: 2px solid color-mix(in srgb, var(--bs-emphasis-color) 60%, transparent);
  box-shadow: 0 1px 4px rgba(0, 0, 0, 0.3);
}

.choice-map-pin--selected {
  border-color: var(--accent-deep);
  background-color: var(--accent);
  color: #fff;
}

.choice-option--selected {
  border-color: var(--accent);
  background-color: var(--wash);
}

.choice-map-pin--correct,
.choice-map-pin--wrong {
  border-color: var(--verdict);
  background-color: var(--verdict);
  color: #fff;
}

/* Map card */
.map-card:focus,
.map-card .leaflet-container:focus {
  outline: none;
}

.map-card .leaflet-container {
  z-index: 1;
}

/* Country cards: the tile-free world where countries are the interface.
   Everything derives from theme tokens, so light, dark, and every accent
   hue follow without map-specific overrides. */
.world-map-frame {
  position: relative;
}

.world-map {
  display: block;
  width: 100%;
  height: 100%;
  background: color-mix(in srgb, var(--sea) 14%, var(--paper));
  cursor: pointer;
  touch-action: none;
  outline: none;
}

.world-map--dragging {
  cursor: grabbing;
}

.world-map .country {
  fill: var(--card);
  stroke: var(--line);
  stroke-width: 1;
  vector-effect: non-scaling-stroke;
  transition: fill 0.15s ease;
}

@media (prefers-reduced-motion: reduce) {
  .world-map .country {
    transition: none;
  }
}

/* Which countries a choice card offers */
.world-map .country--option {
  fill: color-mix(in srgb, var(--accent) 12%, var(--card));
  stroke: var(--accent);
}

.world-map .country--hover {
  fill: color-mix(in srgb, var(--accent) 30%, var(--card));
}

.world-map .country--selected,
.world-map .country--subject {
  fill: var(--accent);
}

/* The neighbor halo an unsure claim would cover, previewed and settled */
.world-map .country--halo-preview {
  fill: color-mix(in srgb, var(--accent) 15%, var(--card));
  stroke: var(--accent);
  stroke-dasharray: 5 4;
}

.world-map .country--correct {
  fill: var(--moss);
}

.world-map .country--wrong {
  fill: var(--rose);
}

.world-map .country--held {
  fill: color-mix(in srgb, var(--moss) 35%, var(--card));
  stroke: var(--moss);
  stroke-dasharray: 5 4;
}

.world-map .country--halo-held {
  fill: color-mix(in srgb, var(--moss) 15%, var(--card));
  stroke: var(--moss);
  stroke-dasharray: 5 4;
}

.world-map .country--halo-missed {
  fill: color-mix(in srgb, var(--rose) 12%, var(--card));
  stroke: var(--rose);
  stroke-dasharray: 5 4;
}

.world-map-label,
.world-map-letter {
  font-family: var(--display);
  font-weight: 700;
  fill: var(--ink);
  paint-order: stroke;
  stroke: var(--card);
  stroke-width: 0.22em;
  stroke-linejoin: round;
  text-anchor: middle;
  pointer-events: none;
}

.world-map-zoom {
  position: absolute;
  top: 0.75rem;
  right: 0.75rem;
  display: flex;
  flex-direction: column;
  gap: 0.25rem;
  z-index: 1;
}

.world-map-zoom button {
  width: 2.1rem;
  height: 2.1rem;
  border: 1px solid var(--line);
  border-radius: 0.5rem;
  background: var(--card);
  color: var(--ink);
  font-size: 1.15rem;
  line-height: 1;
  cursor: pointer;
}

.world-map-zoom button:hover {
  background: var(--wash);
}

.world-map-zoom button:focus-visible {
  outline: 2px solid var(--accent);
}

/* Timeline card */
.timeline-card:focus {
  outline: none;
}

.timeline-card svg {
  display: block;
  width: 100%;
}

.timeline-area {
  height: 140px;
  cursor: crosshair;
  position: relative;
  background: linear-gradient(
    to bottom,
    color-mix(in srgb, var(--bs-emphasis-color) 1%, transparent) 0%,
    color-mix(in srgb, var(--bs-emphasis-color) 2.5%, transparent) 100%
  );
  transition: background 0.3s;
}

.timeline-area:hover {
  background: linear-gradient(
    to bottom,
    color-mix(in srgb, var(--bs-emphasis-color) 1.5%, transparent) 0%,
    color-mix(in srgb, var(--bs-emphasis-color) 3.5%, transparent) 100%
  );
}

.card--revealed .timeline-area {
  cursor: default;
}

/* Marker entrance animation */
.timeline-marker-enter {
  animation: timelineMarkerIn 0.3s ease-out;
}

@keyframes timelineMarkerIn {
  from {
    opacity: 0;
    transform: translateY(6px);
  }
  to {
    opacity: 1;
    transform: translateY(0);
  }
}

/* Marker glow pulse on placement */
.timeline-marker-glow {
  animation: timelineGlowPulse 0.6s ease-out;
}

@keyframes timelineGlowPulse {
  0% {
    r: 5;
    opacity: 1;
  }
  100% {
    r: 14;
    opacity: 0;
  }
}

/* Error zone fade in */
.timeline-error-enter {
  animation: timelineErrorIn 0.4s ease-out;
}

@keyframes timelineErrorIn {
  from { opacity: 0; }
  to { opacity: 1; }
}

/* Range band entrance */
.timeline-band-enter {
  animation: timelineBandIn 0.35s ease-out;
}

@keyframes timelineBandIn {
  from {
    opacity: 0;
    transform: scaleX(0.8);
  }
  to {
    opacity: 1;
    transform: scaleX(1);
  }
}

/* Result feedback styling */
.timeline-result-exact {
  color: #16a34a;
  font-weight: 700;
}

.timeline-result-good {
  color: #16a34a;
}

.timeline-result-ok {
  color: #d97706;
}

.timeline-result-miss {
  color: #dc2626;
}

.form-floating {
  /* move ts-control input element below the floating label */
  .ts-wrapper.form-control,
  .ts-wrapper.form-select {
    height: 0 !important;
  }

  .ts-wrapper.form-control .ts-control,
  .ts-wrapper.form-select .ts-control {
    padding-top: 1.625rem;
    padding-bottom: 0.625rem;
  }

  /* if field is styled as a text field (.form-control instead of .form-select)
   * make sure we apply the same animation as Bootstrap 5 */
  .ts-wrapper.form-control ~ label,
  .ts-wrapper.form-select ~ label {
    transform: scale(1) translateY(0) translateX(0);
    color: var(--ink);
  }

  .ts-wrapper.form-control.focus ~ label,
  .ts-wrapper.form-control.full ~ label,
  .ts-wrapper.form-select.focus ~ label,
  .ts-wrapper.form-select.full ~ label,
  .ts-wrapper.form-select.has-items ~ label {
    transform: scale(0.85) translateY(-0.5rem) translateX(0.15rem);
    color: color-mix(in srgb, var(--ink) 65%, transparent);
  }

  /* hides empty value which tomselect uses as placeholder */
  .ts-wrapper.form-select:not(.focus) .ts-control ::placeholder {
    opacity: 0;
  }
}

/* The dropdown's search input autofocuses on open, so Bootstrap's blue focus
   ring flashes every time a select is opened; keep the resting border instead */
.plugin-dropdown_input.focus .ts-dropdown .dropdown-input {
  border-color: #d0d0d0;
  box-shadow: none;
}

/* Filled floating textareas: Bootstrap tucks the first line right under the
   floated label and the last line against the bottom edge; give both some air. */
.form-floating > textarea.form-control:focus,
.form-floating > textarea.form-control:not(:placeholder-shown) {
  padding-top: 1.875rem;
  padding-bottom: 0.875rem;
}

/* Opt-in: textareas that grow to fit their content. Inside .form-floating,
   Bootstrap's fixed height must yield; its min-height still sets the floor. */
textarea.form-control.autogrow {
  field-sizing: content;
  overflow: hidden;
  resize: none;
}

.form-floating > textarea.form-control.autogrow {
  height: auto;
}

