/* ============================================================
   Coastal Landscapes — Design System
   Duolingo-style, coastal theme. Mobile-first, rem-based.
   ============================================================ */

/* ---------- Design tokens ---------- */
:root {
  /* Core palette */
  --colour-primary: #1CB0A6;
  --colour-primary-dark: #148A82;
  --colour-primary-darker: #0F6B65;
  --colour-primary-light: #5FD0C7;
  --colour-accent: #FFC94A;
  --colour-accent-dark: #E0A824;
  /* Darker shades used specifically as WCAG AA-safe button backgrounds
     for white button text on .btn--accent (see below) — a real screenshot
     showed the "Start the lesson" button (which uses this variant)
     looking washed-out even fully enabled: the original light gold fill
     was only ~1.5:1 against the white welcome card, so despite the dark
     brown text technically clearing 4.5:1 on the gold itself, the button
     as a whole read as low-contrast. These clear 4.5:1 comfortably with
     white text (~6.3:1) and give the button proper visual weight. */
  --colour-accent-darker: #805900;
  --colour-accent-darkest: #4D3600;
  --colour-success: #58CC02;
  --colour-success-dark: #45A302;
  /* Darker success shades used specifically as WCAG AA-safe button
     backgrounds for white button text (see .btn--success) — the base
     --colour-success/--colour-success-dark are both too light for
     4.5:1 with white text at 1rem/16px bold (~2.09:1 / ~3.23:1). */
  --colour-success-darker: #357A01;
  --colour-success-darkest: #1F4701;
  --colour-error: #FF6B6B;
  --colour-error-dark: #E24F4F;
  --colour-bg: #F7FBFA;
  --colour-surface: #FFFFFF;
  --colour-text: #1B3A3A;
  --colour-text-muted: #4C6666;
  --colour-border: #DCEBE9;
  --colour-locked: #B9C6C6;
  --colour-sand: #FFF3D6;
  --colour-sea-deep: #0B5E63;

  /* Typography */
  --font-body: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;
  --font-script: "Snell Roundhand", "Brush Script MT", cursive, var(--font-body);

  /* Spacing scale (rem) */
  --space-1: 0.25rem;
  --space-2: 0.5rem;
  --space-3: 0.75rem;
  --space-4: 1rem;
  --space-5: 1.5rem;
  --space-6: 2rem;
  --space-7: 3rem;
  --space-8: 4rem;

  /* Radii & shadows */
  --radius-sm: 0.5rem;
  --radius-md: 1rem;
  --radius-lg: 1.5rem;
  --radius-full: 999px;
  --shadow-card: 0 0.25rem 0.75rem rgba(15, 60, 60, 0.1);
  --shadow-pop: 0 0.5rem 1.25rem rgba(15, 60, 60, 0.15);

  /* Layout */
  --max-width: 46rem;
  --header-height: 4rem;
}

/* ---------- Reset & base ---------- */
* {
  box-sizing: border-box;
}

html {
  font-size: 100%;
  -webkit-text-size-adjust: 100%;
}

body {
  margin: 0;
  font-family: var(--font-body);
  background: var(--colour-bg);
  color: var(--colour-text);
  font-size: 1rem;
  line-height: 1.5;
  min-height: 100vh;
}

h1, h2, h3, h4, p, ul, ol, figure {
  margin: 0 0 var(--space-4) 0;
}

h1 { font-size: 1.75rem; line-height: 1.2; }
h2 { font-size: 1.5rem; line-height: 1.25; }
h3 { font-size: 1.25rem; line-height: 1.3; }

@media (min-width: 48rem) {
  h1 { font-size: 2.25rem; }
  h2 { font-size: 1.75rem; }
  h3 { font-size: 1.375rem; }
}

p {
  font-size: 1rem;
}

button {
  font-family: inherit;
}

img {
  max-width: 100%;
  display: block;
}

.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;
}

.hidden {
  display: none !important;
}

/* ---------- App shell ---------- */
#app {
  min-height: 100vh;
  display: flex;
  flex-direction: column;
}

.screen {
  flex: 1 1 auto;
  display: flex;
  flex-direction: column;
  width: 100%;
}

.screen-inner {
  width: 100%;
  max-width: var(--max-width);
  margin: 0 auto;
  padding: var(--space-5) var(--space-4) var(--space-8);
  flex: 1 1 auto;
  display: flex;
  flex-direction: column;
}

/* ---------- Header bar ---------- */
.app-header {
  position: sticky;
  top: 0;
  z-index: 20;
  background: var(--colour-surface);
  border-bottom: 0.125rem solid var(--colour-border);
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-4);
  padding: var(--space-3) var(--space-4);
}

.app-header .header-inner {
  width: 100%;
  max-width: var(--max-width);
  margin: 0 auto;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-3);
}

.stat-pill {
  display: inline-flex;
  align-items: center;
  gap: var(--space-1);
  background: var(--colour-sand);
  color: var(--colour-text);
  font-weight: 700;
  font-size: 0.95rem;
  padding: 0.375rem 0.75rem;
  border-radius: var(--radius-full);
  border: 0.125rem solid var(--colour-accent);
  white-space: nowrap;
}

.stat-pill--streak {
  background: #FFE7E0;
  border-color: var(--colour-error);
}

.header-brand {
  display: flex;
  align-items: center;
  gap: var(--space-2);
  font-weight: 800;
  color: var(--colour-primary-darker);
  font-size: 1.05rem;
}

.header-stats {
  display: flex;
  gap: var(--space-2);
}

/* ---------- Buttons (3D pressed Duolingo style) ---------- */
.btn {
  /* WCAG AA requires 4.5:1 for this label (1rem/16px bold doesn't meet
     the 18.66px-bold "large text" 3:1 exception). White text on the
     brighter --colour-primary is only ~2.69:1, so the bare .btn (used
     for the Check button) uses the darker end of the teal ramp instead,
     which clears 4.5:1 comfortably (~6.34:1). Every other button variant
     (accent/success/secondary) overrides --btn-bg/--btn-shadow/--btn-fg
     below, so this only affects the plain, un-modified .btn. */
  --btn-bg: var(--colour-primary-darker);
  --btn-shadow: var(--colour-sea-deep);
  --btn-fg: #FFFFFF;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 0.5rem;
  font-weight: 800;
  font-size: 1rem;
  letter-spacing: 0.01em;
  color: var(--btn-fg);
  background: var(--btn-bg);
  border: none;
  border-radius: var(--radius-md);
  padding: 0.9rem 1.5rem;
  box-shadow: 0 0.25rem 0 var(--btn-shadow);
  cursor: pointer;
  transition: transform 0.06s ease, box-shadow 0.06s ease, opacity 0.15s ease;
  min-height: 3rem;
  touch-action: manipulation;
}

/* engine.js toggles the Check/Continue buttons via the native `hidden`
   attribute (el.checkBtn.hidden = ...) rather than the `.hidden` class used
   elsewhere. Without this rule, the `display: inline-flex` above — a normal
   author-stylesheet declaration — silently wins the cascade over the
   user-agent stylesheet's `[hidden] { display: none }` (author-origin
   beats user-agent-origin at equal specificity), so a "hidden" button
   would still render on screen. This restores real hiding. */
.btn[hidden] {
  display: none !important;
}

.btn:hover:not(:disabled) {
  filter: brightness(1.04);
}

.btn:active:not(:disabled) {
  transform: translateY(0.2rem);
  box-shadow: 0 0.05rem 0 var(--btn-shadow);
}

.btn:focus-visible {
  outline: 0.2rem solid var(--colour-primary-dark);
  outline-offset: 0.15rem;
}

.btn:disabled {
  opacity: 0.5;
  cursor: not-allowed;
  box-shadow: 0 0.25rem 0 var(--btn-shadow);
  transform: none;
}

.btn--accent {
  /* See the --colour-accent-darker/-darkest comment above — this matches
     the same treatment already applied to the plain .btn and .btn--success
     variants for the Check/Continue buttons. */
  --btn-bg: var(--colour-accent-darker);
  --btn-shadow: var(--colour-accent-darkest);
  --btn-fg: #FFFFFF;
}

.btn--success {
  /* White text on the brighter --colour-success is only ~2.09:1 (and
     ~3.23:1 even against --colour-success-dark) — both fail WCAG AA's
     4.5:1 requirement for this bold 1rem label. --colour-success-darker
     clears it comfortably (~5.34:1) while staying recognisably green. */
  --btn-bg: var(--colour-success-darker);
  --btn-shadow: var(--colour-success-darkest);
}

.btn--secondary {
  --btn-bg: #FFFFFF;
  --btn-shadow: var(--colour-border);
  --btn-fg: var(--colour-primary-darker);
  border: 0.125rem solid var(--colour-border);
}

.btn--block {
  width: 100%;
}

.btn--sm {
  padding: 0.6rem 1rem;
  font-size: 0.9rem;
  min-height: 2.5rem;
  box-shadow: 0 0.2rem 0 var(--btn-shadow);
}

.btn--link {
  background: transparent;
  box-shadow: none;
  color: var(--colour-primary-darker);
  text-decoration: underline;
  padding: 0.4rem 0.6rem;
  font-weight: 700;
  min-height: auto;
}

.btn--link:active:not(:disabled) {
  transform: none;
}

/* ---------- Welcome screen ---------- */
.welcome-screen .screen-inner {
  justify-content: center;
  align-items: center;
  text-align: center;
  gap: var(--space-5);
}

.welcome-hero {
  font-size: 4rem;
  line-height: 1;
}

.welcome-card {
  background: var(--colour-surface);
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow-card);
  padding: var(--space-6) var(--space-5);
  width: 100%;
  max-width: 32rem;
}

.welcome-intro {
  color: var(--colour-text-muted);
  font-size: 1.05rem;
}

.name-field {
  width: 100%;
  text-align: left;
  margin: var(--space-5) 0;
}

.name-field label {
  display: block;
  font-weight: 700;
  margin-bottom: var(--space-2);
  color: var(--colour-text);
}

.name-field input {
  width: 100%;
  font-size: 1.1rem;
  padding: 0.85rem 1rem;
  border-radius: var(--radius-md);
  border: 0.15rem solid var(--colour-border);
  background: var(--colour-bg);
  color: var(--colour-text);
}

.name-field input:focus {
  outline: none;
  border-color: var(--colour-primary);
}

/* ---------- Path / map screen ---------- */
.path-screen-inner {
  padding-top: var(--space-6);
}

.path-title {
  text-align: center;
  color: var(--colour-primary-darker);
}

.path-track {
  position: relative;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: var(--space-6);
  padding: var(--space-6) 0;
}

.path-node-wrap {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: var(--space-2);
}

.path-node-wrap:nth-child(odd) { align-self: center; transform: translateX(-3.5rem); }
.path-node-wrap:nth-child(even) { align-self: center; transform: translateX(3.5rem); }

@media (max-width: 26rem) {
  .path-node-wrap:nth-child(odd) { transform: translateX(-2rem); }
  .path-node-wrap:nth-child(even) { transform: translateX(2rem); }
}

.path-node {
  width: 5.5rem;
  height: 5.5rem;
  border-radius: 50%;
  border: none;
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 2.25rem;
  background: var(--colour-primary);
  color: #fff;
  box-shadow: 0 0.3rem 0 var(--colour-primary-darker);
  cursor: pointer;
  position: relative;
  transition: transform 0.06s ease, box-shadow 0.06s ease;
}

.path-node:active:not(:disabled) {
  transform: translateY(0.2rem);
  box-shadow: 0 0.1rem 0 var(--colour-primary-darker);
}

.path-node[data-state="locked"] {
  background: var(--colour-locked);
  box-shadow: 0 0.3rem 0 #92A0A0;
  cursor: not-allowed;
}

.path-node[data-state="completed"] {
  background: var(--colour-success);
  box-shadow: 0 0.3rem 0 var(--colour-success-dark);
}

.path-node[data-state="available"] {
  background: var(--colour-accent);
  box-shadow: 0 0.3rem 0 var(--colour-accent-dark);
  animation: pulse-glow 2.4s ease-in-out infinite;
}

.path-node--certificate {
  font-size: 2.5rem;
}

.path-node-label {
  font-weight: 800;
  text-align: center;
  font-size: 0.95rem;
  color: var(--colour-text);
  max-width: 9rem;
}

.path-node-sub {
  font-size: 0.8rem;
  color: var(--colour-text-muted);
  text-align: center;
}

.path-node-badge {
  position: absolute;
  top: -0.4rem;
  right: -0.4rem;
  background: #fff;
  border-radius: 50%;
  width: 1.6rem;
  height: 1.6rem;
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 1rem;
  box-shadow: var(--shadow-card);
}

.path-footer {
  text-align: center;
  padding: var(--space-6) 0 var(--space-4);
  border-top: 0.0625rem solid var(--colour-border);
  margin-top: var(--space-5);
}

/* ---------- Section player ---------- */
.section-screen-inner {
  padding-top: var(--space-4);
  gap: var(--space-4);
}

.progress-bar-track {
  width: 100%;
  height: 0.9rem;
  background: var(--colour-border);
  border-radius: var(--radius-full);
  overflow: hidden;
  margin-bottom: var(--space-2);
}

.progress-bar-fill {
  height: 100%;
  background: var(--colour-success);
  border-radius: var(--radius-full);
  transition: width 0.35s ease;
  width: 0%;
}

.section-meta-row {
  display: flex;
  justify-content: space-between;
  align-items: center;
  font-size: 0.85rem;
  color: var(--colour-text-muted);
  font-weight: 700;
  margin-bottom: var(--space-3);
}

.difficulty-indicator {
  display: inline-flex;
  align-items: center;
  gap: 0.3rem;
  padding: 0.25rem 0.65rem;
  border-radius: var(--radius-full);
  font-size: 0.8rem;
  font-weight: 800;
  background: var(--colour-sand);
  color: var(--colour-text);
}

.difficulty-indicator[data-level="1"] { background: #FFE7E0; color: #8A2E2E; }
.difficulty-indicator[data-level="3"] { background: #E3F7D9; color: #2C6B12; }

.activity-card {
  background: var(--colour-surface);
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow-card);
  padding: var(--space-5);
  flex: 1 1 auto;
  display: flex;
  flex-direction: column;
  gap: var(--space-4);
}

.activity-photo {
  width: 100%;
  max-height: 17.5rem;
  object-fit: cover;
  border-radius: var(--radius-md);
  box-shadow: var(--shadow-card);
}

.activity-photo-credit {
  font-style: italic;
  font-size: 0.8rem;
  color: var(--colour-text-muted);
  margin-top: -0.75rem;
}

.activity-heading {
  color: var(--colour-primary-darker);
}

.activity-body {
  font-size: 1.05rem;
  min-height: 1.5em;
}

/* Only text that can actually be tapped-to-skip gets the pointer cursor —
   "reveal-target" alone just marks "currently revealing" (used by the
   test suite to find in-flight reveals); the "--skippable" modifier is
   only added when a click really will complete the reveal. On every
   non-"info" question screen the prompt/scenario/question text has no
   skip shortcut at all, so it never gets this modifier or the pointer
   cursor that implies one. */
.activity-heading.reveal-target--skippable,
.activity-body.reveal-target--skippable,
.speech-bubble-text.reveal-target--skippable,
.scenario-text.reveal-target--skippable,
.fill-blank-prompt.reveal-target--skippable {
  cursor: pointer;
}

.reveal-skip-hint {
  font-size: 0.78rem;
  color: var(--colour-text-muted);
  font-style: italic;
  margin-top: -0.5rem;
}

.activity-bullets {
  padding-left: 1.25rem;
  font-size: 1rem;
}

.activity-bullets li {
  margin-bottom: var(--space-2);
}

.extension-fact {
  border: 0.125rem dashed var(--colour-accent-dark);
  background: var(--colour-sand);
  border-radius: var(--radius-md);
  padding: var(--space-3) var(--space-4);
}

.extension-fact summary {
  cursor: pointer;
  font-weight: 800;
  color: var(--colour-accent-dark);
}

.extension-fact[open] summary {
  margin-bottom: var(--space-2);
}

/* Options / choices */
.options-list {
  display: flex;
  flex-direction: column;
  gap: var(--space-3);
}

.option-btn {
  display: flex;
  align-items: center;
  gap: var(--space-3);
  text-align: left;
  width: 100%;
  padding: 0.9rem 1.1rem;
  border-radius: var(--radius-md);
  border: 0.15rem solid var(--colour-border);
  background: var(--colour-surface);
  font-size: 1rem;
  font-weight: 600;
  color: var(--colour-text);
  cursor: pointer;
  box-shadow: 0 0.2rem 0 var(--colour-border);
  transition: transform 0.06s ease, box-shadow 0.06s ease, background 0.15s ease, border-color 0.15s ease;
}

.option-btn:hover:not(:disabled) {
  border-color: var(--colour-primary-light);
}

.option-btn:active:not(:disabled) {
  transform: translateY(0.15rem);
  box-shadow: 0 0.05rem 0 var(--colour-border);
}

.option-btn.selected {
  border-color: var(--colour-primary);
  background: #E6F7F5;
  box-shadow: 0 0.2rem 0 var(--colour-primary);
}

.option-btn.correct-state {
  border-color: var(--colour-success);
  background: #EAF9E0;
  box-shadow: 0 0.2rem 0 var(--colour-success);
}

.option-btn.incorrect-state {
  border-color: var(--colour-error);
  background: #FFEEEE;
  box-shadow: 0 0.2rem 0 var(--colour-error);
  animation: shake-soft 0.4s ease;
}

.option-btn:disabled {
  cursor: default;
}

.option-icon {
  font-size: 1.2rem;
  flex: 0 0 auto;
}

/* Word bank / chips */
.chip-row {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-2);
}

.chip {
  padding: 0.55rem 1rem;
  border-radius: var(--radius-full);
  border: 0.15rem solid var(--colour-primary);
  background: #fff;
  color: var(--colour-primary-darker);
  font-weight: 700;
  cursor: pointer;
  transition: transform 0.06s ease, background 0.15s ease;
}

.chip:hover:not(:disabled) {
  background: #E6F7F5;
}

.chip:active:not(:disabled) {
  transform: translateY(0.1rem);
}

.chip.chip--used {
  opacity: 0.4;
  cursor: not-allowed;
  background: var(--colour-border);
  border-color: var(--colour-border);
  color: var(--colour-text-muted);
}

.chip.chip--selected {
  background: var(--colour-accent);
  border-color: var(--colour-accent-dark);
  color: #4A3200;
}

.fill-blank-prompt {
  font-size: 1.1rem;
  line-height: 1.7;
}

.blank-slot {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-width: 6rem;
  border-bottom: 0.2rem solid var(--colour-primary);
  font-weight: 800;
  color: var(--colour-primary-darker);
  padding: 0.1rem 0.5rem;
  margin: 0 0.2rem;
}

/* Matching */
.matching-grid {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: var(--space-4);
}

.matching-col {
  display: flex;
  flex-direction: column;
  gap: var(--space-2);
}

.match-btn {
  padding: 0.75rem 0.9rem;
  border-radius: var(--radius-md);
  border: 0.15rem solid var(--colour-border);
  background: var(--colour-surface);
  font-weight: 700;
  font-size: 0.95rem;
  cursor: pointer;
  text-align: left;
  box-shadow: 0 0.2rem 0 var(--colour-border);
}

.match-btn.selected {
  border-color: var(--colour-primary);
  background: #E6F7F5;
}

.match-btn.locked-correct {
  border-color: var(--colour-success);
  background: #EAF9E0;
  color: var(--colour-success-dark);
  cursor: default;
}

.match-btn.locked-correct:active { transform: none; }

.match-btn.flash-wrong {
  animation: shake-soft 0.4s ease;
  border-color: var(--colour-error);
  background: #FFEEEE;
}

/* A wrong pairing must never be signalled by colour + shake alone — this
   small inline label gives the same non-colour cue every other activity
   type already has (a checkmark/cross icon). Purely transient: added and
   removed alongside the flash-wrong state. */
.match-wrong-cue {
  display: inline-block;
  margin-left: 0.5rem;
  font-weight: 800;
  font-size: 0.82rem;
  color: var(--colour-error-dark);
}

/* Order / sequencing */
.order-list {
  list-style: none;
  padding: 0;
  margin: 0;
  display: flex;
  flex-direction: column;
  gap: var(--space-2);
}

.order-item {
  display: flex;
  align-items: center;
  gap: var(--space-3);
  padding: 0.7rem 0.9rem;
  border-radius: var(--radius-md);
  border: 0.15rem solid var(--colour-border);
  background: var(--colour-surface);
  font-weight: 600;
}

.order-item .order-index {
  flex: 0 0 auto;
  width: 1.75rem;
  height: 1.75rem;
  border-radius: 50%;
  background: var(--colour-primary);
  color: #fff;
  display: flex;
  align-items: center;
  justify-content: center;
  font-weight: 800;
  font-size: 0.85rem;
}

.order-item-text {
  flex: 1 1 auto;
}

.order-controls {
  display: flex;
  flex-direction: column;
  gap: 0.25rem;
}

.order-move-btn {
  width: 2rem;
  height: 2rem;
  border-radius: var(--radius-sm);
  border: 0.125rem solid var(--colour-border);
  background: #fff;
  cursor: pointer;
  font-size: 0.9rem;
  line-height: 1;
}

.order-pool {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-2);
  padding: var(--space-3);
  background: var(--colour-bg);
  border-radius: var(--radius-md);
  border: 0.125rem dashed var(--colour-border);
  min-height: 3.5rem;
}

.order-pool-item {
  padding: 0.6rem 0.9rem;
  border-radius: var(--radius-md);
  background: #fff;
  border: 0.15rem solid var(--colour-primary);
  font-weight: 700;
  cursor: pointer;
}

/* Sort / categorize */
.sort-cards-row {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-2);
  padding: var(--space-3);
  background: var(--colour-bg);
  border-radius: var(--radius-md);
  border: 0.125rem dashed var(--colour-border);
  min-height: 3.5rem;
}

.sort-card {
  padding: 0.6rem 0.9rem;
  border-radius: var(--radius-md);
  background: #fff;
  border: 0.15rem solid var(--colour-primary);
  font-weight: 700;
  cursor: pointer;
}

.sort-card.chip--used {
  opacity: 0.35;
  cursor: not-allowed;
}

.sort-card.chip--selected {
  background: var(--colour-accent);
  border-color: var(--colour-accent-dark);
  color: #4A3200;
}

.sort-categories {
  display: grid;
  grid-template-columns: 1fr;
  gap: var(--space-3);
}

@media (min-width: 34rem) {
  .sort-categories {
    grid-template-columns: 1fr 1fr;
  }
}

.sort-category {
  border: 0.15rem solid var(--colour-border);
  border-radius: var(--radius-md);
  padding: var(--space-3);
  min-height: 6rem;
  background: var(--colour-surface);
  cursor: pointer;
  display: block;
  width: 100%;
  text-align: left;
  font: inherit;
  color: inherit;
  -webkit-appearance: none;
  appearance: none;
}

.sort-category:focus-visible {
  outline: 0.2rem solid var(--colour-primary-dark);
  outline-offset: 0.15rem;
}

.sort-category h4 {
  margin: 0 0 var(--space-2);
  color: var(--colour-primary-darker);
  font-size: 1rem;
}

.sort-category .sort-category-cards {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-2);
}

.sort-category .placed-card {
  padding: 0.4rem 0.75rem;
  border-radius: var(--radius-full);
  background: #E6F7F5;
  border: 0.1rem solid var(--colour-primary);
  font-size: 0.85rem;
  font-weight: 700;
}

.sort-category .placed-card.wrong {
  background: #FFEEEE;
  border-color: var(--colour-error);
}

/* Label diagram */
.diagram-wrap {
  position: relative;
  width: 100%;
  border-radius: var(--radius-md);
  overflow: hidden;
  background: linear-gradient(#BFE9E4, #BFE9E4);
}

.diagram-zone {
  position: absolute;
  border-radius: var(--radius-full);
  border: 0.2rem dashed rgba(255, 255, 255, 0.9);
  background: rgba(28, 176, 166, 0.25);
  color: #0F3C3C;
  font-weight: 800;
  font-size: 0.85rem;
  display: flex;
  align-items: center;
  justify-content: center;
  cursor: pointer;
  min-width: 2rem;
  min-height: 2rem;
  padding: 0.2rem;
  text-align: center;
}

.diagram-zone.filled {
  background: rgba(255, 201, 74, 0.85);
  border-style: solid;
  border-color: var(--colour-accent-dark);
  color: #4A3200;
}

.diagram-zone.correct-state {
  background: rgba(88, 204, 2, 0.85);
  border-color: var(--colour-success-dark);
  color: #fff;
}

.diagram-zone.incorrect-state {
  background: rgba(255, 107, 107, 0.85);
  border-color: var(--colour-error-dark);
  color: #fff;
  animation: shake-soft 0.4s ease;
}

/* Short answer */
.short-answer-textarea {
  width: 100%;
  min-height: 6rem;
  border-radius: var(--radius-md);
  border: 0.15rem solid var(--colour-border);
  padding: 0.85rem 1rem;
  font-size: 1rem;
  font-family: inherit;
  resize: vertical;
}

.short-answer-textarea:focus {
  outline: none;
  border-color: var(--colour-primary);
}

.model-answer-box {
  background: var(--colour-sand);
  border-radius: var(--radius-md);
  padding: var(--space-3) var(--space-4);
  border-left: 0.3rem solid var(--colour-accent-dark);
}

/* short-answer-reflect's model answer is a <details> element — an
   optional, never-forced expandable, styled to match the existing
   .extension-fact disclosure convention used on info slides. */
.model-answer-box summary {
  cursor: pointer;
  font-weight: 800;
  color: var(--colour-accent-dark);
}

.model-answer-box[open] summary {
  margin-bottom: var(--space-2);
}

/* ---------- Sandy the crab & speech bubble ---------- */
.sandy-wrap {
  display: flex;
  align-items: flex-start;
  gap: var(--space-3);
}

.sandy-avatar {
  flex: 0 0 auto;
  font-size: 2.75rem;
  line-height: 1;
  transform: scaleX(-1);
}

.sandy-avatar.bounce {
  animation: sandy-bounce 0.6s ease;
}

.speech-bubble {
  position: relative;
  background: var(--colour-surface);
  border: 0.15rem solid var(--colour-border);
  border-radius: var(--radius-md);
  padding: var(--space-3) var(--space-4);
  flex: 1 1 auto;
  min-height: 2.5rem;
}

.speech-bubble::before {
  content: "";
  position: absolute;
  left: -0.6rem;
  top: 1rem;
  width: 0;
  height: 0;
  border-top: 0.5rem solid transparent;
  border-bottom: 0.5rem solid transparent;
  border-right: 0.6rem solid var(--colour-border);
}

.speech-bubble::after {
  content: "";
  position: absolute;
  left: -0.45rem;
  top: 1.08rem;
  width: 0;
  height: 0;
  border-top: 0.42rem solid transparent;
  border-bottom: 0.42rem solid transparent;
  border-right: 0.5rem solid var(--colour-surface);
}

.speech-bubble--correct {
  border-color: var(--colour-success);
  background: #F1FBEA;
}

.speech-bubble--incorrect {
  border-color: var(--colour-error);
  background: #FFF3F2;
}

.speech-bubble-icon {
  font-weight: 800;
  margin-right: 0.35rem;
}

.feedback-panel {
  display: flex;
  flex-direction: column;
  gap: var(--space-2);
}

.feedback-panel[hidden] {
  display: none !important;
}

.correct-answer-reveal {
  font-size: 0.92rem;
  color: var(--colour-text-muted);
  margin-top: var(--space-1);
}

/* ---------- Hint ---------- */
.hint-row {
  display: flex;
  justify-content: flex-end;
}

.hint-box {
  background: #FFFBEF;
  border: 0.125rem dashed var(--colour-accent-dark);
  border-radius: var(--radius-md);
  padding: var(--space-3);
  font-size: 0.92rem;
}

/* ---------- Action row ---------- */
.action-row {
  display: flex;
  justify-content: flex-end;
  gap: var(--space-3);
  margin-top: auto;
  padding-top: var(--space-3);
}

/* ---------- Certificate ---------- */
.certificate-screen-inner {
  align-items: center;
  text-align: center;
  gap: var(--space-5);
}

#certificate-canvas {
  max-width: 100%;
  height: auto;
  border-radius: var(--radius-md);
  box-shadow: var(--shadow-pop);
}

.certificate-facts {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-4);
  justify-content: center;
}

.certificate-fact {
  background: var(--colour-surface);
  border-radius: var(--radius-md);
  padding: var(--space-3) var(--space-5);
  box-shadow: var(--shadow-card);
}

.certificate-fact .label {
  font-size: 0.8rem;
  color: var(--colour-text-muted);
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.05em;
}

.certificate-fact .value {
  font-size: 1.3rem;
  font-weight: 800;
  color: var(--colour-primary-darker);
}

.certificate-actions {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-3);
  justify-content: center;
}

/* ---------- Photo credits modal ---------- */
.modal-backdrop {
  position: fixed;
  inset: 0;
  background: rgba(15, 40, 40, 0.55);
  display: flex;
  align-items: center;
  justify-content: center;
  padding: var(--space-4);
  z-index: 100;
}

.modal-panel {
  background: var(--colour-surface);
  border-radius: var(--radius-lg);
  padding: var(--space-5);
  max-width: 32rem;
  width: 100%;
  max-height: 80vh;
  overflow-y: auto;
  box-shadow: var(--shadow-pop);
}

.modal-panel h2 {
  color: var(--colour-primary-darker);
}

.credit-entry {
  padding: var(--space-3) 0;
  border-bottom: 0.0625rem solid var(--colour-border);
  font-size: 0.92rem;
}

.credit-entry:last-child {
  border-bottom: none;
}

.credit-entry a {
  color: var(--colour-primary-dark);
  word-break: break-all;
}

.modal-close-row {
  display: flex;
  justify-content: flex-end;
  margin-top: var(--space-4);
}

/* ---------- Animations ---------- */
@keyframes pulse-glow {
  0%, 100% { box-shadow: 0 0.3rem 0 var(--colour-accent-dark), 0 0 0 0 rgba(255, 201, 74, 0.5); }
  50% { box-shadow: 0 0.3rem 0 var(--colour-accent-dark), 0 0 0 0.5rem rgba(255, 201, 74, 0); }
}

@keyframes shake-soft {
  0%, 100% { transform: translateX(0); }
  20% { transform: translateX(-0.35rem); }
  40% { transform: translateX(0.3rem); }
  60% { transform: translateX(-0.2rem); }
  80% { transform: translateX(0.15rem); }
}

@keyframes sandy-bounce {
  0% { transform: scaleX(-1) translateY(0); }
  30% { transform: scaleX(-1) translateY(-0.5rem); }
  55% { transform: scaleX(-1) translateY(0); }
  75% { transform: scaleX(-1) translateY(-0.2rem); }
  100% { transform: scaleX(-1) translateY(0); }
}

@keyframes confetti-fall {
  0% { transform: translateY(-0.5rem) rotate(0deg); opacity: 1; }
  100% { transform: translateY(3.5rem) rotate(220deg); opacity: 0; }
}

.confetti-burst {
  /* Laid over the whole activity card (not just appended in normal flow
     with left/right/height inline styles) and clipped by its own
     overflow:hidden, with border-radius matched to the card — this keeps
     every falling piece contained inside the card's rounded shape no
     matter where it spawns, instead of letting pieces drift out past the
     card's edges and over whatever sits below it. */
  position: absolute;
  inset: 0;
  overflow: hidden;
  border-radius: inherit;
  pointer-events: none;
}

.confetti-piece {
  position: absolute;
  font-size: 1.1rem;
  animation: confetti-fall 0.9s ease-out forwards;
}

@media (prefers-reduced-motion: reduce) {
  .path-node[data-state="available"] {
    animation: none;
  }
  .sandy-avatar.bounce {
    animation: none;
  }
  .option-btn.incorrect-state,
  .match-btn.flash-wrong,
  .diagram-zone.incorrect-state {
    animation: none;
  }
  .confetti-piece {
    animation: none;
    opacity: 0;
  }
  * {
    scroll-behavior: auto !important;
  }
}

/* ---------- Cursive/script style for certificate HTML fallback ---------- */
.script-name {
  font-family: var(--font-script);
  font-style: italic;
}

/* ---------- Print styles ----------
   Certificate is drawn on an 1000x700 (10:7) canvas, which is wider than an
   A4 page's printable area at native pixel size — so it must be scaled down
   explicitly (canvas CSS width in mm, height:auto keeps the ratio) rather
   than relying on Chrome's print dialog "Fit to page" scaling, which is NOT
   the default (Chrome's default print scale is 100%, no auto-shrink). The
   @page rule keeps generous, explicit margins so the certificate never
   collides with Chrome's own header/footer (URL/date/page number), and
   .certificate-facts (the plain-text name/date/grade duplicate, needed on
   screen for accessibility since canvas text isn't screen-reader-readable)
   is hidden for print — the canvas itself already draws that same
   information as part of the certificate artwork, so repeating it as plain
   text underneath would just look redundant on a printed page. */
@page {
  size: A4;
  margin: 15mm;
}

@media print {
  body * {
    visibility: hidden;
  }
  #certificate-print-area, #certificate-print-area * {
    visibility: visible;
  }
  #certificate-print-area {
    position: absolute;
    top: 0;
    left: 0;
    width: 100%;
    margin: 0;
    padding: 0;
  }
  .app-header, .certificate-actions, .certificate-facts {
    display: none !important;
  }
  #certificate-canvas {
    display: block;
    width: 170mm !important;
    max-width: 170mm !important;
    height: auto !important;
    margin: 0 auto !important;
    box-shadow: none !important;
    break-inside: avoid;
    page-break-inside: avoid;
  }
}

/* ---------- Small screens fine-tuning ---------- */
@media (max-width: 26rem) {
  .matching-grid {
    gap: var(--space-2);
  }
  .activity-card {
    padding: var(--space-4);
  }
  .welcome-hero {
    font-size: 3rem;
  }
}

/* ============================================================
   Diagram artwork (diagrams.js) — flat CSS/HTML coastal scenes
   ============================================================ */
.diagram-canvas {
  position: relative;
  width: 100%;
  height: 14rem;
  border-radius: var(--radius-md);
  overflow: hidden;
  box-shadow: var(--shadow-card);
  background: #BFE9E4;
}

@media (min-width: 34rem) {
  .diagram-canvas {
    height: 17rem;
  }
}

.diagram-art-piece {
  position: absolute;
  pointer-events: none;
}

.diagram-caption {
  position: absolute;
  bottom: 0.4rem;
  left: 0.6rem;
  font-size: 0.7rem;
  font-weight: 700;
  color: rgba(15, 60, 60, 0.55);
  background: rgba(255, 255, 255, 0.6);
  padding: 0.1rem 0.4rem;
  border-radius: var(--radius-sm);
  pointer-events: none;
}

/* headland-bay */
.diagram-headland-bay .hb-sea { inset: 0; background: linear-gradient(180deg, #7FD4CB, #2F9C93); }
.diagram-headland-bay .hb-headland-left {
  top: 0; left: 0; width: 40%; height: 68%;
  background: #A98358;
  clip-path: polygon(0 0, 100% 0, 62% 100%, 0 55%);
}
.diagram-headland-bay .hb-headland-left::after {
  content: "";
  position: absolute; inset: 0;
  background: linear-gradient(180deg, #7FAE5A 0%, #7FAE5A 22%, transparent 22%);
}
.diagram-headland-bay .hb-headland-right {
  top: 0; right: 0; width: 38%; height: 80%;
  background: #97754C;
  clip-path: polygon(100% 0, 0 0, 34% 100%, 100% 50%);
}
.diagram-headland-bay .hb-headland-right::after {
  content: "";
  position: absolute; inset: 0;
  background: linear-gradient(180deg, #6F9E4E 0%, #6F9E4E 18%, transparent 18%);
}
.diagram-headland-bay .hb-bay {
  top: 0; left: 32%; width: 36%; height: 40%;
  background: #F5DFA6;
  border-radius: 0 0 50% 50% / 0 0 70% 70%;
}
.diagram-headland-bay .hb-wcp {
  bottom: 14%; left: 3%; width: 32%; height: 11%;
  background: repeating-linear-gradient(90deg, #C7C2B8 0, #C7C2B8 0.5rem, #ADA89D 0.5rem, #ADA89D 1rem);
  border-radius: 0.25rem;
  opacity: 0.9;
}

/* erosion-sequence */
.diagram-erosion-sequence { display: flex; gap: 0.5%; background: #BFE9E4; padding: 0; }
.diagram-erosion-sequence .es-panel {
  position: relative;
  flex: 1 1 0;
  height: 100%;
  overflow: hidden;
  background: linear-gradient(180deg, #7FD4CB 0%, #2F9C93 100%);
  border-right: 0.1rem solid rgba(255,255,255,0.4);
}
.es-panel .es-label {
  position: absolute; top: 0.35rem; left: 0; right: 0;
  text-align: center; font-size: 0.68rem; font-weight: 800;
  color: #0F3C3C; pointer-events: none;
}
.es-panel .es-rock { position: absolute; background: #97754C; }
.es-panel .es-rock::after {
  content: ""; position: absolute; top: 0; left: 0; right: 0; height: 20%;
  background: #7FAE5A;
}
/* cave: rock block with a notch cut from the base */
.es-cave .es-rock { top: 22%; left: 15%; width: 70%; height: 78%; }
.es-cave .es-notch { position: absolute; bottom: 0; left: 40%; width: 26%; height: 40%; background: #2F9C93; border-radius: 0.3rem 0.3rem 0 0; }
/* arch: two legs with a rock bridge over a sea gap */
.es-arch .es-leg-left { top: 22%; left: 12%; width: 22%; height: 78%; background: #97754C; }
.es-arch .es-leg-right { top: 22%; left: 66%; width: 22%; height: 78%; background: #97754C; }
.es-arch .es-bridge { top: 22%; left: 12%; width: 76%; height: 20%; background: #8A6A45; border-radius: 0.4rem 0.4rem 0 0; }
/* stack: isolated tower surrounded by sea */
.es-stack .es-rock { top: 30%; left: 36%; width: 28%; height: 70%; }
/* stump: short, mostly-submerged remnant */
.es-stump .es-rock { top: 62%; left: 30%; width: 40%; height: 38%; border-radius: 0.2rem 0.2rem 0 0; }
.es-stump .es-rock::after { display: none; }

/* longshore-drift-spit */
.diagram-lds .lds-land {
  top: 0; left: 0; width: 62%; height: 100%;
  background: #7FAE5A;
  clip-path: polygon(0 0, 100% 0, 40% 100%, 0 100%);
}
.diagram-lds .lds-sea { inset: 0; background: linear-gradient(135deg, #7FD4CB, #2F9C93); z-index: -1; }
.diagram-lds .lds-river {
  top: 0; left: 26%; width: 12%; height: 55%;
  background: #2F9C93;
  clip-path: polygon(20% 0, 80% 0, 100% 100%, 0 100%);
}
.diagram-lds .lds-spit {
  top: 46%; left: 30%; width: 42%; height: 20%;
  background: #F5DFA6;
  border-radius: 0 50% 50% 40% / 0 50% 90% 40%;
  transform: rotate(-8deg);
}
.diagram-lds .lds-arrow {
  width: 3.2rem; height: 0.3rem; background: var(--colour-accent-dark);
  border-radius: 999px;
}
.diagram-lds .lds-arrow::after {
  content: "";
  position: absolute; right: -0.15rem; top: -0.35rem;
  border-left: 0.55rem solid var(--colour-accent-dark);
  border-top: 0.5rem solid transparent;
  border-bottom: 0.5rem solid transparent;
}
.diagram-lds .lds-arrow--back {
  background: #fff;
}
.diagram-lds .lds-arrow--back::after {
  border-left-color: #fff;
}

/* groyne-seawall */
.diagram-gs .gs-sea { inset: 0; background: linear-gradient(180deg, #7FD4CB, #2F9C93); }
.diagram-gs .gs-beach {
  bottom: 0; left: 0; width: 100%; height: 55%;
  background: #F5DFA6;
  clip-path: polygon(0 0, 100% 35%, 100% 100%, 0 100%);
}
.diagram-gs .gs-seawall {
  top: 0; left: 0; width: 16%; height: 42%;
  background: #A6A9AD;
  border-radius: 0 0 60% 0;
}
.diagram-gs .gs-groyne {
  top: 22%; width: 2.6%; height: 66%;
  background: #7A5A38;
  border-radius: 0.15rem;
}
.diagram-gs .gs-mound {
  bottom: 30%; width: 9%; height: 22%;
  background: #E8CB86;
  border-radius: 50% 50% 20% 20%;
}

/* Diagram zone number badge content */
.diagram-zone .zone-num {
  display: inline-block;
}

/* ---------- Dark mode support (prefers-color-scheme) ---------- */
@media (prefers-color-scheme: dark) {
  :root {
    --colour-bg: #0E2222;
    --colour-surface: #163333;
    --colour-text: #EAF6F4;
    --colour-text-muted: #A9C7C4;
    --colour-border: #24504D;
    --colour-sand: #3A331A;
    --colour-locked: #3A4A4A;
  }
  .option-btn.selected { background: #1D4A45; }
  .option-btn.correct-state { background: #1E3F1B; }
  .option-btn.incorrect-state { background: #4A2323; }
  .match-btn.locked-correct { background: #1E3F1B; }
  .match-btn.flash-wrong { background: #4A2323; }
  .speech-bubble--correct { background: #1E3F1B; }
  .speech-bubble--incorrect { background: #4A2323; }
  .hint-box { background: #332C15; }
  .diagram-wrap { background: linear-gradient(#0F4A46, #0F4A46); }
}
