/* PsicoPlan — estilos
   Orden: tokens · base · header · "Cómo se lee" · pestañas de año · plan · tarjetas · líneas · barra inferior
          · bottom sheet · tooltip · pantallas táctiles · móvil · movimiento */

/* ---------- Tokens ---------- */

:root {
  color-scheme: light;

  /* Colores por año (fijos en los dos temas) */
  --year-1: #16a34a;
  --year-2: #2563eb;
  --year-3: #db2777;
  --year-4: #ea580c;
  --year-5: #7c3aed;
  /* Relleno con número blanco (chips y contadores). Verde y naranja van un tono más oscuro
     para que el blanco llegue a contraste AA (4.5:1); los otros tres ya llegan con su color. */
  --year-1-fill: #15803d;
  --year-4-fill: #c2410c;
  --promo-bg: #facc15;
  --promo-ink: #422006;

  /* Superficies y texto */
  --bg: #f4f5f7;
  --surface: #ffffff;
  --column: #eceef2;
  --border: #dde1e7;
  --border-strong: #b8c0cc;
  --ink: #0f172a;
  --muted: #566070;
  --accent: #1d4ed8;
  --focus: #2563eb;
  --shadow: 0 1px 2px rgb(15 23 42 / 0.06), 0 4px 12px rgb(15 23 42 / 0.06);
  /* Fondo de las tarjetas sin relación: a mitad de camino entre la tarjeta y la columna. */
  --dim-bg: color-mix(in srgb, var(--surface) 45%, var(--column));
  --mark-w: 5px;
  /* Tono del texto de color por año: se oscurece en claro y se aclara en oscuro.
     En claro, 25% es lo mínimo para que el verde y el naranja lleguen a AA sobre el fondo de la columna. */
  --year-tint: black;
  --year-tint-amount: 25%;

  /* Medidas. El alto de las tarjetas se calcula con estas (ver .plan). */
  --header-h: 52px;
  --bar-h: 56px;
  --plan-pad-y: 12px;
  /* Margen de los costados: 16px, o más si el notch del celular acostado ocupa ese lugar. */
  --safe-x: max(env(safe-area-inset-left, 0px), env(safe-area-inset-right, 0px));
  --plan-pad-x: max(16px, var(--safe-x));
  --col-gap: 12px;
  --col-pad: 8px;
  --col-min: 210px;
  --col-max: 320px;
  --head-h: 24px;
  /* Título de sección: 24px en ventanas bajas (650px de alto) y hasta 31px en las altas,
     donde las tarjetas ya llegaron a su máximo y sobra lugar al pie de la columna. */
  --term-h: clamp(24px, var(--vh) * 0.05 - 8px, 31px);
  --gap: 4px;
  /* Hasta 54px solo si sobra alto (ventanas altas): ahí el nombre usa 3 renglones (ver .card). */
  --card-min: 30px;
  --card-max: 54px;
  --touch: 44px; /* área mínima de lo que se toca en el celular */
  --tabs-h: 0px; /* pestañas de año: solo en el celular */
  --vh: 100vh;
}

@supports (height: 100dvh) {
  :root { --vh: 100dvh; }
}

:root[data-theme="dark"] {
  color-scheme: dark;
  --bg: #0b0f17;
  --surface: #161c27;
  --column: #10151f;
  --border: #262e3c;
  --border-strong: #46516a;
  --ink: #e6eaf1;
  --muted: #9aa4b5;
  --accent: #93c5fd;
  --focus: #93c5fd;
  --shadow: 0 1px 2px rgb(0 0 0 / 0.4);
  --year-tint: white;
  --year-tint-amount: 35%;
}

/* Cualquier elemento con data-year toma el color de su año: --year (franjas, bordes, líneas),
   --year-fill (fondos con número blanco) y --year-ink (texto de color). */
[data-year] {
  --year-fill: var(--year);
  --year-ink: color-mix(in srgb, var(--year), var(--year-tint) var(--year-tint-amount));
}
[data-year="1"] { --year: var(--year-1); --year-fill: var(--year-1-fill); }
[data-year="2"] { --year: var(--year-2); }
[data-year="3"] { --year: var(--year-3); }
[data-year="4"] { --year: var(--year-4); --year-fill: var(--year-4-fill); }
[data-year="5"] { --year: var(--year-5); }

/* ---------- Base ---------- */

*, *::before, *::after { box-sizing: border-box; }

html {
  background: var(--bg);
  /* Lo que se trae a la vista (foco, saltos) no queda debajo de las pestañas ni del sheet del celular.
     --sheet-cover lo mide app.js. */
  scroll-padding-top: var(--tabs-h);
  scroll-padding-bottom: var(--sheet-cover, 0px);
}

body {
  margin: 0;
  min-height: var(--vh);
  display: flex;
  flex-direction: column;
  background: var(--bg);
  color: var(--ink);
  font-family: Inter, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Arial, sans-serif;
  font-size: 14px;
  line-height: 1.4;
  -webkit-font-smoothing: antialiased;
}

button { font: inherit; color: inherit; }

:focus-visible { outline: 2px solid var(--focus); outline-offset: 2px; }

.sr-only {
  position: absolute;
  width: 1px;
  height: 1px;
  margin: -1px;
  padding: 0;
  overflow: hidden;
  clip: rect(0 0 0 0);
  white-space: nowrap;
  border: 0;
}

.code-chip {
  display: inline-grid;
  place-items: center;
  flex: none;
  min-width: 26px;
  height: 22px;
  padding: 0 4px;
  border-radius: 6px;
  background: var(--year-fill);
  color: #fff;
  font-size: 11px;
  font-weight: 800;
  font-variant-numeric: tabular-nums;
  line-height: 1;
}

.promo-badge {
  display: inline-grid;
  place-items: center;
  flex: none;
  width: 16px;
  height: 16px;
  border-radius: 50%;
  background: var(--promo-bg);
  color: var(--promo-ink);
  font-size: 9.5px;
  font-weight: 800;
  line-height: 1;
}

.promo-tag {
  padding: 2px 8px;
  border-radius: 999px;
  background: var(--promo-bg);
  color: var(--promo-ink);
  font-size: 11px;
  font-weight: 700;
  white-space: nowrap;
}

/* ---------- Header ---------- */

.site-header {
  position: relative;
  z-index: 20;
  flex: none;
  height: var(--header-h);
  display: grid;
  /* Costados iguales para que el título quede centrado aunque a la derecha haya dos botones. */
  grid-template-columns: 1fr minmax(0, max-content) 1fr;
  align-items: center;
  gap: 12px;
  padding: 0 var(--plan-pad-x);
  background: var(--surface);
  border-bottom: 1px solid var(--border);
}

.identity { min-width: 0; text-align: center; }

.identity-title {
  margin: 0;
  overflow: hidden;
  font-size: 16px;
  font-weight: 700;
  line-height: 1.2;
  white-space: nowrap;
  text-overflow: ellipsis;
}

.identity-sep { color: var(--muted); }
.identity-degree { color: var(--accent); }

.icon-btn {
  display: grid;
  place-items: center;
  width: 34px;
  height: 34px;
  padding: 0;
  border: 1px solid var(--border);
  border-radius: 8px;
  background: var(--surface);
  font-size: 15px;
  font-weight: 700;
  cursor: pointer;
}

/* Los hover van solo con mouse: en pantallas táctiles quedan pegados en lo último que se tocó. */
@media (hover: hover) { .icon-btn:hover { border-color: var(--border-strong); } }

.header-actions {
  justify-self: end;
  display: flex;
  gap: 8px;
}

.lines-toggle[aria-pressed="true"] {
  border-color: color-mix(in srgb, var(--accent) 50%, var(--border));
  background: color-mix(in srgb, var(--accent) 10%, var(--surface));
  color: var(--accent);
}

.lines-toggle[aria-pressed="false"] { color: var(--muted); }

.icon-curve { fill: none; stroke: currentColor; stroke-width: 2; stroke-linecap: round; }
.icon-head { fill: currentColor; }

/* ---------- "Cómo se lee" ---------- */

.help-popover {
  position: absolute;
  top: calc(100% + 8px);
  left: var(--plan-pad-x);
  width: min(300px, calc(100vw - 2 * var(--plan-pad-x)));
  padding: 14px 16px;
  border: 1px solid var(--border);
  border-radius: 12px;
  background: var(--surface);
  box-shadow: var(--shadow);
}

.help-title { margin: 0 0 10px; font-size: 13px; font-weight: 800; }

.help-flow {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 6px;
  margin-bottom: 12px;
  font-size: 11px;
  font-weight: 700;
  color: var(--muted);
  text-transform: uppercase;
  letter-spacing: 0.04em;
}

.help-arrow { color: var(--muted); font-size: 14px; }

.help-subject {
  padding: 5px 10px;
  border: 1px solid var(--border-strong);
  border-radius: 8px;
  background: var(--surface);
  color: var(--ink);
  text-transform: none;
  letter-spacing: 0;
}

.help-row {
  display: flex;
  align-items: center;
  gap: 8px;
  margin: 6px 0 0;
  font-size: 12.5px;
}

.help-legend {
  --year: var(--muted);
  --year-ink: var(--ink);
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 8px 12px;
  margin: 12px 0 0;
  padding: 12px 0 0;
  border-top: 1px solid var(--border);
  list-style: none;
  font-size: 12px;
}

.help-legend li { display: flex; align-items: center; gap: 8px; }

.legend-swatch {
  flex: none;
  display: flex;
  align-items: center;
  justify-content: flex-end;
  width: 34px;
  height: 18px;
  padding: 0 5px;
  border: 1px solid var(--border-strong);
  border-radius: 5px;
  background: var(--surface);
}

.legend-swatch.rel-requires::before { border-radius: 0 5px 5px 0; }
.legend-swatch.rel-enables::before { border-radius: 5px 0 0 5px; }
.legend-swatch.rel-enables { justify-content: flex-start; }
.legend-swatch .rel-icon { font-size: 12px; }
/* La tarjeta apagada no tiene borde; acá sí, para que se vea sobre el fondo blanco del cartel. */
.legend-swatch.is-dim { border-color: var(--border); }

.legend-link { flex: none; display: flex; width: 34px; height: 18px; }

.help-note { color: var(--muted); font-size: 11.5px; }

/* ---------- Pestañas de año (móvil) ----------
   Se muestran solo en el celular (ver "Móvil"). Las arma app.js: llevan al año, marcan el que se ve
   (aria-current) y, con una materia elegida, cuántas relacionadas hay en cada año. */

.year-tabs { display: none; }

.year-tab {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 4px;
  min-width: 0;
  height: var(--tabs-h);
  padding: 0;
  border: 0;
  background: transparent;
  color: var(--muted);
  font-size: 14px;
  font-weight: 700;
  white-space: nowrap;
  cursor: pointer;
}

/* Raya del color del año debajo de la pestaña activa (va como fondo para no sumar alto). */
.year-tab[aria-current="true"] {
  background: linear-gradient(var(--year), var(--year)) bottom / 100% 3px no-repeat;
  color: var(--year-ink);
}

.year-tab-count {
  min-width: 16px;
  height: 16px;
  padding: 0 4px;
  border-radius: 999px;
  background: var(--year-fill);
  color: #fff;
  font-size: 10px;
  font-weight: 800;
  font-variant-numeric: tabular-nums;
  line-height: 16px;
}

.year-tab-count:empty { display: none; }

/* ---------- Plan ---------- */

.workspace {
  flex: 1 0 auto;
  display: flex;
  flex-direction: column;
  min-width: 0;
}

.plan-viewport {
  position: relative;
  flex: 1 0 auto;
}

/* Degradés que avisan que hay más años hacia un costado. */
.plan-viewport::before,
.plan-viewport::after {
  content: "";
  position: absolute;
  top: 0;
  bottom: var(--sbh, 0px);
  z-index: 2;
  width: 36px;
  opacity: 0;
  pointer-events: none;
}

.plan-viewport::before { left: 0; background: linear-gradient(to right, var(--bg), transparent); }
.plan-viewport::after { right: 0; background: linear-gradient(to left, var(--bg), transparent); }
.plan-viewport.can-scroll-left::before,
.plan-viewport.can-scroll-right::after { opacity: 1; }

.plan-scroller {
  overflow-x: auto;
  overflow-y: hidden;
  overscroll-behavior-x: contain;
  scroll-snap-type: x mandatory;
  scroll-padding-inline: var(--plan-pad-x);
}

/* Lo alto siempre entra: el alto de tarjeta reparte lo que queda de la ventana
   entre las filas de la columna más larga (--rows y --terms los pone app.js desde DATA).
   Lo ancho, si no entra, se desliza: min-width obliga el scroll horizontal. */
.plan {
  --card-h: clamp(
    var(--card-min),
    (var(--vh) - var(--header-h) - var(--bar-h) - var(--sbh, 0px)
      - 2 * var(--plan-pad-y) - 2 * var(--col-pad) - 2px
      - var(--head-h) - var(--terms, 2) * var(--term-h)
      - (var(--rows, 12) - var(--terms, 2)) * var(--gap)) / var(--rows, 12),
    var(--card-max)
  );
  display: grid;
  grid-template-columns: repeat(5, minmax(0, 1fr));
  gap: var(--col-gap);
  width: 100%;
  min-width: calc(5 * var(--col-min) + 4 * var(--col-gap) + 2 * var(--plan-pad-x));
  max-width: calc(5 * var(--col-max) + 4 * var(--col-gap) + 2 * var(--plan-pad-x));
  margin-inline: auto;
  padding: var(--plan-pad-y) var(--plan-pad-x);
  /* Referencia de la capa de líneas. isolation encierra acá los z-index de líneas y tarjetas,
     así todo el plan queda debajo de los degradés de los costados. */
  position: relative;
  isolation: isolate;
}

.year {
  min-width: 0;
  padding: var(--col-pad);
  border: 1px solid var(--border);
  border-radius: 12px;
  /* La franja de color va como fondo para no sumar alto. */
  background: linear-gradient(var(--year), var(--year)) top / 100% 3px no-repeat, var(--column);
  scroll-snap-align: start;
}

.year-title {
  height: var(--head-h);
  margin: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  color: var(--year-ink);
  font-size: 13px;
  font-weight: 800;
  letter-spacing: 0.06em;
  text-transform: uppercase;
}

/* Título de la sección (Anual, 1º y 2º Cuatrimestre): en el color del año, un poco más suave que el
   título de la columna, con una línea fina que marca dónde empieza cada bloque. Entra en --term-h,
   con el texto centrado: el mismo espacio arriba (bloque anterior) que abajo (su primera tarjeta). */
.term-title {
  height: var(--term-h);
  margin: 0;
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 0 2px;
  color: color-mix(in srgb, var(--year-ink) 80%, var(--muted));
  font-size: 12.5px;
  font-weight: 700;
  line-height: 1;
  white-space: nowrap;
}

.term-title::after {
  content: "";
  flex: 1;
  height: 1px;
  background: color-mix(in srgb, var(--year) 35%, transparent);
}

.cards {
  display: grid;
  gap: var(--gap);
  margin: 0;
  padding: 0;
  list-style: none;
}

.cards li { min-width: 0; }

/* ---------- Tarjetas ---------- */

.card {
  position: relative;
  z-index: 1; /* sobre la capa de líneas */
  display: flex;
  align-items: center;
  gap: 8px;
  width: 100%;
  height: var(--card-h);
  padding: 0 8px 0 6px;
  border: 1px solid var(--border);
  border-radius: 8px;
  background: var(--surface);
  text-align: left;
  cursor: pointer;
  /* La tarjeta es contenedor: el nombre sabe cuánto mide para decidir si usa 2 o 3 renglones. */
  container-type: size;
}

@media (hover: hover) { .card:hover { border-color: var(--border-strong); } }

.card-name {
  display: -webkit-box;
  overflow: hidden;
  -webkit-box-orient: vertical;
  -webkit-line-clamp: 2;
  line-clamp: 2;
  font-size: clamp(11px, var(--card-h) * 0.3, 13px);
  flex: 1 1 auto;
  min-width: 0;
  font-weight: 550;
  line-height: 1.15;
}

/* Tarjeta de 50px o más (ventanas altas, donde sobra lugar al pie): 3 renglones de 13px ocupan 45px. */
@container (min-height: 48px) {
  .card-name { -webkit-line-clamp: 3; line-clamp: 3; }
}

.rel-icon {
  flex: none;
  display: flex;
  align-items: baseline;
  color: var(--year-ink);
  font-size: 14px;
  font-weight: 800;
  line-height: 1;
  white-space: nowrap;
}

.rel-icon:empty { display: none; }

.rel-steps {
  margin: 0 1px;
  font-size: 11px;
  font-variant-numeric: tabular-nums;
}

/* ---------- Resaltado por relación ----------
   El plan se lee requerida → seleccionada → habilitada. La marca va del lado por donde la tarjeta
   se conecta con la seleccionada, y la flecha señala hacia ella:
   requerida, franja a la derecha y "→" al final (la seleccionada está a su derecha);
   habilitada, franja a la izquierda y "←" al principio (la seleccionada está a su izquierda).
   Directa: tarjeta llena, número relleno y franja gruesa lisa.
   Indirecta: tarjeta "hueca" (sin fondo, número con contorno, como en la barra inferior), franja fina
   punteada y la cantidad de pasos junto a la flecha (2→, ←2). A 3 o 4 pasos (data-steps) la franja se
   aclara y el nombre pasa a gris; el texto no se hace transparente, para que siga cumpliendo AA.
   Sin relación: fondo plano, sin borde, número y texto en gris (se ven apagadas, pero se leen).
   Las mismas clases dibujan las muestras de "Cómo se lee". */

.card.is-selected {
  border-color: var(--year);
  background: color-mix(in srgb, var(--year) 9%, var(--surface));
  box-shadow: 0 0 0 2px var(--year), 0 6px 16px -4px color-mix(in srgb, var(--year) 60%, transparent);
}

.is-dim {
  border-color: transparent;
  background: var(--dim-bg);
  color: var(--muted);
}

.card.is-dim .code-chip,
.card.is-dim .promo-badge {
  background: var(--border);
  color: var(--muted);
}

.rel-requires,
.rel-enables { position: relative; }

.rel-requires::before,
.rel-enables::before {
  content: "";
  position: absolute;
  top: -1px;
  bottom: -1px;
  border: 0 solid var(--year);
}

.rel-requires::before { right: -1px; border-right-width: var(--mark-w); border-radius: 0 8px 8px 0; }
.rel-enables::before { left: -1px; border-left-width: var(--mark-w); border-radius: 8px 0 0 8px; }
.rel-enables .rel-icon { order: -1; }
.rel-indirect::before { --mark-w: 3px; border-style: dotted; }

.rel-indirect {
  border-style: dashed;
  border-color: var(--border-strong);
  background: transparent;
}

.card.rel-indirect .code-chip {
  background: transparent;
  color: var(--year-ink);
  box-shadow: inset 0 0 0 1.5px var(--year);
}

.card[data-steps="3"]::before { opacity: 0.7; }
.card[data-steps="4"]::before { opacity: 0.5; }
.card[data-steps="3"] .card-name,
.card[data-steps="4"] .card-name { color: var(--muted); }

/* ---------- Líneas de correlatividad ----------
   Función hecha pero oculta: se prende con LINES_ENABLED en app.js, que pone data-lines-feature en <html>.
   Solo las directas de la seleccionada, por debajo de las tarjetas (z-index 0 contra 1): entre años
   vecinos quedan en el pasillo; las que saltan un año se ven a través de las tarjetas apagadas y se
   esconden detrás de las resaltadas.
   Cada línea toma el color de la otra materia (data-year), como continuación de su marca.
   No ocupa lugar: está superpuesta al plan y no suma alto. */

:root:not([data-lines-feature]) .lines-feature { display: none; }

.links {
  position: absolute;
  top: 0;
  left: 0;
  z-index: 0;
  width: 100%;
  height: 100%;
  pointer-events: none;
}

.link-line { fill: none; stroke: var(--year); stroke-width: 2; }
.link-head { fill: var(--year); }

/* ---------- Barra inferior ---------- */

.bottom-bar {
  position: sticky;
  bottom: 0;
  z-index: 10;
  flex: none;
  height: var(--bar-h);
  display: flex;
  align-items: center;
  gap: 16px;
  padding: 0 var(--plan-pad-x);
  border-top: 1px solid var(--border);
  background: var(--surface);
}

.context-bar {
  flex: 1;
  min-width: 0;
  height: 100%;
  display: flex;
  align-items: center;
  gap: 20px;
}

.context-hint { margin: 0; color: var(--muted); font-size: 13px; }

.context-flow {
  position: relative; /* referencia de offsetLeft para centrar la materia */
  flex: 1;
  min-width: 0;
  height: 100%;
  display: flex;
  align-items: center;
  gap: 12px;
  /* 3px a los costados para que no se corte el anillo de la materia cuando queda en una punta. */
  padding-inline: 3px;
  overflow-x: auto;
  scrollbar-width: thin;
}

.context-side {
  flex: none;
  display: flex;
  align-items: center;
  gap: 20px;
}

.context-side:empty { display: none; }

.flow-arrow {
  flex: none;
  color: var(--muted);
  font-size: 16px;
  font-weight: 800;
  line-height: 1;
}

.context-bar.no-relations .flow-arrow { display: none; }

/* La materia elegida, destacada como su tarjeta en la columna: borde, fondo y anillo del color del año
   (sin la sombra de abajo, que la barra cortaría). 502px: con el número, la etiqueta "Promocionable"
   y los márgenes del recuadro, el nombre más largo (26) entra en 2 renglones.
   Alto: si el flujo no entra a lo ancho, su barra de scroll deja 44px visibles; el recuadro con 2 renglones
   y el anillo mide 43, así que no hay que sumarle margen vertical ni alto de renglón. */
.context-selected {
  flex: none;
  max-width: 502px;
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 3px 10px;
  border: 1px solid var(--year);
  border-radius: 8px;
  background: color-mix(in srgb, var(--year) 9%, var(--surface));
  box-shadow: 0 0 0 2px var(--year);
}

/* Hasta 2 renglones: en la computadora es el único lugar donde se lee completo un nombre cortado en su tarjeta. */
.context-name {
  display: -webkit-box;
  min-width: 0;
  overflow: hidden;
  -webkit-box-orient: vertical;
  -webkit-line-clamp: 2;
  line-clamp: 2;
  font-size: 13.5px;
  font-weight: 700;
  line-height: 1.15;
}

.context-bar:not(.has-selection) .context-flow,
.context-bar.has-selection .context-hint { display: none; }

.context-group {
  flex: none;
  display: flex;
  align-items: center;
  gap: 6px;
}

.context-label {
  color: var(--muted);
  font-size: 10.5px;
  font-weight: 700;
  letter-spacing: 0.05em;
  text-transform: uppercase;
}

.context-items { display: flex; gap: 4px; }

.context-empty,
.context-none { color: var(--muted); font-size: 13px; }

.chip {
  min-width: 28px;
  height: 26px;
  padding: 0 6px;
  border: 1.5px solid var(--year-fill);
  border-radius: 6px;
  background: var(--year-fill);
  color: #fff;
  font-size: 11.5px;
  font-weight: 800;
  font-variant-numeric: tabular-nums;
  cursor: pointer;
}

.chip.is-indirect { background: transparent; color: var(--year-ink); }
@media (hover: hover) { .chip:hover { filter: brightness(1.12); } }

.credit {
  flex: none;
  margin: 0;
  color: var(--muted);
  font-size: 10.5px;
  font-weight: 700;
  letter-spacing: 0.08em;
  white-space: nowrap;
}

/* ---------- Bottom sheet (móvil) ---------- */

.sheet { display: none; }

.sheet-bar {
  display: grid;
  grid-template-columns: auto minmax(0, 1fr) auto auto;
  grid-template-areas:
    "code name toggle close"
    "summary summary summary summary";
  align-items: center;
  gap: 2px 10px;
  padding: 6px 4px 6px 14px;
  cursor: pointer;
}

.sheet-code { grid-area: code; }

.sheet-name {
  grid-area: name;
  overflow: hidden;
  font-size: 14px;
  font-weight: 700;
  white-space: nowrap;
  text-overflow: ellipsis;
}

/* Expandido hay lugar: el nombre se ve completo. */
.sheet.expanded .sheet-name { white-space: normal; }

.sheet-summary {
  grid-area: summary;
  min-width: 0;
  overflow: hidden;
  padding-bottom: 4px;
  color: var(--muted);
  font-size: 12px;
  font-weight: 600;
  white-space: nowrap;
  text-overflow: ellipsis;
}

.sheet-btn {
  display: grid;
  place-items: center;
  width: var(--touch);
  height: var(--touch);
  padding: 0;
  border: 0;
  border-radius: 10px;
  background: transparent;
  font-size: 22px;
  line-height: 1;
  cursor: pointer;
}

.sheet-toggle { grid-area: toggle; }
.sheet-close { grid-area: close; }

.sheet-chevron {
  width: 10px;
  height: 10px;
  border-top: 2px solid currentColor;
  border-left: 2px solid currentColor;
  transform: translateY(2px) rotate(45deg);
}

.sheet.expanded .sheet-chevron { transform: translateY(-2px) rotate(225deg); }

.sheet-body {
  max-height: 0;
  overflow: hidden;
  padding: 0 14px;
}

.sheet.expanded .sheet-body {
  max-height: min(65vh, 560px);
  overflow-y: auto;
  padding-bottom: 16px;
}

.panel-meta { display: flex; flex-wrap: wrap; gap: 6px; margin-bottom: 4px; }

.meta-tag {
  padding: 2px 8px;
  border: 1px solid var(--border);
  border-radius: 999px;
  color: var(--muted);
  font-size: 11px;
  font-weight: 700;
}

.meta-tag[data-year] { border-color: var(--year); color: var(--year-ink); }

.rel-title {
  margin: 14px 0 6px;
  color: var(--muted);
  font-size: 11px;
  font-weight: 800;
  letter-spacing: 0.05em;
  text-transform: uppercase;
}

.rel-count { margin-left: 4px; color: var(--ink); }

.rel-none {
  margin-left: 6px;
  color: var(--muted);
  font-weight: 600;
  letter-spacing: 0;
  text-transform: none;
}

.rel-list:not([hidden]) { display: grid; gap: 6px; }

.rel {
  display: grid;
  grid-template-columns: auto minmax(0, 1fr) auto;
  align-items: center;
  gap: 10px;
  min-height: var(--touch);
  padding: 6px 10px;
  border: 1px solid var(--border);
  border-radius: 8px;
  background: var(--surface);
  text-align: left;
  cursor: pointer;
}

.rel.is-indirect .code-chip { background: transparent; color: var(--year-ink); box-shadow: inset 0 0 0 1.5px var(--year); }
.rel-name { font-size: 13px; font-weight: 600; }
.hop { color: var(--muted); font-size: 11px; white-space: nowrap; }

.panel-no-relations { margin: 14px 0 0; color: var(--muted); }

/* Nota sobre directas e indirectas: cerrada por defecto, una línea que se despliega. */
.panel-note {
  margin: 12px 0 0;
  color: var(--muted);
  font-size: 12px;
  line-height: 1.45;
}

.panel-note summary {
  display: flex;
  align-items: center;
  gap: 8px;
  min-height: var(--touch);
  font-weight: 600;
  list-style: none;
  cursor: pointer;
}

.panel-note summary::-webkit-details-marker { display: none; }

/* La misma flecha del botón de expandir el sheet: abajo cerrada, arriba abierta. */
.panel-note summary::after {
  content: "";
  width: 7px;
  height: 7px;
  border-right: 2px solid currentColor;
  border-bottom: 2px solid currentColor;
  transform: translateY(-2px) rotate(45deg);
}

.panel-note[open] summary::after { transform: translateY(2px) rotate(225deg); }

.panel-note p { margin: 0 0 8px; }
.panel-note strong { color: var(--ink); }

/* ---------- Tooltip ---------- */

.tooltip {
  position: fixed;
  z-index: 50;
  max-width: 280px;
  padding: 6px 10px;
  border: 1px solid var(--border-strong);
  border-radius: 8px;
  background: var(--surface);
  box-shadow: var(--shadow);
  color: var(--ink);
  font-size: 12px;
  font-weight: 600;
  line-height: 1.3;
  pointer-events: none;
}

.tooltip-meta { display: block; margin-top: 2px; color: var(--muted); font-weight: 500; }

/* ---------- Pantallas táctiles ----------
   Sobre todo tablets, que usan el modo computadora: lo que se toca mide 44px de alto (--touch), aunque se
   vea igual. Los chips de la barra inferior se ven de 26px y se tocan en 44: un área invisible que crece
   por arriba y por abajo (a los costados no, para no pisar al chip de al lado).
   En el celular la barra no se muestra y los botones ya miden 44px (ver "Móvil"). */

@media (pointer: coarse) {
  .icon-btn { width: var(--touch); height: var(--touch); }
  .chip { position: relative; }
  .chip::after {
    content: "";
    position: absolute;
    top: 50%;
    right: 0;
    left: 0;
    height: var(--touch);
    translate: 0 -50%;
  }
}

/* ---------- Móvil ----------
   Celular parado (hasta 760px de ancho) o acostado (hasta 500px de alto). La misma condición está en
   mobileQuery de app.js: si se cambia acá, hay que cambiarla allá.
   Un año por pantalla, con pestañas para saltar entre años. A diferencia de la computadora, la página
   puede bajar: las tarjetas toman el alto que pide el nombre (completo, sin "…") y miden 48px o más.
   Todo lo que se toca mide 44px o más. La cuenta de --card-h no se usa acá. */

@media (max-width: 760px), (max-height: 500px) {
  :root {
    /* Cada año ocupa el ancho visible menos los márgenes. El % lo resuelve .plan (min-width y max-width)
       contra el ancho del área que se desliza. */
    --col-min: calc(100% - 2 * var(--plan-pad-x));
    --col-max: var(--col-min);
    --card-min: 48px;
    --gap: 6px;
    --tabs-h: 44px;
    --term-h: 36px;
  }

  button { -webkit-tap-highlight-color: transparent; }

  /* Lugar al final de la página para el sheet contraído, así no tapa las últimas tarjetas (lo mide app.js). */
  body { padding-bottom: var(--sheet-rest, 0px); }

  /* Costados y espacios más chicos que en la computadora, para darle lugar al título. */
  .site-header {
    height: auto;
    gap: 4px;
    padding: 8px max(12px, var(--safe-x));
  }

  .icon-btn { width: var(--touch); height: var(--touch); }

  /* Título en dos renglones para que no se corte: institución y carrera arriba, plan abajo.
     Por debajo de unos 370px de ancho la letra se achica para que entre el primer renglón
     (a 14px mide unos 243px y al lado van los dos botones; queda lugar para ancho - 120px). */
  .identity-title { font-size: min(14px, calc(5.75vw - 7.3px)); }
  .identity-sep-break { display: none; }
  .identity-line,
  .identity-plan { display: block; overflow: hidden; text-overflow: ellipsis; }
  .identity-plan { margin-top: 5px; color: var(--muted); font-size: 13px; font-weight: 600; }

  /* No se dibujan líneas (drawLinks no corre en el celular). */
  .lines-toggle { display: none; }

  .year-tabs {
    position: sticky;
    top: 0;
    z-index: 15;
    display: grid;
    grid-template-columns: repeat(5, minmax(0, 1fr));
    padding-inline: var(--safe-x);
    background: var(--surface);
    box-shadow: 0 1px 0 var(--border);
  }

  /* Con el plan deslizado, el degradé cubre solo el margen y deja ver entera la tarjeta (su P y su →). */
  .plan-viewport::before,
  .plan-viewport::after { width: var(--plan-pad-x); }

  /* Un deslizamiento rápido no se saltea años. */
  .year { scroll-snap-stop: always; }

  .term-title { font-size: 13px; }

  /* El alto lo da el nombre: la tarjeta deja de ser contenedor de tamaño (si no, no crecería con el texto). */
  .card {
    height: auto;
    min-height: var(--card-min);
    padding-block: 6px;
    container-type: normal;
  }

  .card-name {
    display: block;
    overflow: visible;
    -webkit-line-clamp: none;
    line-clamp: none;
    font-size: 14px;
    line-height: 1.25;
  }

  .context-bar { display: none; }

  .bottom-bar {
    position: static;
    height: auto;
    justify-content: center;
    padding-block: 10px calc(10px + env(safe-area-inset-bottom, 0px));
  }

  .sheet {
    display: block;
    position: fixed;
    right: 0;
    bottom: 0;
    left: 0;
    z-index: 40;
    padding: 0 env(safe-area-inset-right, 0px) env(safe-area-inset-bottom, 0px) env(safe-area-inset-left, 0px);
    border-top: 1px solid var(--border);
    border-radius: 16px 16px 0 0;
    background: var(--surface);
    box-shadow: 0 -8px 24px rgb(0 0 0 / 0.14);
    transform: translateY(100%);
    visibility: hidden;
  }

  .sheet.open { transform: none; visibility: visible; }
}

/* ---------- Movimiento ---------- */

@media (prefers-reduced-motion: no-preference) {
  .card { transition: background-color 0.15s ease, border-color 0.15s ease, box-shadow 0.15s ease, color 0.15s ease; }
  .plan-viewport::before,
  .plan-viewport::after { transition: opacity 0.2s ease; }
  .sheet { transition: transform 0.22s ease, visibility 0.22s; }
}
