/* ═══════════════════════════════════════════════════════════════
   yimail — sistema visual "cristal cálido"
   Hielo esmerilado sobre una aurora tibia. Teal frío para estructura y
   foco; durazno/ámbar cálido para acciones, activo y no-leído. Dark + Clear.

   PRESUPUESTO DE PERFORMANCE:
   - Fuentes propias servidas same-origin (font-src 'self'), sin CDN.
   - `backdrop-filter` solo en superficies grandes y estables (paneles/barras),
     nunca por fila (se caería el scroll).
   - Animaciones solo sobre `transform`/`opacity`.
   ═══════════════════════════════════════════════════════════════ */

/* ── Fuentes propias (variables, subset latin) ───────────────── */
@font-face {
  font-family: "Bricolage"; font-style: normal; font-weight: 200 800;
  font-display: swap; src: url("/static/fonts/bricolage.woff2") format("woff2");
}
@font-face {
  font-family: "Hanken"; font-style: normal; font-weight: 100 900;
  font-display: swap; src: url("/static/fonts/hanken.woff2") format("woff2");
}

/* ── Tokens ──────────────────────────────────────────────────── */
:root {
  --font-ui:      "Hanken", ui-sans-serif, "Segoe UI", Roboto, system-ui, sans-serif;
  --font-display: "Bricolage", "Hanken", ui-sans-serif, system-ui, sans-serif;
  --font-mono:    ui-monospace, "SF Mono", "Cascadia Mono", "Roboto Mono", Menlo, monospace;

  --step--1: clamp(.75rem, .72rem + .12vw, .8125rem);
  --step-0:  clamp(.8125rem, .79rem + .14vw, .875rem);
  --step-1:  clamp(.9375rem, .90rem + .2vw, 1rem);
  --step-2:  clamp(1.125rem, 1.05rem + .35vw, 1.375rem);
  --step-3:  clamp(1.5rem, 1.3rem + .8vw, 2rem);

  --sp-1: .25rem; --sp-2: .5rem;  --sp-3: .75rem; --sp-4: 1rem;
  --sp-5: 1.5rem; --sp-6: 2rem;   --sp-7: 3rem;

  --r-sm: 8px; --r-md: 12px; --r-lg: 18px; --r-xl: 26px; --r-pill: 999px;

  /* Altura uniforme de controles (botones/inputs) */
  --ctl-h: 2.25rem; --ctl-h-sm: 1.75rem;

  --dur-fast: 120ms; --dur: 220ms; --dur-slow: 420ms;
  --ease: cubic-bezier(.22, .61, .28, 1);
  --ease-out: cubic-bezier(.16, 1, .3, 1);

  --sidebar-w: 248px; --sidebar-w-collapsed: 66px;
  --list-w: 400px;
}

/* ── Tema DARK (default) — charcoal cálido ───────────────────── */
:root, :root[data-theme="dark"] {
  color-scheme: dark;
  --bg-0:  #0a0908;
  --bg-1:  #14110e;

  /* Aurora tibia: dos focos cálidos + uno teal frío */
  --aur-1: rgba(255, 158, 96, .17);
  --aur-2: rgba(72, 214, 190, .15);
  --aur-3: rgba(255, 196, 128, .12);

  --glass:      rgba(255, 250, 245, .055);
  --glass-hi:   rgba(255, 250, 245, .095);
  --glass-brd:  rgba(255, 248, 240, .10);
  --glass-brd-hi: rgba(255, 248, 240, .19);
  --sheen: linear-gradient(180deg, rgba(255,252,248,.14), rgba(255,252,248,0) 42%);

  /* Neutros templados (warm-gray) */
  --ink:      #f3efe9;
  --ink-mid:  #b3aaa0;
  --ink-dim:  #837a6f;
  --ink-fade: #575049;

  --accent:    #5fe6cf;   /* teal — estructura, foco, links */
  --accent-2:  #8bb6ff;
  --accent-ink: #052620;
  --warm:      #ffb27a;   /* durazno — acciones, activo, no-leído */
  --warm-2:    #ff9f5b;
  --warm-ink:  #2c1605;
  --danger:    #fb7185;
  --warn:      #fbbf24;

  --shadow-lg: 0 24px 60px -18px rgba(0,0,0,.78), 0 4px 14px -6px rgba(0,0,0,.55);
  --shadow-sm: 0 2px 10px -4px rgba(0,0,0,.6);
  --grain-op: .035;
}

/* ── Tema CLEAR — papel cálido ───────────────────────────────── */
:root[data-theme="clear"] {
  color-scheme: light;
  --bg-0:  #f0ebe3;
  --bg-1:  #faf6ef;

  --aur-1: rgba(232, 134, 63, .15);
  --aur-2: rgba(13, 148, 136, .14);
  --aur-3: rgba(245, 190, 120, .16);

  --glass:      rgba(255, 253, 250, .62);
  --glass-hi:   rgba(255, 253, 250, .85);
  --glass-brd:  rgba(255, 255, 255, .92);
  --glass-brd-hi: #ffffff;
  --sheen: linear-gradient(180deg, rgba(255,255,255,.9), rgba(255,255,255,0) 48%);

  --ink:      #201a13;
  --ink-mid:  #574e43;
  --ink-dim:  #837a6d;
  --ink-fade: #a99f90;

  --accent:    #0d9488;
  --accent-2:  #4f46e5;
  --accent-ink: #ffffff;
  --warm:      #e07b34;   /* terracota-ámbar */
  --warm-2:    #d96f27;
  --warm-ink:  #ffffff;
  --danger:    #e11d48;
  --warn:      #b45309;

  --shadow-lg: 0 22px 50px -20px rgba(60, 40, 21, .26), 0 3px 10px -4px rgba(60,40,21,.12);
  --shadow-sm: 0 2px 8px -3px rgba(60, 40, 21, .15);
  --grain-op: .02;
}

/* Respeta el sistema si el usuario nunca eligio (data-theme lo pisa siempre) */
@media (prefers-color-scheme: light) {
  :root:not([data-theme]) { color-scheme: light; }
}

/* ── Reset acotado ───────────────────────────────────────────── */
*, *::before, *::after { box-sizing: border-box; }
html, body { height: 100%; }

/* El atributo `hidden` le tiene que ganar a CUALQUIER `display` de clase, y es el
   único `!important` del archivo porque la regla existe justamente para eso: la del
   navegador tiene especificidad 0 y pierde contra cualquier `.clase{display:…}`.
   Sin esto, `el.hidden = true` desde el JS no hace NADA en un elemento con clase
   `.bar`, `.btn` o `.pane` — y eso es lo que dejaba la barra de selección visible
   diciendo "0 seleccionados" arriba de la barra de la carpeta. Es el mismo bug que
   ya nos comió `.pane-reader` contra `.pane`; la línea `.list-sentinel[hidden]` que
   estaba más abajo era el parche local de este mismo problema. */
[hidden] { display: none !important; }
body {
  margin: 0;
  font-family: var(--font-ui);
  font-size: var(--step-0);
  line-height: 1.55;
  color: var(--ink);
  background: var(--bg-0);
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
  overflow: hidden;              /* el scroll vive en los paneles */
}
button, input, textarea, select { font: inherit; color: inherit; }

/* El desplegable de un `<select>` NO lo dibuja esta hoja: lo dibuja el sistema, y para el
   fondo usa el `background-color` computado del `<select>`. El nuestro es de cristal
   —`--glass` es un rgba con alpha .055—, así que el navegador lo componía sobre blanco y
   quedaba un popup casi blanco con las opciones heredando `--ink`, que es claro. Gris
   clarito sobre blanco: ilegible, y sólo con el desplegable ABIERTO, que es por qué no se
   veía en ninguna captura de la pantalla quieta.
   Se arregla dándole a la opción un fondo OPACO propio. `--bg-1` sigue al tema, así que
   vale igual en oscuro y en claro. */
option, optgroup {
  background-color: var(--bg-1);
  color: var(--ink);
}

a { color: var(--accent); text-decoration: none; }
a:hover { text-decoration: underline; }
:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; border-radius: 4px; }
::selection { background: color-mix(in srgb, var(--accent) 35%, transparent); }

/* ── Atmosfera: aurora + grano ───────────────────────────────── */
/* Fija, no re-pinta con el scroll de los paneles. */
.aurora {
  position: fixed; inset: 0; z-index: -2; pointer-events: none;
  background:
    radial-gradient(52vw 46vh at 12% -6%,  var(--aur-1), transparent 62%),
    radial-gradient(46vw 52vh at 88% 8%,   var(--aur-2), transparent 60%),
    radial-gradient(58vw 50vh at 62% 104%, var(--aur-3), transparent 62%),
    linear-gradient(160deg, var(--bg-1), var(--bg-0) 70%);
  /* Deriva lentisima: da vida sin costar nada (solo transform). */
  animation: drift 44s var(--ease) infinite alternate;
}
@keyframes drift {
  from { transform: translate3d(0,0,0) scale(1); }
  to   { transform: translate3d(-2.5%, 1.5%, 0) scale(1.06); }
}
/* Grano SVG inline: rompe el degradado plano (banding) sin pedir un asset. */
.grain {
  position: fixed; inset: 0; z-index: -1; pointer-events: none;
  opacity: var(--grain-op);
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='140' height='140'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='.82' numOctaves='3'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23n)'/%3E%3C/svg%3E");
}

/* ── Superficie de cristal ───────────────────────────────────── */
.glass {
  position: relative;
  background: var(--glass);
  border: 1px solid var(--glass-brd);
  border-radius: var(--r-lg);
  backdrop-filter: blur(22px) saturate(165%);
  -webkit-backdrop-filter: blur(22px) saturate(165%);
  box-shadow: var(--shadow-lg);
}
/* El filo de luz superior — el detalle que vende el "cristal". */
.glass::before {
  content: ''; position: absolute; inset: 0; border-radius: inherit;
  background: var(--sheen); opacity: .8; pointer-events: none;
}
.glass > * { position: relative; }

/* ── Layout de la app ────────────────────────────────────────── */
/* Ancho del sidebar animable (colapsado ↔ expandido). @property permite la
   transición suave del grid. Colapsado por defecto. */
@property --sb { syntax: '<length>'; inherits: true; initial-value: 66px; }
:root { --sb: var(--sidebar-w-collapsed); }
:root[data-sidebar="expanded"] { --sb: var(--sidebar-w); }

.app {
  display: grid;
  /* 2 paneles: barra de navegación + área principal. La lista y el lector
     se turnan en la 2ª columna (el oculto sale del grid con display:none). */
  grid-template-columns: var(--sb) minmax(0, 1fr);
  gap: var(--sp-3);
  height: 100vh;
  height: 100dvh;
  padding: var(--sp-3);
  transition: --sb var(--dur) var(--ease);
}
.app.no-reader { grid-template-columns: var(--sb) minmax(0, 1fr); }

/* ── Los dos modos de lectura ──────────────────────────────────
   FULLSCREEN (default): la lista y el lector se TURNAN en la 2ª columna.
   INLINE: tres columnas — rail de iconos + lista angosta + el mail al lado.
   El modo es una preferencia (`data-preview`), igual que el tema.

   OJO con esconder el lector. `.pane-reader { display: none }` NO alcanza:
   el markup es `class="pane pane-reader"` y `.pane { display: flex }` está más
   abajo en este archivo con la MISMA especificidad, así que ganaba y el lector
   quedaba dibujado siempre. Con `.reading` no se notaba (esa regla es más
   específica), pero al volver a la lista el panel seguía visible y, como el grid
   tiene dos columnas, caía en la fila 2 / columna 1: debajo del sidebar, ~250 px
   de ancho, con el asunto partido una palabra por línea.

   Por eso el estado se maneja SIEMPRE desde el contenedor: así ninguna regla
   genérica posterior puede volver a ganar. */
.pane-reader { position: relative; }
.app:not(.reading) .pane-reader { display: none; }
.app.reading .pane-list   { display: none; }
.app.reading .pane-reader { display: flex; }

/* ── MODO INLINE: tres columnas ────────────────────────────────
   Sólo desde 1101 px: tres paneles en 900 px no se leen, así que abajo de eso
   inline se comporta como fullscreen. La degradación es del CSS y no hay estado
   que sincronizar — la preferencia de la persona no se toca. */
@media (min-width: 1101px) {
  :root[data-preview="inline"] .app.reading {
    grid-template-columns: var(--sb) var(--list-w) minmax(0, 1fr);
  }
  /* La lista NO se oculta: es la columna del medio. */
  :root[data-preview="inline"] .app.reading .pane-list { display: flex; }
  /* En 340-400 px, asunto y snippet en la misma línea dejan al snippet en dos
     palabras. Se esconde: en fullscreen se sigue viendo. */
  :root[data-preview="inline"] .app.reading .row-snippet { display: none; }
}

/* ── Sidebar colapsado: solo iconos + tooltips (title nativo) ──
   `data-rail` es el MISMO look pero efímero: lo pone el JS al abrir un mail en
   modo inline y lo saca al volver. No se persiste, así que la preferencia de
   sidebar de la persona queda intacta — pisarla sería cambiarle la
   configuración en silencio. */
:root[data-sidebar="collapsed"] .brand-name,
:root[data-sidebar="collapsed"] .side-label,
:root[data-sidebar="collapsed"] .nav-item .txt,
:root[data-sidebar="collapsed"] .compose-btn .txt,
:root[data-sidebar="collapsed"] .sidebar-email,
:root[data-rail] .brand-name,
:root[data-rail] .side-label,
:root[data-rail] .nav-item .txt,
:root[data-rail] .compose-btn .txt,
:root[data-rail] .sidebar-email { display: none; }
:root[data-rail] { --sb: var(--sidebar-w-collapsed); }
:root[data-sidebar="collapsed"] .brand,
:root[data-rail] .brand { justify-content: center; padding-left: var(--sp-2); padding-right: var(--sp-2); }
:root[data-sidebar="collapsed"] .nav,
:root[data-rail] .nav { padding-left: var(--sp-2); padding-right: var(--sp-2); }
:root[data-sidebar="collapsed"] .nav-item,
:root[data-rail] .nav-item { justify-content: center; gap: 0; padding-left: 0; padding-right: 0; }
:root[data-sidebar="collapsed"] .nav-item:hover,
:root[data-rail] .nav-item:hover { transform: none; }
/* Colapsado: el botón Escribir se vuelve un icono cuadrado centrado, alineado
   al rail (mismo ancho/alto que el resto de los controles). */
:root[data-sidebar="collapsed"] .compose-btn,
:root[data-rail] .compose-btn {
  width: var(--ctl-h); min-height: var(--ctl-h); padding: 0;
  margin: var(--sp-1) auto var(--sp-3); border-radius: var(--r-md);
}
/* Badge en colapsado: puntito en la esquina del icono */
:root[data-sidebar="collapsed"] .nav-item .badge,
:root[data-rail] .nav-item .badge {
  position: absolute; top: 4px; right: 6px; min-width: 8px; height: 8px; padding: 0;
  font-size: 0; line-height: 0;
}
/* Botón de colapso: rota el chevron según el estado */
.sidebar-toggle .ico { transition: transform var(--dur) var(--ease); }
:root[data-sidebar="collapsed"] .sidebar-toggle .ico,
:root[data-rail] .sidebar-toggle .ico { transform: rotate(180deg); }

.pane { display: flex; flex-direction: column; min-height: 0; overflow: hidden; }
.pane-scroll { overflow-y: auto; overscroll-behavior: contain; scrollbar-width: thin; flex: 1; min-height: 0; }
.pane-scroll::-webkit-scrollbar { width: 9px; }
.pane-scroll::-webkit-scrollbar-thumb {
  background: var(--glass-brd-hi); border-radius: var(--r-pill);
  border: 3px solid transparent; background-clip: content-box;
}
.pane-scroll::-webkit-scrollbar-track { background: transparent; }

/* ── Marca ───────────────────────────────────────────────────── */
.brand {
  display: flex; align-items: center; gap: var(--sp-2);
  padding: var(--sp-4) var(--sp-4) var(--sp-3);
  font-family: var(--font-display);
}
.brand-mark {
  width: 26px; height: 26px; flex: none; border-radius: 9px;
  background: conic-gradient(from 200deg, var(--accent), var(--warm), var(--accent));
  box-shadow: 0 0 0 1px var(--glass-brd-hi), 0 6px 18px -6px color-mix(in srgb, var(--warm) 55%, transparent);
  position: relative;
}
.brand-mark::after {                    /* esquirla de hielo interior */
  content: ''; position: absolute; inset: 5px 5px auto auto; width: 8px; height: 8px;
  border-radius: 3px; background: rgba(255,255,255,.75); transform: rotate(28deg);
}
.brand-mark { border: 0; padding: 0; cursor: pointer; }
.brand-name {
  font-size: var(--step-2); font-weight: 400; letter-spacing: -.03em; line-height: 1;
}
.brand-name b { font-weight: 700; }
/* Footer del sidebar (antes con estilos inline) */
.sidebar-foot { border-top: 1px solid var(--glass-brd); padding-top: var(--sp-2); }
.sidebar-email { padding-bottom: var(--sp-3); text-transform: none; letter-spacing: 0; }

/* ── Quién soy: la identidad de SALIDA ───────────────────────── */
/* La dirección del dominio arriba y grande; el Gmail abajo y en chico. El orden no es
   estético: el Gmail es dónde vive el correo, la dirección del dominio es quién sos
   para el que lo recibe — y es lo que Google rompió al cortar "Send mail as". */
.yo { padding: 0 var(--sp-2); }
.yo-actual {
  display: flex; align-items: center; gap: var(--sp-2);
  width: 100%; padding: var(--sp-2); border: 0; border-radius: var(--r-md);
  background: none; color: var(--ink); cursor: pointer; text-align: left;
  font-family: var(--font-ui); font-size: var(--step--1); font-weight: 600;
}
.yo-actual:disabled { cursor: default; }
.yo-actual:not(:disabled):hover { background: var(--glass-hi); }
.yo-dir { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.yo-tag {
  flex: none; font-size: .625rem; font-weight: 600; text-transform: uppercase;
  letter-spacing: .04em; padding: .05rem .35rem; border-radius: var(--r-pill);
  background: var(--glass-hi); color: var(--ink-dim);
}
.yo-caret { flex: none; opacity: .6; }
.yo-caret svg { width: 12px; height: 12px; transform: rotate(90deg); }
.yo-aviso { color: var(--warn); text-transform: none; letter-spacing: 0; padding: 0 var(--sp-2); }
/* Con la barra colapsada no cabe: queda el ícono de la casilla y nada más. */
:root[data-sidebar="collapsed"] .yo,
:root[data-rail] .yo { display: none; }
.sidebar-email .txt { font-weight: 400; }
/* nav-items que son <button> (tema, etc.) — reset uniforme */
button.nav-item { border: 0; background: none; font: inherit; text-align: left; width: 100%; cursor: pointer; }

/* ── Sidebar ─────────────────────────────────────────────────── */
.side-label {
  padding: var(--sp-3) var(--sp-4) var(--sp-1);
  font-size: var(--step--1); letter-spacing: .1em; text-transform: uppercase;
  color: var(--ink-fade); font-weight: 600;
}
.nav { padding: 0 var(--sp-2) var(--sp-3); display: flex; flex-direction: column; gap: 2px; }
.nav-item {
  display: flex; align-items: center; gap: var(--sp-3);
  padding: .5rem var(--sp-3); border-radius: var(--r-md);
  color: var(--ink-mid); text-decoration: none;
  transition: background var(--dur-fast) var(--ease), color var(--dur-fast) var(--ease),
              transform var(--dur-fast) var(--ease);
}
.nav-item:hover { background: var(--glass-hi); color: var(--ink); text-decoration: none; transform: translateX(2px); }
.nav-item:active { transform: translateX(2px) scale(.985); }
.nav-item.active { background: var(--glass-hi); color: var(--ink); box-shadow: inset 0 0 0 1px var(--glass-brd); }
/* Marca de carpeta activa: barrita de acento a la izquierda */
.nav-item.active::before {
  content: ''; position: absolute; left: -1px; width: 3px; height: 18px;
  border-radius: var(--r-pill); background: var(--warm);
  box-shadow: 0 0 10px color-mix(in srgb, var(--warm) 80%, transparent);
}
.nav-item { position: relative; }
.nav-item .ico { width: 17px; height: 17px; flex: none; opacity: .85; }
.nav-item .txt { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.badge {
  font-size: var(--step--1); font-variant-numeric: tabular-nums; font-weight: 600;
  padding: .05rem .42rem; border-radius: var(--r-pill);
  background: var(--warm); color: var(--warm-ink);
}
.badge.muted { background: var(--glass-hi); color: var(--ink-dim); }

/* ── Árbol de carpetas ───────────────────────────────────────── */
/* La fila envuelve el chevron y el link. El nav sigue siendo PLANO en el DOM (no hay
   <ul> anidados): la jerarquía la dibuja `--depth`, y así los badges, el "mover a" y
   la navegación siguen andando sin saber nada del árbol. */
.nav-row { display: flex; align-items: center; gap: 2px; }
.nav-row .nav-item { flex: 1; min-width: 0; padding-left: calc(var(--sp-2) + var(--depth, 0) * .85rem); }
.nav-twist {
  flex: none; width: 16px; height: 22px; padding: 0; border: 0; background: none;
  display: flex; align-items: center; justify-content: center;
  color: var(--ink-fade); cursor: pointer; border-radius: var(--r-sm);
}
.nav-twist .ico { width: 13px; height: 13px; transform: rotate(-90deg); transition: transform var(--dur-fast) var(--ease); }
.nav-twist.cerrado .ico { transform: rotate(0deg); }
.nav-twist:hover { color: var(--ink); background: var(--glass-hi); }
/* El hueco de las hojas: sin él, las hijas sin subcarpetas no se alinean con las que
   sí tienen chevron y el árbol se ve torcido. */
.nav-twist-empty { pointer-events: none; }
/* Con la barra colapsada no hay lugar para el chevron ni para la indentación: se ven
   los íconos y nada más. */
:root[data-sidebar="collapsed"] .nav-twist,
:root[data-rail] .nav-twist { display: none; }
/* `padding-left: 0` y no `--sp-2`: es lo que ya usa el rail para centrar los íconos
   (línea 274), y mi selector es más específico, así que si pongo otro valor le gano
   sin querer y los íconos quedan corridos. */
:root[data-sidebar="collapsed"] .nav-row .nav-item,
:root[data-rail] .nav-row .nav-item { padding-left: 0; }

/* El `⋯` de la carpeta y el `+` de "carpeta nueva": aparecen al hover para no llenar
   el sidebar de controles que casi nunca se usan. */
.side-label-row { display: flex; align-items: center; justify-content: space-between; }
.side-add, .nav-more {
  flex: none; border: 0; background: none; cursor: pointer; color: var(--ink-fade);
  padding: 0; width: 20px; height: 20px; border-radius: var(--r-sm);
  display: flex; align-items: center; justify-content: center; line-height: 1;
  opacity: 0; transition: opacity var(--dur-fast) var(--ease), color var(--dur-fast) var(--ease);
}
.side-add .ico { width: 14px; height: 14px; }
.pane-scroll:hover .side-add, .side-add:focus-visible,
.nav-row:hover .nav-more, .nav-more:focus-visible { opacity: 1; }
.side-add:hover, .nav-more:hover { color: var(--ink); background: var(--glass-hi); }
/* En touch no hay hover: si dependieran de él, la única forma de mover una carpeta
   sería arrastrar, que en touch tampoco anda. */
@media (pointer: coarse) { .side-add, .nav-more { opacity: .7; } }
:root[data-sidebar="collapsed"] .nav-more,
:root[data-rail] .nav-more,
:root[data-sidebar="collapsed"] .side-add,
:root[data-rail] .side-add { display: none; }

/* ── Un envio que todavia no llego a Enviados ─────────────────
   No es un link y no se arrastra: el mensaje NO esta en la carpeta del servidor. Se ve
   como una fila normal apenas apagada, con un chip que dice en que anda. */
.row-pendiente { cursor: default; }
.row-pendiente .row-from, .row-pendiente .row-subject { color: var(--ink-mid); }
.row-pendiente .row-avatar { opacity: .6; }
.chip-pend {
  display: inline-flex; align-items: center; gap: 5px;
  font-size: var(--step--1); color: var(--ink-dim); white-space: nowrap;
}
.chip-pend .spin { width: 11px; height: 11px; border-width: 2px; }
.chip-pend.malo { color: var(--danger); }
/* El que no salio: se ve el motivo y las dos salidas. La fila crece a lo alto porque
   los botones no caben en el ancho de la columna de la fecha, y esta bien que crezca —
   es una fila que pide una decision, no una mas de la lista. */
.row-fallo { background: color-mix(in srgb, var(--danger) 7%, transparent); }
.pend-acciones { flex-wrap: wrap; gap: var(--sp-2); justify-content: flex-end; }
.pend-error {
  font-size: var(--step--1); color: var(--danger); opacity: .85;
  max-width: 34ch; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
/* Nada de `pointer-events` aca: la fila pendiente no se abre porque los handlers de
   click la excluyen con `:not(.row-pendiente)`, no porque este bloqueada. Asi los botones
   funcionan sin necesitar una excepcion. */

/* ── Accion pedida y sin confirmar ("en vuelo") ───────────────
   Mover o borrar un mensaje SI pasa por el cache: el servidor lo escribe antes de hablar
   con IMAP y lo revierte si falla. Lo que faltaba no era bloquear —el mensaje ya
   existe— sino MOSTRAR que la accion se registro: la fila se sacaba recien con la
   respuesta, asi que con la red lenta arrastrabas un mail y no pasaba nada visible.

   Se apaga la fila y se le pone un spinner ENCIMA del avatar, que es la columna de
   estado: el punto de no-leido y el circulo de iniciales ya viven ahi. */
.row.en-vuelo { opacity: .5; pointer-events: none; }
.row.en-vuelo .row-avatar { visibility: hidden; }
.row.en-vuelo .row-avatar::before {
  content: ''; visibility: visible; position: absolute; inset: 4px;
  border-radius: 50%; border: 2px solid var(--glass-brd-hi); border-top-color: var(--accent);
  animation: spin .7s linear infinite;
}

/* ── Escritura de carpetas en curso ───────────────────────────
   Crear o mover una carpeta es la unica accion NO optimista de la app: la carpeta no
   existe hasta que el servidor la crea. Asi que en vez de fingir que ya paso, el nav se
   bloquea de verdad.

   `pointer-events:none` porque los items son <a> y un <a> no se deshabilita; el
   `aria-busy` lo pone el JS para que un lector de pantalla lo anuncie. */
#nav-folders.ocupado { pointer-events: none; }
/* La opacidad va en las FILAS y no en el contenedor: `opacity` crea un contexto de
   apilado y se aplica a todo el subarbol, asi que un hijo no puede volver a 1 — la fila
   pendiente se veria apagada igual que el resto y el spinner tambien. */
#nav-folders.ocupado .nav-row { opacity: .5; }
#nav-folders.ocupado .nav-row.pendiente { opacity: 1; }
/* El spinner se dibuja en el lugar del chevron, con `::after` sobre la fila: asi no hay
   que insertar ni sacar un elemento del DOM que despues la recarga se lleva igual. */
#nav-folders .nav-row.pendiente { position: relative; }
#nav-folders .nav-row.pendiente::after {
  content: ''; position: absolute; left: 2px; top: 50%; margin-top: -7px;
  width: 13px; height: 13px; border-radius: 50%;
  border: 2px solid var(--glass-brd-hi); border-top-color: var(--accent);
  animation: spin .7s linear infinite;
}
#nav-folders .nav-row.pendiente .nav-twist { visibility: hidden; }

/* Arrastrar: una carpeta del nav, o mensajes de la lista hacia el nav */
.nav-item.arrastrando, .row.arrastrando { opacity: .45; }
.nav-row.drop-aca {
  outline: 2px dashed color-mix(in srgb, var(--accent) 70%, transparent);
  outline-offset: -2px; border-radius: var(--r-md);
}
/* Con mensajes en la mano, el nav entero se insinua como destino: un realce apenas
   perceptible es lo que dice "solta aca y algo pasa" antes de sobrevolar una fila. */
.dragging-msg #nav-folders {
  background: color-mix(in srgb, var(--accent) 6%, transparent); border-radius: var(--r-md);
}
.dragging-msg .nav-row.drop-aca { background: color-mix(in srgb, var(--accent) 16%, transparent); }
.nav-raiz {
  margin: var(--sp-2) var(--sp-2) 0; padding: var(--sp-2);
  border: 1px dashed var(--glass-brd); border-radius: var(--r-md);
  font-size: var(--step--1); color: var(--ink-fade); text-align: center;
  /* Sólo aparece mientras se arrastra algo: el resto del tiempo es ruido. */
  display: none;
}
.dragging-folder .nav-raiz { display: block; }
.nav-raiz.drop-aca { border-style: solid; border-color: var(--accent); color: var(--ink); }
:root[data-sidebar="collapsed"] .nav-raiz,
:root[data-rail] .nav-raiz { display: none !important; }

/* ── Botones ─────────────────────────────────────────────────── */
.btn {
  display: inline-flex; align-items: center; justify-content: center; gap: var(--sp-2);
  min-height: var(--ctl-h); padding: 0 var(--sp-4); border-radius: var(--r-md);
  background: var(--glass); border: 1px solid var(--glass-brd);
  color: var(--ink); cursor: pointer; white-space: nowrap; font-weight: 500;
  transition: transform var(--dur-fast) var(--ease), background var(--dur-fast) var(--ease),
              border-color var(--dur-fast) var(--ease), box-shadow var(--dur-fast) var(--ease);
}
.btn:hover { background: var(--glass-hi); border-color: var(--glass-brd-hi); transform: translateY(-1px); }
.btn:active { transform: translateY(0) scale(.985); }
.btn[disabled] { opacity: .45; pointer-events: none; }
.btn-primary {
  /* Cálido con cuerpo de cristal: gloss arriba, sombra cálida difusa, borde de luz.
     No es un slab plano — pertenece al mismo material que el resto de la UI. */
  background: linear-gradient(165deg,
              color-mix(in srgb, var(--warm) 86%, #fff 14%) 0%,
              var(--warm-2) 100%);
  color: var(--warm-ink); border-color: transparent; font-weight: 600;
  box-shadow: 0 8px 20px -12px color-mix(in srgb, var(--warm) 70%, transparent),
              0 2px 5px -3px color-mix(in srgb, var(--warm-ink) 28%, transparent),
              inset 0 1px 0 color-mix(in srgb, #fff 45%, transparent),
              inset 0 -1px 0 color-mix(in srgb, var(--warm-ink) 12%, transparent);
}
.btn-primary:hover {
  /* Re-afirmar el gradiente cálido: si no, .btn:hover lo pinta gris
     (negro en dark / blanco en clear). Un punto más brillante en hover. */
  background: linear-gradient(165deg,
              color-mix(in srgb, var(--warm) 80%, #fff 20%) 0%,
              color-mix(in srgb, var(--warm-2) 92%, #fff 8%) 100%);
  border-color: transparent;
  transform: translateY(-1px);
  box-shadow: 0 12px 26px -12px color-mix(in srgb, var(--warm) 80%, transparent),
              0 3px 7px -3px color-mix(in srgb, var(--warm-ink) 32%, transparent),
              inset 0 1px 0 color-mix(in srgb, #fff 55%, transparent),
              inset 0 -1px 0 color-mix(in srgb, var(--warm-ink) 12%, transparent);
}
.btn-primary:active { transform: translateY(0) scale(.985); }
.btn-ghost { background: transparent; border-color: transparent; color: var(--ink-mid); }
.btn-ghost:hover { background: var(--glass-hi); color: var(--ink); }
.btn-danger { color: var(--danger); }
.btn-icon { padding: 0; width: var(--ctl-h); min-height: var(--ctl-h); border-radius: var(--r-md); }
.btn-block { width: 100%; }
.btn-sm { min-height: var(--ctl-h-sm); padding: 0 var(--sp-3); font-size: var(--step--1); }
.btn-sm.btn-icon { width: var(--ctl-h-sm); }

.compose-btn {
  /* Flex-item del aside (columna, align stretch): con width:auto estira a
     "ancho del sidebar − márgenes", igual que la píldora de carpeta. Ojo:
     .btn-block pone width:100%, que ignora los márgenes y desborda 16px. */
  width: auto;
  margin: 0 var(--sp-2) var(--sp-3);
  min-height: 2.6rem; letter-spacing: -.01em;
}
.compose-btn .ico { width: 16px; height: 16px; opacity: .95; }

/* ── Barra superior de panel ─────────────────────────────────── */
.bar {
  display: flex; align-items: center; gap: var(--sp-2);
  padding: var(--sp-3); border-bottom: 1px solid var(--glass-brd);
  flex: none;
}
.bar-title { font-family: var(--font-display); font-size: var(--step-1); font-weight: 500; letter-spacing: -.02em; }
.bar-spacer { flex: 1; }
.bar-meta { font-size: var(--step--1); color: var(--ink-dim); font-variant-numeric: tabular-nums; }

/* ── Search ──────────────────────────────────────────────────── */
.search { position: relative; margin: var(--sp-3) var(--sp-3) var(--sp-2); flex: none; }
.search input {
  width: 100%; padding: .5rem .75rem .5rem 2.1rem;
  background: var(--glass); border: 1px solid var(--glass-brd);
  border-radius: var(--r-pill); color: var(--ink);
  transition: border-color var(--dur-fast) var(--ease), background var(--dur-fast) var(--ease);
}
.search input::placeholder { color: var(--ink-fade); }
.search input:focus { outline: none; border-color: var(--accent); background: var(--glass-hi); }
.search .ico { position: absolute; left: .7rem; top: 50%; transform: translateY(-50%); width: 15px; height: 15px; color: var(--ink-fade); }

/* ── Lista de mensajes ───────────────────────────────────────── */
.list { display: flex; flex-direction: column; }
.row {
  display: grid; grid-template-columns: 30px minmax(0,1fr) auto;
  gap: var(--sp-1) var(--sp-3);
  padding: .68rem var(--sp-3);
  border-bottom: 1px solid color-mix(in srgb, var(--glass-brd) 55%, transparent);
  cursor: pointer; text-decoration: none; color: inherit;
  /* Sin backdrop-filter aca a proposito (ver nota de performance arriba). */
  transition: background var(--dur-fast) var(--ease), box-shadow var(--dur-fast) var(--ease);
}
/* ── Leído vs no leído ────────────────────────────────────────
   El que recede es el LEÍDO, no al revés, y no es estética: hover, `.row.active` y
   `.row.picked` ya marcan su estado AGREGANDO color (glass, teal, durazno). Un cuarto
   fondo agregado para el no-leído competiría con los tres, y además se confundiría con
   "seleccionada".
   Así que el no-leído se queda a contraste pleno —negrita, asunto claro, el punto del
   avatar— y el leído se hunde.
   VA ANTES de las reglas de estado a propósito: `.row:not(.unseen)` tiene la MISMA
   especificidad que `.row:hover` (`:not()` cuenta lo de adentro), así que si fuera
   después le ganaría por orden y el hover no se vería sobre las filas leídas — o sea,
   sobre casi todas. */
.row:not(.unseen) { background: color-mix(in srgb, var(--bg-0) 42%, transparent); }
.row:not(.unseen) .row-from { color: var(--ink-mid); font-weight: 400; }
.row:not(.unseen) .row-avatar { opacity: .68; }
.row:hover .row-avatar { opacity: 1; }

/* Hover cálido: tinte durazno + filo de luz que entra por la izquierda.
   Activo usa teal (estructura); más específico, gana sobre el hover. */
.row:hover { background: color-mix(in srgb, var(--glass-hi) 84%, var(--warm) 9%); text-decoration: none;
  box-shadow: inset 2px 0 0 color-mix(in srgb, var(--warm) 62%, transparent); }
.row:active { background: color-mix(in srgb, var(--glass-hi) 70%, var(--warm) 12%); }
.row.active { background: var(--glass-hi); box-shadow: inset 2px 0 0 var(--accent); }

/* ── El avatar: iniciales, color del remitente, y control de selección ──
   UNA sola cosa en la columna 1, y ahí está la lección: antes había un punto y un
   checkbox peleándose la celda, y como el punto no declaraba `grid-column` el
   auto-placement lo empujaba a la columna 2 y arrastraba el remitente y el asunto
   con él (la fila medía el doble y el remitente quedaba en "G…"). */
.row-avatar {
  grid-row: 1 / span 2; grid-column: 1;
  align-self: center; justify-self: center; position: relative;
  width: 30px; height: 30px; padding: 0; border: 0; border-radius: 50%;
  display: flex; align-items: center; justify-content: center;
  cursor: pointer; flex: none;
  /* Luminancia y croma FIJOS, sólo gira el tono. Con `hsl()` el mismo 50% de
     luminosidad se ve casi blanco en amarillo y oscuro en azul, así que el texto
     blanco se pierde en media rueda de tonos; en oklch el contraste es parejo en
     los 360 y alcanza un solo color de texto. */
  background: oklch(58% .13 calc(var(--hue, 0) * 1deg));
  color: #fff;
  transition: box-shadow var(--dur-fast) var(--ease), transform var(--dur-fast) var(--ease);
}
.row-avatar:hover { box-shadow: 0 0 0 2px color-mix(in srgb, var(--warm) 55%, transparent); }
.row-avatar:active { transform: scale(.92); }
.row-ini {
  font-family: var(--font-ui); font-size: .6875rem; font-weight: 700;
  letter-spacing: .02em; line-height: 1; user-select: none;
}
/* El "no leído" pierde su columna, así que pasa a ser un badge en la esquina del
   avatar. Sumarle una columna al grid no era opción: la lista angosta del modo
   inline no la soporta. */
.row-dot {
  position: absolute; top: -1px; right: -1px;
  width: 8px; height: 8px; border-radius: 50%; background: transparent;
}
.row.unseen .row-dot {
  background: var(--warm);
  box-shadow: 0 0 0 2px var(--bg-1), 0 0 9px color-mix(in srgb, var(--warm) 85%, transparent);
}
.row-top { display: flex; align-items: baseline; gap: var(--sp-2); min-width: 0; }
.row-from { font-weight: 500; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.row.unseen .row-from { font-weight: 700; }
.row-subject {
  grid-column: 2; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
  color: var(--ink-mid);
}
.row.unseen .row-subject { color: var(--ink); }
.row-snippet { color: var(--ink-dim); font-weight: 400; }
/* De que carpeta es un resultado de la busqueda global. Va ANTES del asunto y no en una
   columna propia: la lista angosta del modo inline no soporta una columna mas, y leido de
   corrido ("Enviados · Presupuesto") dice lo mismo. */
.row-carpeta {
  display: inline-block; margin-right: var(--sp-2);
  font-size: .625rem; font-weight: 600; text-transform: uppercase; letter-spacing: .04em;
  padding: .05rem .35rem; border-radius: var(--r-pill);
  background: var(--glass-hi); color: var(--ink-dim); vertical-align: 1px;
}

/* La barra que dice DONDE se esta buscando, y deja cambiarlo. Existe porque el alcance
   por omision era invisible: el buscador recortaba a la carpeta abierta sin decirlo. */
.search-alcance {
  display: flex; align-items: center; gap: var(--sp-2); flex-wrap: wrap;
  margin: 0 var(--sp-3) var(--sp-2); font-size: var(--step--1); color: var(--ink-dim);
}
.search-alcance b { color: var(--ink-mid); font-weight: 600; }
.search-alcance a, .search-alcance .link { color: var(--accent); }
/* `.link`: un <button> que se ve como un link. Hace falta porque la accion es de la
   pagina (re-buscar por AJAX) y no una navegacion — un <a href> ahi recargaria. */
.link {
  background: none; border: 0; padding: 0; font: inherit; cursor: pointer;
  color: var(--accent); text-decoration: underline; text-underline-offset: 2px;
}
.link:hover { color: var(--ink); }

/* El skeleton de la busqueda aumentada, al final de la lista: DONDE van a aparecer los
   resultados. Ponerlo arriba o en la barra diria "estoy cargando algo" sin decir donde. */
.search-mas {
  display: flex; align-items: center; justify-content: center; gap: var(--sp-2);
  padding: var(--sp-4); font-size: var(--step--1); color: var(--ink-dim);
}
.row-date {
  grid-row: 1; grid-column: 3; font-size: var(--step--1); color: var(--ink-dim);
  font-variant-numeric: tabular-nums; white-space: nowrap;
}
.row-icons { grid-row: 2; grid-column: 3; display: flex; gap: .3rem; align-items: center; justify-content: flex-end; color: var(--ink-fade); }
.row-icons .ico { width: 14px; height: 14px; }
/* Sentinel del scroll infinito */
.list-sentinel { display: flex; align-items: center; justify-content: center; padding: var(--sp-4); min-height: 44px; }

.row .star { color: var(--ink-fade); background: none; border: 0; cursor: pointer; padding: 0; line-height: 1; }
.row .star.on { color: var(--warn); }
/* Botón "mover" — aparece al hover de la fila (o siempre en touch) */
.row-move { color: var(--ink-fade); background: none; border: 0; cursor: pointer; padding: 0; line-height: 1;
  opacity: 0; transition: opacity var(--dur-fast) var(--ease), color var(--dur-fast) var(--ease); }
.row:hover .row-move, .row.active .row-move { opacity: 1; }
.row-move:hover { color: var(--accent); }
@media (pointer: coarse) { .row-move { opacity: .7; } }

/* ── Menú "Mover a…" (flotante) ──────────────────────────────── */
.move-menu {
  position: fixed; z-index: 70; min-width: 190px; max-height: 60vh; overflow: auto;
  padding: var(--sp-2); border-radius: var(--r-md);
  animation: cardIn var(--dur-fast) var(--ease-out);
}
.move-menu-head { font-size: var(--step--1); color: var(--ink-fade); font-weight: 600;
  padding: var(--sp-1) var(--sp-2) var(--sp-2); letter-spacing: .04em; text-transform: uppercase; }
.move-item { display: flex; align-items: center; gap: var(--sp-2); width: 100%;
  padding: .45rem var(--sp-2); border: 0; background: none; color: var(--ink); cursor: pointer;
  border-radius: var(--r-sm); text-align: left; font: inherit;
  transition: background var(--dur-fast) var(--ease); }
.move-item:hover { background: var(--glass-hi); }
.move-item .ico { width: 15px; height: 15px; color: var(--ink-dim); flex: none; }

/* ── Estado del borrador (autosave) ──────────────────────────── */
.draft-status { font-size: var(--step--1); color: var(--ink-dim); font-variant-numeric: tabular-nums;
  margin-left: var(--sp-2); white-space: nowrap; }

/* Reveal escalonado del primer pintado — el "AAAAA" que se nota */
.list.reveal .row {
  animation: rise var(--dur-slow) var(--ease-out) backwards;
}
.list.reveal .row:nth-child(1){animation-delay:0ms}   .list.reveal .row:nth-child(2){animation-delay:22ms}
.list.reveal .row:nth-child(3){animation-delay:44ms}  .list.reveal .row:nth-child(4){animation-delay:66ms}
.list.reveal .row:nth-child(5){animation-delay:88ms}  .list.reveal .row:nth-child(6){animation-delay:110ms}
.list.reveal .row:nth-child(7){animation-delay:132ms} .list.reveal .row:nth-child(8){animation-delay:154ms}
.list.reveal .row:nth-child(9){animation-delay:176ms} .list.reveal .row:nth-child(n+10){animation-delay:198ms}
@keyframes rise { from { opacity: 0; transform: translateY(7px); } to { opacity: 1; transform: none; } }

/* ── Skeletons (la latencia es parte del diseño) ─────────────── */
.skel { border-radius: var(--r-sm); background: var(--glass-hi); position: relative; overflow: hidden; }
.skel::after {
  content: ''; position: absolute; inset: 0;
  background: linear-gradient(90deg, transparent, var(--glass-brd-hi), transparent);
  transform: translateX(-100%);
  animation: shimmer 1.25s infinite;
}
@keyframes shimmer { to { transform: translateX(100%); } }
.skel-line { height: 10px; margin-bottom: .5rem; }
.skel-row { display: grid; grid-template-columns: 20px 1fr auto; gap: var(--sp-3); padding: .78rem var(--sp-3);
            border-bottom: 1px solid color-mix(in srgb, var(--glass-brd) 55%, transparent); }
.skel-msg { padding: var(--sp-5); }

/* ── Lectura del mensaje ─────────────────────────────────────── */
.msg-head { padding: var(--sp-5) var(--sp-5) var(--sp-4); border-bottom: 1px solid var(--glass-brd); flex: none; }
/* Espacio reservado a la derecha para que el botón "Volver" flotante no pise el asunto */
#reader .msg-head { padding-right: calc(var(--sp-5) + 150px); }
/* Botón "Volver a la lista": pastilla de cristal flotante, arriba a la derecha */
.reader-back {
  position: absolute; top: var(--sp-4); right: var(--sp-4); z-index: 14;
  display: inline-flex; align-items: center; gap: var(--sp-2);
  min-height: var(--ctl-h); padding: 0 var(--sp-4);
  border-radius: var(--r-pill); font: inherit; font-weight: 600; cursor: pointer;
  color: var(--ink); background: var(--glass); border: 1px solid var(--glass-brd-hi);
  -webkit-backdrop-filter: blur(14px) saturate(1.25); backdrop-filter: blur(14px) saturate(1.25);
  box-shadow: 0 8px 22px -12px rgba(0,0,0,.55), inset 0 1px 0 color-mix(in srgb, #fff 22%, transparent);
  transition: transform var(--dur-fast) var(--ease), background var(--dur-fast) var(--ease),
              border-color var(--dur-fast) var(--ease), box-shadow var(--dur-fast) var(--ease);
}
.reader-back:hover {
  background: var(--glass-hi); border-color: color-mix(in srgb, var(--warm) 45%, var(--glass-brd-hi));
  transform: translateY(-1px);
  box-shadow: 0 12px 28px -12px rgba(0,0,0,.6), 0 0 0 3px color-mix(in srgb, var(--warm) 14%, transparent),
              inset 0 1px 0 color-mix(in srgb, #fff 28%, transparent);
}
.reader-back:active { transform: translateY(0) scale(.98); }
.reader-back .ico { width: 16px; height: 16px; }
.msg-subject {
  font-family: var(--font-display); font-size: var(--step-2); font-weight: 500;
  letter-spacing: -.02em; margin: 0 0 var(--sp-3); line-height: 1.25;
}
.msg-who { display: flex; align-items: center; gap: var(--sp-3); }
.avatar {
  width: 38px; height: 38px; flex: none; border-radius: 50%;
  display: grid; place-items: center; font-weight: 600; font-size: var(--step-0);
  background: linear-gradient(140deg, color-mix(in srgb, var(--accent) 30%, transparent),
                                      color-mix(in srgb, var(--accent-2) 30%, transparent));
  border: 1px solid var(--glass-brd-hi); color: var(--ink);
  text-transform: uppercase;
}
.msg-from { font-weight: 600; }
.msg-addr, .msg-to { font-size: var(--step--1); color: var(--ink-dim); }
.msg-date { font-size: var(--step--1); color: var(--ink-dim); white-space: nowrap; font-variant-numeric: tabular-nums; }
.msg-actions { display: flex; gap: var(--sp-2); padding: var(--sp-3) var(--sp-5); flex-wrap: wrap; flex: none; }
.msg-body { padding: var(--sp-5); flex: 1; min-height: 0; position: relative; }
/* Entrada del lector: los nodos se recrean en cada open → el fade-rise
   escalonado corre solo. Solo transform/opacity. */
@keyframes readerIn { from { opacity: 0; transform: translateY(9px); } to { opacity: 1; transform: none; } }
#reader .msg-head    { animation: readerIn 260ms var(--ease-out) both; }
#reader .msg-actions { animation: readerIn 260ms var(--ease-out) 45ms both; }
#reader .msg-body    { animation: readerIn 320ms var(--ease-out) 80ms both; }
/* El cuerpo se renderiza en un iframe sandbox: aislamiento real del HTML ajeno */
.msg-frame { width: 100%; border: 0; background: transparent; display: block; min-height: 220px;
  opacity: 1; transition: opacity var(--dur) var(--ease-out); }
.msg-frame.loading { opacity: 0; }        /* preloader visible hasta que el cuerpo se arma */
.body-loading {
  position: absolute; inset: 0; display: grid; place-items: center; z-index: 2;
  background: var(--glass); border-radius: var(--r-md);
}
.body-loading .spin { width: 26px; height: 26px; border-width: 3px; }

.notice {
  display: flex; align-items: center; gap: var(--sp-2); flex-wrap: wrap;
  margin: 0 var(--sp-5) var(--sp-3); padding: .55rem .8rem;
  border-radius: var(--r-md); border: 1px dashed var(--glass-brd-hi);
  background: var(--glass); font-size: var(--step--1); color: var(--ink-mid);
}
/* El `.notice` nacio para el lector, que tiene padding de --sp-5. En la lista los
   margenes son --sp-3, asi que sin esto queda desalineado con la barra y el buscador. */
.notice-inline { margin: 0 var(--sp-3) var(--sp-2); }

.attachments { display: flex; flex-wrap: wrap; gap: var(--sp-2); padding: 0 var(--sp-5) var(--sp-5); }
.attach {
  display: inline-flex; align-items: center; gap: var(--sp-2);
  padding: .45rem .7rem; border-radius: var(--r-md);
  background: var(--glass); border: 1px solid var(--glass-brd); color: var(--ink);
  font-size: var(--step--1); text-decoration: none;
  transition: transform var(--dur-fast) var(--ease), border-color var(--dur-fast) var(--ease);
}
.attach:hover { transform: translateY(-1px); border-color: var(--accent); text-decoration: none; }
.attach .sz { color: var(--ink-fade); }

/* ── Estado vacio ────────────────────────────────────────────── */
.empty {
  flex: 1; display: grid; place-content: center; justify-items: center;
  gap: var(--sp-3); padding: var(--sp-7); text-align: center; color: var(--ink-dim);
}
.empty-mark {
  width: 62px; height: 62px; border-radius: var(--r-xl);
  background: var(--glass); border: 1px solid var(--glass-brd);
  display: grid; place-items: center; color: var(--ink-fade);
  animation: float 6s var(--ease) infinite alternate;
}
@keyframes float { from { transform: translateY(-3px); } to { transform: translateY(4px); } }
.empty h3 { font-family: var(--font-display); font-weight: 400; font-size: var(--step-1); color: var(--ink-mid); margin: 0; }

/* ═══════════════════════════════════════════════════════════════
   Transición de carpeta (nav AJAX) — genjutsu cristal
   3 variantes asignadas por carpeta. Solo transform/opacity/filter.
   El preloader es un filo de luz que barre el borde superior.
   ═══════════════════════════════════════════════════════════════ */

/* Preloader: filo accent que barre el tope de la lista */
.list-loader {
  position: absolute; top: 0; left: 0; right: 0; height: 2px;
  overflow: hidden; pointer-events: none; opacity: 0; z-index: 5;
  transition: opacity 120ms var(--ease);
}
.list-loader::before {
  content: ''; position: absolute; inset: 0; transform: translateX(-100%);
  /* Filo frío (teal) con un beso cálido en la cola — cool-dominante + calidez. */
  background: linear-gradient(90deg, transparent, var(--accent) 38%, var(--warm) 66%, transparent);
  box-shadow: 0 0 12px color-mix(in srgb, var(--warm) 45%, var(--accent));
}
.pane-list.loading .list-loader { opacity: 1; }
.pane-list.loading .list-loader::before { animation: sweepX 560ms var(--ease-out); }
@keyframes sweepX { from { transform: translateX(-100%); } to { transform: translateX(100%); } }

/* Salida del contenido actual (contenedor) */
.list.exit-a { animation: exitA 120ms var(--ease) forwards; }
.list.exit-b { animation: exitB 150ms var(--ease) forwards; }
.list.exit-c { animation: exitC 160ms var(--ease) forwards; }
@keyframes exitA { to { opacity: 0; } }
@keyframes exitB { to { opacity: 0; filter: blur(3px); transform: translateY(-4px); } }
@keyframes exitC { to { opacity: 0; transform: translateX(-12px) scale(.99); } }

/* Entrada escalonada — el stagger sale de --row-i * --stagger (escala a N filas) */
.list.enter-a, .list.enter-b, .list.enter-c { }
.list.enter-a { --stagger: 16ms; }
.list.enter-b { --stagger: 28ms; }
.list.enter-c { --stagger: 40ms; }
.list.enter-a .row,
.list.enter-b .row,
.list.enter-c .row {
  animation-delay: calc(var(--row-i, 0) * var(--stagger));
  animation-fill-mode: backwards;
  animation-timing-function: var(--ease-out);
}
.list.enter-a .row { animation-name: enterA; animation-duration: 170ms; }
.list.enter-b .row { animation-name: enterB; animation-duration: 230ms; }
.list.enter-c .row { animation-name: enterC; animation-duration: 300ms; }
@keyframes enterA { from { opacity: 0; transform: translateY(6px); }               to { opacity: 1; transform: none; } }
@keyframes enterB { from { opacity: 0; transform: translateY(9px); }               to { opacity: 1; transform: none; } }
@keyframes enterC { from { opacity: 0; transform: translateY(12px) scale(.985); }  to { opacity: 1; transform: none; } }

/* El vacío también entra con un fade suave */
.list-enter-empty { animation: enterA 200ms var(--ease-out); }

/* Variante C: pulso de glow en la carpeta activa del sidebar */
.nav-item.pulse::before { animation: navPulse 600ms var(--ease-out); }
@keyframes navPulse {
  0%   { box-shadow: 0 0 0 var(--accent); opacity: .4; }
  40%  { box-shadow: 0 0 16px var(--accent); opacity: 1; }
  100% { box-shadow: 0 0 10px var(--accent); opacity: 1; }
}

@media (prefers-reduced-motion: reduce) {
  .pane-list.loading .list-loader { opacity: 0; }
  .list.exit-a, .list.exit-b, .list.exit-c,
  .list.enter-a .row, .list.enter-b .row, .list.enter-c .row { animation: none !important; }
}

/* ── Formularios ─────────────────────────────────────────────── */
.field { display: flex; flex-direction: column; gap: var(--sp-1); margin-bottom: var(--sp-3); }
.field > label { font-size: var(--step--1); color: var(--ink-dim); font-weight: 600; letter-spacing: .02em; }
.input, .textarea, select.input {
  width: 100%; padding: .55rem .8rem;
  background: var(--glass); border: 1px solid var(--glass-brd);
  border-radius: var(--r-md); color: var(--ink);
  transition: border-color var(--dur-fast) var(--ease), background var(--dur-fast) var(--ease);
}
.input:focus, .textarea:focus { outline: none; border-color: var(--accent); background: var(--glass-hi); }
.textarea { min-height: 96px; resize: vertical; font-family: inherit; }
.hint { font-size: var(--step--1); color: var(--ink-fade); }
.row-inline { display: flex; gap: var(--sp-3); flex-wrap: wrap; align-items: flex-end; }
.row-inline > * { flex: 1; min-width: 180px; }

/* Switch (autoresponder, imagenes remotas, etc.) */
.switch { display: inline-flex; align-items: center; gap: var(--sp-3); cursor: pointer; }
.switch input { position: absolute; opacity: 0; width: 0; height: 0; }
.switch .track {
  width: 42px; height: 24px; border-radius: var(--r-pill); flex: none;
  background: var(--glass-hi); border: 1px solid var(--glass-brd); position: relative;
  transition: background var(--dur) var(--ease), border-color var(--dur) var(--ease);
}
.switch .track::after {
  content: ''; position: absolute; top: 2px; left: 2px; width: 18px; height: 18px;
  border-radius: 50%; background: var(--ink-dim);
  transition: transform var(--dur) var(--ease), background var(--dur) var(--ease);
}
.switch input:checked + .track { background: color-mix(in srgb, var(--accent) 40%, transparent); border-color: var(--accent); }
.switch input:checked + .track::after { transform: translateX(18px); background: var(--accent); }

/* ── Compositor WYSIWYG ──────────────────────────────────────── */
.compose { display: flex; flex-direction: column; height: 100%; min-height: 0; }
.compose-fields { padding: var(--sp-4) var(--sp-5) 0; flex: none; }
.addr-row {
  display: flex; align-items: center; gap: var(--sp-3);
  border-bottom: 1px solid var(--glass-brd); padding: .4rem 0;
}
.addr-row label { font-size: var(--step--1); color: var(--ink-dim); width: 52px; flex: none; font-weight: 600; }
.addr-row input {
  flex: 1; background: transparent; border: 0; padding: .25rem 0; color: var(--ink); min-width: 0;
}
.addr-row input:focus { outline: none; }
.addr-row .btn-ghost { flex: none; }

.toolbar {
  display: flex; align-items: center; gap: var(--sp-1); flex-wrap: wrap;
  padding: var(--sp-2) var(--sp-5); flex: none;
  border-bottom: 1px solid var(--glass-brd);
}
.tool {
  width: 30px; height: 30px; display: grid; place-items: center;
  border-radius: var(--r-sm); border: 1px solid transparent; background: transparent;
  color: var(--ink-mid); cursor: pointer;
  transition: background var(--dur-fast) var(--ease), color var(--dur-fast) var(--ease);
}
.tool:hover { background: var(--glass-hi); color: var(--ink); }
.tool.on { background: var(--glass-hi); color: var(--accent); border-color: var(--glass-brd); }
.tool-sep { width: 1px; height: 18px; background: var(--glass-brd); margin: 0 var(--sp-1); }

.editor {
  flex: 1; min-height: 0; overflow-y: auto; padding: var(--sp-4) var(--sp-5);
  line-height: 1.6; outline: none;
}
.editor:empty::before { content: attr(data-placeholder); color: var(--ink-fade); }
.editor img { max-width: 100%; height: auto; }
.editor blockquote, .yimail-quote {
  margin: var(--sp-3) 0; padding-left: var(--sp-4);
  border-left: 2px solid var(--glass-brd-hi); color: var(--ink-dim);
}
.quote-head { color: var(--ink-dim); font-size: var(--step--1); }
.compose-foot {
  display: flex; align-items: center; gap: var(--sp-2); flex-wrap: wrap;
  padding: var(--sp-3) var(--sp-5); border-top: 1px solid var(--glass-brd); flex: none;
}
.chip {
  display: inline-flex; align-items: center; gap: var(--sp-2);
  padding: .3rem .6rem; border-radius: var(--r-pill);
  background: var(--glass); border: 1px solid var(--glass-brd); font-size: var(--step--1);
}
.chip button { background: none; border: 0; color: var(--ink-dim); cursor: pointer; padding: 0; line-height: 1; }
.chip button:hover { color: var(--danger); }
.chips { display: flex; flex-wrap: wrap; gap: var(--sp-2); padding: 0 var(--sp-5) var(--sp-2); }

/* ── Login ───────────────────────────────────────────────────── */
.login-wrap { height: 100dvh; display: grid; place-items: center; padding: var(--sp-4); overflow: auto; }
.login-card { width: min(420px, 100%); padding: var(--sp-6); animation: cardIn var(--dur-slow) var(--ease-out); }
@keyframes cardIn { from { opacity: 0; transform: translateY(14px) scale(.985); } to { opacity: 1; transform: none; } }
.login-card .brand { padding: 0 0 var(--sp-5); justify-content: center; }
.login-sub { text-align: center; color: var(--ink-dim); font-size: var(--step--1); margin: calc(-1 * var(--sp-4)) 0 var(--sp-5); }

/* ── Flash / alertas ─────────────────────────────────────────── */
.flash-stack { position: fixed; top: var(--sp-4); right: var(--sp-4); z-index: 60; display: flex; flex-direction: column; gap: var(--sp-2); max-width: min(380px, calc(100vw - 2rem)); }
.flash {
  padding: .6rem .9rem; border-radius: var(--r-md);
  background: var(--glass); border: 1px solid var(--glass-brd);
  backdrop-filter: blur(18px); -webkit-backdrop-filter: blur(18px);
  box-shadow: var(--shadow-lg); font-size: var(--step-0);
  animation: slideIn var(--dur) var(--ease-out);
}
@keyframes slideIn { from { opacity: 0; transform: translateX(18px); } to { opacity: 1; transform: none; } }
.flash.error   { border-color: color-mix(in srgb, var(--danger) 55%, transparent); color: var(--danger); }
.flash.success { border-color: color-mix(in srgb, var(--accent) 55%, transparent); }
.alert { padding: .6rem .9rem; border-radius: var(--r-md); background: var(--glass); border: 1px solid var(--glass-brd); font-size: var(--step-0); margin-bottom: var(--sp-4); }
.alert.error { border-color: color-mix(in srgb, var(--danger) 55%, transparent); color: var(--danger); }

/* ── "Deshacer envío": barra con cuenta regresiva ────────────── */
.flash.undo { display: flex; align-items: center; gap: var(--sp-3); padding: .55rem .7rem; }
.undo-txt { flex: 1; }
.undo-ring {
  width: 26px; height: 26px; flex: none; border-radius: 50%;
  display: grid; place-items: center;
  border: 2px solid var(--glass-brd-hi);
  /* El anillo se "vacía" con la cuenta regresiva (animación pura, sin JS). */
  background: conic-gradient(var(--accent) var(--undo-pct, 100%), transparent 0);
  animation: undoDrain var(--undo-ms, 10s) linear forwards;
  position: relative;
}
.undo-ring::after {
  content: ''; position: absolute; inset: 3px; border-radius: 50%; background: var(--bg-1);
}
.undo-num {
  position: relative; z-index: 1; font-size: 11px; font-weight: 700;
  font-variant-numeric: tabular-nums; color: var(--ink);
}
@keyframes undoDrain { from { --undo-pct: 100%; } to { --undo-pct: 0%; } }
@property --undo-pct { syntax: '<percentage>'; inherits: false; initial-value: 100%; }

/* ── Overlay (ayuda de atajos) ───────────────────────────────── */
.overlay {
  position: fixed; inset: 0; z-index: 80;
  display: grid; place-items: center; padding: var(--sp-4);
  background: color-mix(in srgb, var(--bg-0) 62%, transparent);
  backdrop-filter: blur(6px); -webkit-backdrop-filter: blur(6px);
  animation: fadeIn var(--dur) var(--ease-out);
}
@keyframes fadeIn { from { opacity: 0; } to { opacity: 1; } }
.help-card {
  width: min(520px, 100%); max-height: 82vh; overflow: auto;
  animation: cardIn var(--dur) var(--ease-out);
}
.help-grid {
  display: grid; grid-template-columns: auto 1fr; gap: var(--sp-2) var(--sp-4);
  padding: var(--sp-4) var(--sp-5) var(--sp-5); align-items: center;
}
.help-grid span { color: var(--ink-mid); font-size: var(--step-0); }

/* ── Modal de servicios de Google ─────────────────────────────
   Comparte la tarjeta con la ayuda (`.help-card`); lo unico propio es la grilla de
   accesos, que es de baldosas y no de lista: son 7 y con dos columnas entran sin
   scrollear. */
.gserv-body { padding: var(--sp-3) var(--sp-5) var(--sp-5); }
.gserv-grid {
  display: grid; grid-template-columns: repeat(auto-fit, minmax(150px, 1fr));
  gap: var(--sp-2); margin-bottom: var(--sp-3);
}
.gserv-item {
  display: flex; align-items: center; gap: var(--sp-2);
  padding: var(--sp-3); border-radius: var(--r-md);
  background: var(--glass); border: 1px solid var(--glass-brd);
  color: var(--ink); text-decoration: none; font-size: var(--step--1);
  transition: background var(--dur-fast) var(--ease), transform var(--dur-fast) var(--ease);
}
.gserv-item:hover { background: var(--glass-hi); transform: translateY(-1px); text-decoration: none; }
.gserv-item .ico { width: 16px; height: 16px; flex: none; opacity: .8; }
.gserv-nota { margin: 0; opacity: .6; }
kbd {
  font-family: var(--font-mono); font-size: var(--step--1);
  padding: .18rem .45rem; border-radius: 6px; white-space: nowrap;
  background: var(--glass-hi); border: 1px solid var(--glass-brd);
  box-shadow: 0 1px 0 var(--glass-brd-hi); color: var(--ink);
}

/* ── Settings ────────────────────────────────────────────────── */
.settings { max-width: 760px; margin: 0 auto; padding: var(--sp-5); }
.card { padding: var(--sp-5); margin-bottom: var(--sp-4); }
.card h2 {
  font-family: var(--font-display); font-size: var(--step-1); font-weight: 500;
  letter-spacing: -.02em; margin: 0 0 var(--sp-2);
}
.card .sub { color: var(--ink-dim); font-size: var(--step--1); margin: 0 0 var(--sp-4); }
.sig-item { border-top: 1px solid var(--glass-brd); padding-top: var(--sp-4); margin-top: var(--sp-4); }
.sig-preview {
  padding: var(--sp-3); border-radius: var(--r-md); background: var(--glass);
  border: 1px dashed var(--glass-brd-hi); min-height: 72px; margin-bottom: var(--sp-3);
}
.sig-preview img { max-width: 100%; }

/* ── Utilidades ──────────────────────────────────────────────── */
/* Tamaño por defecto de todo icono SVG. Los contextos que necesitan otro
   tamaño (nav, filas, search…) lo pisan por especificidad. Sin esto, los
   iconos de la toolbar y los botones quedan sin dimensiones (invisibles). */
.ico { display: inline-block; vertical-align: middle; width: 18px; height: 18px; flex: none; }
.empty-mark .ico { width: 26px; height: 26px; }
.tool .ico { width: 17px; height: 17px; }
.mono { font-family: var(--font-mono); font-size: var(--step--1); }
.dim { color: var(--ink-dim); }
.plain { white-space: pre-wrap; word-wrap: break-word; font-family: var(--font-mono); font-size: var(--step-0); margin: 0; }
.img-blocked { display: inline-block; padding: 0 .2rem; opacity: .5; }
.sr { position: absolute; width: 1px; height: 1px; overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; }
.spin { width: 15px; height: 15px; border: 2px solid var(--glass-brd-hi); border-top-color: var(--accent);
        border-radius: 50%; animation: spin .7s linear infinite; }
@keyframes spin { to { transform: rotate(360deg); } }
.back-btn { display: none; }

/* ── Responsive: 3 → 2 → 1 columna ───────────────────────────── */
@media (max-width: 1180px) {
  :root { --list-w: 340px; --sidebar-w: 200px; }
}
@media (max-width: 940px) {
  .app { grid-template-columns: 64px minmax(0,1fr); }
  .app.no-reader { grid-template-columns: 64px minmax(0,1fr); }
  /* El swap lista↔lector lo maneja .reading en todos los anchos (arriba). */
  .brand-name, .nav-item .txt, .side-label { display: none; }
  .nav-item { justify-content: center; }
  .brand { justify-content: center; padding: var(--sp-4) 0 var(--sp-3); }
  .compose-btn { margin: 0 var(--sp-2) var(--sp-2); }
  .compose-btn .txt { display: none; }
}
@media (max-width: 620px) {
  /* Botón "Volver" compacto (solo icono) y menos reserva en el header */
  .reader-back { padding: 0; width: var(--ctl-h); justify-content: center; }
  .reader-back .txt { display: none; }
  #reader .msg-head { padding-right: calc(var(--sp-4) + 52px); }
}
@media (max-width: 620px) {
  /* Dos filas: la franja del logo arriba y el panel abierto abajo. Antes el sidebar
     estaba en `display:none` y el ☰ de la barra de la lista era la ÚNICA forma de
     abrirlo; ahora que el logo es el único control, tiene que estar a la vista. */
  .app {
    padding: var(--sp-2); gap: var(--sp-2);
    grid-template-columns: minmax(0,1fr);
    grid-template-rows: auto minmax(0,1fr);
  }
  .app.no-reader { grid-template-columns: minmax(0,1fr); }
  /* La franja: sólo la marca. El nav, el botón de escribir y el pie quedan para
     cuando se abre — si no, el sidebar se comería media pantalla del teléfono. */
  .pane-side { display: flex; width: auto; height: auto; }
  .pane-side > .pane-scroll,
  .pane-side > .compose-btn,
  .pane-side > .sidebar-foot { display: none; }
  .pane-side .brand { padding: var(--sp-2) var(--sp-3); justify-content: flex-start; }
  .pane-side .brand-name { display: block; }

  /* Al abrirse, cada uno recupera SU display, no un `block` genérico: el botón de
     escribir es inline-flex (centra el ícono con el texto) y el pie es un `.nav`
     en columna. Un `display:block` acá los desarmaría a los dos. */
  .app.show-side .pane-side { position: fixed; inset: var(--sp-2); z-index: 50; }
  .app.show-side .pane-side > .pane-scroll { display: block; }
  .app.show-side .pane-side > .compose-btn { display: inline-flex; }
  .app.show-side .pane-side > .sidebar-foot { display: flex; }
  .app.show-side .brand-name, .app.show-side .nav-item .txt, .app.show-side .side-label { display: block; }
  .app.show-side .nav-item { justify-content: flex-start; }
  .msg-head, .msg-body, .msg-actions, .attachments, .compose-fields, .toolbar, .editor, .compose-foot {
    padding-left: var(--sp-4); padding-right: var(--sp-4);
  }
}

/* ── Accesibilidad: respetar "menos movimiento" ──────────────── */
@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after { animation-duration: .01ms !important; animation-iteration-count: 1 !important;
                            transition-duration: .01ms !important; }
  .aurora { animation: none; }
}

/* ── Contactos: barrita de sync + autocompletado ─────────────── */

.contacts-bar {
  position: fixed; left: 50%; bottom: 18px; transform: translate(-50%, 12px);
  display: flex; flex-direction: column; gap: 6px;
  padding: 8px 14px 10px; min-width: 220px;
  border-radius: var(--r-md, 12px);
  background: var(--glass-bg, rgba(20,20,24,.72));
  border: 1px solid var(--glass-br, rgba(255,255,255,.10));
  backdrop-filter: blur(14px) saturate(140%);
  box-shadow: 0 8px 30px rgba(0,0,0,.32);
  font-size: var(--step--1, .85rem); color: var(--fg-dim, #b9b9c2);
  opacity: 0; transition: opacity .25s ease, transform .25s ease;
  z-index: 60; pointer-events: none;
}
.contacts-bar.on { opacity: 1; transform: translate(-50%, 0); }
.contacts-bar-fill {
  height: 3px; border-radius: 3px; width: 8%;
  background: linear-gradient(90deg, var(--accent, #7aa2f7), transparent);
  transition: width .3s ease;
}

.ac-menu {
  position: fixed; z-index: 70; max-height: 260px; overflow-y: auto;
  padding: 6px; border-radius: var(--r-md, 12px);
  background: var(--glass-bg, rgba(20,20,24,.86));
  border: 1px solid var(--glass-br, rgba(255,255,255,.10));
  backdrop-filter: blur(16px) saturate(140%);
  box-shadow: 0 12px 40px rgba(0,0,0,.4);
}
.ac-item {
  display: flex; flex-direction: column; gap: 1px; width: 100%;
  padding: 7px 10px; border: 0; border-radius: 8px;
  background: transparent; color: inherit; text-align: left; cursor: pointer;
  font: inherit;
}
.ac-item:hover, .ac-item.sel { background: var(--hover, rgba(255,255,255,.07)); }
.ac-name { font-weight: 500; }
.ac-mail, .ac-org { font-size: var(--step--2, .78rem); color: var(--fg-dim, #9a9aa4); }

/* ── Login: botón de Google y separador ──────────────────────── */
.btn-google { display: flex; align-items: center; justify-content: center; gap: 10px; }
.login-note {
  margin: 10px 2px 0; font-size: var(--step--2, .78rem);
  color: var(--fg-dim, #9a9aa4); line-height: 1.45;
}
.login-or {
  display: flex; align-items: center; gap: 10px;
  margin: var(--sp-4, 16px) 0 var(--sp-2, 8px);
  color: var(--fg-dim, #9a9aa4); font-size: var(--step--2, .78rem);
}
.login-or::before, .login-or::after {
  content: ''; flex: 1; height: 1px;
  background: var(--glass-br, rgba(255,255,255,.10));
}

/* ── Gestor ──────────────────────────────────────────────────── */

/* El webmail pone `overflow: hidden` en el body porque ahi el scroll vive dentro
   de cada panel. El gestor NO es eso: es un documento normal y largo. Heredar
   esa regla dejaba el contenido cortado abajo sin ninguna forma de bajar, y de
   paso rompia el `position: sticky` de la barra (sin ancestro que scrollee, no
   hay a que pegarse). */
body.admin {
  padding: 0;
  height: auto;
  min-height: 100%;
  overflow-y: auto;
  overflow-x: hidden;
}
.admin-bar {
  display: flex; align-items: center; gap: 16px;
  padding: 10px 18px; margin: 0; border-radius: 0;
  border-bottom: 1px solid var(--glass-br, rgba(255,255,255,.10));
  position: sticky; top: 0; z-index: 20;
}
.admin-nav { display: flex; gap: 4px; }
.admin-nav a {
  padding: 5px 11px; border-radius: 8px; text-decoration: none;
  color: var(--fg-dim, #9a9aa4); font-size: var(--step--1, .85rem);
}
.admin-nav a:hover { background: var(--hover, rgba(255,255,255,.06)); }
.admin-nav a.on { background: var(--hover, rgba(255,255,255,.10)); color: var(--fg, #e7e7ee); }
.admin-who { font-size: var(--step--2, .78rem); }
.admin-main { max-width: 1100px; margin: 0 auto; padding: 20px 18px 60px; }
.admin-grid { display: grid; gap: 16px; }

.stat-row { display: flex; flex-wrap: wrap; gap: 18px; margin: 8px 0; font-size: var(--step--1, .85rem); }
.stat-row b { font-size: var(--step-1, 1.1rem); }
.warn { color: var(--warn, #e0af68); }

/* Una tabla de direcciones y destinos se pasa de ancho en cualquier pantalla
   chica. Que scrollee ELLA y no la pagina: el body nunca scrollea horizontal. */
.tbl-wrap { overflow-x: auto; overscroll-behavior-x: contain; margin: 0 -2px; }
.tbl-wrap .tbl { min-width: 560px; }

.tbl { width: 100%; border-collapse: collapse; font-size: var(--step--1, .85rem); }
.tbl th {
  text-align: left; padding: 6px 8px; font-weight: 500;
  color: var(--fg-dim, #9a9aa4); border-bottom: 1px solid var(--glass-br, rgba(255,255,255,.10));
}
.tbl td { padding: 6px 8px; border-bottom: 1px solid rgba(255,255,255,.04); vertical-align: middle; }
.tbl tr.off td { opacity: .45; }
.tbl form { display: inline; }

/* ── Tabla de alias: un <tbody> por dirección ──────────────────
   Dos niveles en UNA tabla, sin tablas anidadas: la dirección es la fila del grupo y
   cada destino es una fila hija. Las columnas quedan alineadas entre grupos, que es
   justamente lo que se pierde anidando. */
.tbl-alias tbody.grp { border-bottom: 1px solid var(--glass-br, rgba(255,255,255,.10)); }
.tbl-alias .grp-head th { border-bottom: 0; font-weight: 600; color: var(--fg, #e8e8ec); }
.tbl-alias .grp-head td { border-bottom: 0; }
.tbl-alias tbody.off { opacity: .45; }
/* Las filas hijas se hunden un poco: se lee de un saque quién cuelga de qué. */
.tbl-alias .grp-row td, .tbl-alias .grp-add td {
  border-bottom: 0; padding-top: 3px; padding-bottom: 3px;
  background: rgba(255,255,255,.015);
}
.tbl-alias .sub-cell { padding-left: 22px !important; color: var(--fg-dim, #9a9aa4); }
.tbl-alias .arrow { color: var(--fg-dim, #9a9aa4); opacity: .6; margin-right: 4px; }
.inline-add { display: flex; align-items: center; gap: var(--sp-2); padding-left: 22px; }
.inline-add .input { max-width: 260px; }
.inline-toggle { display: inline-flex; }

.chip {
  display: inline-block; padding: 1px 8px; border-radius: 99px;
  font-size: var(--step--2, .78rem); background: var(--hover, rgba(255,255,255,.08));
}
.chip.on { background: rgba(158,206,106,.18); color: #9ece6a; }
.chip.off { background: rgba(224,175,104,.18); color: #e0af68; }

.alias-new { display: flex; gap: 8px; margin: 12px 0; flex-wrap: wrap; align-items: center; }
.alias-new .input { flex: 1; min-width: 220px; }
/* El dominio ya lo fija la pantalla, así que se escribe sólo la parte izquierda y el
   `@dominio` va pegado, en texto: es lo que evita tipear mal el dominio del cliente. */
.dir-nueva { display: inline-flex; align-items: center; gap: 6px; flex: 1; min-width: 220px; }
.dir-nueva .input { min-width: 90px; }

.diff {
  max-height: 420px; overflow: auto; padding: 12px;
  border-radius: var(--r-md, 12px); background: rgba(0,0,0,.28);
  font-family: ui-monospace, monospace; font-size: var(--step--2, .78rem); line-height: 1.5;
  white-space: pre-wrap; word-break: break-all;
}

/* ── Composer: la identidad de envío ─────────────────────────── */
.from-fixed {
  flex: 1; padding: 6px 2px; font-size: var(--step--1, .85rem);
  color: var(--fg, #e7e7ee);
}
.addr-row select.input { flex: 1; }

/* ── Gestor por dominio ──────────────────────────────────────── */
/* Extiende el sistema que ya existe (cristal, dark/clear, escala --step-*).
   No hay tokens nuevos: los estados usan --accent/--warn/--danger. */

.filtros {
  display: flex; flex-wrap: wrap; gap: var(--sp-2); align-items: center;
  margin-bottom: var(--sp-4);
}
.filtros .input, .filtros select { min-height: var(--ctl-h-sm); font-size: var(--step--1); }
.filtros select {
  padding: 0 var(--sp-3); border-radius: var(--r-md);
  background: var(--glass); border: 1px solid var(--glass-brd); color: var(--ink);
}
.filtros label { font-size: var(--step--2, .78rem); color: var(--ink-dim); }
.filtro-activo { color: var(--warm); }

/* Tarjeta de dominio: nombre, modo de DNS, chips de salud, contadores. */
.dom-grid {
  display: grid; gap: var(--sp-3);
  grid-template-columns: repeat(auto-fill, minmax(320px, 1fr));
}
.dom-card {
  padding: var(--sp-4); display: flex; flex-direction: column; gap: var(--sp-2);
  border-radius: var(--r-lg); text-decoration: none; color: inherit;
  transition: transform var(--dur-fast) var(--ease), border-color var(--dur-fast) var(--ease);
}
.dom-card:hover { transform: translateY(-1px); border-color: var(--glass-brd-hi); text-decoration: none; }
.dom-card-head { display: flex; align-items: baseline; gap: var(--sp-2); flex-wrap: wrap; }
.dom-name {
  font-family: var(--font-display); font-size: var(--step-1); font-weight: 500;
  letter-spacing: -.02em; overflow-wrap: anywhere;
}
.dom-mode { font-size: var(--step--2, .78rem); color: var(--ink-dim); }
.dom-counts { font-size: var(--step--1); color: var(--ink-mid); display: flex; gap: var(--sp-3); flex-wrap: wrap; }
.dom-card.dim-off { opacity: .55; }

/* Chips de estado. El ÁMBAR es la pieza importante: "propagando" es esperá, no
   toques nada. Sin ese estado la gente vuelve a aplicar tres veces algo que
   solo necesitaba tiempo. */
.chips { display: flex; gap: var(--sp-1); flex-wrap: wrap; }
.hchip {
  display: inline-flex; align-items: center; gap: 3px;
  padding: 1px 7px; border-radius: var(--r-pill);
  font-size: var(--step--2, .78rem); font-weight: 500;
  border: 1px solid transparent; white-space: nowrap;
}
.hchip.ok   { background: color-mix(in srgb, var(--accent) 18%, transparent); color: var(--accent); }
.hchip.mid  { background: color-mix(in srgb, var(--warn) 20%, transparent);   color: var(--warn); }
.hchip.bad  { background: color-mix(in srgb, var(--danger) 18%, transparent); color: var(--danger); }
.hchip.none { background: var(--glass-hi); color: var(--ink-dim); }

.salud { font-weight: 600; font-size: var(--step--1); }
.salud.ok { color: var(--accent); }
.salud.propagando { color: var(--warn); }
.salud.incompleto, .salud.sin-dns { color: var(--danger); }
.salud.sin-chequear { color: var(--ink-dim); }

/* Resumen de salud arriba del listado. */
.resumen { display: flex; gap: var(--sp-4); flex-wrap: wrap; font-size: var(--step--1); }
.resumen b { font-size: var(--step-1); }

/* ── Wizard ──────────────────────────────────────────────────── */
.stepper { display: flex; flex-wrap: wrap; gap: var(--sp-1); margin-bottom: var(--sp-5); }
.step {
  display: flex; align-items: center; gap: var(--sp-2);
  padding: var(--sp-2) var(--sp-3); border-radius: var(--r-md);
  font-size: var(--step--1); color: var(--ink-dim);
  border: 1px solid transparent; text-decoration: none;
}
.step .n {
  width: 20px; height: 20px; flex: none; border-radius: 50%;
  display: grid; place-items: center; font-size: var(--step--2, .78rem); font-weight: 600;
  background: var(--glass-hi); color: var(--ink-mid);
}
/* Los pasos ya hechos son LINKS: volver atrás sin perder lo hecho es la mitad
   de por qué un wizard se tolera. */
.step.hecho { color: var(--ink-mid); }
.step.hecho .n { background: color-mix(in srgb, var(--accent) 22%, transparent); color: var(--accent); }
.step.hecho:hover { background: var(--glass); text-decoration: none; }
.step.actual { color: var(--ink); border-color: var(--glass-brd-hi); background: var(--glass); }
.step.actual .n { background: var(--warm); color: var(--warm-ink); }
.step .det { color: var(--ink-fade); font-size: var(--step--2, .78rem); }
@media (max-width: 720px) { .step .det { display: none; } }

.wiz-actions { display: flex; gap: var(--sp-2); align-items: center; margin-top: var(--sp-5); flex-wrap: wrap; }
.wiz-actions .sep { flex: 1; }

/* Elegir entre dos caminos: nuestro DNS o externo. */
.opciones { display: grid; gap: var(--sp-3); grid-template-columns: repeat(auto-fit, minmax(260px, 1fr)); }
.opcion {
  padding: var(--sp-4); border-radius: var(--r-lg); cursor: pointer;
  border: 1px solid var(--glass-brd); background: var(--glass);
  display: flex; flex-direction: column; gap: var(--sp-2);
}
.opcion:has(input:checked) { border-color: var(--warm); background: var(--glass-hi); }
.opcion input { margin: 0; }
.opcion b { font-size: var(--step-1); font-weight: 500; }
.opcion .por { color: var(--ink-dim); font-size: var(--step--1); }

/* Registros para copiar y pegar cuando el DNS es de otro. */
.recs { display: grid; gap: var(--sp-2); }
.rec {
  display: grid; grid-template-columns: 68px 150px minmax(0, 1fr);
  gap: var(--sp-2); align-items: start;
  padding: var(--sp-2) var(--sp-3); border-radius: var(--r-md);
  background: rgba(0,0,0,.16); font-family: var(--font-mono); font-size: var(--step--2, .78rem);
}
:root[data-theme="clear"] .rec { background: rgba(0,0,0,.05); }
.rec .t { color: var(--accent); font-weight: 600; }
.rec .v { overflow-wrap: anywhere; color: var(--ink-mid); }
@media (max-width: 620px) { .rec { grid-template-columns: 1fr; } }

/* Los nameservers para pegar en el registrador. Es lo único que delega. */
.ns-list { display: grid; gap: var(--sp-1); font-family: var(--font-mono); font-size: var(--step--1); }
.ns-list li { list-style: none; padding: var(--sp-1) var(--sp-2); background: rgba(0,0,0,.16); border-radius: var(--r-sm); }
:root[data-theme="clear"] .ns-list li { background: rgba(0,0,0,.05); }

.check-list { display: grid; gap: var(--sp-2); margin: var(--sp-3) 0; }
.check-item { display: flex; gap: var(--sp-3); align-items: baseline; font-size: var(--step-0); }
.check-item .mark { width: 1.2em; flex: none; font-weight: 700; }
.check-item.si .mark { color: var(--accent); }
.check-item.no .mark { color: var(--danger); }
.check-item .det { color: var(--ink-dim); font-size: var(--step--1); overflow-wrap: anywhere; }
/* En el gestor los `field` son `<label>` con un `<span>` adentro, no un label
   hermano: el selector `.field > label` del webmail no los alcanza. */
.field > span:first-child {
  font-size: var(--step--1); color: var(--ink-dim); font-weight: 600; letter-spacing: .02em;
}

/* ── Tabla de dominios ───────────────────────────────────────── */
/* Las tarjetas se leen bien con 5 dominios y son ilegibles con 40: no se pueden
   comparar columnas ni barrer con la vista. */
.tbl-dom { min-width: 860px; }
.tbl-dom thead a { color: var(--ink-dim); text-decoration: none; }
.tbl-dom thead a:hover { color: var(--ink); text-decoration: none; }
.tbl-dom thead a.on { color: var(--warm); }
.tbl-dom .cel-chk { text-align: center; font-weight: 700; width: 3.2rem; }
.tbl-dom .num { text-align: right; font-variant-numeric: tabular-nums; }
.tbl-dom .nowrap { white-space: nowrap; }
/* Las dos tablas que tienen selección múltiple: dominios y direcciones. */
.tbl .cel-sel { width: 2.2rem; text-align: center; }
.tbl .cel-acc { width: 2.6rem; text-align: center; }

/* ── Marcados «para borrar» ──────────────────────────────────── */
/* Casi transparentes y al fondo de la tabla. Tienen que verse CLARAMENTE más apagados
   que un `.off` (una baja, al 45%): son dos cosas distintas y confundirlas es creer
   que algo dejó de recibir correo cuando sigue recibiendo igual.
   La celda del checkbox y la de acciones quedan al 100%: lo marcado tiene que poder
   desmarcarse, y un cuadradito de 14 px al 22% no se ve ni se acierta.
   Vale para las dos tablas: los dominios son `<tr>` y las direcciones son `<tbody>`. */
.tbl tr.borrar td:not(.cel-sel):not(.cel-acc),
.tbl tbody.borrar td:not(.cel-sel):not(.cel-acc),
.tbl tbody.borrar th { opacity: .22; }
.tbl tr.borrar:hover td, .tbl tr.borrar:focus-within td,
.tbl tbody.borrar:hover td, .tbl tbody.borrar:hover th,
.tbl tbody.borrar:focus-within td, .tbl tbody.borrar:focus-within th { opacity: .85; }
.chip.borrar, .salud.borrar { color: var(--danger); }
.chip.borrar { background: color-mix(in srgb, var(--danger) 16%, transparent); }

/* La barra de la tanda. Aparece recién cuando hay algo seleccionado (`hidden` lo pone
   el JS), así que en reposo no ocupa nada. */
.sel-bar {
  display: flex; align-items: center; gap: var(--sp-3); flex-wrap: wrap;
  margin-bottom: var(--sp-3); padding: var(--sp-2) var(--sp-3);
  border-radius: var(--r-md);
  background: color-mix(in srgb, var(--warm) 12%, transparent);
  border: 1px solid color-mix(in srgb, var(--warm) 25%, transparent);
}
.sel-bar[hidden] { display: none; }

.ok  { color: var(--accent); }
.mid { color: var(--warn); }
.bad { color: var(--danger); }
.salud.parcial { color: var(--warn); }

/* ── Selección múltiple ──────────────────────────────────────── */
/* No hay checkbox: el avatar es el control. Seleccionada = la fila pintada y el
   avatar con anillo, sin tilde — el estado se ve en el renglón entero, que es más
   legible que un cuadradito de 14 px. */
.row.picked .row-avatar {
  box-shadow: 0 0 0 2px var(--warm), 0 0 0 4px color-mix(in srgb, var(--warm) 25%, transparent);
}
.row.picked { background: color-mix(in srgb, var(--warm) 14%, transparent); }
.row.picked:hover { background: color-mix(in srgb, var(--warm) 20%, transparent); }
/* Foco del teclado: un filo, no un fondo — así se distingue de "seleccionada". */
.row.focus { box-shadow: inset 3px 0 0 var(--accent); }

/* La barra contextual reemplaza a la de la carpeta cuando hay algo marcado. */
.sel-bar { gap: var(--sp-2); }
.sel-bar .sel-all { display: flex; align-items: center; padding: 0 var(--sp-1); }
.sel-bar .sel-all input { margin: 0; width: 15px; height: 15px; accent-color: var(--warm); }
.sel-bar .bar-title { font-family: var(--font-ui); font-size: var(--step-0); font-weight: 500; }
.app.selecting .bar:not(.sel-bar) { display: none; }
@media (max-width: 620px) { .sel-bar .btn .txt { display: none; } }

/* Toast con acción (el "Deshacer" de las acciones en masa). */
.flash-action { display: flex; align-items: center; gap: var(--sp-3); }

/* Toggles: el estado se ve, no se lee — por eso cambian de color en vez de cambiar
   de texto. `.preview-toggle` es el lector inline; `.light-bg-toggle` es el fondo
   blanco del mensaje abierto (antes era un cartel con una ✕). */
.preview-toggle.on,
.light-bg-toggle.on { color: var(--warm); background: color-mix(in srgb, var(--warm) 14%, transparent); }
.light-bg-toggle.on { border-color: color-mix(in srgb, var(--warm) 45%, var(--glass-brd)); }
/* Acciones destructivas: el color de peligro sólo en hover, para que el botón no
   grite desde la barra pero sí avise antes del click. */
.danger-hover:hover { color: var(--danger); background: color-mix(in srgb, var(--danger) 12%, transparent); }

/* Zona de peligro (admin): lo irreversible va detrás de un `<details>` cerrado y con
   borde propio. Que se distinga a simple vista del botón inocuo de al lado es parte de
   la guarda — el otro control de la misma tarjeta sólo reintenta la entrega. */
.danger-zone {
  border: 1px solid color-mix(in srgb, var(--danger) 45%, var(--glass-brd));
  border-radius: var(--r-md); padding: var(--sp-3);
  background: color-mix(in srgb, var(--danger) 6%, transparent);
}
.danger-zone > summary { color: var(--danger); font-weight: 600; }

/* ── Panel de diagnóstico del tiempo real (?debug=rt) ─────────────────────────
   Sirve para contestar «¿llega el push, o lo que actualiza la lista es el poll de
   30 s?» sin reconstruir a mano un camino de cinco saltos. No se muestra nunca
   salvo que se pida explícitamente. */
#rt-debug {
  position: fixed; right: var(--sp-3); bottom: var(--sp-3); z-index: 9999;
  width: min(30rem, calc(100vw - 2 * var(--sp-3)));
  max-height: 45vh; display: flex; flex-direction: column;
  font: 400 11px/1.5 ui-monospace, SFMono-Regular, Menlo, monospace;
  background: var(--bg-1); color: var(--ink);
  border: 1px solid var(--glass-brd-hi); border-radius: var(--r-md);
  box-shadow: 0 10px 40px rgb(0 0 0 / .45); overflow: hidden;
}
#rt-debug .rtd-bar {
  display: flex; align-items: center; gap: var(--sp-2);
  padding: var(--sp-2) var(--sp-3); border-bottom: 1px solid var(--glass-brd);
  background: var(--glass);
}
#rt-debug .rtd-estado { color: var(--ink-mid); }
#rt-debug .rtd-mal { color: var(--danger); font-weight: 600; }
#rt-debug .rtd-x {
  margin-left: auto; background: none; border: 0; cursor: pointer;
  color: var(--ink-mid); font-size: 13px; line-height: 1; padding: var(--sp-1);
}
#rt-debug .rtd-lista { overflow-y: auto; }
#rt-debug .rtd-ev {
  display: grid; grid-template-columns: 4.5rem 5.5rem 1fr 3.5rem;
  gap: var(--sp-2); padding: 2px var(--sp-3); white-space: nowrap;
}
#rt-debug .rtd-ev:nth-child(even) { background: var(--glass); }
#rt-debug .rtd-h, #rt-debug .rtd-dt { color: var(--ink-mid); }
#rt-debug .rtd-dt { text-align: right; }
#rt-debug .rtd-d { overflow: hidden; text-overflow: ellipsis; }
/* Un `changed` que se USÓ (coincidía con la carpeta abierta) contra uno que llegó y
   no hizo nada: es justo la distinción que el bug del fan-out volvía invisible. */
#rt-debug .rtd-changed .rtd-t { color: var(--ink-mid); }
#rt-debug .rtd-usado .rtd-t { color: var(--ok, #48d6be); font-weight: 600; }
#rt-debug .rtd-error .rtd-t { color: var(--danger); font-weight: 600; }

/* El «Salir» es un <form> con un <button>, no un <a>: con GET, cualquier página ajena podía
   cerrar la sesión con un `<img src=".../logout">`. Esto lo hace ver igual que los demás
   items del sidebar. */
.nav-form { margin: 0; display: block; }
.nav-form > .nav-item { width: 100%; background: none; border: 0; cursor: pointer;
  font: inherit; color: inherit; text-align: left; }
.btn-link { background: none; border: 0; padding: 0; color: inherit; cursor: pointer;
  font: inherit; text-decoration: underline; }

/* ── Los tokens que el CSS del gestor usaba sin definir ───────────────────────
   `--fg`, `--fg-dim`, `--hover` y `--step--2` se usaban con valor de fallback en ~17
   reglas del bloque del admin, así que la barra de navegación se pintaba con colores
   hardcodeados (#e7e7ee) en lugar de los del sistema. Por eso el gestor se veía de otra
   familia que el webmail, aunque cargue el mismo archivo.
   Se definen como alias de los tokens que sí existen, y así siguen el tema claro/oscuro. */
:root {
  --fg: var(--ink);
  --fg-dim: var(--ink-mid);
  --hover: var(--glass-hi);
  --step--2: .78rem;
}

/* ── Tarjetas que cargan solas ────────────────────────────────────────────────
   Cada tarjeta del gestor se pide aparte y llega cuando llega. Lo que hace que eso se
   sienta rápido en vez de sentirse roto es que el hueco RESERVE la altura final: si no,
   la tarjeta lenta que llega última empuja todo lo de abajo justo cuando empezaste a leer. */
.card-head { display: flex; align-items: baseline; gap: var(--sp-3); }
.card-head h2 { margin: 0; flex: 1; }
.card-tools { display: flex; align-items: center; gap: var(--sp-2); }
.card-edad { font-size: var(--step--2); white-space: nowrap; }
/* Ámbar pasados los 5 minutos: un dato viejo que no avisa que es viejo es una mentira. */
.card-edad.viejo { color: var(--warn); }

/* El dato anterior mientras se refresca. Atenuado y fechado no es mentir; el valor casi
   siempre sigue siendo cierto, y un skeleton donde había un número se siente como un paso
   atrás. (Después de ACTUAR sobre ese dato, en cambio, el JS pone skeleton.) */
.frag-viejo > *:not(.card-head) { opacity: .55; transition: opacity var(--dur) var(--ease); }

.frag-hueco .skel-line { max-width: 100%; }
.frag-error { display: flex; align-items: center; gap: var(--sp-3); flex-wrap: wrap; }

/* La barra de carga por tarjeta. Reusa el barrido que ya existe para el panel de la lista
   (`.list-loader`), pero anclada a la tarjeta — una barra global en una pantalla que ya está
   80% pintada mentiría sobre el estado. La prende el JS sólo si el pedido pasa de 300 ms. */
.glass.card { position: relative; }
.glass.card.loading::after {
  content: ''; position: absolute; inset: 0 0 auto 0; height: 2px;
  border-radius: var(--r-md) var(--r-md) 0 0; overflow: hidden;
  background: linear-gradient(90deg, transparent, var(--accent), var(--warm), transparent);
  background-size: 40% 100%; background-repeat: no-repeat;
  animation: cardSweep 900ms var(--ease-out) infinite;
}
@keyframes cardSweep { from { background-position: -40% 0; } to { background-position: 140% 0; } }

/* Piezas de skeleton con la forma del contenido que viene. Un skeleton genérico en una
   tarjeta alta deja un vacío que se lee como error de render; con la forma puesta se lee
   como «esto está viniendo» y además anticipa qué esperar. */
.skel-chips { display: flex; gap: var(--sp-2); margin-bottom: var(--sp-3); }
.skel-chip { width: 96px; height: 20px; border-radius: var(--r-pill); }

/* ── Seguimiento en vivo (play/pause del maillog y la cola) ───────────────────
   Arranca en PAUSA: nadie abre el panel para que empiece a consumir SSH solo. */
.vivo { display: flex; align-items: center; gap: var(--sp-2); margin: var(--sp-2) 0; }
.vivo-estado { font-size: var(--step--2); }
.vivo-estado.viejo { color: var(--warn); }
/* Mientras sigue en vivo, el botón se marca: es un estado que conviene ver de reojo, porque
   significa que hay una consulta al SSH de minte cada 15 segundos. */
.vivo.vivo-on [data-vivo-toggle] {
  border-color: color-mix(in srgb, var(--accent) 55%, var(--glass-brd));
  color: var(--accent);
}
.vivo.vivo-on [data-vivo-toggle]::after {
  content: ''; width: 6px; height: 6px; border-radius: 50%; background: var(--accent);
  margin-left: 2px; animation: latido 1.6s ease-in-out infinite;
}
@keyframes latido { 0%, 100% { opacity: 1; } 50% { opacity: .25; } }

/* ── El maillog coloreado ──────────────────────────────────────────────────────
   El color del queue ID y del pid sale de un hash del propio texto (mismo FNV-1a que el
   avatar del webmail), así que el mismo ID da siempre el mismo color: es lo que permite
   seguir una entrega entre 200 líneas de decenas de entregas entremezcladas. Los colores
   semánticos, en cambio, están acá porque significan algo. */
.log-fecha { color: var(--ink-fade); }
.log-host  { color: var(--ink-fade); }
.log-dem   { color: var(--ink-mid); }
.log-pid   { font-weight: 600; }
.log-id    { font-weight: 700; border-radius: 3px; padding: 0 3px; }
.log-mail  { color: var(--ink); text-decoration: underline dotted var(--glass-brd-hi); }
.log-ok    { color: var(--ok, #48d6be); font-weight: 600; }
.log-warn  { color: var(--warn); font-weight: 600; }
.log-bad   { color: var(--danger); font-weight: 600; }

/* Las dos acciones secundarias del gestor (Aplicar, Auditoría) van separadas de las cuatro
   secciones: a las dos se llega por un motivo que nació en otra pantalla, así que no tienen
   que competir por la atención con los destinos. */
.admin-nav-sep { width: 1px; align-self: stretch; margin: 4px 8px;
  background: var(--glass-brd-hi); }
.admin-nav a.sec { color: var(--ink-dim); }
.admin-nav a.sec:hover, .admin-nav a.sec.on { color: var(--fg); }
