Género
+ {/if} + +o {alias.map((a) => `«${a.nombre}»`).join(', ')}
+ {/if} + + {#if capitulo.resumen} +{capitulo.resumen}
+ {/if} + + {#if ficha?.origenLugar} ++ {ficha.origenLugar}{#if anoAparte}, {anoAparte}{/if} +
+ {/if} + + + {#if paises.length > 0} +{etiqueta}
+{valor}
+{ILUSTRA[ejemplo.ilustra] ?? ejemplo.ilustra}
+{linea.texto}
+ {#if linea.silabas.length > 0} + + {/if} + {linea.medida} + {#if linea.rima && linea.rima !== '-'} + {linea.rima} + {/if} ++ Los ejemplos están escritos para el taller, no son de ninguna canción. Sirven para enseñar la + cuenta y la rima del género; para oírlo de verdad, arriba están las obras de referencia. +
+{obra.titulo}
+ {#if obra.autores.length > 0} +{obra.autores.join(' · ')}
+ {/if} + {#if obra.cita} +{obra.cita}
+ {/if} + {#if obra.nota} +{obra.nota}
+ {/if} + {#if obra.enlaces.length > 0} ++ Los fragmentos se reproducen al amparo del derecho de cita, para ilustrar el estilo. Las + letras completas son de sus autores y no se alojan aquí. +
+De dónde viene
+Qué viene de él
++ Esta ficha la reunió un modelo de lenguaje y está pendiente de revisión: los + datos —instrumentación, letristas, obras de referencia, linaje— y también los ejemplos de versos + y su escansión. Las fechas y las atribuciones no se han comprobado una a una. +
+{/if} + +{#if capitulo.anterior || capitulo.siguiente} + +{/if} + + diff --git a/src/lib/components/GlobosDeGlosario.svelte b/src/lib/components/GlobosDeGlosario.svelte index 7ac368f..34560a3 100644 --- a/src/lib/components/GlobosDeGlosario.svelte +++ b/src/lib/components/GlobosDeGlosario.svelte @@ -1,3 +1,20 @@ + + + + + + diff --git a/src/lib/components/IndiceTaller.svelte b/src/lib/components/IndiceTaller.svelte index 077266b..eaf98f5 100644 --- a/src/lib/components/IndiceTaller.svelte +++ b/src/lib/components/IndiceTaller.svelte @@ -2,9 +2,8 @@ /** * Índice del taller, para la barra lateral de un capítulo. * - * Enseña la estructura entera —los principios numerados y las fichas de - * estilo— con el capítulo abierto marcado. En un curso, saber dónde estás y - * qué queda es parte de poder seguirlo. + * Enseña los principios numerados con el capítulo abierto marcado. En un + * curso, saber dónde estás y qué queda es parte de poder seguirlo. * * En pantallas estrechas no se esconde: baja debajo del texto, antes de la * navegación de anterior y siguiente. Ocultar la estructura en móvil sería @@ -25,12 +24,11 @@ interface Props { principios: Entrada[]; - fichas: Entrada[]; /** Slug del capítulo abierto, si lo hay. */ actual?: string; } - let { principios, fichas, actual }: Props = $props(); + let { principios, actual }: Props = $props(); diff --git a/src/lib/components/MapaDeGeneros.svelte b/src/lib/components/MapaDeGeneros.svelte new file mode 100644 index 0000000..e2c5e84 --- /dev/null +++ b/src/lib/components/MapaDeGeneros.svelte @@ -0,0 +1,181 @@ + + ++ {#if buscando} + {encontradas.length} + {encontradas.length === 1 ? 'entrada' : 'entradas'} + {:else} + {data.entradas.length} + {data.entradas.length === 1 ? 'entrada' : 'entradas'} en total + {/if} +
+ + {#if encontradas.length === 0} ++ {#if data.entradas.length === 0} + Todavía no hay ninguna entrada. + {:else} + Nada con eso. Prueba con otra palabra o quita el filtro de etiqueta. + {/if} +
+ {:else if vista === 'tabla'} +| Fecha | +Título | +De qué va | +Etiquetas | +
|---|---|---|---|
| + + | ++ {entrada.titulo} + | +{entrada.resumen} | +{entrada.etiquetas.join(', ')} | +
- -
-{entrada.resumen}
- {/if} - {#if entrada.etiquetas.length > 0} -+ +
+{entrada.resumen}
+ {/if} + {#if entrada.etiquetas.length > 0} +Todavía no hay ninguna entrada.
{/if} @@ -86,24 +243,164 @@ font-size: var(--fs-sm); } - .chips { - margin-top: var(--sp-3); + /* --- La barra de consulta ------------------------------------------------ */ + + .barra { + display: flex; + align-items: stretch; + border: 1px solid var(--c-border); + border-radius: var(--radius-boton); + background: var(--c-bg-sunken); + overflow: hidden; + } + + .barra:focus-within { + border-color: var(--c-accent); + box-shadow: 0 0 0 2px color-mix(in oklab, var(--c-accent) 30%, transparent); + } + + input[type='search'] { + flex: 1 1 12rem; + min-width: 0; + padding: var(--boton-relleno); + border: 0; + background: transparent; + color: inherit; + font: inherit; + font-size: var(--boton-texto); + } + + input[type='search']:focus-visible { + outline: none; + } + + .vistas { + display: flex; + border-left: 1px solid var(--c-border); } + .vista { + padding: var(--boton-relleno); + border: 0; + background-color: transparent; + font: inherit; + font-size: var(--boton-texto); + white-space: nowrap; + cursor: pointer; + transition: + background-color 0.2s var(--suave), + color 0.2s var(--suave); + } + + /* Ver el comentario de la misma barra en la página de música. */ + .vista:not(.oro) { + color: var(--c-text-muted); + } + + .vista + .vista { + border-left: 1px solid var(--c-border); + } + + .vista:hover:not(.oro) { + background-color: var(--c-bg-raised); + color: var(--c-text); + } + + .etiquetas { + display: flex; + flex-wrap: wrap; + gap: var(--sp-2); + padding-top: var(--sp-3); + } + + .filtro { + display: inline-flex; + align-items: baseline; + gap: var(--sp-2); + padding: 0.25rem 0.7rem; + border: 1px solid var(--c-border); + border-radius: var(--radius-boton); + background: transparent; + color: var(--c-text-muted); + font: inherit; + font-size: var(--fs-xs); + cursor: pointer; + } + + .filtro:hover { + color: var(--c-text); + border-color: var(--c-text-muted); + } + + .filtro[aria-pressed='true'] { + color: var(--c-accent); + border-color: color-mix(in oklab, var(--c-accent) 45%, transparent); + background: color-mix(in oklab, var(--c-accent) 10%, transparent); + } + + .cuantas { + font-family: var(--font-mono); + opacity: 0.7; + } + + .resultado { + padding-block: var(--sp-3); + font-size: var(--fs-sm); + } + + .vacio { + padding-block: var(--sp-6); + } + + /* --- Tarjetas ------------------------------------------------------------ */ + + /* + * `auto-fit` y no `auto-fill`: con dos entradas, `auto-fill` crea las cuatro + * columnas que caben y deja dos vacías a la derecha. `auto-fit` colapsa las + * que sobran y lo que hay se reparte el ancho entero. + */ .entradas { + display: grid; + grid-template-columns: repeat(auto-fit, minmax(min(20rem, 100%), 1fr)); + gap: var(--sp-4); list-style: none; margin: 0; padding: 0 0 var(--sp-7); - border-top: 1px solid var(--c-border); } - .entradas > li { - padding-block: var(--sp-5); - border-bottom: 1px solid var(--c-border); + .entradas article { + display: grid; + grid-template-rows: auto 1fr; + height: 100%; + } + + /* + * La portada, con proporción fija. Sin ella, dos imágenes de distinto alto + * descuadran la fila entera y las tarjetas dejan de alinearse. + */ + .portada { + display: block; + aspect-ratio: 16 / 9; + overflow: hidden; + background: var(--c-bg-sunken); + } + + .portada img { + width: 100%; + height: 100%; + object-fit: cover; + display: block; + } + + .cuerpo { + display: flex; + flex-direction: column; + gap: var(--sp-2); + padding: var(--sp-4); } .fecha { - margin: 0 0 var(--sp-2); + margin: 0; font-family: var(--font-mono); font-size: var(--fs-xs); text-transform: uppercase; @@ -112,8 +409,7 @@ h2 { margin: 0; - font-size: var(--fs-2xl); - max-width: 24ch; + font-size: var(--fs-xl); } h2 a { @@ -127,11 +423,89 @@ } .resumen { - max-width: 62ch; - margin-top: var(--sp-2); + margin: 0; + font-size: var(--fs-sm); + } + + .chips { + margin-top: auto; + padding-top: var(--sp-2); + } + + /* --- Tabla --------------------------------------------------------------- */ + + /* Que la tabla se desplace dentro de su caja y no arrastre la página. */ + .tabla-envoltura { + overflow-x: auto; + padding-bottom: var(--sp-7); + } + + .tabla { + width: 100%; + border-collapse: collapse; + font-size: var(--fs-sm); + } + + .tabla th { + text-align: left; + padding: var(--sp-2) var(--sp-3); + border-bottom: 1px solid var(--c-border); + font-size: var(--fs-xs); + text-transform: uppercase; + letter-spacing: 0.1em; + color: var(--c-text-muted); + white-space: nowrap; + } + + .tabla td { + padding: var(--sp-3); + border-bottom: 1px solid var(--c-border); + vertical-align: baseline; + } + + .tabla td a { + font-family: var(--font-display); + font-size: var(--fs-lg); + text-decoration: none; } + + .celda-fecha { + white-space: nowrap; + font-family: var(--font-mono); + font-size: var(--fs-xs); + color: var(--c-text-muted); + } + + .celda-resumen { + min-width: 24ch; + } + + .celda-etiquetas { + white-space: nowrap; + } + + @media (max-width: 30rem) { + .barra { + flex-direction: column; + } + + input[type='search'] { + flex: 0 0 auto; + } + + .vistas { + border-left: 0; + border-top: 1px solid var(--c-border); + } + + .vista { + flex: 1; + } + } + @media (prefers-reduced-motion: reduce) { - h2 a { + h2 a, + .vista { transition: none; } } diff --git a/src/routes/generos/+layout.server.ts b/src/routes/generos/+layout.server.ts new file mode 100644 index 0000000..035865a --- /dev/null +++ b/src/routes/generos/+layout.server.ts @@ -0,0 +1,10 @@ +import { indiceDelTaller } from '$lib/server/taller'; + +/** + * El índice de géneros vive en el layout, así que se carga una vez y lo tienen + * la portada de la sección y cada ficha. + */ +export async function load() { + const { fichas } = await indiceDelTaller(); + return { fichas }; +} diff --git a/src/routes/generos/+layout.svelte b/src/routes/generos/+layout.svelte new file mode 100644 index 0000000..be96fa1 --- /dev/null +++ b/src/routes/generos/+layout.svelte @@ -0,0 +1,69 @@ + + ++ Una ficha por estilo, con lo que hace falta para escribir una letra en él y que suene a lo que + es. Pulsa un país para ver lo suyo, o busca por nombre, por tema o por cómo se llama en otro + sitio. +
++ {#if filtrando} + {encontrados.length} + {encontrados.length === 1 ? 'género' : 'géneros'} + {:else} + {data.generos.length} géneros + {/if} +
+ +{#if encontrados.length === 0} ++ Nada con eso. Prueba con otra palabra, o quita el país si lo tienes puesto. +
+{:else if pais} + {#if nacidos.length > 0} +Taller de letras
++ Las palabras que hacen falta para hablar de una letra. Pulsa una para leer su definición; las + mismas salen marcadas dentro de los capítulos. +
++ {encontrados.length} de {data.glosario.length} +
++ Nada con «{consulta.trim()}». Prueba con una palabra suelta: «rima», «verso», «acento». +
+{:else} ++ Quién fijó cada estilo. Salen de las fichas de género, donde cada uno está acreditado con su + papel: quien lo fundó, quien lo escribió y quien lo cantó. +
++ {encontrados.length} de {data.letristas.length} +
+Nada con «{consulta.trim()}».
+{:else} +{persona.nombre}
++ {persona.pais ?? ''}{#if persona.pais && vida(persona.nacimiento, persona.defuncion)} + · + {/if}{vida(persona.nacimiento, persona.defuncion)} +
+{persona.semblanza}
+ {/if} + ++ {#each persona.generos as genero, i (genero.slug + genero.papel)} + {#if i > 0}{/if} + {genero.nombre} + {PAPEL[genero.papel] ?? genero.papel} + {/each} +
+ + {#if persona.obras.length > 0} ++ {persona.obras.map((o) => (o.ano ? `${o.titulo} (${o.ano})` : o.titulo)).join(' · ')} +
+ {/if} +Género
- {/if} - -o {alias.map((a) => `«${a.nombre}»`).join(', ')}
- {/if} - - {#if capitulo.resumen} -{capitulo.resumen}
- {/if} - - {#if ficha?.origenLugar} -- {ficha.origenLugar}{#if anoAparte}, {anoAparte}{/if} -
- {/if} - - - {#if paises.length > 0} -{etiqueta}
-{valor}
-{ILUSTRA[ejemplo.ilustra] ?? ejemplo.ilustra}
-{linea.texto}
- {#if linea.silabas.length > 0} - - {/if} - {linea.medida} - {#if linea.rima && linea.rima !== '-'} - {linea.rima} - {/if} -- Los ejemplos están escritos para el taller, no son de ninguna canción. Sirven para enseñar la - cuenta y la rima del género; para oírlo de verdad, arriba están las obras de referencia. -
-{obra.titulo}
- {#if obra.autores.length > 0} -{obra.autores.join(' · ')}
- {/if} - {#if obra.cita} -{obra.cita}
- {/if} - {#if obra.nota} -{obra.nota}
- {/if} - {#if obra.enlaces.length > 0} -- Los fragmentos se reproducen al amparo del derecho de cita, para ilustrar el estilo. Las - letras completas son de sus autores y no se alojan aquí. -
-De dónde viene
-Qué viene de él
-- Esta ficha la reunió un modelo de lenguaje y está pendiente de revisión: los - datos —instrumentación, letristas, obras de referencia, linaje— y también los ejemplos de versos - y su escansión. Las fechas y las atribuciones no se han comprobado una a una. -
-{/if} - -{#if capitulo.anterior || capitulo.siguiente} - -{/if} - - +Taller de letras
-- Las palabras que hacen falta para hablar de una letra. Salen marcadas en el texto de los - capítulos: al pulsarlas se abre su definición sin salir de donde estabas. -
-{CATEGORIAS[acepcion.categoria] ?? acepcion.categoria}
-{acepcion.definicion}
- {#if acepcion.ampliacion} -{acepcion.ampliacion}
- {/if} - {#if acepcion.ejemplo} -{acepcion.ejemplo}
- {/if} -