<template>
  <div class="app">

    <!-- Start screen -->
    <div v-if="screen === null" class="center">
      <h1>🧱 Blocks</h1>
      <button @click="screen = 'exercises'">Demo de Ejercicios</button>
      <button @click="screen = 'creator'">Crear Ejercicio</button>
    </div>

    <!-- Demo Exercises screen -->
    <div v-else-if="screen === 'exercises'" class="page">
      <div class="bar">
        <button @click="screen = null">Volver</button>
        <button @click="resetAll">Reiniciar</button>
      </div>
      <div class="exercise-scroll">
        <div class="exercise-list">
          <Blocks v-for="(ex, idx) in demoExercises" :key="'demo-' + demoKeys[idx]" :exercise="ex"
            @complete="r => onComplete('demo', idx, r)" />
        </div>
      </div>
    </div>

    <!-- User Exercises screen -->
    <div v-else-if="screen === 'user-exercises'" class="page">
      <div class="bar">
        <button @click="screen = null">Volver</button>
        <button @click="resetAllUser">Reiniciar</button>
        <button @click="screen = 'creator'" style="margin-left:auto">+ Crear</button>
      </div>
      <div class="exercise-scroll">
        <div class="exercise-list">
          <div v-if="!userExercises.length" class="empty-state">No hay ejercicios creados todavía.</div>
          <Blocks v-for="(ex, idx) in userExercises" :key="'user-' + userKeys[idx]" :exercise="ex"
            @complete="r => onComplete('user', idx, r)" />
        </div>
      </div>
    </div>

    <!-- Creator screen -->
    <div v-else-if="screen === 'creator'" class="page">
      <div class="bar">
        <button @click="screen = 'user-exercises'">Volver</button>
        <span style="font-weight:600">Crear ejercicio</span>
        <button v-if="draft.length" class="btn-load" @click="loadDraft" style="margin-left:auto">
          Cargar {{ draft.length }} ejercicio{{ draft.length > 1 ? 's' : '' }}
        </button>
      </div>

      <div class="creator-scroll">
        <div class="creator-layout">

          <!-- LEFT: form -->
          <div class="creator-left">

            <!-- Draft list -->
            <div v-if="draft.length" class="draft-list">
              <div v-for="(ex, i) in draft" :key="i" class="draft-item"
                :class="{ 'draft-item--pinned': pinnedPreview === ex }"
                @click="pinnedPreview = pinnedPreview === ex ? null : ex">
                <span class="draft-nums">{{ex.grids.filter(g => g.mode !== 'target').map(g => g.label ||
                  g.value).join(' + ')}}</span>
                <span class="draft-dropzones">→ {{ex.grids.filter(g => g.mode === 'target').map(g => g.label).join(',')
                  || 'sin banca' }}</span>
                <button class="btn-icon btn-delete"
                  @click.stop="draft.splice(i, 1); if (pinnedPreview === ex) pinnedPreview = null">✕</button>
              </div>
            </div>

            <!-- Form -->
            <div class="creator-form">

              <!-- Exercise type -->
              <div class="field">
                <label>Tipo de ejercicio</label>
                <div class="mode-toggle">
                  <button class="mode-btn" :class="{ 'mode-btn--active': form.exerciseType === 'move-blocks' }"
                    @click="form.exerciseType = 'move-blocks'">Mover bloques</button>
                  <button class="mode-btn" :class="{ 'mode-btn--active': form.exerciseType === 'input-check' }"
                    @click="form.exerciseType = 'input-check'">Escribir número</button>
                  <button class="mode-btn" :class="{ 'mode-btn--active': form.exerciseType === 'sides' }"
                    @click="form.exerciseType = 'sides'">Lados ↔</button>
                  <button class="mode-btn" :class="{ 'mode-btn--active': form.exerciseType === 'mark-options' }"
                    @click="form.exerciseType = 'mark-options'">Marcar ✕</button>
                </div>
              </div>

              <!-- Layout -->
              <div class="field" v-if="form.exerciseType !== 'sides' && form.exerciseType !== 'mark-options'">
                <label>Disposición</label>
                <div class="mode-toggle">
                  <button v-if="form.exerciseType !== 'move-blocks'" class="mode-btn"
                    :class="{ 'mode-btn--active': form.layout === 'row' }" @click="form.layout = 'row'">Fila →</button>
                  <button v-if="form.exerciseType !== 'move-blocks'" class="mode-btn"
                    :class="{ 'mode-btn--active': form.layout === 'column' }" @click="form.layout = 'column'">Columna
                    ↓</button>
                  <button v-if="form.exerciseType === 'move-blocks'" class="mode-btn"
                    :class="{ 'mode-btn--active': form.layout === 'row-answer-right' }"
                    @click="form.layout = 'row-answer-right'">Resp. →</button>
                  <button v-if="form.exerciseType === 'move-blocks'" class="mode-btn"
                    :class="{ 'mode-btn--active': form.layout === 'row-answer-bottom' }"
                    @click="form.layout = 'row-answer-bottom'">Resp. ↓</button>
                  <button v-if="form.exerciseType === 'move-blocks'" class="mode-btn"
                    :class="{ 'mode-btn--active': form.layout === 'column' }" @click="form.layout = 'column'">Columna
                    ↓</button>
                </div>
              </div>

              <!-- Answer position for input-check -->
              <div class="field" v-if="form.exerciseType === 'input-check'">
                <label>Posición de la casilla</label>
                <div class="mode-toggle">
                  <button class="mode-btn" :class="{ 'mode-btn--active': form.answerPosition === 'right' }"
                    @click="form.answerPosition = 'right'">Derecha →</button>
                  <button class="mode-btn" :class="{ 'mode-btn--active': form.answerPosition === 'bottom' }"
                    @click="form.answerPosition = 'bottom'">Abajo ↓</button>
                </div>
              </div>

              <div class="field">
                <label>Opciones</label>
                <div class="mode-toggle">
                  <button class="mode-btn" :class="{ 'mode-btn--active': !form.hideBorders }"
                    @click="form.hideBorders = false">Bordes visibles</button>
                  <button class="mode-btn" :class="{ 'mode-btn--active': form.hideBorders }"
                    @click="form.hideBorders = true">Sin bordes</button>
                </div>
              </div>

              <div class="field">
                <label>Enunciado <span class="hint">(opcional)</span></label>
                <input v-model="form.text" type="text" placeholder="Ej: Pedro tiene 5 manzanas..." />
              </div>

              <div class="field">
                <label>Grids <span class="hint">— bloques por grupo</span></label>
                <div class="grids-col">
                  <div v-for="(g, i) in form.grids" :key="i" class="grid-entry">
                    <div class="grid-row">
                      <span class="grid-idx">{{ i + 1 }}</span>
                      <input class="grid-num-input" type="number" min="1" max="20" placeholder=""
                        :value="g.value > 0 ? g.value : ''" @input="onGridValueInput(i, $event)"
                        @blur="onGridBlur(i, $event)" />
                      <input v-if="g.value > 0" class="grid-label-input" type="text" :placeholder="'Nombre ' + (i + 1)"
                        v-model="g.label" />
                    </div>
                    <!-- Fruit picker — dropdown select -->
                    <div v-if="g.value > 0" class="image-select-wrap">
                      <select class="image-select" v-model="g.image">
                        <option :value="null">🟥 Bloques de color</option>
                        <option v-for="f in FRUITS" :key="f.key" :value="f.key">
                          {{ f.emoji }} {{ f.label }}
                        </option>
                      </select>
                    </div>
                  </div>
                </div>
              </div>

              <!-- mark-options: which grid is correct -->
              <div class="field" v-if="form.exerciseType === 'mark-options' && validGrids.length >= 2">
                <label>Respuesta correcta</label>
                <select class="image-select" v-model="form.correctGridIdx" style="max-width:220px">
                  <option v-for="(g, i) in validGrids" :key="i" :value="i">
                    {{ g.label || ('Grid ' + (form.grids.indexOf(g) + 1)) }}
                  </option>
                </select>
              </div>

              <!-- move-blocks / sides: banca config -->
              <div class="field"
                v-if="(form.exerciseType === 'move-blocks' || form.exerciseType === 'sides') && validGrids.length">
                <label>Banca <span class="hint">— respuesta esperada por origen</span></label>
                <div class="grid-row" style="margin-bottom:0.5rem">
                  <input class="grid-label-input" type="text" placeholder="Etiqueta respuesta" v-model="form.bancaLabel"
                    style="max-width:180px" />
                </div>
                <div class="needs-table">
                  <div v-for="(g, i) in validGrids" :key="i" class="needs-row">
                    <span class="needs-grid-idx">{{ form.grids.indexOf(g) + 1 }}</span>
                    <span class="needs-label">{{ g.label || ('Grid ' + (form.grids.indexOf(g) + 1)) }}</span>
                    <span class="needs-arrow">→</span>
                    <input class="grid-num-input grid-num-input--sm" type="number" min="0" max="20" placeholder="0"
                      :value="g.needs > 0 ? g.needs : ''" @input="onGridNeedsInput(form.grids.indexOf(g), $event)" />
                    <span class="needs-hint">bloques</span>
                  </div>
                </div>
              </div>

              <!-- input-check: expected answer -->
              <div class="field" v-if="form.exerciseType === 'input-check' && validGrids.length">
                <label>Respuesta correcta</label>
                <div class="grid-row">
                  <input class="grid-num-input" type="number" min="0" max="99" placeholder="?"
                    v-model.number="form.expectedAnswer" />
                  <span class="needs-hint">valor esperado</span>
                </div>
              </div>

              <button class="btn-add-draft" @click="addToDraft" :disabled="!canAdd">
                + Agregar a la lista
              </button>
            </div>
          </div>

          <!-- RIGHT: live preview -->
          <div class="creator-right">
            <div class="preview-label">Vista previa</div>
            <div v-if="!previewExercise" class="preview-empty">
              Ingresa al menos un número para ver el ejercicio.
            </div>
            <div v-else class="preview-card" :class="{ 'preview-card--last': !previewIsLive }">
              <p v-if="!previewIsLive" class="preview-last-label">Último agregado</p>
              <div class="preview-blocks-wrap">
                <Blocks :key="previewKey" :exercise="previewExercise" />
              </div>
            </div>
          </div>

        </div>
      </div>
    </div>

  </div>
</template>

<script setup>
import { ref, computed, watch } from 'vue';
import Blocks from './components/Blocks.vue';

// ── SCREEN ──
const screen = ref(null);

// ── FRUIT CATALOGUE ──
// Keep in sync with IMAGE_DICT in Blocks.vue manually when adding/removing images.
const FRUITS = [
  { key: 'manzana', emoji: '🍎', label: 'Manzana' },
  { key: 'banana', emoji: '🍌', label: 'Banana' },
  { key: 'frutilla', emoji: '🍓', label: 'Frutilla' },
  { key: 'zanahoria', emoji: '🥕', label: 'Zanahoria' },
  { key: 'limon', emoji: '🍋', label: 'Limón' },
  { key: 'mango', emoji: '🥭', label: 'Mango' },
  { key: 'uva', emoji: '🍇', label: 'Uva' },
  { key: 'tomate', emoji: '🍅', label: 'Tomate' },
  { key: 'palta', emoji: '🥑', label: 'Palta' },
  { key: 'kiwi', emoji: '🥝', label: 'Kiwi' },
  { key: 'naranja', emoji: '🍊', label: 'Naranja' },
  { key: 'pina', emoji: '🍍', label: 'Piña' },
];

// ── DEMO EXERCISES ──
// New schema:
// exerciseType: 'move-blocks' | 'input-check' | 'mark-options'
// layout: 'row' | 'column' | 'row-answer-right' | 'row-answer-bottom'
// answerPosition (input-check only): 'right' | 'bottom'
// grids[].mode: 'active' | 'static' | 'target'
// grids[].id: string (used to match origins in answerSlot)
// answerSlot: { from: 'any' | string[], count: number } (for target grids)
// answerSlot: { expects: number } (for input-check at exercise level)

const demoExercises = ref([

  // ════════════════════════════════════════════
  // NEW EXERCISE COMPONENTS
  // ════════════════════════════════════════════

  // ── compose-decompose ──
  {
    exerciseType: 'compose-decompose',
    text: '¿Qué números forman el 10?',
    whole: 10, numberOfOptions: 4, image: 'manzana',
  },
  {
    exerciseType: 'compose-decompose',
    text: '¿Qué números forman el 7?',
    whole: 7, numberOfOptions: 3, image: 'naranja',
  },

  // ── picture-choose ──
  {
    exerciseType: 'picture-choose',
    text: 'Hay 5 manzanas y 4 naranjas. ¿Cuántas hay en total?',
    firstImage: 'manzana', secondImage: 'naranja',
    options: [
      { first: 3, second: 4, correct: false },
      { first: 5, second: 2, correct: false },
      { first: 5, second: 4, correct: true },
    ],
  },
  {
    exerciseType: 'picture-choose',
    text: 'Hay 6 fresas y 3 limones. ¿Cuántas hay en total?',
    firstImage: 'frutilla', secondImage: 'limon',
    options: [
      { first: 4, second: 3, correct: false },
      { first: 6, second: 3, correct: true },
      { first: 6, second: 5, correct: false },
      { first: 5, second: 4, correct: false },
    ],
  },

  // ── where-more ──
  {
    exerciseType: 'where-more',
    text: '¿Dónde hay más? Marca con una X.',
    mode: 'more',
    comparisons: [
      { left: { value: 6, image: 'manzana' }, right: { value: 5, image: 'banana' } },
      { left: { value: 4, image: 'naranja' }, right: { value: 7, image: 'frutilla' } },
      { left: { value: 8, image: 'uva' }, right: { value: 3, image: 'limon' } },
    ],
  },
  {
    exerciseType: 'where-more',
    text: '¿Dónde hay menos? Marca con una X.',
    mode: 'less',
    comparisons: [
      { left: { value: 9, image: 'manzana' }, right: { value: 2, image: 'naranja' } },
      { left: { value: 3, image: 'banana' }, right: { value: 8, image: 'kiwi' } },
    ],
  },

  // ── connect: labels ──
  {
    exerciseType: 'connect',
    text: 'Conecta las sumas que tienen el mismo resultado.',
    columns: 2,
    leftItems: [
      { id: 'l1', label: '3 + 5' },
      { id: 'l2', label: '2 + 4' },
      { id: 'l3', label: '4 + 5' },
    ],
    rightItems: [
      { id: 'r1', label: '6 + 3' },
      { id: 'r2', label: '4 + 4' },
      { id: 'r3', label: '1 + 5' },
    ],
    correctPairs: [
      { left: 'l1', right: 'r2' },
      { left: 'l2', right: 'r3' },
      { left: 'l3', right: 'r1' },
    ],
  },

  // ── connect: grids 2 columns ──
  {
    exerciseType: 'connect',
    text: 'Conecta los que tienen la misma cantidad.',
    columns: 2,
    leftItems: [
      { id: 'l1', grids: [{ value: 3, image: 'manzana' }, { value: 5, image: 'manzana' }] },
      { id: 'l2', grids: [{ value: 2, image: 'naranja' }, { value: 4, image: 'naranja' }] },
      { id: 'l3', grids: [{ value: 4, image: 'banana' }, { value: 5, image: 'banana' }] },
    ],
    rightItems: [
      { id: 'r1', grids: [{ value: 4, image: 'frutilla' }, { value: 4, image: 'frutilla' }] },
      { id: 'r2', grids: [{ value: 6, image: 'zanahoria' }, { value: 3, image: 'zanahoria' }] },
      { id: 'r3', grids: [{ value: 5, image: 'limon' }, { value: 1, image: 'limon' }] },
    ],
    correctPairs: [
      { left: 'l1', right: 'r1' },
      { left: 'l2', right: 'r3' },
      { left: 'l3', right: 'r2' },
    ],
  },

  // ── connect: 3 columns ──
  {
    exerciseType: 'connect',
    text: 'Conecta cada grupo con su número.',
    columns: 3,
    leftItems: [
      { id: 'l1', grids: [{ value: 4, image: 'naranja' }] },
      { id: 'l2', grids: [{ value: 2, image: 'manzana' }] },
      { id: 'l3', grids: [{ value: 3, image: 'banana' }] },
    ],
    centerItems: [
      { id: 'c1', grids: [{ value: 2, color: '#6366f1' }] },
      { id: 'c2', grids: [{ value: 3, color: '#6366f1' }] },
      { id: 'c3', grids: [{ value: 4, color: '#6366f1' }] },
    ],
    rightItems: [
      { id: 'r1', grids: [{ value: 3, image: 'limon' }] },
      { id: 'r2', grids: [{ value: 4, image: 'zanahoria' }] },
      { id: 'r3', grids: [{ value: 2, image: 'frutilla' }] },
    ],
    correctPairs: [
      { left: 'l1', center: 'c3' },
      { left: 'l2', center: 'c1' },
      { left: 'l3', center: 'c2' },
      { right: 'r1', center: 'c2' },
      { right: 'r2', center: 'c3' },
      { right: 'r3', center: 'c1' },
    ],
  },

  // ── subtract-visual ──
  {
    exerciseType: 'subtract-visual',
    text: 'Hay 5 manzanas. Se comieron 2. ¿Cuántas quedan?',
    initialQuantity: 5, removedQuantity: 2, image: 'manzana',
    options: [{ id: 'o1', value: 3 }, { id: 'o2', value: 4 }, { id: 'o3', value: 2 }, { id: 'o4', value: 1 }],
    correctAnswer: 3,
  },
  {
    exerciseType: 'subtract-visual',
    text: 'Hay 9 naranjas. Se sacaron 4. ¿Cuántas quedan?',
    initialQuantity: 9, removedQuantity: 4, image: 'naranja',
    options: [{ id: 'o1', value: 5 }, { id: 'o2', value: 6 }, { id: 'o3', value: 3 }, { id: 'o4', value: 4 }],
    correctAnswer: 5,
  },

  // ════════════════════════════════════════════
  // LEGACY / BLOCKS-BASED EXERCISES
  // ════════════════════════════════════════════

  // ── move-blocks: answer right ──
  {
    exerciseType: 'move-blocks',
    layout: 'row-answer-right',
    text: "María tiene 2 manzanas y Juan tiene 3. ¿Cuántas tienen en total?",
    grids: [
      { id: 'maria', mode: 'active', value: 2, label: 'María', image: 'manzana' },
      { id: 'juan', mode: 'active', value: 3, label: 'Juan', image: 'zanahoria' },
      { id: 'resp', mode: 'target', label: 'Total', answerSlot: { from: 'any', count: 5 } },
    ],
  },

  // ── move-blocks: answer bottom, by origin ──
  {
    exerciseType: 'move-blocks',
    layout: 'row-answer-bottom',
    text: "Pedro tiene 3 manzanas y Alicia tiene 2. Pedro le da 2 a Alicia. ¿Cuántas tiene Alicia?",
    grids: [
      { id: 'pedro', mode: 'active', value: 3, label: 'Pedro', image: 'manzana' },
      { id: 'alicia', mode: 'active', value: 2, label: 'Alicia', image: 'frutilla' },
      {
        id: 'resp', mode: 'target', label: 'Alicia al final',
        answerSlot: { from: [{ id: 'pedro', count: 2 }, { id: 'alicia', count: 2 }] }
      },
    ],
  },

  // ── sides ──
  {
    exerciseType: 'sides',
    text: "Junta los bloques de ambos lados en el centro.",
    grids: [
      { id: 'izq1', mode: 'active', value: 3, label: 'Grupo A', image: 'manzana' },
      { id: 'der1', mode: 'active', value: 2, label: 'Grupo B', image: 'banana' },
      { id: 'izq2', mode: 'active', value: 1, label: 'Grupo C', image: 'naranja' },
      { id: 'resp', mode: 'target', label: 'Total', answerSlot: { from: 'any', count: 6 } },
    ],
  },

  // ── input-check ──
  {
    exerciseType: 'input-check',
    layout: 'row', answerPosition: 'right',
    text: "¿Cuántos hay en total?",
    answerSlot: { expects: 5 },
    grids: [
      { id: 'g1', mode: 'static', value: 2, label: 'Grupo 1', image: 'naranja' },
      { id: 'g2', mode: 'static', value: 3, label: 'Grupo 2' },
    ],
  },

  // ── mark-options ──
  {
    exerciseType: 'mark-options',
    layout: 'row',
    text: "¿Dónde hay menos? Marca con una X.",
    answerSlot: { correctId: 'koalas' },
    grids: [
      { id: 'pandas', mode: 'static', value: 6, label: 'Pandas' },
      { id: 'koalas', mode: 'static', value: 5, label: 'Koalas' },
    ],
  },

]);

// ── USER EXERCISES ──
const userExercises = ref([]);

// ── KEYS (para forzar re-render al resetear) ──
const demoKeys = ref(demoExercises.value.map((_, i) => i * 100));
const userKeys = ref([]);

const growUserArrays = (exercises) => {
  exercises.forEach(() => {
    userKeys.value.push(userKeys.value.length * 100 + Date.now() % 1000);
  });
};

// ── COMPLETE ──
const onComplete = (_group, _idx, _result) => { };

// ── RESET ──
const resetAll = () => { demoKeys.value = demoKeys.value.map(k => k + 1000); };
const resetAllUser = () => { userKeys.value = userKeys.value.map(k => k + 1000); };

// ── CREATOR ──
const defaultGrid = () => ({ value: '', label: '', needs: '', image: null });
const defaultForm = () => ({
  text: '',
  exerciseType: 'move-blocks',
  layout: 'row-answer-right',
  answerPosition: 'right',
  grids: [defaultGrid()],
  bancaLabel: '',
  expectedAnswer: '',
});

const form = ref(defaultForm());
const draft = ref([]);
const lastAdded = ref(null);
const pinnedPreview = ref(null);

const validGrids = computed(() =>
  form.value.grids.filter(g => parseInt(g.value) > 0)
);

const canAdd = computed(() => {
  if (!validGrids.value.length) return false;
  if (form.value.exerciseType === 'move-blocks')
    return validGrids.value.some(g => parseInt(g.needs) > 0);
  if (form.value.exerciseType === 'input-check')
    return form.value.expectedAnswer !== '' && !isNaN(Number(form.value.expectedAnswer));
  if (form.value.exerciseType === 'sides')
    return validGrids.value.some(g => parseInt(g.needs) > 0);
  if (form.value.exerciseType === 'mark-options') return validGrids.value.length >= 2;
  return false;
});

// Grid inputs — cascade: fill → next slot appears
const onGridValueInput = (i, e) => {
  const raw = parseInt(e.target.value);
  const val = isNaN(raw) ? '' : Math.min(20, Math.max(1, raw));
  e.target.value = val === '' ? '' : val;
  form.value.grids[i].value = val;
  if (i === form.value.grids.length - 1 && val > 0 && form.value.grids.length < 7)
    form.value.grids.push(defaultGrid());
};
const onGridBlur = (i, e) => {
  const parsed = parseInt(e.target.value);
  if (!e.target.value || isNaN(parsed) || parsed <= 0) form.value.grids[i].value = '';
  const gs = form.value.grids;
  let last = gs.length - 1;
  while (last > 0 && (!gs[last].value || parseInt(gs[last].value) <= 0)) last--;
  form.value.grids = [...gs.slice(0, last + 1), defaultGrid()];
};
const onGridNeedsInput = (i, e) => {
  const raw = parseInt(e.target.value);
  const val = isNaN(raw) ? '' : Math.min(20, Math.max(0, raw));
  e.target.value = val === '' ? '' : val;
  form.value.grids[i].needs = val;
};

// ── PREVIEW ──
const previewKey = ref(0);
const previewIsLive = computed(() => validGrids.value.length > 0 && !pinnedPreview.value);

const previewExercise = computed(() => {
  if (pinnedPreview.value) return pinnedPreview.value;
  if (!validGrids.value.length) return lastAdded.value;

  const srcGrids = validGrids.value.map((g, i) => ({
    id: 'g' + i,
    mode: form.value.exerciseType === 'move-blocks' ? 'active' : 'static',
    value: parseInt(g.value),
    label: g.label || String(g.value),
    ...(g.image ? { image: g.image } : {}),
  }));

  if (form.value.exerciseType === 'move-blocks') {
    const answers = validGrids.value
      .filter(g => parseInt(g.needs) > 0)
      .map((g, _i, arr) => ({ id: 'g' + validGrids.value.indexOf(g), count: parseInt(g.needs) }));

    return {
      exerciseType: 'move-blocks',
      layout: form.value.layout,
      hideBorders: form.value.hideBorders,
      text: form.value.text,
      grids: [
        ...srcGrids,
        {
          id: 'target',
          mode: 'target',
          label: form.value.bancaLabel || 'Respuesta',
          answerSlot: answers.length
            ? { from: answers }
            : { from: 'any', count: srcGrids.reduce((s, g) => s + g.value, 0) },
        },
      ],
    };
  }

  if (form.value.exerciseType === 'input-check') {
    return {
      exerciseType: 'input-check',
      layout: form.value.layout,
      answerPosition: form.value.answerPosition,
      hideBorders: form.value.hideBorders,
      text: form.value.text,
      answerSlot: { expects: Number(form.value.expectedAnswer) },
      grids: srcGrids,
    };
  }

  // sides: target in center, sources alternate left/right
  if (form.value.exerciseType === 'sides') {
    const answers = validGrids.value
      .filter(g => parseInt(g.needs) > 0)
      .map(g => ({ id: 'g' + validGrids.value.indexOf(g), count: parseInt(g.needs) }));
    return {
      exerciseType: 'sides',
      hideBorders: form.value.hideBorders,
      text: form.value.text,
      grids: [
        ...srcGrids,
        {
          id: 'target',
          mode: 'target',
          label: form.value.bancaLabel || 'Respuesta',
          answerSlot: answers.length
            ? { from: answers }
            : { from: 'any', count: srcGrids.reduce((s, g) => s + g.value, 0) },
        },
      ],
    };
  }

  // mark-options
  return {
    exerciseType: 'mark-options',
    hideBorders: form.value.hideBorders,
    layout: 'row',
    text: form.value.text,
    answerSlot: { correctId: srcGrids[form.value.correctGridIdx]?.id ?? srcGrids[0]?.id },
    grids: srcGrids,
  };
});

watch(() => JSON.stringify(form.value), () => {
  if (pinnedPreview.value && validGrids.value.length > 0) pinnedPreview.value = null;
}, { deep: true });

const addToDraft = () => {
  if (!canAdd.value || !previewExercise.value) return;
  const ex = JSON.parse(JSON.stringify(previewExercise.value));
  draft.value.push(ex);
  lastAdded.value = ex;
  form.value = defaultForm();
};

const loadDraft = () => {
  growUserArrays(draft.value);
  userExercises.value.push(...draft.value);
  draft.value = [];
  lastAdded.value = null;
  screen.value = 'user-exercises';
};
</script>

<style scoped>
* {
  box-sizing: border-box;
  margin: 0;
  padding: 0;
}

.app {
  width: 100%;
  height: 100vh;
  font-family: system-ui, sans-serif;
  font-size: 14px;
  background: #f0f4f8;
  display: flex;
  flex-direction: column;
}

.center {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  height: 100vh;
  gap: 0.75rem;
}

.center h1 {
  font-size: 1.5rem;
  margin-bottom: 0.5rem;
}

.page {
  height: 100vh;
  display: flex;
  flex-direction: column;
}

.bar {
  display: flex;
  align-items: center;
  gap: 0.5rem;
  padding: 0.5rem 0.75rem;
  background: white;
  border-bottom: 1px solid #ddd;
  font-weight: 600;
  color: #333;
  flex-shrink: 0;
  z-index: 500;
}

.exercise-scroll {
  flex: 1;
  overflow-y: auto;
  padding: 1.5rem 1rem 3rem;
}

.exercise-list {
  max-width: 860px;
  margin: 0 auto;
  display: flex;
  flex-direction: column;
  gap: 1.5rem;
}

/* ── Creator ── */
.creator-scroll {
  flex: 1;
  overflow-y: auto;
  padding: 1rem;
}

.creator-layout {
  max-width: 900px;
  margin: 0 auto;
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 1.25rem;
  align-items: start;
}

.creator-left {
  display: flex;
  flex-direction: column;
  gap: 0.75rem;
}

.creator-form {
  background: white;
  border: 1px solid #e5e7eb;
  border-radius: 10px;
  padding: 1rem;
  display: flex;
  flex-direction: column;
  gap: 0.85rem;
}

.field {
  display: flex;
  flex-direction: column;
  gap: 0.3rem;
}

.field label {
  font-size: 0.78rem;
  font-weight: 700;
  color: #374151;
  text-transform: uppercase;
  letter-spacing: 0.04em;
}

.hint {
  font-weight: 400;
  color: #9ca3af;
  text-transform: none;
  letter-spacing: 0;
}

.field input[type="text"] {
  width: 100%;
  padding: 0.38rem 0.55rem;
  border: 1px solid #d1d5db;
  border-radius: 6px;
  font-size: 0.875rem;
  font-family: inherit;
  background: white;
  color: #333;
}

.field input[type="text"]:focus {
  outline: 2px solid #6366f1;
  outline-offset: -1px;
}

.grids-col {
  display: flex;
  flex-direction: column;
  gap: 0.3rem;
}

.grid-entry {
  display: flex;
  flex-direction: column;
  gap: 0.25rem;
}

.grid-row {
  display: flex;
  align-items: center;
  gap: 0.5rem;
}

.grid-idx {
  width: 18px;
  height: 18px;
  border-radius: 50%;
  background: #e0e7ff;
  color: #6366f1;
  font-size: 0.65rem;
  font-weight: 700;
  display: flex;
  align-items: center;
  justify-content: center;
  flex-shrink: 0;
}

.needs-table {
  display: flex;
  flex-direction: column;
  gap: 0.3rem;
}

.needs-row {
  display: flex;
  align-items: center;
  gap: 0.4rem;
  font-size: 0.82rem;
}

.needs-grid-idx {
  width: 18px;
  height: 18px;
  border-radius: 50%;
  background: #e0e7ff;
  color: #6366f1;
  font-size: 0.65rem;
  font-weight: 700;
  display: flex;
  align-items: center;
  justify-content: center;
  flex-shrink: 0;
}

.needs-label {
  color: #374151;
  font-weight: 600;
  min-width: 60px;
}

.needs-arrow {
  color: #9ca3af;
}

.needs-hint {
  color: #9ca3af;
  font-size: 0.75rem;
}

.grid-num-input {
  width: 58px;
  padding: 0.35rem 0.4rem;
  border: 1px solid #d1d5db;
  border-radius: 6px;
  font-size: 0.875rem;
  font-family: inherit;
  background: white;
  color: #333;
  text-align: center;
}

.grid-num-input:focus {
  outline: 2px solid #6366f1;
  outline-offset: -1px;
}

.grid-num-input--sm {
  width: 46px;
}

.grid-label-input {
  flex: 1;
  padding: 0.35rem 0.5rem;
  border: 1px solid #d1d5db;
  border-radius: 6px;
  font-size: 0.8rem;
  font-family: inherit;
  background: white;
  color: #555;
  max-width: 130px;
}

.grid-label-input:focus {
  outline: 2px solid #6366f1;
  outline-offset: -1px;
}

/* Preview */
.creator-right {
  position: sticky;
  top: 0;
  display: flex;
  flex-direction: column;
  gap: 0.5rem;
}

.preview-label {
  font-size: 0.72rem;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.07em;
  color: #94a3b8;
}

.preview-empty {
  background: white;
  border: 1px dashed #d1d5db;
  border-radius: 8px;
  padding: 2rem 1rem;
  text-align: center;
  color: #9ca3af;
  font-size: 0.85rem;
}

.preview-card {
  background: white;
  border: 1px solid #e5e7eb;
  border-radius: 10px;
  overflow: visible;
}

.preview-card--last {
  border-color: #c7d2fe;
  background: #fafbff;
}

.preview-last-label {
  font-size: 0.7rem;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.06em;
  color: #818cf8;
  padding: 0.5rem 0.75rem 0;
}

.preview-blocks-wrap {
  pointer-events: none;
  user-select: none;
}

/* Buttons */
button {
  padding: 0.4rem 0.9rem;
  background: white;
  border: 1px solid #d1d5db;
  border-radius: 6px;
  font-size: 0.85rem;
  font-weight: 600;
  cursor: pointer;
  font-family: inherit;
  color: #333;
}

button:hover {
  background: #f0f0f0;
}

button:disabled {
  opacity: 0.5;
  cursor: default;
}

.btn-icon {
  padding: 0.2rem 0.45rem;
  font-size: 0.78rem;
  border-color: #e5e7eb;
  color: #6b7280;
}

.btn-add-draft {
  align-self: flex-start;
}

.btn-load {
  background: #6366f1;
  color: white;
  border-color: #6366f1;
}

.btn-load:hover {
  background: #4f46e5;
}

.mode-toggle {
  display: flex;
  gap: 0;
  border: 1px solid #d1d5db;
  border-radius: 6px;
  overflow: hidden;
  width: fit-content;
}

.mode-btn {
  padding: 0.3rem 0.75rem;
  border: none;
  border-radius: 0;
  font-size: 0.8rem;
  font-weight: 500;
  background: white;
  color: #6b7280;
  cursor: pointer;
}

.mode-btn:hover {
  background: #f0f0f0;
}

.mode-btn--active {
  background: #6366f1;
  color: white;
}

.mode-btn--active:hover {
  background: #4f46e5;
}

.empty-state {
  text-align: center;
  color: #6b7280;
  padding: 2rem 0;
  font-size: 0.9rem;
}

.draft-list {
  background: white;
  border: 1px solid #e5e7eb;
  border-radius: 8px;
  overflow: hidden;
}

.draft-item {
  display: flex;
  align-items: center;
  gap: 0.5rem;
  padding: 0.45rem 0.75rem;
  border-bottom: 1px solid #f3f4f6;
  cursor: pointer;
  font-size: 0.82rem;
}

.draft-item:last-child {
  border-bottom: none;
}

.draft-item:hover {
  background: #fafbff;
}

.draft-item--pinned {
  background: #eef2ff;
}

.draft-nums {
  font-weight: 600;
  color: #374151;
}

.draft-dropzones {
  color: #9ca3af;
  font-size: 0.78rem;
}

/* ── Fruit picker (select) ── */
.image-select-wrap {
  padding: 2px 0 4px 26px;
}

.image-select {
  padding: 0.3rem 0.5rem;
  border: 1px solid #d1d5db;
  border-radius: 6px;
  font-size: 0.85rem;
  font-family: inherit;
  background: white;
  color: #374151;
  cursor: pointer;
  width: 100%;
  max-width: 200px;
}

.image-select:focus {
  outline: 2px solid #6366f1;
  outline-offset: -1px;
}
</style>