version: 1
directus: "10.10.0"
# ═══════════════════════════════════════════════════════════════════
# ZGZ TURISMO — DIRECTUS 10 SCHEMA SNAPSHOT
# Basado en esquema Asturias DigitalMetaverso (ar_scenes, pois,
# analytics_events, routes, categories, translations)
# + Requisitos C1/C2/PR_260047 · DeuSens Hyperxperience S.L.
# Apply: npx directus schema apply ./snapshots/zgz_schema_snapshot.yaml
# ═══════════════════════════════════════════════════════════════════

collections:
  - collection: languages
    meta: { hidden: false, icon: translate, color: "#2ECDA7", note: "Idiomas disponibles: es-ES, en-US, fr-FR, ca-ES, ru-RU" }
    schema: { name: languages }

  - collection: categories
    meta: { hidden: false, icon: category, color: "#FF6B35", sort_field: sort, note: "Taxonomia jerarquica (C1-F5)" }
    schema: { name: categories }

  - collection: categories_translations
    meta: { hidden: true }
    schema: { name: categories_translations }

  - collection: tags
    meta: { hidden: false, icon: label, color: "#9C27B0" }
    schema: { name: tags }

  - collection: tags_translations
    meta: { hidden: true }
    schema: { name: tags_translations }

  - collection: ar_scenes
    meta: { hidden: false, icon: view_in_ar, color: "#7E57C2", sort_field: sort, note: "Escenas AR y viewers 3D — GLB/Needle Engine. Estructura Asturias adaptada." }
    schema: { name: ar_scenes }

  - collection: ar_scenes_translations
    meta: { hidden: true }
    schema: { name: ar_scenes_translations }

  - collection: hotspots
    meta: { hidden: false, icon: location_on, color: "#F44336", sort_field: sort, note: "Puntos multimedia vinculados a PoIs (C1-F2)" }
    schema: { name: hotspots }

  - collection: hotspots_translations
    meta: { hidden: true }
    schema: { name: hotspots_translations }

  - collection: pois
    meta: { hidden: false, icon: place, color: "#E91E63", sort_field: sort, note: "Puntos de Interes geolocalizados (C1-F1). Estructura Asturias." }
    schema: { name: pois }

  - collection: pois_translations
    meta: { hidden: true }
    schema: { name: pois_translations }

  - collection: pois_categories
    meta: { hidden: true }
    schema: { name: pois_categories }

  - collection: pois_tags
    meta: { hidden: true }
    schema: { name: pois_tags }

  - collection: routes
    meta: { hidden: false, icon: route, color: "#009688", sort_field: sort, note: "Rutas tematicas con track GPS (C1-F3). Estructura Asturias." }
    schema: { name: routes }

  - collection: routes_translations
    meta: { hidden: true }
    schema: { name: routes_translations }

  - collection: routes_pois
    meta: { hidden: true, note: "Junction: orden de paradas en ruta" }
    schema: { name: routes_pois }

  - collection: kiosk_contents
    meta: { hidden: false, icon: tv, color: "#FF9800", sort_field: sort, note: "Contenidos App Kiosco Plaza del Pilar (PR_260047 F4) — bilingue ES/EN" }
    schema: { name: kiosk_contents }

  - collection: kiosk_categories
    meta: { hidden: false, icon: grid_view, color: "#F57C00", note: "Categorias para grid kiosco (6-10 segun cliente)" }
    schema: { name: kiosk_categories }

  - collection: kiosk_contents_categories
    meta: { hidden: true }
    schema: { name: kiosk_contents_categories }

  - collection: kiosk_contents_tags
    meta: { hidden: true }
    schema: { name: kiosk_contents_tags }

  - collection: contact_submissions
    meta: { hidden: false, icon: email, color: "#795548", note: "Formulario contacto — email via Directus Flows + SMTP" }
    schema: { name: contact_submissions }

  - collection: analytics_events
    meta: { hidden: false, icon: analytics, color: "#00BCD4", note: "Telemetria privacy-first PWA+Kiosco. IPs anonimizadas. Estructura Asturias." }
    schema: { name: analytics_events }

  - collection: media_assets
    meta: { hidden: false, icon: perm_media, color: "#4CAF50", note: "Biblioteca multimedia centralizada con metadatos (C1-F4)" }
    schema: { name: media_assets }

  - collection: ui_translations
    meta: { hidden: false, icon: translate, color: "#607D8B", note: "Traducciones UI para PWA y Kiosco (i18n keys)" }
    schema: { name: ui_translations }

  - collection: homepage_content
    meta: { hidden: false, icon: home, color: "#2196F3", singleton: true, note: "Contenido singleton pagina de inicio" }
    schema: { name: homepage_content }

  - collection: homepage_slides
    meta: { hidden: false, icon: slideshow, color: "#2196F3", sort_field: sort, note: "Slides del hero slider en la pagina de inicio" }
    schema: { name: homepage_slides }

  - collection: events_page_content
    meta: { hidden: false, icon: event, color: "#7A4738", singleton: true, note: "Contenido singleton pagina Events" }
    schema: { name: events_page_content }


fields:
  # ──────────────────────────────────────────────────────────────
  # LANGUAGES
  # ──────────────────────────────────────────────────────────────
  - { collection: languages, field: code, type: string, schema: { is_primary_key: true, length: 255, has_auto_increment: false }, meta: { interface: input, required: true } }
  - { collection: languages, field: name, type: string, meta: { interface: input, required: true } }
  - { collection: languages, field: direction, type: string, schema: { default_value: ltr }, meta: { interface: select-dropdown, options: { choices: [{text: LTR, value: ltr},{text: RTL, value: rtl}] } } }

  # ──────────────────────────────────────────────────────────────
  # CATEGORIES (jerarquia multinivel C1-F5)
  # ──────────────────────────────────────────────────────────────
  - { collection: categories, field: id, type: integer, schema: { is_primary_key: true, has_auto_increment: true } }
  - { collection: categories, field: slug, type: string, schema: { is_unique: true }, meta: { interface: input, required: true } }
  - { collection: categories, field: icon, type: string, meta: { interface: input, note: "Nombre icono lucide-react o URL SVG" } }
  - { collection: categories, field: color_hex, type: string, meta: { interface: color } }
  - { collection: categories, field: parent_id, type: integer, meta: { interface: many-to-one, note: "Para jerarquia parent_id multinivel" } }
  - { collection: categories, field: sort, type: integer, meta: { interface: input-sort, hidden: true } }
  - { collection: categories, field: status, type: string, schema: { default_value: published }, meta: { interface: select-dropdown, options: { choices: [{text: Published, value: published},{text: Draft, value: draft},{text: Archived, value: archived}] } } }
  - { collection: categories, field: created_at, type: timestamp, schema: { default_value: "now()" }, meta: { special: [date-created], readonly: true, hidden: true } }
  - { collection: categories, field: updated_at, type: timestamp, meta: { special: [date-updated], readonly: true, hidden: true } }
  - { collection: categories, field: translations, type: alias, meta: { special: [translations], interface: translations, options: { languageField: languages_code, defaultLanguage: es-ES } } }

  - { collection: categories_translations, field: id, type: integer, schema: { is_primary_key: true, has_auto_increment: true } }
  - { collection: categories_translations, field: categories_id, type: integer, meta: { hidden: true } }
  - { collection: categories_translations, field: languages_code, type: string, meta: { hidden: true } }
  - { collection: categories_translations, field: name, type: string, meta: { interface: input, required: true } }
  - { collection: categories_translations, field: description, type: text, meta: { interface: input-multiline } }

  # ──────────────────────────────────────────────────────────────
  # TAGS
  # ──────────────────────────────────────────────────────────────
  - { collection: tags, field: id, type: integer, schema: { is_primary_key: true, has_auto_increment: true } }
  - { collection: tags, field: slug, type: string, schema: { is_unique: true }, meta: { interface: input, required: true } }
  - { collection: tags, field: translations, type: alias, meta: { special: [translations], interface: translations, options: { languageField: languages_code, defaultLanguage: es-ES } } }

  - { collection: tags_translations, field: id, type: integer, schema: { is_primary_key: true, has_auto_increment: true } }
  - { collection: tags_translations, field: tags_id, type: integer, meta: { hidden: true } }
  - { collection: tags_translations, field: languages_code, type: string, meta: { hidden: true } }
  - { collection: tags_translations, field: name, type: string, meta: { interface: input } }

  # ──────────────────────────────────────────────────────────────
  # AR_SCENES (estructura Asturias: glb_model, build_zip, scene_mode,
  # location, tracking_marker, audio_es/en/fr, popup_text, needle_config)
  # ──────────────────────────────────────────────────────────────
  - { collection: ar_scenes, field: id, type: integer, schema: { is_primary_key: true, has_auto_increment: true } }
  - { collection: ar_scenes, field: slug, type: string, schema: { is_unique: true }, meta: { interface: input, required: true } }

  - { collection: ar_scenes, field: ar_type, type: string, meta: { interface: select-dropdown, note: "Tipo de experiencia AR/3D", options: { choices: [{text: "WebXR Nativo", value: webxr},{text: "AR.js Geo", value: arjs_geo},{text: "AR.js Marker", value: arjs_marker},{text: "Viewer 3D", value: viewer_3d},{text: "Needle Engine", value: needle}] } } }
  - { collection: ar_scenes, field: scene_mode, type: string, meta: { interface: select-dropdown, options: { choices: [{text: "GLB simple (Three.js)", value: glb_simple},{text: "Needle Engine Build", value: needle_build},{text: "AR.js + GLB", value: arjs_glb}] } } }

  # --- GLB Model ---
  - { collection: ar_scenes, field: glb_model, type: uuid, meta: { interface: file, note: "Modelo 3D GLB/GLTF principal", options: { allowedTypes: ["model/gltf-binary","application/octet-stream"] } } }
  - { collection: ar_scenes, field: glb_scale, type: float, schema: { default_value: 1.0 }, meta: { interface: input, note: "Escala modelo (1.0 = normal)" } }
  - { collection: ar_scenes, field: glb_rotation_y, type: float, schema: { default_value: 0 }, meta: { interface: input, note: "Rotacion Y inicial en grados" } }
  - { collection: ar_scenes, field: glb_position_offset, type: json, meta: { interface: input-code, note: "JSON {x, y, z} offset posicion" } }

  # --- Needle Engine Build ---
  - { collection: ar_scenes, field: build_zip, type: uuid, meta: { interface: file, note: "ZIP build Needle Engine para escenas complejas" } }
  - { collection: ar_scenes, field: build_path, type: string, meta: { interface: input, note: "Ruta dentro del ZIP al index.html de Needle" } }
  - { collection: ar_scenes, field: needle_config, type: json, meta: { interface: input-code, note: "Config Needle Engine: {autoAR, environmentMap, lightIntensity, shadows, autoRotate, backgroundColor, animationClip}" } }

  # --- Geolocalizacion ---
  - { collection: ar_scenes, field: location_lat, type: float, meta: { interface: input } }
  - { collection: ar_scenes, field: location_lng, type: float, meta: { interface: input } }
  - { collection: ar_scenes, field: location_radius_meters, type: integer, schema: { default_value: 50 }, meta: { interface: input, note: "Radio activacion AR (max 100m, C3-F5)" } }

  # --- AR.js Marker ---
  - { collection: ar_scenes, field: tracking_marker, type: uuid, meta: { interface: file, note: "Imagen marcador AR.js" } }
  - { collection: ar_scenes, field: marker_size_cm, type: float, schema: { default_value: 10 }, meta: { interface: input } }

  # --- Media ---
  - { collection: ar_scenes, field: preview_image, type: uuid, meta: { interface: file-image } }
  - { collection: ar_scenes, field: preview_video, type: uuid, meta: { interface: file } }

  # --- Audio guides trilingue (igual que Asturias) ---
  - { collection: ar_scenes, field: audio_es, type: uuid, meta: { interface: file, note: "Audioguia espanol MP3/OGG" } }
  - { collection: ar_scenes, field: audio_en, type: uuid, meta: { interface: file } }
  - { collection: ar_scenes, field: audio_fr, type: uuid, meta: { interface: file } }

  # --- Popup text trilingue inline (igual que Asturias) ---
  - { collection: ar_scenes, field: popup_text_es, type: text, meta: { interface: input-multiline } }
  - { collection: ar_scenes, field: popup_text_en, type: text, meta: { interface: input-multiline } }
  - { collection: ar_scenes, field: popup_text_fr, type: text, meta: { interface: input-multiline } }

  # --- Meta ---
  - { collection: ar_scenes, field: duration_minutes, type: integer, meta: { interface: input } }
  - { collection: ar_scenes, field: difficulty, type: string, meta: { interface: select-dropdown, options: { choices: [{text: Facil, value: easy},{text: Moderado, value: moderate},{text: Dificil, value: hard}] } } }
  - { collection: ar_scenes, field: requires_outdoors, type: boolean, schema: { default_value: false }, meta: { interface: toggle } }
  - { collection: ar_scenes, field: featured, type: boolean, schema: { default_value: false }, meta: { interface: toggle } }
  - { collection: ar_scenes, field: seo_title, type: string, meta: { interface: input } }
  - { collection: ar_scenes, field: seo_description, type: text, meta: { interface: input-multiline } }
  - { collection: ar_scenes, field: view_count, type: integer, schema: { default_value: 0 }, meta: { readonly: true } }
  - { collection: ar_scenes, field: launch_count, type: integer, schema: { default_value: 0 }, meta: { readonly: true } }
  - { collection: ar_scenes, field: completion_count, type: integer, schema: { default_value: 0 }, meta: { readonly: true } }
  - { collection: ar_scenes, field: status, type: string, schema: { default_value: draft }, meta: { interface: select-dropdown, options: { choices: [{text: Draft, value: draft},{text: "En Revision", value: review},{text: Published, value: published},{text: Archived, value: archived}] } } }
  - { collection: ar_scenes, field: sort, type: integer, meta: { interface: input-sort, hidden: true } }
  - { collection: ar_scenes, field: created_at, type: timestamp, schema: { default_value: "now()" }, meta: { special: [date-created], readonly: true, hidden: true } }
  - { collection: ar_scenes, field: updated_at, type: timestamp, meta: { special: [date-updated], readonly: true, hidden: true } }
  - { collection: ar_scenes, field: translations, type: alias, meta: { special: [translations], interface: translations, options: { languageField: languages_code, defaultLanguage: es-ES } } }

  - { collection: ar_scenes_translations, field: id, type: integer, schema: { is_primary_key: true, has_auto_increment: true } }
  - { collection: ar_scenes_translations, field: ar_scenes_id, type: integer, meta: { hidden: true } }
  - { collection: ar_scenes_translations, field: languages_code, type: string, meta: { hidden: true } }
  - { collection: ar_scenes_translations, field: name, type: string, meta: { interface: input, required: true } }
  - { collection: ar_scenes_translations, field: description, type: text, meta: { interface: input-multiline } }
  - { collection: ar_scenes_translations, field: audio_guide_text, type: text, meta: { interface: input-multiline, note: "Transcripcion audioguia para WCAG 2.1 AA" } }

  # ──────────────────────────────────────────────────────────────
  # HOTSPOTS (C1-F2)
  # ──────────────────────────────────────────────────────────────
  - { collection: hotspots, field: id, type: integer, schema: { is_primary_key: true, has_auto_increment: true } }
  - { collection: hotspots, field: poi_id, type: integer, meta: { interface: many-to-one, hidden: true, note: "POI al que pertenece este hotspot" } }
  - { collection: hotspots, field: slug, type: string, schema: { is_unique: true }, meta: { interface: input, required: true } }
  - { collection: hotspots, field: media_type, type: string, meta: { interface: select-dropdown, options: { choices: [{text: Image, value: image},{text: Video, value: video},{text: Audio, value: audio},{text: "3D/AR", value: ar_3d},{text: "360 Tour", value: tour_360}] } } }
  - { collection: hotspots, field: media_file, type: uuid, meta: { interface: file, note: "media segun media_type" } }
  - { collection: hotspots, field: ar_scene_id, type: integer, meta: { interface: many-to-one, note: "Escena AR si media_type=ar_3d" } }
  - { collection: hotspots, field: location_lat, type: float }
  - { collection: hotspots, field: location_lng, type: float }
  - { collection: hotspots, field: sort, type: integer, meta: { interface: input-sort, hidden: true, note: "Orden dentro de ruta" } }
  - { collection: hotspots, field: status, type: string, schema: { default_value: draft }, meta: { interface: select-dropdown, options: { choices: [{text: Draft, value: draft},{text: "En Revision", value: review},{text: Published, value: published}] } } }
  - { collection: hotspots, field: created_at, type: timestamp, schema: { default_value: "now()" }, meta: { special: [date-created], readonly: true, hidden: true } }
  - { collection: hotspots, field: updated_at, type: timestamp, meta: { special: [date-updated], readonly: true, hidden: true } }
  - { collection: hotspots, field: translations, type: alias, meta: { special: [translations], interface: translations, options: { languageField: languages_code, defaultLanguage: es-ES } } }

  - { collection: hotspots_translations, field: id, type: integer, schema: { is_primary_key: true, has_auto_increment: true } }
  - { collection: hotspots_translations, field: hotspots_id, type: integer, meta: { hidden: true } }
  - { collection: hotspots_translations, field: languages_code, type: string, meta: { hidden: true } }
  - { collection: hotspots_translations, field: name, type: string, meta: { interface: input, required: true } }
  - { collection: hotspots_translations, field: description, type: text, meta: { interface: input-multiline } }

  # ──────────────────────────────────────────────────────────────
  # POIS (C1-F1, estructura Asturias)
  # ──────────────────────────────────────────────────────────────
  - { collection: pois, field: id, type: integer, schema: { is_primary_key: true, has_auto_increment: true } }
  - { collection: pois, field: slug, type: string, schema: { is_unique: true }, meta: { interface: input, required: true } }
  - { collection: pois, field: poi_code, type: string, meta: { interface: input, note: "Codigo QR unico para acceso directo" } }
  - { collection: pois, field: experience_type, type: string, meta: { interface: select-dropdown, options: { choices: [{text: Patrimonio, value: patrimonio},{text: Gastronomia, value: gastronomia},{text: Naturaleza, value: naturaleza},{text: Cultura, value: cultura},{text: Ocio, value: ocio}] } } }
  - { collection: pois, field: lat, type: float, meta: { interface: input, required: true } }
  - { collection: pois, field: lng, type: float, meta: { interface: input, required: true } }
  - { collection: pois, field: address, type: string, meta: { interface: input } }
  - { collection: pois, field: opening_hours, type: json, meta: { interface: input-code, note: "JSON horarios {mon:'10-20', tue:'10-20',...}" } }
  - { collection: pois, field: price_info, type: json, meta: { interface: input-code, note: "JSON precios {adult:5, child:0,...}" } }
  - { collection: pois, field: accessibility, type: json, meta: { interface: input-code, note: "JSON accesibilidad {wheelchair:true,...}" } }
  - { collection: pois, field: cover_image, type: uuid, meta: { interface: file-image } }
  - { collection: pois, field: gallery, type: alias, meta: { special: [files], interface: files } }
  - { collection: pois, field: audio_es, type: uuid, meta: { interface: file, note: "Audioguia espanol" } }
  - { collection: pois, field: audio_en, type: uuid, meta: { interface: file } }
  - { collection: pois, field: audio_fr, type: uuid, meta: { interface: file } }
  - { collection: pois, field: audio_duration_seconds, type: integer, meta: { interface: input } }
  - { collection: pois, field: ar_scene_id, type: integer, meta: { interface: many-to-one, note: "Escena AR/3D asociada al POI" } }
  - { collection: pois, field: route_id, type: integer, meta: { interface: many-to-one } }
  - { collection: pois, field: phone, type: string, meta: { interface: input } }
  - { collection: pois, field: email, type: string, meta: { interface: input } }
  - { collection: pois, field: website, type: string, meta: { interface: input } }
  - { collection: pois, field: share_url, type: string, meta: { interface: input, note: "URL deep-link /poi/{slug}" } }
  - { collection: pois, field: featured, type: boolean, schema: { default_value: false }, meta: { interface: toggle } }
  - { collection: pois, field: seo_title, type: string, meta: { interface: input } }
  - { collection: pois, field: seo_description, type: text, meta: { interface: input-multiline } }
  - { collection: pois, field: view_count, type: integer, schema: { default_value: 0 }, meta: { readonly: true } }
  - { collection: pois, field: status, type: string, schema: { default_value: draft }, meta: { interface: select-dropdown, options: { choices: [{text: Draft, value: draft},{text: "En Revision", value: review},{text: Published, value: published},{text: Archived, value: archived}] } } }
  - { collection: pois, field: sort, type: integer, meta: { interface: input-sort, hidden: true } }
  - { collection: pois, field: created_at, type: timestamp, schema: { default_value: "now()" }, meta: { special: [date-created], readonly: true, hidden: true } }
  - { collection: pois, field: updated_at, type: timestamp, meta: { special: [date-updated], readonly: true, hidden: true } }
  - { collection: pois, field: translations, type: alias, meta: { special: [translations], interface: translations, options: { languageField: languages_code, defaultLanguage: es-ES } } }
  - { collection: pois, field: categories, type: alias, meta: { special: [m2m], interface: list-m2m } }
  - { collection: pois, field: tags, type: alias, meta: { special: [m2m], interface: list-m2m } }
  - { collection: pois, field: hotspots, type: alias, meta: { special: [o2m], interface: list-o2m, note: "Hotspots vinculados 1:N" } }

  - { collection: pois_translations, field: id, type: integer, schema: { is_primary_key: true, has_auto_increment: true } }
  - { collection: pois_translations, field: pois_id, type: integer, meta: { hidden: true } }
  - { collection: pois_translations, field: languages_code, type: string, meta: { hidden: true } }
  - { collection: pois_translations, field: name, type: string, meta: { interface: input, required: true } }
  - { collection: pois_translations, field: description, type: text, meta: { interface: input-multiline } }
  - { collection: pois_translations, field: short_description, type: string, meta: { interface: input } }
  - { collection: pois_translations, field: rich_text, type: text, meta: { interface: input-rich-text-html } }
  - { collection: pois_translations, field: slug_localized, type: string, meta: { interface: input, note: "Slug localizado para deep-linking ES/EN/FR" } }
  - { collection: pois_translations, field: seo_title, type: string, meta: { interface: input } }
  - { collection: pois_translations, field: seo_description, type: text, meta: { interface: input-multiline } }

  - { collection: pois_categories, field: id, type: integer, schema: { is_primary_key: true, has_auto_increment: true } }
  - { collection: pois_categories, field: pois_id, type: integer }
  - { collection: pois_categories, field: categories_id, type: integer }

  - { collection: pois_tags, field: id, type: integer, schema: { is_primary_key: true, has_auto_increment: true } }
  - { collection: pois_tags, field: pois_id, type: integer }
  - { collection: pois_tags, field: tags_id, type: integer }

  # ──────────────────────────────────────────────────────────────
  # ROUTES (C1-F3, estructura Asturias)
  # ──────────────────────────────────────────────────────────────
  - { collection: routes, field: id, type: integer, schema: { is_primary_key: true, has_auto_increment: true } }
  - { collection: routes, field: slug, type: string, schema: { is_unique: true }, meta: { interface: input, required: true } }
  - { collection: routes, field: route_code, type: string, meta: { interface: input } }
  - { collection: routes, field: difficulty, type: string, meta: { interface: select-dropdown, options: { choices: [{text: Facil, value: easy},{text: Moderada, value: moderate},{text: Dificil, value: hard}] } } }
  - { collection: routes, field: distance_km, type: float, meta: { interface: input } }
  - { collection: routes, field: duration_minutes, type: integer, meta: { interface: input } }
  - { collection: routes, field: route_type, type: string, meta: { interface: select-dropdown, options: { choices: [{text: Circular, value: circular},{text: "Ida y vuelta", value: out_and_back},{text: Lineal, value: linear}] } } }
  - { collection: routes, field: track_geojson, type: json, meta: { interface: input-code, note: "GeoJSON LineString track GPS" } }
  - { collection: routes, field: gpx_file, type: uuid, meta: { interface: file } }
  - { collection: routes, field: cover_image, type: uuid, meta: { interface: file-image } }
  - { collection: routes, field: gallery, type: alias, meta: { special: [files], interface: files } }
  - { collection: routes, field: featured, type: boolean, schema: { default_value: false }, meta: { interface: toggle } }
  - { collection: routes, field: seo_title, type: string, meta: { interface: input } }
  - { collection: routes, field: seo_description, type: text, meta: { interface: input-multiline } }
  - { collection: routes, field: view_count, type: integer, schema: { default_value: 0 }, meta: { readonly: true } }
  - { collection: routes, field: status, type: string, schema: { default_value: draft }, meta: { interface: select-dropdown, options: { choices: [{text: Draft, value: draft},{text: Published, value: published}] } } }
  - { collection: routes, field: sort, type: integer, meta: { interface: input-sort, hidden: true } }
  - { collection: routes, field: created_at, type: timestamp, schema: { default_value: "now()" }, meta: { special: [date-created], readonly: true, hidden: true } }
  - { collection: routes, field: updated_at, type: timestamp, meta: { special: [date-updated], readonly: true, hidden: true } }
  - { collection: routes, field: translations, type: alias, meta: { special: [translations], interface: translations, options: { languageField: languages_code, defaultLanguage: es-ES } } }
  - { collection: routes, field: categories, type: alias, meta: { special: [m2m], interface: list-m2m } }
  - { collection: routes, field: points, type: alias, meta: { special: [m2m], interface: list-m2m, note: "POIs en la ruta con orden (routes_pois.order)" } }

  - { collection: routes_translations, field: id, type: integer, schema: { is_primary_key: true, has_auto_increment: true } }
  - { collection: routes_translations, field: routes_id, type: integer, meta: { hidden: true } }
  - { collection: routes_translations, field: languages_code, type: string, meta: { hidden: true } }
  - { collection: routes_translations, field: name, type: string, meta: { interface: input, required: true } }
  - { collection: routes_translations, field: description, type: text, meta: { interface: input-multiline } }
  - { collection: routes_translations, field: narrative, type: text, meta: { interface: input-rich-text-html, note: "Narrativa tematica de la ruta" } }

  - { collection: routes_pois, field: id, type: integer, schema: { is_primary_key: true, has_auto_increment: true } }
  - { collection: routes_pois, field: routes_id, type: integer }
  - { collection: routes_pois, field: pois_id, type: integer }
  - { collection: routes_pois, field: order, type: integer, meta: { interface: input-sort, note: "Orden de parada en la ruta" } }

  # ──────────────────────────────────────────────────────────────
  # KIOSK_CONTENTS (PR_260047 F4)
  # ──────────────────────────────────────────────────────────────
  - { collection: kiosk_contents, field: id, type: integer, schema: { is_primary_key: true, has_auto_increment: true } }
  - { collection: kiosk_contents, field: title_es, type: string, meta: { interface: input, required: true } }
  - { collection: kiosk_contents, field: title_en, type: string, meta: { interface: input } }
  - { collection: kiosk_contents, field: description_es, type: text, meta: { interface: input-multiline } }
  - { collection: kiosk_contents, field: description_en, type: text, meta: { interface: input-multiline } }
  - { collection: kiosk_contents, field: content_type, type: string, meta: { interface: select-dropdown, options: { choices: [{text: Video, value: video},{text: Image, value: image},{text: Gallery, value: gallery}] } } }
  - { collection: kiosk_contents, field: media_file, type: uuid, meta: { interface: file, note: "Video H.264/AAC/MP4 max500MB, imagen JPG/PNG max50MB" } }
  - { collection: kiosk_contents, field: thumbnail, type: uuid, meta: { interface: file-image } }
  - { collection: kiosk_contents, field: gallery_files, type: alias, meta: { special: [files], interface: files } }
  - { collection: kiosk_contents, field: featured, type: boolean, schema: { default_value: false }, meta: { interface: toggle, note: "Aparece en attract loop" } }
  - { collection: kiosk_contents, field: attract_order, type: integer, meta: { interface: input, note: "Orden en carrusel attract loop (15s por slide)" } }
  - { collection: kiosk_contents, field: sort, type: integer, meta: { interface: input-sort, hidden: true } }
  - { collection: kiosk_contents, field: status, type: string, schema: { default_value: draft }, meta: { interface: select-dropdown, options: { choices: [{text: Draft, value: draft},{text: Published, value: published},{text: Archived, value: archived}] } } }
  - { collection: kiosk_contents, field: created_at, type: timestamp, schema: { default_value: "now()" }, meta: { special: [date-created], readonly: true, hidden: true } }
  - { collection: kiosk_contents, field: updated_at, type: timestamp, meta: { special: [date-updated], readonly: true, hidden: true } }
  - { collection: kiosk_contents, field: categories, type: alias, meta: { special: [m2m], interface: list-m2m } }
  - { collection: kiosk_contents, field: tags, type: alias, meta: { special: [m2m], interface: list-m2m } }

  - { collection: kiosk_categories, field: id, type: integer, schema: { is_primary_key: true, has_auto_increment: true } }
  - { collection: kiosk_categories, field: slug, type: string, schema: { is_unique: true }, meta: { interface: input } }
  - { collection: kiosk_categories, field: name_es, type: string, meta: { interface: input, required: true } }
  - { collection: kiosk_categories, field: name_en, type: string, meta: { interface: input } }
  - { collection: kiosk_categories, field: icon, type: string, meta: { interface: input } }
  - { collection: kiosk_categories, field: color_hex, type: string, meta: { interface: color } }
  - { collection: kiosk_categories, field: sort, type: integer, meta: { interface: input-sort } }
  - { collection: kiosk_categories, field: status, type: string, schema: { default_value: published }, meta: { interface: select-dropdown, options: { choices: [{text: Published, value: published},{text: Draft, value: draft}] } } }

  - { collection: kiosk_contents_categories, field: id, type: integer, schema: { is_primary_key: true, has_auto_increment: true } }
  - { collection: kiosk_contents_categories, field: kiosk_contents_id, type: integer }
  - { collection: kiosk_contents_categories, field: kiosk_categories_id, type: integer }

  - { collection: kiosk_contents_tags, field: id, type: integer, schema: { is_primary_key: true, has_auto_increment: true } }
  - { collection: kiosk_contents_tags, field: kiosk_contents_id, type: integer }
  - { collection: kiosk_contents_tags, field: tags_id, type: integer }

  # ──────────────────────────────────────────────────────────────
  # CONTACT_SUBMISSIONS (formulario + email via Flows)
  # ──────────────────────────────────────────────────────────────
  - { collection: contact_submissions, field: id, type: integer, schema: { is_primary_key: true, has_auto_increment: true } }
  - { collection: contact_submissions, field: name, type: string, meta: { interface: input, required: true } }
  - { collection: contact_submissions, field: email, type: string, meta: { interface: input, required: true } }
  - { collection: contact_submissions, field: phone, type: string, meta: { interface: input } }
  - { collection: contact_submissions, field: submission_type, type: string, meta: { interface: select-dropdown, options: { choices: [{text: Queja, value: queja},{text: Sugerencia, value: sugerencia},{text: Incidencia, value: incidencia},{text: Consulta, value: consulta}] } } }
  - { collection: contact_submissions, field: preferred_contact, type: string, meta: { interface: select-dropdown, options: { choices: [{text: Email, value: email},{text: Telefono, value: phone},{text: Cualquiera, value: either}] } } }
  - { collection: contact_submissions, field: subject, type: string, meta: { interface: input } }
  - { collection: contact_submissions, field: message, type: text, meta: { interface: input-multiline, required: true } }
  - { collection: contact_submissions, field: language, type: string, schema: { default_value: es-ES }, meta: { interface: select-dropdown, options: { choices: [{text: ES, value: es-ES},{text: EN, value: en-US},{text: FR, value: fr-FR},{text: CA, value: ca-ES},{text: RU, value: ru-RU}] } } }
  - { collection: contact_submissions, field: source, type: string, meta: { interface: select-dropdown, options: { choices: [{text: PWA, value: pwa},{text: Kiosco, value: kiosk}] } } }
  - { collection: contact_submissions, field: poi_slug, type: string, meta: { interface: input, note: "Slug del POI donde se abrio el formulario" } }
  - { collection: contact_submissions, field: privacy_accepted, type: boolean, schema: { default_value: false }, meta: { interface: boolean, note: "Consentimiento expreso de privacidad" } }
  - { collection: contact_submissions, field: status, type: string, schema: { default_value: pending }, meta: { interface: select-dropdown, options: { choices: [{text: Pending, value: pending},{text: Replied, value: replied},{text: Spam, value: spam}] } } }
  - { collection: contact_submissions, field: ip_hash, type: string, meta: { interface: input, note: "SHA-256 IP anonimizada RGPD", readonly: true } }
  - { collection: contact_submissions, field: created_at, type: timestamp, schema: { default_value: "now()" }, meta: { special: [date-created], readonly: true } }

  # ──────────────────────────────────────────────────────────────
  # ANALYTICS_EVENTS (estructura Asturias adaptada)
  # Privacy-first: sin PII, IPs anonimizadas, session_id TTL 24h
  # ──────────────────────────────────────────────────────────────
  - { collection: analytics_events, field: id, type: integer, schema: { is_primary_key: true, has_auto_increment: true } }
  - { collection: analytics_events, field: event_type, type: string, meta: { interface: select-dropdown, options: { choices: [
      {text: page_view, value: page_view},
      {text: view_poi, value: view_poi},
      {text: view_hotspot, value: view_hotspot},
      {text: language_switch, value: language_switch},
      {text: ar_activated, value: ar_activated},
      {text: ar_fallback, value: ar_fallback},
      {text: ar_completed, value: ar_completed},
      {text: glb_loaded, value: glb_loaded},
      {text: needle_loaded, value: needle_loaded},
      {text: kiosk_attract_tap, value: kiosk_attract_tap},
      {text: kiosk_content_view, value: kiosk_content_view},
      {text: kiosk_video_play, value: kiosk_video_play},
      {text: kiosk_video_complete, value: kiosk_video_complete},
      {text: kiosk_inactivity_reset, value: kiosk_inactivity_reset},
      {text: contact_form_open, value: contact_form_open},
      {text: contact_form_submit, value: contact_form_submit},
      {text: search_performed, value: search_performed},
      {text: route_view, value: route_view},
      {text: audio_play, value: audio_play}
    ] } } }
  - { collection: analytics_events, field: resource_type, type: string, meta: { interface: input, note: "poi | hotspot | ar_scene | route | kiosk_content" } }
  - { collection: analytics_events, field: resource_id, type: string, meta: { interface: input } }
  - { collection: analytics_events, field: session_id, type: string, meta: { interface: input, note: "UUID anonimo TTL 24h sin datos personales (RGPD C3-F15)" } }
  - { collection: analytics_events, field: device_type, type: string, meta: { interface: select-dropdown, options: { choices: [{text: Mobile, value: mobile},{text: Tablet, value: tablet},{text: Desktop, value: desktop},{text: Kiosk, value: kiosk}] } } }
  - { collection: analytics_events, field: language, type: string, meta: { interface: select-dropdown, options: { choices: [{text: ES, value: es},{text: EN, value: en},{text: FR, value: fr}] } } }
  - { collection: analytics_events, field: duration_seconds, type: integer, meta: { interface: input } }
  - { collection: analytics_events, field: completion_percentage, type: float, meta: { interface: input, note: "0-100" } }
  - { collection: analytics_events, field: source, type: string, meta: { interface: select-dropdown, options: { choices: [{text: PWA, value: pwa},{text: Kiosco, value: kiosk}] } } }
  - { collection: analytics_events, field: page_url, type: string, meta: { interface: input } }
  - { collection: analytics_events, field: screen_resolution, type: string, meta: { interface: input } }
  - { collection: analytics_events, field: is_returning, type: boolean, schema: { default_value: false }, meta: { interface: toggle } }
  - { collection: analytics_events, field: extra_data, type: json, meta: { interface: input-code, note: "Datos adicionales sin PII (ar_type, glb_file_id, ...)" } }
  - { collection: analytics_events, field: created_at, type: timestamp, schema: { default_value: "now()" }, meta: { special: [date-created], readonly: true } }

  # ──────────────────────────────────────────────────────────────
  # MEDIA_ASSETS (C1-F4 biblioteca multimedia)
  # ──────────────────────────────────────────────────────────────
  - { collection: media_assets, field: id, type: uuid, schema: { is_primary_key: true, has_auto_increment: false } }
  - { collection: media_assets, field: directus_file_id, type: uuid, meta: { interface: file, required: true } }
  - { collection: media_assets, field: title, type: string, meta: { interface: input, required: true } }
  - { collection: media_assets, field: description, type: text, meta: { interface: input-multiline } }
  - { collection: media_assets, field: alt_text, type: string, meta: { interface: input, note: "Alt text WCAG 2.1 AA" } }
  - { collection: media_assets, field: credits, type: string, meta: { interface: input, note: "Autor/fotografo/fuente" } }
  - { collection: media_assets, field: license, type: string, meta: { interface: select-dropdown, options: { choices: [{text: "CC0 Dominio publico", value: cc0},{text: "CC BY", value: cc_by},{text: "Zaragoza Turismo", value: owned},{text: "Uso restringido", value: restricted}] } } }
  - { collection: media_assets, field: sha256_hash, type: string, meta: { interface: input, readonly: true, note: "Hash integridad SHA-256 (C1-F4)" } }
  - { collection: media_assets, field: tags, type: json, meta: { interface: tags } }
  - { collection: media_assets, field: created_at, type: timestamp, schema: { default_value: "now()" }, meta: { special: [date-created], readonly: true } }
  - { collection: media_assets, field: updated_at, type: timestamp, meta: { special: [date-updated], readonly: true } }

  # ──────────────────────────────────────────────────────────────
  # UI_TRANSLATIONS (i18n keys para PWA y Kiosco)
  # ──────────────────────────────────────────────────────────────
  - { collection: ui_translations, field: id, type: integer, schema: { is_primary_key: true, has_auto_increment: true } }
  - { collection: ui_translations, field: key, type: string, schema: { is_unique: true }, meta: { interface: input, required: true, note: "Ej: nav.explore, poi.arButton" } }
  - { collection: ui_translations, field: translations, type: json, meta: { interface: input-code, note: "JSON localizado: {\"es-ES\": \"...\", \"en-US\": \"...\"}" } }
  - { collection: ui_translations, field: es, type: text, meta: { interface: input-multiline } }
  - { collection: ui_translations, field: en, type: text, meta: { interface: input-multiline } }
  - { collection: ui_translations, field: fr, type: text, meta: { interface: input-multiline } }
  - { collection: ui_translations, field: ca, type: text, meta: { interface: input-multiline } }
  - { collection: ui_translations, field: scope, type: string, meta: { interface: select-dropdown, options: { choices: [{text: PWA, value: public},{text: Admin, value: admin},{text: Kiosco, value: kiosk},{text: Ambos, value: both}] } } }
  - { collection: ui_translations, field: updated_at, type: timestamp, meta: { special: [date-updated], readonly: true } }

  # ──────────────────────────────────────────────────────────────
  # HOMEPAGE_CONTENT (singleton contenido pagina de inicio)
  # ──────────────────────────────────────────────────────────────
  - { collection: homepage_content, field: id, type: integer, schema: { is_primary_key: true, has_auto_increment: true } }
  - { collection: homepage_content, field: hero_cta_label, type: string, meta: { interface: input, note: "Texto boton CTA hero" } }
- { collection: homepage_content, field: intro_text, type: json, meta: { interface: input-code, note: "JSON localizado {\"es-ES\": \"...\"}" } }
- { collection: homepage_content, field: featured_title, type: json, meta: { interface: input-code } }
- { collection: homepage_content, field: featured_heading, type: json, meta: { interface: input-code } }
- { collection: homepage_content, field: featured_poi_slugs, type: json, meta: { interface: input-code, note: "Array de slugs para las 4 tarjetas No te pierdas" } }
- { collection: homepage_content, field: explore_title, type: json, meta: { interface: input-code } }
  - { collection: homepage_content, field: coming_soon_title, type: json, meta: { interface: input-code } }
  - { collection: homepage_content, field: routes_title, type: json, meta: { interface: input-code } }
  - { collection: homepage_content, field: routes_subtitle, type: json, meta: { interface: input-code } }

  # ──────────────────────────────────────────────────────────────
  # EVENTS_PAGE_CONTENT (singleton contenido pagina events)
  # ──────────────────────────────────────────────────────────────
  - { collection: events_page_content, field: id, type: integer, schema: { is_primary_key: true, has_auto_increment: true } }
  - { collection: events_page_content, field: enabled, type: boolean, schema: { default_value: true }, meta: { interface: boolean } }
  - { collection: events_page_content, field: show_event_pois_in_poi_list, type: boolean, schema: { default_value: false }, meta: { interface: boolean } }
  - { collection: events_page_content, field: min_events_for_dedicated_page, type: integer, schema: { default_value: 2 }, meta: { interface: input } }
  - { collection: events_page_content, field: eyebrow, type: json, meta: { interface: input-code } }
  - { collection: events_page_content, field: title, type: json, meta: { interface: input-code } }
  - { collection: events_page_content, field: intro, type: json, meta: { interface: input-code } }
  - { collection: events_page_content, field: featured_event_slugs, type: json, meta: { interface: input-code } }
  - { collection: events_page_content, field: upcoming_event_slugs, type: json, meta: { interface: input-code } }
  - { collection: events_page_content, field: active_event_slugs, type: json, meta: { interface: input-code } }
  - { collection: events_page_content, field: archive_event_slugs, type: json, meta: { interface: input-code } }

  # ──────────────────────────────────────────────────────────────
  # HOMEPAGE_SLIDES (slides del hero slider)
  # ──────────────────────────────────────────────────────────────
  - { collection: homepage_slides, field: id, type: integer, schema: { is_primary_key: true, has_auto_increment: true } }
  - { collection: homepage_slides, field: sort, type: integer, meta: { interface: input-sort, hidden: true } }
  - { collection: homepage_slides, field: status, type: string, schema: { default_value: published }, meta: { interface: select-dropdown, options: { choices: [{text: Published, value: published},{text: Draft, value: draft}] } } }
  - { collection: homepage_slides, field: image, type: uuid, meta: { interface: file-image, note: "Imagen del slide (formato apaisado 1600x900 recomendado)" } }
  - { collection: homepage_slides, field: title, type: json, meta: { interface: input-code, note: "JSON localizado {\"es-ES\": \"...\"}" } }
  - { collection: homepage_slides, field: subtitle, type: json, meta: { interface: input-code } }
  - { collection: homepage_slides, field: link_type, type: string, schema: { is_nullable: true, default_value: "none" }, meta: { interface: select-dropdown, options: { choices: [{text: "Sin enlace", value: none},{text: POI, value: poi},{text: Ruta, value: route},{text: "URL Externa", value: url}] }, note: "Destino al pulsar el slide" } }
  - { collection: homepage_slides, field: link_poi, type: string, schema: { is_nullable: true }, meta: { interface: input, note: "Slug del POI (ej: basilica-del-pilar). Solo cuando link_type=poi" } }
  - { collection: homepage_slides, field: link_route, type: string, schema: { is_nullable: true }, meta: { interface: input, note: "Slug de la ruta. Solo cuando link_type=route" } }
  - { collection: homepage_slides, field: link_url, type: string, schema: { is_nullable: true }, meta: { interface: input, note: "URL externa completa (https://...). Solo cuando link_type=url" } }


relations:
  # categories self-referencing
  - { collection: categories, field: parent_id, related_collection: categories }

  # categories translations
  - { collection: categories_translations, field: categories_id, related_collection: categories }
  - { collection: categories_translations, field: languages_code, related_collection: languages }

  # tags translations
  - { collection: tags_translations, field: tags_id, related_collection: tags }
  - { collection: tags_translations, field: languages_code, related_collection: languages }

  # ar_scenes translations
  - { collection: ar_scenes_translations, field: ar_scenes_id, related_collection: ar_scenes }
  - { collection: ar_scenes_translations, field: languages_code, related_collection: languages }

  # hotspots → pois
  - { collection: hotspots, field: poi_id, related_collection: pois, meta: { many_field: poi_id, one_field: hotspots, one_collection: pois } }
  # hotspots → ar_scenes
  - { collection: hotspots, field: ar_scene_id, related_collection: ar_scenes }
  # hotspots translations
  - { collection: hotspots_translations, field: hotspots_id, related_collection: hotspots }
  - { collection: hotspots_translations, field: languages_code, related_collection: languages }

  # pois → ar_scenes
  - { collection: pois, field: ar_scene_id, related_collection: ar_scenes }
  # pois → routes
  - { collection: pois, field: route_id, related_collection: routes }
  # pois translations
  - { collection: pois_translations, field: pois_id, related_collection: pois }
  - { collection: pois_translations, field: languages_code, related_collection: languages }
  # pois N:M categories
  - { collection: pois_categories, field: pois_id, related_collection: pois, meta: { many_field: pois_id, one_field: categories, one_collection: pois } }
  - { collection: pois_categories, field: categories_id, related_collection: categories }
  # pois N:M tags
  - { collection: pois_tags, field: pois_id, related_collection: pois }
  - { collection: pois_tags, field: tags_id, related_collection: tags }

  # routes translations
  - { collection: routes_translations, field: routes_id, related_collection: routes }
  - { collection: routes_translations, field: languages_code, related_collection: languages }
  # routes N:M pois (con orden)
  - { collection: routes_pois, field: routes_id, related_collection: routes, meta: { many_field: routes_id, one_field: points, one_collection: routes } }
  - { collection: routes_pois, field: pois_id, related_collection: pois }

  # kiosk_contents N:M kiosk_categories
  - { collection: kiosk_contents_categories, field: kiosk_contents_id, related_collection: kiosk_contents }
  - { collection: kiosk_contents_categories, field: kiosk_categories_id, related_collection: kiosk_categories }
  # kiosk_contents N:M tags
  - { collection: kiosk_contents_tags, field: kiosk_contents_id, related_collection: kiosk_contents }
  - { collection: kiosk_contents_tags, field: tags_id, related_collection: tags }
