/* Estilo propio sobre Bootstrap 5.3. Los colores que cambian con el tema salen de variables para
   que `data-bs-theme="light|dark"` los resuelva solo. La barra lateral es oscura en los dos temas:
   da el contraste de consola que buscamos y mantiene la identidad al cambiar de modo.

   El acento es el dorado de la marca, el color de la luz de la atalaya. Va en dos valores porque
   un mismo dorado no sirve en los dos fondos: sobre claro hay que oscurecerlo para que el texto
   se lea, sobre oscuro hay que aclararlo. `--acc-contraste` es el color del texto que se apoya
   ENCIMA del acento, y cambia con él: blanco sobre el dorado oscuro, noche sobre el claro. */
:root {
  --acc: #8a6327;
  --acc-soft: rgba(138, 99, 39, .1);
  --acc-contraste: #ffffff;
  --app-bg: #f2f4f3;
  --app-surface: #ffffff;
  --app-line: rgba(16, 22, 25, .1);
  --app-muted: #5c6b72;

  --side-bg: #0b1013;
  --side-fg: #c6d0d3;
  --side-fg-dim: #7a8b92;
  --side-hover: rgba(255, 255, 255, .06);
  --side-active: rgba(232, 183, 115, .16);
  --side-line: rgba(255, 255, 255, .07);
  --side-w: 248px;

  --oro: #e8b773;
  --pergamino: #efe7da;
  --serif: Georgia, "Iowan Old Style", "Palatino Linotype", Palatino, serif;

  --app-diff-header-bg: #e9ecef;
  --app-diff-gutter-bg: #f8f9fa;
  --app-diff-gutter-fg: #94a3b8;
  --app-diff-add: #d4f8d4;
  --app-diff-chg: #fff3bf;
  --app-diff-sub: #ffd7d5;
}

[data-bs-theme="dark"] {
  --acc: #e8b773;
  --acc-soft: rgba(232, 183, 115, .13);
  --acc-contraste: #0b1013;
  --app-bg: #0b1013;
  --app-surface: #121a1e;
  --app-line: rgba(159, 176, 182, .14);
  --app-muted: #9fb0b6;

  --side-bg: #070b0d;
  --side-active: rgba(232, 183, 115, .16);

  --app-diff-header-bg: #1e293b;
  --app-diff-gutter-bg: #141f33;
  --app-diff-gutter-fg: #64748b;
  --app-diff-add: #0f3d22;
  --app-diff-chg: #453a10;
  --app-diff-sub: #4a1f1d;
}

body {
  background: var(--app-bg);
  font-family: system-ui, -apple-system, "Segoe UI", Roboto, "Helvetica Neue", sans-serif;
  letter-spacing: -.005em;
}

/* --------------------------------------------------------------- estructura */
.app-shell { display: flex; min-height: 100vh; }

.sidebar {
  width: var(--side-w);
  flex: 0 0 var(--side-w);
  background: var(--side-bg);
  color: var(--side-fg);
  display: flex;
  flex-direction: column;
  position: fixed;
  inset: 0 auto 0 0;
  z-index: 1045;
  overflow-y: auto;
  transition: transform .18s ease;
}
.sidebar-brand {
  display: flex; align-items: center; gap: .6rem;
  padding: 1.05rem 1.15rem;
  color: #fff; text-decoration: none;
  font-weight: 650; letter-spacing: -.02em;
  border-bottom: 1px solid var(--side-line);
}
.sidebar-brand i { color: var(--acc); font-size: 1.25rem; }
.sidebar-brand small { display: block; font-weight: 400; font-size: .68rem; color: var(--side-fg-dim); letter-spacing: .04em; text-transform: uppercase; }

.sidebar-section {
  padding: 1rem 1.15rem .35rem;
  font-size: .67rem; font-weight: 600; letter-spacing: .09em;
  text-transform: uppercase; color: var(--side-fg-dim);
}
.sidebar-nav { list-style: none; margin: 0; padding: 0 .6rem; }
.sidebar-nav a {
  display: flex; align-items: center; gap: .65rem;
  padding: .5rem .55rem; margin-bottom: 1px;
  color: var(--side-fg); text-decoration: none;
  border-radius: .45rem; font-size: .895rem;
  border-left: 2px solid transparent;
}
.sidebar-nav a i { width: 1.1rem; text-align: center; color: var(--side-fg-dim); }
.sidebar-nav a:hover { background: var(--side-hover); color: #fff; }
.sidebar-nav a:hover i { color: var(--side-fg); }
.sidebar-nav a.active { background: var(--side-active); color: #fff; border-left-color: var(--acc); font-weight: 550; }
.sidebar-nav a.active i { color: var(--acc); }
.sidebar-foot { margin-top: auto; padding: .9rem 1.15rem; border-top: 1px solid var(--side-line); font-size: .72rem; color: var(--side-fg-dim); }

.app-main { flex: 1 1 auto; min-width: 0; margin-left: var(--side-w); display: flex; flex-direction: column; }

.topbar {
  position: sticky; top: 0; z-index: 1030;
  display: flex; align-items: center; gap: .75rem;
  padding: .55rem 1.25rem;
  background: color-mix(in srgb, var(--app-surface) 88%, transparent);
  backdrop-filter: blur(10px);
  border-bottom: 1px solid var(--app-line);
}
.topbar .btn-burger { display: none; }

.content { padding: 1.4rem 1.25rem 3rem; }
.page-title { font-size: 1.35rem; font-weight: 650; letter-spacing: -.02em; margin: 0; }

@media (max-width: 991.98px) {
  .sidebar { transform: translateX(-100%); box-shadow: 0 0 40px rgba(0,0,0,.4); }
  .sidebar.open { transform: none; }
  .app-main { margin-left: 0; }
  .topbar .btn-burger { display: inline-flex; }
  .sidebar-backdrop { position: fixed; inset: 0; background: rgba(2,6,23,.5); z-index: 1040; }
}

/* --------------------------------------------------------------- buscador global */
.global-search { position: relative; flex: 1 1 420px; max-width: 520px; }
.global-search .form-control { padding-left: 2.1rem; background: var(--app-bg); border-color: var(--app-line); }
.global-search .form-control:focus { background: var(--app-surface); }
.global-search > .bi-search { position: absolute; left: .72rem; top: 50%; transform: translateY(-50%); color: var(--app-muted); pointer-events: none; }
.global-search kbd { position: absolute; right: .5rem; top: 50%; transform: translateY(-50%); font-size: .68rem; opacity: .55; background: var(--app-line); color: inherit; padding: .1rem .35rem; border-radius: .25rem; }

.search-results {
  position: absolute; left: 0; right: 0; top: calc(100% + .35rem);
  background: var(--app-surface); border: 1px solid var(--app-line);
  border-radius: .6rem; box-shadow: 0 12px 32px rgba(2, 6, 23, .18);
  max-height: 70vh; overflow-y: auto; padding: .3rem; display: none;
}
.search-results.show { display: block; }
.search-results .group-label { font-size: .66rem; text-transform: uppercase; letter-spacing: .08em; color: var(--app-muted); padding: .5rem .6rem .25rem; font-weight: 600; }
.search-results a { display: flex; align-items: center; gap: .6rem; padding: .45rem .6rem; border-radius: .4rem; color: inherit; text-decoration: none; }
.search-results a:hover, .search-results a.active { background: var(--acc-soft); }
.search-results a i { color: var(--acc); width: 1.1rem; text-align: center; }
.search-results .sub { font-size: .78rem; color: var(--app-muted); }
.search-results .empty { padding: .9rem .6rem; color: var(--app-muted); font-size: .88rem; }

/* --------------------------------------------------------------- superficies */
.card {
  border: 1px solid var(--app-line);
  border-radius: .7rem;
  background: var(--app-surface);
  box-shadow: 0 1px 2px rgba(2, 6, 23, .04);
}
.card-header { background: transparent; border-bottom: 1px solid var(--app-line); font-weight: 600; }
.stat-card .value { font-size: 1.9rem; font-weight: 650; line-height: 1; letter-spacing: -.03em; }
.stat-card .label { color: var(--app-muted); font-size: .72rem; text-transform: uppercase; letter-spacing: .07em; font-weight: 600; }

.btn { border-radius: .45rem; font-weight: 500; }
.btn-primary {
  --bs-btn-bg: var(--acc); --bs-btn-border-color: var(--acc); --bs-btn-color: var(--acc-contraste);
  --bs-btn-hover-bg: color-mix(in srgb, var(--acc) 85%, #000);
  --bs-btn-hover-border-color: color-mix(in srgb, var(--acc) 85%, #000);
  --bs-btn-hover-color: var(--acc-contraste);
  --bs-btn-active-bg: color-mix(in srgb, var(--acc) 75%, #000);
  --bs-btn-active-color: var(--acc-contraste);
  --bs-btn-disabled-bg: var(--acc); --bs-btn-disabled-border-color: var(--acc);
  --bs-btn-disabled-color: var(--acc-contraste);
}
.table-pager .pages button[aria-current="page"] { color: var(--acc-contraste); }
.form-control, .form-select { border-radius: .45rem; border-color: var(--app-line); }
.form-control:focus, .form-select:focus { border-color: var(--acc); box-shadow: 0 0 0 .2rem var(--acc-soft); }
.badge { font-weight: 550; letter-spacing: .01em; }

/* --------------------------------------------------------------- tablas */
.table { --bs-table-border-color: var(--app-line); margin-bottom: 0; }
.table > thead th {
  font-size: .7rem; text-transform: uppercase; letter-spacing: .06em;
  color: var(--app-muted); font-weight: 600; white-space: nowrap;
  border-bottom: 1px solid var(--app-line); background: transparent;
}
.table td, .table th { vertical-align: middle; }
.table-sm td { font-size: .9rem; }
.table-hover > tbody > tr:hover > * { --bs-table-bg-state: var(--acc-soft); }

/* Encabezados ordenables */
th[data-sortable] { cursor: pointer; user-select: none; position: relative; padding-right: 1.25rem !important; }
th[data-sortable]:hover { color: var(--acc); }
th[data-sortable]::after {
  content: "\F0DC"; font-family: bootstrap-icons; font-size: .62rem;
  position: absolute; right: .45rem; top: 50%; transform: translateY(-50%); opacity: .3;
}
th[data-dir="asc"]::after { content: "\F0DD"; opacity: 1; color: var(--acc); }
th[data-dir="desc"]::after { content: "\F0DE"; opacity: 1; color: var(--acc); }

/* Filas que llevan a un detalle */
tr[data-href] { cursor: pointer; }

.table-pager {
  display: flex; align-items: center; justify-content: space-between; gap: 1rem; flex-wrap: wrap;
  padding: .6rem .9rem; border-top: 1px solid var(--app-line); font-size: .85rem; color: var(--app-muted);
}
.table-pager .pages { display: flex; gap: .2rem; }
.table-pager .pages button {
  min-width: 1.9rem; padding: .18rem .45rem; font-size: .82rem; line-height: 1.4;
  border: 1px solid var(--app-line); background: transparent; color: inherit; border-radius: .35rem;
}
.table-pager .pages button:hover:not(:disabled) { border-color: var(--acc); color: var(--acc); }
.table-pager .pages button[aria-current="page"] { background: var(--acc); border-color: var(--acc); color: #fff; font-weight: 600; }
.table-pager .pages button:disabled { opacity: .4; }

.table-empty td { color: var(--app-muted); padding: 2.2rem 1rem; text-align: center; }

/* --------------------------------------------------------------- varios */
.text-mono, code.cfg, .text-mono input { font-family: ui-monospace, SFMono-Regular, Consolas, monospace; }
/* El visor de configuración es oscuro en ambos temas: imita la consola de RouterOS. */
pre.config { background: #0d1117; color: #d4d4d4; padding: 1rem; border-radius: .5rem; max-height: 75vh; overflow: auto; font-size: .82rem; }
pre.config .c { color: #6a9955; }
pre.config .p { color: #569cd6; }

.secret-field input { font-family: ui-monospace, Consolas, monospace; letter-spacing: .02em; }

/* difflib.HtmlDiff */
table.diff { font-family: ui-monospace, Consolas, monospace; font-size: .8rem; border-collapse: collapse; width: 100%; background: var(--bs-body-bg); color: var(--bs-body-color); }
table.diff td { padding: 0 .4rem; white-space: pre-wrap; word-break: break-all; vertical-align: top; }
table.diff th { background: var(--app-diff-header-bg); padding: .3rem .4rem; }
table.diff td.diff_header { color: var(--app-diff-gutter-fg); text-align: right; background: var(--app-diff-gutter-bg); width: 1%; }
table.diff td.diff_next { display: none; }
.diff_add { background: var(--app-diff-add); }
.diff_chg { background: var(--app-diff-chg); }
.diff_sub { background: var(--app-diff-sub); }

.version-timeline .list-group-item.current { border-left: 3px solid var(--acc); }
.error-text { max-width: 420px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; display: inline-block; vertical-align: bottom; }

/* --------------------------------------------------------------- marca y lemas
   Dos lemas y no se mezclan. La declaración («Trabajamos en la oscuridad…») aparece al cruzar al
   modo noche y en la tarjeta de ingreso; el oficio («La red que nadie mira…» y sus variantes) va
   fijo al pie del menú y al pie del ingreso. Ver `app/brand.py`. */
.sidebar-brand .logo { width: 1.55rem; height: 1.55rem; flex: none; color: var(--side-fg); }
.sidebar-brand .nombre {
  font-family: var(--serif);
  font-size: 1rem; font-weight: 500;
  letter-spacing: .2em; text-transform: uppercase;
  line-height: 1.1;
}
.sidebar-brand small { letter-spacing: .13em; margin-top: .2rem; }

/* El credo en la barra superior, entre el buscador y el botón de apariencia. Entra como quien se
   materializa —desenfocado y disperso, va tomando forma— y sale al revés, difuminándose hacia los
   costados: la bomba de humo del asesino. No ocupa lugar cuando no está. */
.credo-barra {
  flex: 1 1 auto; min-width: 0;
  display: flex; justify-content: center;
  overflow: hidden;
}
.credo-barra p {
  margin: 0; max-width: 100%;
  font-family: var(--serif); font-style: italic;
  font-size: clamp(.7rem, 1.1vw, .85rem);
  white-space: nowrap;
  color: var(--app-muted);
  opacity: 0;
  filter: blur(7px);
  letter-spacing: .22em;
  transform: scale(1.03);
}
.credo-barra .luz { color: var(--acc); font-style: normal; }
.credo-barra p.visible { animation: humo 7.5s cubic-bezier(.3, 0, .3, 1) forwards; }

@keyframes humo {
  0%   { opacity: 0;   filter: blur(7px); letter-spacing: .22em;  transform: scale(1.03); }
  22%  { opacity: .95; filter: blur(0);   letter-spacing: .045em; transform: scale(1); }
  70%  { opacity: .95; filter: blur(0);   letter-spacing: .045em; transform: scale(1); }
  100% { opacity: 0;   filter: blur(9px); letter-spacing: .3em;   transform: scale(1.04); }
}

@keyframes aparecer {
  0%, 100% { opacity: 0;   filter: none; letter-spacing: .045em; transform: none; }
  8%, 88%  { opacity: .95; filter: none; letter-spacing: .045em; transform: none; }
}
/* A quien pidió menos movimiento el credo se le muestra quieto y se va sin aspavientos. */
@media (prefers-reduced-motion: reduce) {
  .credo-barra p.visible { animation-name: aparecer; animation-timing-function: linear; }
}

/* En pantalla angosta la barra superior ya está apretada entre el buscador y los botones. */
@media (max-width: 767.98px) { .credo-barra { display: none; } }

/* --------------------------------------------------------------- pantalla de ingreso
   Una sola tarjeta centrada sobre la noche. La unica luz de la escena sale del emblema --la
   atalaya con su vano encendido--, que va arriba de todo: alumbra hacia abajo el nombre, el credo
   y el formulario, y deja el resto en penumbra. Es oscura en los dos temas a proposito. */
/* Red de seguridad contra el scroll lateral. El desborde se evita en el origen —ver el ancho del
   resplandor, más abajo—; esto es por si alguna vez algo vuelve a asomarse. No alcanza por sí
   solo: el recorte del viewport se toma de la raíz y Chrome no honra `clip` ahí, así que esto
   impide arrastrar la página de costado pero no borra el área sobrante. */
html.ingreso { overflow-x: hidden; }

body.ingreso {
  background: #080c0f;
  color: var(--pergamino);
  min-height: 100vh;
  display: flex;
  padding: clamp(2rem, 6vw, 4rem) 1.25rem clamp(4.5rem, 8vw, 6rem);
}

.ingreso .tarjeta {
  position: relative;
  /* `margin: auto` y no `align-items: center`: centra igual, pero cuando la tarjeta es mas alta
     que la pantalla --un telefono chico con el teclado abierto-- el sobrante no se va para arriba
     dejando el emblema inalcanzable, que es lo que hace el centrado del contenedor. */
  margin: auto;
  width: min(24rem, 100%);
  background: rgba(18, 26, 30, .76);
  border: 1px solid rgba(232, 183, 115, .17);
  border-radius: .75rem;
  padding: 2.2rem 1.9rem 2rem;
  backdrop-filter: blur(2px);
  box-shadow: 0 24px 60px -30px rgba(0, 0, 0, .9);
}
/* El resplandor del emblema. Va detras de la tarjeta y desborda sus bordes: la tarjeta es
   traslucida, asi que la luz se filtra y parece venir de adentro, no apoyada encima. */
.ingreso .tarjeta::before {
  content: "";
  position: absolute;
  left: 50%; top: 2.9rem;
  /* El tope de `100vw` es lo que evita el scroll lateral en el teléfono: el resplandor es más
     ancho que la tarjeta a propósito, pero si además es más ancho que la pantalla deja la página
     corrida hacia la derecha, con un vacío al costado. Cortarlo ahí no deja borde visible porque
     a esa distancia del centro el degradé ya se apagó. */
  width: min(34rem, 100vw); height: 34rem;
  transform: translate(-50%, -50%);
  background: radial-gradient(circle,
              rgba(255, 230, 189, .17) 0%,
              rgba(232, 183, 115, .085) 11%,
              rgba(232, 183, 115, .032) 26%,
              rgba(232, 183, 115, .01) 42%,
              transparent 62%);
  pointer-events: none;
  z-index: -1;
}

.ingreso .marca {
  display: flex; flex-direction: column; align-items: center; gap: .55rem;
  margin-bottom: .45rem;
}
.ingreso .marca .logo {
  width: 2.7rem; height: 2.7rem;
  /* El halo pegado al vano: es la fuente, tiene que ser el punto mas brillante de la pantalla. */
  filter: drop-shadow(0 0 13px rgba(232, 183, 115, .55));
}
.ingreso .marca .nombre {
  font-family: var(--serif); font-size: 1.35rem; font-weight: 400;
  letter-spacing: .28em; text-transform: uppercase; color: var(--pergamino);
  /* El espaciado entre letras deja un hueco sobrante a la derecha; esto recentra la palabra. */
  text-indent: .28em;
}
.ingreso .credo {
  font-family: var(--serif); font-style: italic; font-size: .85rem;
  text-align: center;
  color: rgba(239, 231, 218, .62); margin: 0 0 1.7rem;
}
.ingreso .credo .luz { color: var(--oro); font-style: normal; }

.ingreso .form-label {
  font-size: .7rem; letter-spacing: .1em; text-transform: uppercase;
  color: rgba(239, 231, 218, .5); margin-bottom: .3rem;
}
.ingreso .form-control {
  background: rgba(8, 12, 15, .7);
  border-color: rgba(239, 231, 218, .14);
  color: var(--pergamino);
}
/* El autorrelleno del navegador pinta el campo con un celeste propio que no se puede cambiar con
   `background`: hay que taparlo con una sombra interior opaca y pedir el color del texto aparte. */
.ingreso .form-control:-webkit-autofill,
.ingreso .form-control:-webkit-autofill:hover,
.ingreso .form-control:-webkit-autofill:focus {
  -webkit-box-shadow: 0 0 0 100vmax #0b1013 inset;
  -webkit-text-fill-color: var(--pergamino);
  caret-color: var(--pergamino);
}
.ingreso .form-control:focus {
  background: rgba(8, 12, 15, .85);
  border-color: var(--oro);
  box-shadow: 0 0 0 .2rem rgba(232, 183, 115, .18);
  color: var(--pergamino);
}
.ingreso .form-control::placeholder { color: rgba(239, 231, 218, .3); }
.ingreso .form-text, .ingreso .text-muted { color: rgba(239, 231, 218, .45) !important; }
.ingreso .btn-entrar {
  width: 100%; background: var(--oro); color: #0b1013;
  border: 0; border-radius: .45rem; padding: .55rem; font-weight: 650;
}
.ingreso .btn-entrar:hover { background: color-mix(in srgb, var(--oro) 88%, #fff); color: #0b1013; }
.ingreso .alert-danger {
  background: rgba(179, 37, 63, .16); border-color: rgba(240, 115, 140, .35); color: #ffc3ce;
}
.ingreso a { color: var(--oro); }

/* El lema del oficio, centrado al pie de la pantalla. Cambia en cada visita y cada tanto mientras
   la pantalla está abierta: la ve siempre la misma gente y una frase repetida deja de leerse. */
.ingreso .lema-pie {
  position: fixed;
  left: 0; right: 0; bottom: clamp(1.1rem, 2.5vw, 1.8rem);
  margin: 0; padding: 0 1rem; text-align: center;
  font-family: var(--serif); font-style: italic; font-size: .85rem;
  color: rgba(239, 231, 218, .4);
  transition: opacity .9s ease;
}
@media (prefers-reduced-motion: reduce) { .ingreso .lema-pie { transition: none; } }
