:root {
  color-scheme: light dark;

  --bg: #fbfaf7;
  --surface: #ffffff;
  --surface-2: #f0efe6;
  --line: #e2e0d5;
  --fg: #1c2321;
  --muted: #5c6864;

  --accent: #2f6b5e;
  --accent-fg: #245a4e;
  --accent-tint: #eaf3f0;
  --accent-line: #bfdcd2;

  --urgent-fg: #9c2f18;
  --urgent-tint: #fbeeea;
  --urgent-line: #e8b8a8;
  --urgent-accent: #b3432d;
  --urgent-on-accent: #fff7f5;

  --high-fg: #7a5310;
  --high-tint: #faf1de;
  --high-line: #e3cd9c;
  --high-accent: #b3822d;

  --focus: #245a4e;

  /* 4px spacing scale. */
  --s1: 0.25rem;
  --s2: 0.5rem;
  --s3: 0.75rem;
  --s4: 1rem;
  --s5: 1.5rem;
  --s6: 2rem;
  --s7: 3rem;

  --r-card: 14px;
  --gutter: var(--s4);

  /* No light source in dark mode — the border carries the card, not a shadow. */
  --shadow-card: 0 1px 2px rgb(16 24 40 / 0.04), 0 1px 3px rgb(16 24 40 / 0.06);
}

@media (prefers-color-scheme: dark) {
  :root {
    --bg: #12181a;
    --surface: #1a2123;
    --surface-2: #212a2c;
    --line: #2a3234;
    --fg: #e8ebf0;
    --muted: #9fa9b8;

    --accent: #7cc7b0;
    --accent-fg: #7cc7b0;
    --accent-tint: #16241f;
    --accent-line: #2d4a40;

    --urgent-fg: #ff9c82;
    --urgent-tint: #2b1712;
    --urgent-line: #5d3226;
    --urgent-accent: #ff7d55;
    --urgent-on-accent: #1a0d08;

    --high-fg: #e0b866;
    --high-tint: #2a2313;
    --high-line: #574a20;
    --high-accent: #d9a53f;

    --focus: #7cc7b0;
    --shadow-card: none;
  }
}

@media (min-width: 40rem) {
  :root { --gutter: var(--s6); }
  .equipo-tabla { font-size: 0.9375rem; }
  .equipo-tabla th, .equipo-tabla td { padding: var(--s3) var(--s4); }
}

* { box-sizing: border-box; }
html { -webkit-text-size-adjust: 100%; }
body {
  margin: 0;
  background: var(--bg);
  color: var(--fg);
  font-family: system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
  font-size: 1rem;
  line-height: 1.5;
}

/* ── Layout ─────────────────────────────────────────────────────────────── */
.envolvente { max-width: 42rem; margin: 0 auto; padding: var(--s6) var(--gutter) var(--s7); }

/* ── Header ─────────────────────────────────────────────────────────────── */
.cabecera { display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between; gap: var(--s2) var(--s3); margin-bottom: var(--s5); }
.ref {
  margin: 0;
  font-size: clamp(1.375rem, 1.1rem + 1.5vw, 1.75rem);
  line-height: 1.2;
  font-weight: 700;
  letter-spacing: -0.015em;
  font-variant-numeric: tabular-nums;
  text-wrap: balance;
}
/* Full-width within the wrapping header row — sits under the title, never
   beside it, whether or not badges are present. */
.sub { flex-basis: 100%; margin: var(--s2) 0 0; color: var(--muted); font-size: 0.9375rem; }
.insignias { display: flex; align-items: center; gap: var(--s2); flex-wrap: wrap; }

/* The lista/obra "ver completados" toggle — a plain link, not a button: it's
   a mode switch for the whole page, not an action taken on anything in it. */
.filtro-toggle { margin: calc(-1 * var(--s3)) 0 var(--s4); font-size: 0.875rem; }
.enlace-filtro { color: var(--accent-fg); font-weight: 600; text-decoration: none; }
.enlace-filtro:hover, .enlace-filtro:focus-visible { text-decoration: underline; }

/* ── Badges ─────────────────────────────────────────────────────────────── */
.insignia {
  display: inline-flex;
  align-items: center;
  padding: 0.15rem 0.65rem;
  border-radius: 999px;
  background: var(--surface-2);
  color: var(--fg);
  font-size: 0.8125rem;
  font-weight: 600;
  line-height: 1.4;
  font-variant-numeric: tabular-nums;
  /* A pill wrapping its own label across lines reads as broken, not
     compact — matters now that a badge can land in a narrow table cell
     (equipo's Gerencia column) instead of only a roomy header. */
  white-space: nowrap;
}
/* Graduated by weight and tone, not by hue alone — baja stays quiet, media
   just gets bolder, alta and urgente are the only two that spend color. */
.insignia--baja { color: var(--muted); }
.insignia--media { font-weight: 700; }
.insignia--alta { background: var(--high-tint); border: 1px solid var(--high-line); color: var(--high-fg); font-weight: 700; }
.insignia--urgente { background: var(--urgent-accent); border: 1px solid var(--urgent-accent); color: var(--urgent-on-accent); font-weight: 700; }
/* "gerencia" is a role marker, not a severity — it reuses "resuelto"'s tint
   styling (same accent tokens, contrast already verified for that pairing)
   rather than getting its own near-duplicate ruleset. */
.insignia--gerencia, .insignia--resuelto { background: var(--accent-tint); border: 1px solid var(--accent-line); color: var(--accent-fg); font-weight: 700; }

/* ── Section labels ─────────────────────────────────────────────────────── */
.seccion { margin-top: var(--s6); }
.seccion h2 {
  margin: 0 0 var(--s3);
  font-size: 0.8125rem;
  font-weight: 700;
  letter-spacing: 0.07em;
  text-transform: uppercase;
  color: var(--muted);
}

/* ── Resumen / texto original ───────────────────────────────────────────── */
.resumen { font-size: 1.15rem; font-weight: 650; line-height: 1.35; margin: 0 0 var(--s2); }
.texto-original { color: var(--muted); margin: 0 0 var(--s6); white-space: pre-wrap; line-height: 1.5; }

/* ── Label:value cards ────────────────────────────────────────────────────
   One seamless-card pattern for every label:value list on the page — meta
   and tiempos share it, rather than near-identical components drifting
   apart. No overflow:hidden bug here either — none of these rows ever hold
   a focusable child. (The roster used to be a third row-list sharing this
   exact pattern — see .equipo-grilla below for why it moved out: a name
   isn't a label:value pair, and a role's card list didn't hold up once a
   role had more than a couple of people in it.) */
.meta, .etapas {
  margin: 0 0 var(--s6);
  border: 1px solid var(--line);
  border-radius: var(--r-card);
  background: var(--surface);
  box-shadow: var(--shadow-card);
  overflow: hidden;
}
.meta { display: grid; grid-template-columns: minmax(8rem, auto) 1fr; }
.meta dt, .meta dd { padding: var(--s3) var(--s4); font-size: 0.9375rem; }
.meta dt { color: var(--muted); }
.meta dd { margin: 0; text-align: end; font-variant-numeric: tabular-nums; }
.meta dt:not(:first-of-type), .meta dt:not(:first-of-type) + dd { border-top: 1px solid var(--line); }

.etapas { display: flex; flex-direction: column; }
.etapa { display: flex; justify-content: space-between; gap: var(--s3); padding: var(--s3) var(--s4); font-size: 0.9375rem; }
.etapa + .etapa { border-top: 1px solid var(--line); }
.etapa span:last-child { font-variant-numeric: tabular-nums; font-weight: 600; }

/* ── Equipo (roster) ───────────────────────────────────────────────────────
   A real table — one continuous roster, not the label:value pattern above
   and not a card grid either (both tried in earlier passes). Row per
   person, three columns (Persona / Rol / Gerencia): the shape GitHub's org
   members / Linear's / Vercel's team settings all converge on. Role
   grouping lives in the Rol column plus the data's own already-grouped
   order — no divider rows, no per-role container. table-layout: auto (the
   default — not set explicitly, so a cell wraps rather than forcing the
   whole table into horizontal scroll) is deliberate: this page is opened
   from a phone link by non-technical staff, not a desktop admin panel, so
   letting a long name wrap to a second line beats a cramped single-line
   row. .tabla-envoltorio's overflow-x stays as the escape hatch only for a
   genuinely extreme case — the real fix for narrow phones is letting cells
   hyphenate: a single long unbroken word ("Instalaciones", "Contreras")
   otherwise sets a hard per-column minimum width a plain auto-layout table
   can't shrink past, and three such minimums together don't fit a ~360px
   screen even though each one individually looks fine. hyphens: auto
   (the page already declares lang="es" on the html element, which is what
   a real Spanish hyphenation dictionary needs) breaks at an actual
   syllable, not an arbitrary character — "Insta-laciones", not
   "Instalac-iones" — so a forced break still reads as a word, not damage.
   overflow-wrap: break-word is the fallback for the rare case hyphenation
   isn't available. */
.tabla-envoltorio {
  margin: 0 0 var(--s6);
  border: 1px solid var(--line);
  border-radius: var(--r-card);
  background: var(--surface);
  box-shadow: var(--shadow-card);
  overflow-x: auto;
}
/* Mobile-first compact by default (a narrow phone is the common case here,
   not the exception) — roomier font/padding return at the same >=40rem
   breakpoint --gutter already widens at, rather than a one-off table
   breakpoint. */
.equipo-tabla { width: 100%; border-collapse: collapse; font-size: 0.875rem; }
.equipo-tabla th, .equipo-tabla td {
  padding: var(--s2) var(--s3);
  text-align: start;
  vertical-align: middle;
  overflow-wrap: break-word;
  -webkit-hyphens: auto;
  hyphens: auto;
}
.equipo-tabla thead th {
  font-size: 0.8125rem;
  font-weight: 700;
  letter-spacing: 0.07em;
  text-transform: uppercase;
  color: var(--muted);
  border-bottom: 1px solid var(--line);
}
.equipo-tabla tbody tr + tr { border-top: 1px solid var(--line); }
.celda-persona { display: flex; align-items: center; gap: var(--s3); }
.persona-avatar {
  flex-shrink: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  width: 2.25rem;
  height: 2.25rem;
  border-radius: 50%;
  background: var(--accent-tint);
  color: var(--accent-fg);
  font-size: 0.8125rem;
  font-weight: 700;
  font-variant-numeric: tabular-nums;
}
.persona-nombre { font-weight: 600; }
.celda-rol { color: var(--muted); }
.celda-vacia { color: var(--muted); }

/* ── Fotos ──────────────────────────────────────────────────────────────── */
.fotos { display: grid; grid-template-columns: repeat(auto-fill, minmax(110px, 1fr)); gap: var(--s2); }
.foto { display: block; width: 100%; aspect-ratio: 1; object-fit: cover; border-radius: 10px; border: 1px solid var(--line); background: var(--surface-2); box-shadow: var(--shadow-card); }
.foto-ausente { display: flex; align-items: center; justify-content: center; aspect-ratio: 1; border-radius: 10px; border: 1px dashed var(--line); color: var(--muted); font-size: 0.78rem; text-align: center; padding: var(--s2); }

/* ── Historial (línea de tiempo) ────────────────────────────────────────── */
.hitos { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: var(--s4); }
.hito { position: relative; padding-inline-start: var(--s4); border-inline-start: 2px solid var(--accent-line); font-size: 0.9375rem; }
.hito::before {
  content: "";
  position: absolute;
  inset-inline-start: -5px;
  top: 0.35em;
  width: 8px;
  height: 8px;
  border-radius: 50%;
  background: var(--accent);
  box-shadow: 0 0 0 2px var(--bg);
}
.hito-linea { display: flex; gap: var(--s2); flex-wrap: wrap; color: var(--muted); }
.hito-linea strong { color: var(--fg); }
.hito-nota { margin: var(--s1) 0 0; color: var(--fg); }

/* The one not-yet-reached milestone — a hollow marker and muted label read
   as "coming up", never mistaken for something that already happened. */
.hito--pendiente::before { background: var(--bg); border: 2px solid var(--muted); box-shadow: none; }
.hito--pendiente .hito-linea strong { color: var(--muted); font-weight: 600; }

/* ── Filas de cola (lista / obra / atención) ─────────────────────────────
   The rail always reserves its 4px — urgency changes its COLOR, never its
   presence, so the column never jumps width as the eye scans the queue.
   The card's fill never changes: state lives on the rail only. */
.lista { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: var(--s3); }
.fila {
  border: 1px solid var(--line);
  border-inline-start: 4px solid var(--line);
  border-radius: var(--r-card);
  background: var(--surface);
  box-shadow: var(--shadow-card);
  padding: var(--s3) var(--s4);
}
.fila--alta { border-color: var(--high-line); border-inline-start-color: var(--high-accent); }
.fila--urgente { border-color: var(--urgent-line); border-inline-start-color: var(--urgent-accent); }
.fila-linea { display: flex; align-items: center; justify-content: space-between; gap: var(--s2); }
.fila-ref { font-weight: 700; font-variant-numeric: tabular-nums; }
.fila-resumen { margin: var(--s2) 0 var(--s1); line-height: 1.4; }
.fila-meta { margin: 0; color: var(--muted); font-size: 0.9rem; display: flex; align-items: center; gap: var(--s2); flex-wrap: wrap; }
/* Negative-margin/matching-padding so the WHOLE card is the tap target, not
   just its text — .fila keeps its own padding for the no-link case, this
   just re-covers the same box from the inside. border-radius: inherit,
   never overflow:hidden on .fila itself, so the anchor's own focus ring
   still paints outside the border box (the exact bug ficha.css's own
   history warns about — see the design-refresh commit). */
.fila-enlace {
  display: block;
  margin: calc(-1 * var(--s3)) calc(-1 * var(--s4));
  padding: var(--s3) calc(var(--s4) + var(--s5)) var(--s3) var(--s4);
  border-radius: inherit;
  color: inherit;
  text-decoration: none;
  position: relative;
}
/* Vertically centered on the card's right edge, not the top corner — the
   top row already has the priority badge there (.fila-linea's own
   space-between layout); a same-corner chevron would collide with it. */
.fila-enlace::after { content: "›"; position: absolute; inset-inline-end: var(--s3); inset-block-start: 50%; transform: translateY(-50%); color: var(--muted); font-weight: 400; font-size: 1.1rem; }
.fila-enlace:active { background: var(--surface-2); }
@media (hover: hover) {
  .fila-enlace:hover { background: var(--surface-2); }
}

/* ── Estados vacíos ───────────────────────────────────────────────────────
   El sereno's whole job is calling out that all's calm — an empty queue is
   that call, not a broken page, so it gets a mark of its own instead of one
   grey line of text. The same mark carries over to the failure page: an
   expired link is the same kind of "nothing to show you, on purpose". */
.vacio {
  margin: 0;
  padding: var(--s7) var(--s4);
  border: 1px dashed var(--line);
  border-radius: var(--r-card);
  text-align: center;
}
.vacio-marca { display: block; width: 1.5rem; height: 1.5rem; margin: 0 auto var(--s3); }
.vacio-marca::before {
  content: "";
  display: block;
  width: 0.55rem;
  height: 1rem;
  margin: 0 auto;
  border: 0 solid var(--accent-fg);
  border-inline-end-width: 3px;
  border-block-end-width: 3px;
  transform: rotate(40deg) translateY(-0.05rem);
}
.vacio-titulo { margin: 0 0 var(--s2); font-size: 1.2rem; font-weight: 700; }
.vacio-texto { margin: 0 auto; max-width: 32ch; color: var(--muted); font-size: 0.9375rem; }

/* ── Página de falla ────────────────────────────────────────────────────── */
.falla { min-height: 70vh; display: flex; align-items: center; justify-content: center; padding: var(--s5); }
.falla .vacio { max-width: 28rem; border-style: solid; }

/* ── Accesibilidad ──────────────────────────────────────────────────────── */
:focus-visible { outline: 3px solid var(--focus); outline-offset: 2px; }

@media (prefers-reduced-motion: reduce) {
  * { transition-duration: 0.01ms !important; animation-duration: 0.01ms !important; }
}

@media (forced-colors: active) {
  .fila--alta, .fila--urgente { border-inline-start-width: 6px; }
  .insignia--alta, .insignia--urgente, .insignia--resuelto, .insignia--gerencia { forced-color-adjust: none; }
}