Base de conocimiento para el personal del Instituto Santiago Tapia: oferta educativa (en tarjetas y en tabla), requisitos y titulacion, becas y fechas de inscripcion, links de clases de Google Meet, preguntas frecuentes, mensajes listos y datos del instituto. Acceso con Magic Login: enlace de un solo uso, 15 minutos de vigencia, y en la base solo se guarda el SHA-256 del token. El canje es atomico, asi que dos canjes simultaneos del mismo enlace no pueden crear dos sesiones. Tres roles con 19 permisos. El catalogo lo edita direccion; los links de clases, direccion y administracion; el resto del equipo consulta. El menu se pinta con lo que el servidor autoriza y cada endpoint exige la misma clave, asi que no hay pantallas alcanzables escribiendo la direccion a mano. Toda edicion pasa por una lista blanca de campos validados y queda en la bitacora. Un precio vacio no se guarda como cero, un link que no es una direccion se rechaza, y no se puede marcar una validez oficial como confirmada sin numero de acuerdo. Pensado para leerse comodo: texto de 17 px, contraste AA, areas de toque de 44 px, tema claro y bloques plegados en telefono. La oferta, los costos, las becas, los requisitos y el contacto son los reales del instituto, tomados del CSV de oferta educativa y de la base de conocimiento. Los usuarios de acceso y los links de Meet son de demostracion. Verificado: 103 comprobaciones de API y 51 pruebas en WebKit escritorio y iPhone 13. Co-Authored-By: Claude Opus 5 (1M context) <[email protected]>
775 lines
35 KiB
CSS
775 lines
35 KiB
CSS
/* =====================================================================
|
||
Portal Interno INSTA — hoja de estilo
|
||
---------------------------------------------------------------------
|
||
Tema claro, texto grande y contrastes altos: el portal lo usa gente
|
||
que lleva años en el instituto y lo consulta a media conversación,
|
||
muchas veces desde el teléfono. Se prefiere una línea de más antes que
|
||
una letra más chica.
|
||
|
||
La geometría sale del logo: una placa con radio grande en la esquina
|
||
superior izquierda e inferior derecha, y casi recto en las otras dos.
|
||
El amarillo se usa solo como marcador sobre el dato importante.
|
||
===================================================================== */
|
||
|
||
:root {
|
||
/* --- marca (muestreada del logo oficial) --- */
|
||
--azul: #4275b7;
|
||
--azul-profundo: #30517e;
|
||
--azul-panel: #9dc2e8;
|
||
--azul-niebla: #e7effa;
|
||
--azul-humo: #f3f7fc;
|
||
--marca: #efef07;
|
||
|
||
/* --- texto y superficies (contraste alto sobre papel) --- */
|
||
--carbon: #14181d; /* 15.6:1 sobre papel */
|
||
--tinta: #16283f; /* títulos */
|
||
--gris: #45535f; /* 8.4:1 · texto secundario */
|
||
--gris-claro: #66737f; /* 5.4:1 · etiquetas pequeñas */
|
||
--papel: #fafbfc;
|
||
--papel-hueco: #ffffff;
|
||
--linea: #cfdce9;
|
||
--linea-suave: #e5edf5;
|
||
|
||
/* --- estado --- */
|
||
--alerta: #b32222; /* 6.5:1 */
|
||
--atencion: #a95c00; /* 4.9:1 */
|
||
--bien: #0c7350; /* 5.1:1 */
|
||
|
||
/* --- tipografía --- */
|
||
--serif: 'Iowan Old Style', 'Palatino Linotype', Palatino, 'Book Antiqua', Georgia, serif;
|
||
--sans: 'Segoe UI Variable Text', 'Segoe UI', -apple-system, BlinkMacSystemFont, 'Helvetica Neue', system-ui, sans-serif;
|
||
--mono: 'Cascadia Mono', Consolas, 'SF Mono', 'Roboto Mono', ui-monospace, monospace;
|
||
|
||
/* --- forma --- */
|
||
--radio-placa: 20px 4px 20px 4px;
|
||
--radio-chico: 10px 2px 10px 2px;
|
||
--radio-pill: 999px;
|
||
|
||
--sombra: 0 1px 2px rgba(22, 40, 63, .07), 0 8px 24px -14px rgba(22, 40, 63, .2);
|
||
--sombra-alta: 0 2px 6px rgba(22, 40, 63, .1), 0 22px 50px -20px rgba(22, 40, 63, .3);
|
||
|
||
--ancho: 1120px;
|
||
--barra: 282px;
|
||
--toque: 44px; /* alto mínimo de cualquier cosa que se pueda tocar */
|
||
}
|
||
|
||
*, *::before, *::after { box-sizing: border-box; }
|
||
|
||
html { -webkit-text-size-adjust: 100%; color-scheme: light; }
|
||
|
||
body {
|
||
margin: 0;
|
||
background: var(--papel);
|
||
color: var(--carbon);
|
||
font-family: var(--sans);
|
||
font-size: 17px;
|
||
line-height: 1.6;
|
||
-webkit-font-smoothing: antialiased;
|
||
}
|
||
|
||
h1, h2, h3, h4 { font-family: var(--serif); font-weight: 600; line-height: 1.2; margin: 0; }
|
||
p { margin: 0; }
|
||
a { color: var(--azul-profundo); text-decoration-thickness: 1px; text-underline-offset: 3px; }
|
||
a:hover { color: var(--azul); }
|
||
|
||
:focus-visible { outline: 3px solid var(--azul); outline-offset: 2px; border-radius: 3px; }
|
||
::selection { background: var(--marca); color: #14181d; }
|
||
|
||
/* ---------------------------------------------------------------------
|
||
Rótulo
|
||
--------------------------------------------------------------------- */
|
||
|
||
.rotulo {
|
||
display: flex; align-items: center; gap: 12px;
|
||
text-decoration: none; color: inherit;
|
||
min-height: var(--toque); /* es un enlace: tiene que poder tocarse */
|
||
}
|
||
.rotulo img { width: 48px; height: auto; flex: none; border-radius: var(--radio-chico); }
|
||
.rotulo__texto { display: flex; flex-direction: column; line-height: 1.2; }
|
||
.rotulo__nombre { font-family: var(--serif); font-size: 17px; font-weight: 600; color: var(--tinta); }
|
||
.rotulo__sub { font-size: 13px; letter-spacing: .05em; text-transform: uppercase; color: var(--gris); }
|
||
|
||
/* ---------------------------------------------------------------------
|
||
Etiquetas y datos
|
||
--------------------------------------------------------------------- */
|
||
|
||
/* 14 px y en gris oscuro: en mayúsculas y con tracking, cualquier cosa más
|
||
chica se vuelve difícil de leer, y en teléfono esta etiqueta es lo único
|
||
que nombra el valor de cada celda. */
|
||
.ceja {
|
||
font-size: 14px; font-weight: 700;
|
||
text-transform: uppercase; letter-spacing: .07em; color: var(--gris);
|
||
}
|
||
.dato { font-family: var(--mono); font-variant-numeric: tabular-nums; }
|
||
|
||
/* Marcador amarillo: el único uso del amarillo sobre texto. La banda se
|
||
queda por debajo de la línea base para no comerse los descendentes de la
|
||
g, la j o la p en texto blanco sobre el azul. */
|
||
.marcado > * {
|
||
padding: 0 .1em;
|
||
background-image: linear-gradient(to top, rgba(239, 239, 7, .92) 12%, transparent 12%);
|
||
background-size: 100% .34em;
|
||
background-position: 0 100%;
|
||
background-repeat: no-repeat;
|
||
box-decoration-break: clone;
|
||
-webkit-box-decoration-break: clone;
|
||
}
|
||
|
||
/* ---------------------------------------------------------------------
|
||
Entrada · Magic Login
|
||
--------------------------------------------------------------------- */
|
||
|
||
.entrada { min-height: 100vh; min-height: 100dvh; display: grid; grid-template-columns: 1fr 1fr; }
|
||
|
||
.entrada__lienzo {
|
||
background: var(--azul-profundo); color: #eef4fb;
|
||
padding: 48px 44px;
|
||
display: flex; flex-direction: column; justify-content: space-between; gap: 30px;
|
||
position: relative; overflow: hidden;
|
||
}
|
||
.entrada__lienzo::before {
|
||
content: ''; position: absolute; inset: 0;
|
||
background:
|
||
radial-gradient(120% 90% at 78% -12%, rgba(157, 194, 232, .26), transparent 60%),
|
||
radial-gradient(90% 70% at 8% 108%, rgba(239, 239, 7, .06), transparent 62%);
|
||
pointer-events: none;
|
||
}
|
||
.entrada__lienzo > * { position: relative; }
|
||
.entrada__lienzo .rotulo__nombre { color: #fff; }
|
||
.entrada__lienzo .rotulo__sub { color: rgba(238, 244, 251, .88); }
|
||
|
||
.entrada__promesa { max-width: 33rem; }
|
||
.entrada__promesa h1 { font-size: clamp(30px, 4.2vw, 48px); color: #fff; }
|
||
.entrada__promesa h1 em { font-style: normal; color: var(--marca); }
|
||
.entrada__promesa p { margin-top: 18px; color: rgba(238, 244, 251, .85); font-size: 17px; max-width: 30rem; }
|
||
|
||
.entrada__hechos { display: flex; flex-wrap: wrap; gap: 14px 32px; }
|
||
.entrada__hecho { display: flex; flex-direction: column; }
|
||
.entrada__hecho b { font-family: var(--mono); font-size: 22px; color: #fff; font-variant-numeric: tabular-nums; }
|
||
.entrada__hecho span { font-size: 13px; text-transform: uppercase; letter-spacing: .07em; color: rgba(238, 244, 251, .88); }
|
||
|
||
.entrada__acceso { padding: 44px; display: flex; flex-direction: column; justify-content: center; background: var(--papel-hueco); }
|
||
.acceso { width: 100%; max-width: 460px; margin-inline: auto; }
|
||
.acceso > .ceja { display: block; margin-bottom: 8px; }
|
||
.acceso h2 { font-size: 29px; color: var(--tinta); }
|
||
.acceso__nota { margin-top: 10px; color: var(--gris); }
|
||
|
||
.acceso__roles { margin-top: 26px; display: flex; flex-direction: column; gap: 10px; }
|
||
.tarjeta-rol {
|
||
display: grid; grid-template-columns: 44px 1fr; align-items: center; gap: 14px;
|
||
width: 100%; text-align: left; cursor: pointer;
|
||
padding: 14px 16px; min-height: var(--toque);
|
||
background: var(--papel-hueco);
|
||
border: 2px solid var(--linea);
|
||
border-left: 5px solid var(--rol, var(--azul));
|
||
border-radius: var(--radio-chico);
|
||
font: inherit; color: inherit;
|
||
transition: border-color .16s, box-shadow .16s;
|
||
}
|
||
.tarjeta-rol:hover:not(:disabled) { border-color: var(--azul); box-shadow: var(--sombra); }
|
||
.tarjeta-rol:disabled { opacity: .6; cursor: progress; }
|
||
.tarjeta-rol__txt { min-width: 0; }
|
||
.tarjeta-rol__txt b { display: block; font-size: 17px; color: var(--tinta); font-weight: 600; }
|
||
.tarjeta-rol__txt span { display: block; font-size: 14.5px; color: var(--gris); line-height: 1.45; }
|
||
|
||
.ficha {
|
||
width: 44px; height: 44px; border-radius: var(--radio-chico); flex: none;
|
||
display: grid; place-items: center;
|
||
background: var(--azul-niebla); color: var(--azul-profundo);
|
||
border: 2px solid var(--azul-panel);
|
||
font-family: var(--mono); font-size: 15px; font-weight: 700;
|
||
}
|
||
.ficha--chica { width: 36px; height: 36px; font-size: 13px; }
|
||
|
||
.separador {
|
||
display: flex; align-items: center; gap: 12px; margin: 26px 0 18px;
|
||
font-size: 12.5px; font-weight: 700; text-transform: uppercase; letter-spacing: .09em; color: var(--gris-claro);
|
||
}
|
||
.separador::before, .separador::after { content: ''; height: 1px; background: var(--linea); flex: 1; }
|
||
|
||
/* ---------------------------------------------------------------------
|
||
Formularios
|
||
--------------------------------------------------------------------- */
|
||
|
||
.campo { display: flex; flex-direction: column; gap: 7px; }
|
||
.campo__ayuda { font-size: 15.5px; color: var(--gris); }
|
||
label { font-size: 16px; font-weight: 600; color: var(--tinta); }
|
||
|
||
.campo-casilla {
|
||
display: flex; align-items: center; gap: 13px; cursor: pointer;
|
||
min-height: var(--toque); padding: 8px 12px;
|
||
border: 2px solid var(--linea); border-radius: var(--radio-chico);
|
||
}
|
||
.campo-casilla:hover { border-color: var(--azul); background: var(--azul-humo); }
|
||
.campo-casilla:has(input:checked) { border-color: var(--azul); background: var(--azul-niebla); }
|
||
.campo-casilla input {
|
||
width: 26px; height: 26px; min-height: auto; flex: none;
|
||
accent-color: var(--azul-profundo); margin: 0;
|
||
}
|
||
.campo-casilla span { font-weight: 600; }
|
||
|
||
input[type=email], input[type=text], input[type=search], input[type=url], input[type=number], select, textarea {
|
||
font: inherit; font-size: 17px;
|
||
padding: 11px 13px; min-height: var(--toque);
|
||
border: 2px solid var(--linea);
|
||
border-radius: var(--radio-chico);
|
||
background: var(--papel-hueco); color: var(--carbon);
|
||
width: 100%;
|
||
}
|
||
textarea { min-height: 120px; resize: vertical; line-height: 1.55; }
|
||
input::placeholder, textarea::placeholder { color: var(--gris-claro); }
|
||
input:focus, select:focus, textarea:focus {
|
||
outline: none; border-color: var(--azul); box-shadow: 0 0 0 3px rgba(66, 117, 183, .22);
|
||
}
|
||
input[aria-invalid=true], textarea[aria-invalid=true] { border-color: var(--alerta); }
|
||
|
||
.boton {
|
||
font: inherit; font-size: 16px; font-weight: 600;
|
||
display: inline-flex; align-items: center; justify-content: center; gap: 8px;
|
||
padding: 10px 20px; min-height: var(--toque); cursor: pointer;
|
||
border-radius: var(--radio-chico);
|
||
border: 2px solid var(--azul-profundo);
|
||
background: var(--azul-profundo); color: #fff;
|
||
text-decoration: none;
|
||
transition: background .15s, border-color .15s;
|
||
}
|
||
.boton:hover:not(:disabled) { background: var(--azul); border-color: var(--azul); color: #fff; }
|
||
.boton:disabled { opacity: .55; cursor: not-allowed; }
|
||
.boton svg { width: 19px; height: 19px; flex: none; }
|
||
.boton--fantasma { background: transparent; color: var(--azul-profundo); border-color: var(--linea); }
|
||
.boton--fantasma:hover:not(:disabled) { background: var(--azul-niebla); color: var(--azul-profundo); border-color: var(--azul); }
|
||
.boton--peligro { background: transparent; color: var(--alerta); border-color: color-mix(in srgb, var(--alerta) 40%, transparent); }
|
||
.boton--peligro:hover:not(:disabled) { background: color-mix(in srgb, var(--alerta) 10%, transparent); color: var(--alerta); border-color: var(--alerta); }
|
||
.boton--chico { font-size: 14.5px; padding: 7px 13px; min-height: 38px; }
|
||
.boton--bloque { width: 100%; }
|
||
|
||
.aviso {
|
||
padding: 13px 16px;
|
||
border-radius: var(--radio-chico);
|
||
border: 1px solid var(--linea);
|
||
border-left: 5px solid var(--gris-claro);
|
||
background: var(--azul-humo);
|
||
font-size: 16px; color: var(--carbon);
|
||
}
|
||
.aviso--error { border-left-color: var(--alerta); background: color-mix(in srgb, var(--alerta) 8%, transparent); }
|
||
.aviso--ok { border-left-color: var(--bien); background: color-mix(in srgb, var(--bien) 9%, transparent); }
|
||
.aviso--atencion { border-left-color: var(--atencion); background: color-mix(in srgb, var(--atencion) 9%, transparent); }
|
||
.aviso--nota { border-left-color: var(--azul-panel); }
|
||
.aviso + .aviso { margin-top: 10px; }
|
||
|
||
.enlace-magico code {
|
||
display: block; margin-top: 8px; padding: 10px 12px;
|
||
font-family: var(--mono); font-size: 13px; word-break: break-all;
|
||
background: var(--azul-niebla); border-radius: var(--radio-chico); color: var(--azul-profundo);
|
||
}
|
||
|
||
.pie-demo { margin-top: 26px; font-size: 14.5px; color: var(--gris); }
|
||
|
||
@media (max-width: 900px) {
|
||
.entrada { grid-template-columns: 1fr; }
|
||
.entrada__lienzo { padding: 28px 22px 32px; }
|
||
.entrada__acceso { padding: 30px 22px 46px; }
|
||
}
|
||
|
||
/* ---------------------------------------------------------------------
|
||
Estructura del portal
|
||
--------------------------------------------------------------------- */
|
||
|
||
.portal { display: grid; grid-template-columns: var(--barra) minmax(0, 1fr); min-height: 100vh; min-height: 100dvh; }
|
||
|
||
.barra {
|
||
position: sticky; top: 0; height: 100vh; height: 100dvh;
|
||
display: flex; flex-direction: column;
|
||
background: var(--papel-hueco);
|
||
border-right: 1px solid var(--linea);
|
||
padding: 18px 14px 14px;
|
||
overflow-y: auto;
|
||
}
|
||
.barra__cabeza { padding: 0 6px 16px; border-bottom: 1px solid var(--linea-suave); }
|
||
.barra__nav { flex: 1; padding-top: 12px; display: flex; flex-direction: column; gap: 3px; }
|
||
.barra__grupo { margin: 16px 0 5px; padding: 0 8px; }
|
||
.nav-item {
|
||
display: flex; align-items: center; gap: 12px;
|
||
padding: 10px 12px; min-height: var(--toque);
|
||
border-radius: var(--radio-chico);
|
||
border: 2px solid transparent;
|
||
background: none; font: inherit; font-size: 16px; color: var(--gris);
|
||
cursor: pointer; text-align: left; width: 100%;
|
||
transition: background .14s, color .14s;
|
||
}
|
||
.nav-item:hover { background: var(--azul-humo); color: var(--tinta); }
|
||
.nav-item[aria-current='page'] {
|
||
background: var(--azul-niebla); color: var(--azul-profundo); font-weight: 700;
|
||
border-color: var(--azul-panel);
|
||
}
|
||
.nav-item svg { width: 21px; height: 21px; flex: none; stroke-width: 1.7; }
|
||
|
||
.barra__pie { border-top: 1px solid var(--linea-suave); padding-top: 12px; }
|
||
.usuario { display: grid; grid-template-columns: 44px 1fr; gap: 11px; align-items: center; padding: 0 6px 10px; }
|
||
.usuario__txt { min-width: 0; }
|
||
.usuario__txt b { display: block; font-size: 15.5px; color: var(--tinta); font-weight: 600; }
|
||
/* El color del rol iría por debajo del contraste mínimo como texto, así que
|
||
va en un punto al lado y el nombre del rol en gris legible. */
|
||
.usuario__txt span { display: flex; align-items: center; gap: 7px; font-size: 14px; font-weight: 600; color: var(--gris); }
|
||
.usuario__txt span::before {
|
||
content: ''; width: 9px; height: 9px; border-radius: 50%; flex: none;
|
||
background: var(--rol, var(--azul-profundo));
|
||
}
|
||
|
||
.tope {
|
||
display: none;
|
||
position: sticky; top: 0; z-index: 40;
|
||
align-items: center; gap: 12px;
|
||
padding: 10px 16px;
|
||
background: var(--papel-hueco);
|
||
border-bottom: 1px solid var(--linea);
|
||
}
|
||
.tope__menu {
|
||
width: var(--toque); height: var(--toque); display: grid; place-items: center;
|
||
border: 2px solid var(--linea); border-radius: var(--radio-chico);
|
||
background: var(--papel-hueco); cursor: pointer; color: var(--tinta);
|
||
}
|
||
.tope__menu svg { width: 22px; height: 22px; }
|
||
.tope .ficha { margin-left: auto; }
|
||
|
||
.lienzo { min-width: 0; padding: 30px 34px 80px; }
|
||
.lienzo__interno { max-width: var(--ancho); margin-inline: auto; }
|
||
|
||
.cabecera-seccion { margin-bottom: 24px; }
|
||
.cabecera-seccion h1 { font-size: clamp(27px, 3vw, 36px); color: var(--tinta); margin-top: 5px; }
|
||
.cabecera-seccion p { color: var(--gris); margin-top: 8px; max-width: 62ch; }
|
||
.cabecera-seccion__acciones { display: flex; gap: 10px; flex-wrap: wrap; margin-top: 16px; }
|
||
|
||
@media (max-width: 1040px) {
|
||
.portal { grid-template-columns: 1fr; }
|
||
.tope { display: flex; }
|
||
.barra {
|
||
position: fixed; inset: 0 auto 0 0; z-index: 60; width: min(310px, 86vw);
|
||
transform: translateX(-102%); transition: transform .22s ease;
|
||
box-shadow: var(--sombra-alta);
|
||
}
|
||
.barra[data-abierta='1'] { transform: none; }
|
||
.velo { position: fixed; inset: 0; z-index: 50; background: rgba(22, 40, 63, .45); border: 0; }
|
||
.lienzo { padding: 20px 18px 70px; }
|
||
}
|
||
@media (max-width: 520px) { .lienzo { padding: 16px 14px 64px; } }
|
||
|
||
/* ---------------------------------------------------------------------
|
||
La placa
|
||
--------------------------------------------------------------------- */
|
||
|
||
.placa {
|
||
background: var(--papel-hueco);
|
||
border: 1px solid var(--linea);
|
||
border-radius: var(--radio-placa);
|
||
padding: 20px 22px;
|
||
min-width: 0;
|
||
}
|
||
.placa--acento { border-left: 5px solid var(--acento, var(--azul)); }
|
||
.placa__ceja { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; margin-bottom: 12px; }
|
||
.placa h3 { font-size: 21px; color: var(--tinta); }
|
||
.placa h4 { font-size: 18px; color: var(--tinta); }
|
||
|
||
/* La placa de respuesta: lo más importante de cada pantalla. */
|
||
.respuesta {
|
||
background: var(--azul-profundo); color: #eef4fb;
|
||
border-radius: var(--radio-placa);
|
||
padding: 24px 26px;
|
||
display: grid; gap: 16px;
|
||
}
|
||
.respuesta .ceja { color: rgba(238, 244, 251, .72); }
|
||
.respuesta h2 { color: #fff; font-size: clamp(21px, 2.4vw, 28px); max-width: 46ch; }
|
||
.respuesta p { color: rgba(238, 244, 251, .88); max-width: 66ch; }
|
||
.respuesta__fila { display: flex; align-items: flex-end; gap: 30px; flex-wrap: wrap; }
|
||
.respuesta__cifra { display: flex; flex-direction: column; gap: 3px; }
|
||
.respuesta__cifra b { font-family: var(--mono); font-size: clamp(26px, 3.4vw, 36px); color: #fff; font-variant-numeric: tabular-nums; line-height: 1; }
|
||
.respuesta__cifra span { font-size: 12.5px; text-transform: uppercase; letter-spacing: .09em; color: rgba(238, 244, 251, .7); }
|
||
.respuesta__acciones { display: flex; gap: 10px; flex-wrap: wrap; }
|
||
.respuesta .boton { border-color: rgba(238, 244, 251, .45); background: transparent; color: #fff; }
|
||
.respuesta .boton:hover:not(:disabled) { background: rgba(238, 244, 251, .16); border-color: #fff; color: #fff; }
|
||
.respuesta .boton--marca { background: var(--marca); border-color: var(--marca); color: #14181d; }
|
||
.respuesta .boton--marca:hover:not(:disabled) { background: #f7f735; border-color: #f7f735; color: #14181d; }
|
||
|
||
/* ---------------------------------------------------------------------
|
||
Rejillas
|
||
--------------------------------------------------------------------- */
|
||
|
||
.rejilla { display: grid; gap: 16px; }
|
||
.rejilla--2 { grid-template-columns: repeat(auto-fit, minmax(min(320px, 100%), 1fr)); }
|
||
.rejilla--3 { grid-template-columns: repeat(auto-fit, minmax(min(250px, 100%), 1fr)); }
|
||
/* Las fichas de programa llevan nombres largos y filas de horario con la hora
|
||
a la derecha: a menos de 430 px se parten en tres renglones y se leen mal. */
|
||
.rejilla--fichas { grid-template-columns: repeat(auto-fit, minmax(min(430px, 100%), 1fr)); }
|
||
.rejilla > *, .pila > * { min-width: 0; }
|
||
.rejilla--arriba { align-items: start; }
|
||
.pila { display: grid; gap: 16px; }
|
||
.pila--ancha { gap: 24px; }
|
||
|
||
/* ---------------------------------------------------------------------
|
||
Insignias
|
||
--------------------------------------------------------------------- */
|
||
|
||
/* Dos clases de insignia, y la diferencia es de contraste, no de gusto:
|
||
- Etiqueta (por omisión): el tono puede ser un color claro del catálogo
|
||
(el verde pálido de una maestría), así que el texto va en tinta y el
|
||
color solo tiñe el fondo y el borde. Así nunca queda ilegible.
|
||
- Estado (--fuerte): el tono es uno de los semánticos, que sí tienen
|
||
contraste suficiente, y ahí el color del texto es la información. */
|
||
.insignia {
|
||
display: inline-flex; align-items: center; gap: 7px;
|
||
font-size: 14px; font-weight: 700;
|
||
padding: 4px 12px; border-radius: var(--radio-pill);
|
||
background: color-mix(in srgb, var(--tono, var(--gris)) 16%, #fff);
|
||
color: var(--carbon);
|
||
border: 1px solid color-mix(in srgb, var(--tono, var(--gris)) 50%, #fff);
|
||
white-space: nowrap;
|
||
}
|
||
.insignia--fuerte {
|
||
color: var(--tono, var(--gris));
|
||
background: color-mix(in srgb, var(--tono, var(--gris)) 11%, #fff);
|
||
border-color: color-mix(in srgb, var(--tono, var(--gris)) 38%, #fff);
|
||
}
|
||
.insignia__punto {
|
||
width: 9px; height: 9px; border-radius: 50%; flex: none;
|
||
background: var(--tono, var(--gris));
|
||
}
|
||
.etiquetas { display: flex; flex-wrap: wrap; gap: 7px; }
|
||
|
||
/* ---------------------------------------------------------------------
|
||
Tablas: en escritorio son tabla, abajo de 780 px se apilan
|
||
--------------------------------------------------------------------- */
|
||
|
||
.envoltura-tabla { overflow-x: auto; -webkit-overflow-scrolling: touch; max-width: 100%; }
|
||
.tabla { width: 100%; border-collapse: collapse; font-size: 16px; }
|
||
.tabla th {
|
||
text-align: left; padding: 10px 14px;
|
||
font-size: 14px; font-weight: 700;
|
||
text-transform: uppercase; letter-spacing: .05em; color: var(--gris);
|
||
border-bottom: 2px solid var(--linea);
|
||
white-space: nowrap; background: var(--azul-humo);
|
||
}
|
||
.tabla td { padding: 13px 14px; border-bottom: 1px solid var(--linea-suave); vertical-align: top; }
|
||
.tabla tbody tr:last-child td { border-bottom: 0; }
|
||
.tabla tbody tr:hover { background: var(--azul-humo); }
|
||
.tabla__num { text-align: right; font-family: var(--mono); font-variant-numeric: tabular-nums; white-space: nowrap; }
|
||
.tabla__acciones { white-space: nowrap; text-align: right; }
|
||
|
||
@media (max-width: 780px) {
|
||
.tabla--apila thead { display: none; }
|
||
.tabla--apila tbody tr {
|
||
display: grid; gap: 4px; padding: 15px 0;
|
||
border-bottom: 1px solid var(--linea);
|
||
}
|
||
.tabla--apila tbody tr:hover { background: none; }
|
||
.tabla--apila td { display: grid; grid-template-columns: 38% 1fr; gap: 12px; padding: 3px 0; border: 0; }
|
||
/* En teléfono esta etiqueta es el único encabezado que ve la persona, así
|
||
que va al mismo tamaño y contraste que el resto del texto. */
|
||
.tabla--apila td::before {
|
||
content: attr(data-col);
|
||
font-size: 14px; font-weight: 700; text-transform: uppercase; letter-spacing: .05em;
|
||
color: var(--gris);
|
||
}
|
||
.tabla--apila td:empty { display: none; }
|
||
.tabla__num, .tabla__acciones { text-align: left; }
|
||
}
|
||
|
||
/* ---------------------------------------------------------------------
|
||
Oferta educativa: la ficha de programa
|
||
--------------------------------------------------------------------- */
|
||
|
||
.vista-alterna { display: inline-flex; border: 2px solid var(--linea); border-radius: var(--radio-chico); overflow: hidden; }
|
||
.vista-alterna button {
|
||
font: inherit; font-size: 15.5px; font-weight: 600;
|
||
padding: 9px 18px; min-height: 42px; cursor: pointer;
|
||
border: 0; background: var(--papel-hueco); color: var(--gris);
|
||
display: inline-flex; align-items: center; gap: 8px;
|
||
}
|
||
.vista-alterna button + button { border-left: 2px solid var(--linea); }
|
||
.vista-alterna button:hover { background: var(--azul-humo); color: var(--tinta); }
|
||
.vista-alterna button[aria-pressed='true'] { background: var(--azul-profundo); color: #fff; }
|
||
.vista-alterna svg { width: 18px; height: 18px; }
|
||
|
||
.programa { border-left: 5px solid var(--acento); display: grid; gap: 14px; }
|
||
.programa__cabeza { display: flex; align-items: flex-start; justify-content: space-between; gap: 12px; flex-wrap: wrap; }
|
||
.programa h3 { font-size: 21px; max-width: 26ch; }
|
||
|
||
.precio { display: flex; align-items: baseline; gap: 10px; flex-wrap: wrap; }
|
||
.precio b { font-family: var(--mono); font-size: 30px; color: var(--tinta); font-variant-numeric: tabular-nums; line-height: 1.1; }
|
||
.precio s { font-family: var(--mono); font-size: 17px; color: var(--gris-claro); }
|
||
.precio small { font-size: 14.5px; color: var(--gris); }
|
||
|
||
.detalles { display: grid; gap: 0; }
|
||
.detalle { display: grid; grid-template-columns: 34% 1fr; gap: 14px; padding: 9px 0; align-items: baseline; }
|
||
.detalle:not(:last-child) { border-bottom: 1px solid var(--linea-suave); }
|
||
.detalle > dt { font-size: 15px; font-weight: 600; color: var(--gris); }
|
||
.detalle > dd { margin: 0; font-size: 16.5px; color: var(--carbon); }
|
||
@media (max-width: 560px) { .detalle { grid-template-columns: 1fr; gap: 2px; } }
|
||
|
||
.horario { display: flex; align-items: center; gap: 11px; padding: 9px 0; flex-wrap: wrap; }
|
||
.horario:not(:last-child) { border-bottom: 1px solid var(--linea-suave); }
|
||
.horario__punto { width: 12px; height: 12px; border-radius: 3px 0 3px 0; flex: none; }
|
||
.horario b { color: var(--tinta); font-weight: 600; }
|
||
.horario__hora { margin-left: auto; font-family: var(--mono); font-size: 16px; color: var(--carbon); white-space: nowrap; }
|
||
|
||
/* ---------------------------------------------------------------------
|
||
Links de clases
|
||
--------------------------------------------------------------------- */
|
||
|
||
.clase-enlace {
|
||
display: inline-flex; align-items: center; gap: 8px;
|
||
font-size: 15.5px; font-weight: 600; text-decoration: none;
|
||
padding: 8px 14px; min-height: 40px;
|
||
border-radius: var(--radio-chico);
|
||
background: var(--bien); color: #fff;
|
||
border: 2px solid var(--bien);
|
||
}
|
||
.clase-enlace:hover { background: #0a6144; border-color: #0a6144; color: #fff; }
|
||
.clase-enlace svg { width: 17px; height: 17px; }
|
||
.clase-inactiva { opacity: .55; }
|
||
|
||
/* La materia es lo que se busca con la vista, así que se lleva el ancho;
|
||
la hora nunca se parte en varias líneas. */
|
||
.tabla--clases { min-width: 880px; }
|
||
.tabla--clases th:nth-child(1), .tabla--clases td:nth-child(1) { width: 27%; }
|
||
.tabla--clases th:nth-child(2), .tabla--clases td:nth-child(2) { width: 14%; }
|
||
.tabla--clases th:nth-child(3), .tabla--clases td:nth-child(3) { width: 16%; }
|
||
.tabla--clases th:nth-child(4), .tabla--clases td:nth-child(4) { width: 15%; }
|
||
.tabla--clases td:nth-child(5) { white-space: nowrap; }
|
||
.tabla--clases td:nth-child(2) { white-space: nowrap; }
|
||
|
||
@media (max-width: 780px) {
|
||
.tabla--clases { min-width: 0; }
|
||
.tabla--clases th, .tabla--clases td { width: auto !important; }
|
||
.tabla--clases td:nth-child(5) { white-space: normal; }
|
||
}
|
||
|
||
/* ---------------------------------------------------------------------
|
||
Filtros y acordeón
|
||
--------------------------------------------------------------------- */
|
||
|
||
.filtros { display: flex; gap: 8px; flex-wrap: wrap; margin-bottom: 18px; }
|
||
.filtro {
|
||
font: inherit; font-size: 15px; font-weight: 600;
|
||
padding: 8px 16px; min-height: 40px; cursor: pointer;
|
||
border: 2px solid var(--linea); border-radius: var(--radio-pill);
|
||
background: var(--papel-hueco); color: var(--gris);
|
||
}
|
||
.filtro:hover { border-color: var(--azul); color: var(--tinta); }
|
||
.filtro[aria-pressed='true'] { background: var(--azul-profundo); border-color: var(--azul-profundo); color: #fff; }
|
||
|
||
details.acordeon { border-bottom: 1px solid var(--linea-suave); }
|
||
details.acordeon:last-child { border-bottom: 0; }
|
||
details.acordeon > summary {
|
||
cursor: pointer; padding: 15px 0; list-style: none;
|
||
display: flex; align-items: center; gap: 12px;
|
||
font-size: 18px; font-weight: 600; color: var(--tinta); min-height: var(--toque);
|
||
}
|
||
details.acordeon > summary::-webkit-details-marker { display: none; }
|
||
details.acordeon > summary::after {
|
||
content: '+'; margin-left: auto; flex: none;
|
||
font-family: var(--mono); font-size: 22px; color: var(--azul-profundo); line-height: 1;
|
||
}
|
||
details.acordeon[open] > summary::after { content: '–'; }
|
||
details.acordeon > summary:hover { color: var(--azul-profundo); }
|
||
.acordeon__cuerpo { padding: 0 0 18px; color: var(--carbon); max-width: 78ch; }
|
||
|
||
/* Lo que se escribe en una caja de texto se muestra con sus renglones. Sin
|
||
esto, una respuesta con viñetas en líneas separadas salía en un solo
|
||
párrafo corrido y se perdía el trabajo de quien la redactó. */
|
||
.respeta-renglones { white-space: pre-wrap; }
|
||
|
||
/* Plegable solo en teléfono: en escritorio el contenido va abierto y el
|
||
resumen desaparece, así que la tarjeta se ve completa. En pantalla chica
|
||
se cierra para que la sección no se convierta en un scroll infinito.
|
||
El atributo open lo pone el JS según el ancho al pintar. */
|
||
details.plegable > summary {
|
||
cursor: pointer; list-style: none;
|
||
display: flex; align-items: center; gap: 10px;
|
||
padding: 11px 0; min-height: var(--toque);
|
||
font-size: 16px; font-weight: 600; color: var(--azul-profundo);
|
||
border-top: 1px solid var(--linea-suave);
|
||
}
|
||
details.plegable > summary::-webkit-details-marker { display: none; }
|
||
details.plegable > summary::after { content: '+'; margin-left: auto; font-family: var(--mono); font-size: 22px; line-height: 1; }
|
||
details.plegable[open] > summary::after { content: '–'; }
|
||
details.plegable > summary:hover { color: var(--azul); }
|
||
details.plegable > .plegable__cuerpo { display: grid; gap: 14px; }
|
||
@media (min-width: 781px) { details.plegable > summary { display: none; } }
|
||
|
||
.mensaje-listo {
|
||
font-size: 16px; line-height: 1.65;
|
||
white-space: pre-wrap; word-break: break-word;
|
||
padding: 15px 17px; border-radius: var(--radio-chico);
|
||
background: var(--azul-humo); border: 1px solid var(--linea-suave);
|
||
color: var(--carbon);
|
||
}
|
||
|
||
/* ---------------------------------------------------------------------
|
||
Matriz de permisos
|
||
--------------------------------------------------------------------- */
|
||
|
||
.matriz { width: 100%; border-collapse: collapse; font-size: 16px; min-width: 520px; }
|
||
/* position:relative para que cualquier hijo absoluto quede recortado por
|
||
el contenedor con scroll y no estire la página. */
|
||
.matriz th, .matriz td { padding: 11px 12px; border-bottom: 1px solid var(--linea-suave); text-align: left; position: relative; }
|
||
.matriz th { font-size: 13px; text-transform: uppercase; letter-spacing: .07em; color: var(--gris); border-bottom: 2px solid var(--linea); background: var(--azul-humo); }
|
||
.matriz td:not(:first-child), .matriz th:not(:first-child) { text-align: center; width: 118px; }
|
||
.marca-si { color: var(--bien); font-size: 19px; font-weight: 700; }
|
||
.marca-no { color: var(--gris-claro); font-size: 19px; }
|
||
|
||
/* ---------------------------------------------------------------------
|
||
Ventana de edición
|
||
--------------------------------------------------------------------- */
|
||
|
||
dialog.editor {
|
||
padding: 0; border: 0; max-width: 640px; width: calc(100% - 28px);
|
||
border-radius: var(--radio-placa);
|
||
background: var(--papel-hueco); color: var(--carbon);
|
||
box-shadow: var(--sombra-alta);
|
||
}
|
||
dialog.editor::backdrop { background: rgba(22, 40, 63, .52); }
|
||
.editor__cabeza {
|
||
padding: 20px 24px 14px; border-bottom: 1px solid var(--linea);
|
||
display: flex; align-items: flex-start; gap: 14px;
|
||
}
|
||
.editor__cabeza h2 { font-size: 23px; color: var(--tinta); }
|
||
.editor__cabeza p { font-size: 15px; color: var(--gris); margin-top: 4px; }
|
||
.editor__cerrar {
|
||
margin-left: auto; flex: none;
|
||
width: 40px; height: 40px; display: grid; place-items: center;
|
||
border: 2px solid var(--linea); border-radius: var(--radio-chico);
|
||
background: var(--papel-hueco); color: var(--gris); cursor: pointer; font-size: 20px; line-height: 1;
|
||
}
|
||
.editor__cerrar:hover { border-color: var(--azul); color: var(--tinta); }
|
||
.editor__cuerpo { padding: 20px 24px; display: grid; gap: 18px; overflow-y: auto; }
|
||
.editor__pie {
|
||
padding: 16px 24px 20px; border-top: 1px solid var(--linea);
|
||
display: flex; gap: 10px; flex-wrap: wrap; align-items: center;
|
||
}
|
||
.editor__pie .boton--peligro { margin-right: auto; }
|
||
.editor__error { padding: 14px 24px 0; }
|
||
.editor__par { display: grid; grid-template-columns: 1fr 1fr; gap: 14px; }
|
||
|
||
/* La ventana se estructura como una columna: cabeza y pie fijos, y el
|
||
formulario ocupa lo que queda y rueda. Con una altura máxima fija en el
|
||
cuerpo, en un teléfono se veía media forma y no había manera de saber que
|
||
faltaba lo demás. */
|
||
dialog.editor > form { display: flex; flex-direction: column; max-height: 100%; }
|
||
dialog.editor { max-height: calc(100dvh - 32px); }
|
||
dialog.editor .editor__cuerpo { flex: 1; min-height: 0; }
|
||
|
||
@media (max-width: 560px) {
|
||
.editor__par { grid-template-columns: 1fr; }
|
||
dialog.editor {
|
||
width: 100%; max-width: none;
|
||
max-height: 92dvh;
|
||
margin: auto auto 0; /* hoja pegada al borde inferior, como en el móvil */
|
||
border-radius: 20px 20px 0 0;
|
||
}
|
||
.editor__cabeza, .editor__cuerpo, .editor__pie, .editor__error { padding-inline: 18px; }
|
||
.editor__pie { position: sticky; bottom: 0; background: var(--papel-hueco); }
|
||
.editor__pie .boton { flex: 1 1 46%; }
|
||
.editor__pie .boton--peligro { flex-basis: 100%; margin-right: 0; order: 3; }
|
||
}
|
||
|
||
/* Un pie de tarjeta con las acciones de edición. */
|
||
.acciones-edicion {
|
||
display: flex; gap: 9px; flex-wrap: wrap; align-items: center;
|
||
padding-top: 14px; margin-top: 2px; border-top: 1px dashed var(--linea);
|
||
}
|
||
.acciones-edicion .ceja { margin-right: auto; }
|
||
|
||
/* ---------------------------------------------------------------------
|
||
Estados vacíos y de carga
|
||
--------------------------------------------------------------------- */
|
||
|
||
.vacio {
|
||
padding: 44px 24px; text-align: center;
|
||
border: 2px dashed var(--linea); border-radius: var(--radio-placa);
|
||
color: var(--gris);
|
||
}
|
||
.vacio h3 { font-size: 20px; color: var(--tinta); margin-bottom: 8px; }
|
||
.vacio p { max-width: 46ch; margin-inline: auto; }
|
||
|
||
.cargando { display: grid; gap: 14px; }
|
||
.hueso {
|
||
height: 86px; border-radius: var(--radio-placa);
|
||
background: linear-gradient(100deg, var(--linea-suave) 30%, var(--azul-humo) 50%, var(--linea-suave) 70%);
|
||
background-size: 220% 100%;
|
||
animation: barrido 1.3s linear infinite;
|
||
}
|
||
@keyframes barrido { from { background-position: 130% 0; } to { background-position: -30% 0; } }
|
||
|
||
/* ---------------------------------------------------------------------
|
||
Aviso flotante
|
||
--------------------------------------------------------------------- */
|
||
|
||
.brindis {
|
||
position: fixed; left: 50%; bottom: 26px; z-index: 90;
|
||
transform: translate(-50%, 14px);
|
||
display: flex; align-items: center; gap: 10px;
|
||
padding: 13px 20px; max-width: calc(100% - 32px);
|
||
background: var(--tinta); color: #fff;
|
||
border-radius: var(--radio-chico);
|
||
font-size: 16px; box-shadow: var(--sombra-alta);
|
||
opacity: 0; pointer-events: none;
|
||
transition: opacity .2s, transform .2s;
|
||
}
|
||
.brindis[data-visible='1'] { opacity: 1; transform: translate(-50%, 0); }
|
||
.brindis__marca { width: 18px; height: 4px; background: var(--marca); border-radius: 1px; flex: none; }
|
||
|
||
/* ---------------------------------------------------------------------
|
||
Entrada en escena
|
||
--------------------------------------------------------------------- */
|
||
|
||
@media (prefers-reduced-motion: no-preference) {
|
||
.aparece { animation: sube .32s cubic-bezier(.22, .7, .3, 1) backwards; }
|
||
@keyframes sube { from { opacity: 0; transform: translateY(8px); } to { opacity: 1; transform: none; } }
|
||
}
|
||
|
||
/* ---------------------------------------------------------------------
|
||
Utilidades
|
||
--------------------------------------------------------------------- */
|
||
|
||
.prosa { max-width: 76ch; }
|
||
.nowrap { white-space: nowrap; }
|
||
.fila { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; }
|
||
.fila--sep { justify-content: space-between; }
|
||
/* Botones que van juntos en una celda estrecha: no se parten en dos renglones. */
|
||
.fila--junta { flex-wrap: nowrap; gap: 7px; }
|
||
.crece { flex: 1; min-width: 0; }
|
||
.tenue { color: var(--gris); }
|
||
.mini { font-size: 15px; }
|
||
.recorte { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
|
||
/* Texto solo para lectores de pantalla. Sin position:absolute a propósito:
|
||
dentro de una tabla con scroll horizontal, un absoluto sin ancestro
|
||
posicionado se cuelga del bloque inicial, se escapa del contenedor y
|
||
estira la página entera. Esta versión se queda en el flujo. */
|
||
.solo-lectores {
|
||
display: inline-block;
|
||
width: 1px; height: 1px; margin: -1px; padding: 0; border: 0;
|
||
overflow: hidden; white-space: nowrap;
|
||
clip-path: inset(50%);
|
||
}
|
||
|
||
/* Una pista que solo tiene sentido cuando la tabla se desliza. */
|
||
.solo-movil { display: none; }
|
||
@media (max-width: 780px) { .solo-movil { display: block; } }
|
||
.tira-demo {
|
||
display: inline-flex; align-items: center; gap: 7px;
|
||
font-size: 13px; font-weight: 700; text-transform: uppercase; letter-spacing: .07em;
|
||
padding: 4px 12px; border-radius: var(--radio-pill);
|
||
background: color-mix(in srgb, var(--marca) 32%, transparent);
|
||
color: #4a4300; border: 1px solid color-mix(in srgb, var(--marca) 60%, transparent);
|
||
}
|
||
|
||
@media print {
|
||
.barra, .tope, .cabecera-seccion__acciones, .brindis, .acciones-edicion, .vista-alterna { display: none !important; }
|
||
.portal { grid-template-columns: 1fr; }
|
||
.placa, .respuesta { break-inside: avoid; box-shadow: none; }
|
||
.respuesta { background: #fff; color: #000; border: 2px solid #000; }
|
||
.respuesta h2, .respuesta__cifra b, .respuesta p, .respuesta .ceja { color: #000; }
|
||
details.acordeon > summary::after { display: none; }
|
||
.acordeon__cuerpo { display: block !important; }
|
||
}
|