:root {
    --bg: #0b0e11;
    --sidebar-bg: #12161a;
    --panel-bg: #161a1e;
    --panel2-bg: #1d2228;
    --border-color: #1f252b;
    --text-color: #e6edf3;
    --muted-color: #848e9c;
    --surface: var(--panel-bg);
    --text: var(--text-color);
    --muted: var(--muted-color);
    --border: var(--border-color);
    --surface-2: var(--panel2-bg);
    --accent: #00c582;
    --accent-hover: #00a86f;
    --accent-soft: rgba(0, 197, 130, 0.12);
    --accent-contrast: #06110d;
    --accent-blue: var(--accent);
    --accent-blue-hover: var(--accent-hover);
    --accent-blue-soft: var(--accent-soft);
    --pos-color: #00c582;
    --pos-color-soft: rgba(0, 197, 130, 0.1);
    --neg-color: #f84960;
    --neg-color-soft: rgba(248, 73, 96, 0.1);
    /* Los ejes de las gráficas. Estaban escritos a fuego en el JavaScript, con
       un gris pensado para fondo oscuro: sobre el tema claro daba 2,4:1 y las
       etiquetas casi no se leían. Como token, cada tema pone el suyo. */
    --chart-text: #9ca3af;
    --chart-grid: rgba(156, 163, 175, 0.12);
    /* Las cajas de clase del mapa. Sobre oscuro basta con muy poco: el marco
       separa bloques saturados sobre casi negro y con 1,13:1 ya se lee. */
    --treemap-marco: var(--border-color);
    --treemap-hueco: var(--panel-bg);
    --treemap-cabecera: var(--panel2-bg);
    --accent-green: var(--accent);
    --accent-green-hover: var(--accent-hover);
    --sans-font: 'Inter', -apple-system, sans-serif;
    --mono-font: 'JetBrains Mono', monospace;
    /* `easeOutQuart`, la misma curva que `suavizado()` usa para las cifras que
       corren: arranca rápido y frena al llegar. Compartirla es lo que hace que
       la pantalla se mueva a un solo ritmo. */
    --curva-salida: cubic-bezier(0.165, 0.84, 0.44, 1);
  }

  :root[data-theme="light"] {
    --bg: #f5f1e8;
    --sidebar-bg: #fbf8f2;
    --panel-bg: #fbf8f2;
    --panel2-bg: #f0ece3;
    --border-color: #ded8ce;
    --text-color: #1d1d1f;
    --muted-color: #6f6a61;
    --surface: var(--panel-bg);
    --surface-2: var(--panel2-bg);
    --text: var(--text-color);
    --muted: var(--muted-color);
    --border: var(--border-color);

    /* El tema claro no tenía colores de DATO propios: heredaba el verde y el
       rojo del oscuro, que están hechos para brillar sobre casi negro. Medido
       sobre el panel claro, aquel verde daba 2,13:1 —la cifra grande de la
       cabecera va en ese color— y el rojo 3,24:1. Los dos por debajo del 4,5:1
       que pide un texto.

       Estos son los mismos colores bajados de luminosidad hasta que se leen:
       verde 5,71:1 y rojo 5,78:1 sobre la tarjeta, 5,37 y 5,43 sobre el fondo
       de página. Siguen siendo el mismo verde y el mismo rojo, no otra gama.

       `--accent` NO se toca: ahí el color es FONDO de botón y lo que tiene que
       contrastar es el texto que lleva encima, que es otro requisito. */
    --pos-color: #07714a;
    --pos-color-soft: rgba(7, 113, 74, 0.12);
    --neg-color: #c01933;
    --neg-color-soft: rgba(192, 25, 51, 0.12);

    /* Etiquetas de los ejes: 5,07:1. La rejilla, en el color del borde de las
       tarjetas: pesa lo mismo sobre claro (1,34:1) que la del tema oscuro sobre
       oscuro (1,21:1), en vez de desaparecer con 1,09:1. */
    --chart-text: #6f6a61;
    --chart-grid: #ded8ce;

    /* Sobre claro no vale lo mismo: la caja de clase usa el fondo de la tarjeta,
       así que lo único que la delimitaba era una línea de 1,34:1 entre celdas
       saturadas y un fondo casi blanco. Se perdía.

       El marco sube a 1,96:1 —una línea estructural, no una jaula—, el hueco
       entre grupos pasa al color de la PÁGINA para que cada clase se lea como
       una pieza recortada sobre la tarjeta, y la cabecera gana algo de cuerpo
       para que la región se vea rotulada y no solo separada. */
    --treemap-marco: #bdb3a1;
    --treemap-hueco: var(--bg);
    --treemap-cabecera: #e9e1d2;
  }

  :root[data-accent="orange"] {
    --accent: #f59e0b;
    --accent-hover: #d97706;
    --accent-soft: rgba(245, 158, 11, 0.14);
    --accent-contrast: #1c1001;
  }

  :root[data-accent="blue"] {
    --accent: #2563eb;
    --accent-hover: #1d4ed8;
    --accent-soft: rgba(37, 99, 235, 0.14);
    --accent-contrast: #ffffff;
  }

  * {
    box-sizing: border-box;
    margin: 0;
    padding: 0;
  }

  body {
    background-color: var(--bg);
    color: var(--text-color);
    font-family: var(--sans-font);
    min-height: 100vh;
    display: flex;
    overflow: hidden;
  }

  /* --- PANTALLA DE LOGIN --- */
  .login-container {
    display: flex;
    align-items: center;
    justify-content: center;
    width: 100vw;
    height: 100vh;
    background: var(--bg);
    position: fixed;
    top: 0; left: 0;
    z-index: 2000;
  }
  .login-box {
    background: var(--panel-bg);
    border: 1px solid var(--border-color);
    border-radius: 16px;
    padding: 40px;
    width: 100%;
    max-width: 430px;
    max-height: 92vh;
    overflow-y: auto;
    box-shadow: 0 12px 40px rgba(0, 0, 0, 0.5);
    text-align: center;
  }
  .login-logo {
    display: inline-flex;
    align-items: center;
    gap: 10px;
    margin-bottom: 24px;
  }
  .login-logo-icon {
    width: 32px;
    height: 32px;
    background-color: var(--accent-blue);
    border-radius: 8px;
    display: flex;
    align-items: center;
    justify-content: center;
  }
  .login-logo-icon svg,
  .brand-icon svg {
    /* La M va dibujada a trazo y no a relleno: es la misma línea quebrada de
       una cotización —sube, cae al valle, vuelve a subir— y con `fill` se
       cerraría en un triángulo que no se lee como una letra. */
    fill: none;
    stroke: var(--accent-contrast);
    stroke-width: 2.6;
    stroke-linecap: round;
    stroke-linejoin: round;
  }
  .login-logo-icon svg {
    width: 18px;
    height: 18px;
  }
  .login-logo span {
    font-size: 20px;
    font-weight: 700;
    letter-spacing: -0.5px;
  }
  .login-box h2 {
    font-size: 20px;
    font-weight: 600;
    margin-bottom: 8px;
  }
  .login-box p {
    color: var(--muted-color);
    font-size: 13px;
    margin-bottom: 28px;
  }
  .form-group {
    margin-bottom: 20px;
    text-align: left;
  }
  .form-group label {
    display: block;
    font-size: 11px;
    text-transform: uppercase;
    color: var(--muted-color);
    margin-bottom: 8px;
    font-family: var(--mono-font);
    letter-spacing: 0.05em;
  }
  .form-group input, .form-group select, .form-group textarea {
    width: 100%;
    background: var(--panel2-bg);
    border: 1px solid var(--border-color);
    border-radius: 8px;
    padding: 12px 14px;
    color: var(--text-color);
    font-size: 14px;
    outline: none;
    transition: border-color 0.2s;
  }
  .form-group textarea {
    min-height: 96px;
    resize: vertical;
    line-height: 1.5;
    font-family: inherit;
  }
  .form-group input:focus, .form-group select:focus, .form-group textarea:focus {
    border-color: var(--accent-blue);
  }
  .form-group input[readonly], .form-group input:disabled {
    background-color: var(--panel-bg);
    cursor: not-allowed;
    color: var(--muted-color);
  }
  .btn-submit {
    width: 100%;
    background: var(--accent-blue);
    color: var(--accent-contrast);
    border: none;
    border-radius: 8px;
    padding: 14px;
    font-size: 14px;
    font-weight: 600;
    cursor: pointer;
    transition: background-color 0.2s;
  }
  .btn-submit:hover {
    background-color: var(--accent-blue-hover);
  }
  .btn-submit:disabled {
    opacity: 0.62;
    cursor: not-allowed;
  }
  .login-error {
    color: var(--neg-color);
    font-size: 12px;
    margin-top: 16px;
    display: none;
    line-height: 1.4;
  }
  .auth-form {
    display: block;
  }
  .auth-form.hidden {
    display: none;
  }
  .auth-toggle {
    margin-top: 14px;
    color: var(--muted-color);
    font-size: 13px;
  }
  .auth-toggle button {
    background: transparent;
    border: none;
    color: var(--accent-blue-hover);
    font-weight: 600;
    cursor: pointer;
    padding: 0;
  }
  .auth-toggle button:hover {
    color: var(--text-color);
  }

  /* --- APLICACIÓN PRINCIPAL (LAYOUT HORIZONTAL) --- */
  .app-container {
    display: none; /* Se activa por JS */
    width: 100%;
    height: 100vh;
  }

  /* Menú lateral izquierdo (Sidebar) */
  .sidebar {
    width: 240px;
    background-color: var(--sidebar-bg);
    border-right: 1px solid var(--border-color);
    display: flex;
    flex-direction: column;
    justify-content: space-between;
    padding: 24px 0;
    flex-shrink: 0;
    height: 100%;
    transition: width 0.22s ease;
  }
  .sidebar-top {
    display: flex;
    flex-direction: column;
    gap: 28px;
    min-height: 0;
  }
  .brand {
    display: flex;
    align-items: center;
    gap: 10px;
    padding: 0 24px;
  }
  .brand-name {
    flex: 1;
    min-width: 0;
  }

  /* --- MENÚ PLEGADO ---
   *
   * Se va del nombre de perfil al botón de cerrar sesión; la marca y el botón
   * se quedan, porque plegado ese botón es el único camino de vuelta. */
  .btn-sidebar-toggle {
    display: flex;
    align-items: center;
    justify-content: center;
    width: 30px;
    height: 30px;
    flex-shrink: 0;
    border: 1px solid var(--border-color);
    border-radius: 8px;
    background: var(--panel-bg);
    color: var(--muted-color);
    cursor: pointer;
    transition: color 0.2s, background-color 0.2s;
  }
  .btn-sidebar-toggle svg {
    width: 15px;
    height: 15px;
    fill: currentColor;
  }
  .btn-sidebar-toggle:hover {
    color: var(--text-color);
    background: var(--panel2-bg);
  }

  .app-container.menu-plegado .sidebar {
    width: 68px;
  }
  /* Ocultos y NO solo estrechados: un texto recortado a 68 px se lee como un
     fallo de maquetación, no como un menú plegado. */
  .app-container.menu-plegado .profile-indicator,
  .app-container.menu-plegado .nav-menu,
  .app-container.menu-plegado .sidebar-bottom,
  .app-container.menu-plegado .brand-name {
    display: none;
  }
  /* En columna: el icono y el botón no caben uno al lado del otro en 68 px. */
  .app-container.menu-plegado .brand {
    flex-direction: column;
    gap: 14px;
    padding: 0 12px;
  }
  .brand-icon {
    width: 28px;
    height: 28px;
    background-color: var(--accent-green);
    border-radius: 6px;
    display: flex;
    align-items: center;
    justify-content: center;
  }
  .brand-icon svg {
    width: 16px;
    height: 16px;
  }
  .brand span {
    font-size: 18px;
    font-weight: 700;
    letter-spacing: -0.5px;
  }
  .profile-indicator {
    display: flex;
    align-items: center;
    gap: 12px;
    padding: 12px 16px;
    margin: 0 16px;
    background-color: var(--panel-bg);
    border: 1px solid var(--border-color);
    border-radius: 12px;
  }
  .profile-indicator-icon {
    width: 32px;
    height: 32px;
    background-color: var(--pos-color-soft);
    border-radius: 8px;
    display: flex;
    align-items: center;
    justify-content: center;
  }
  .profile-indicator-icon svg {
    fill: var(--pos-color);
    width: 16px;
    height: 16px;
  }
  .profile-indicator-details h4 {
    font-size: 12px;
    font-weight: 600;
  }
  .profile-indicator-details p {
    font-size: 10px;
    color: var(--muted-color);
    margin-top: 1px;
  }
  .nav-menu {
    display: flex;
    flex-direction: column;
    gap: 4px;
    padding: 0 12px;
  }
  .sidebar-following-section {
    display: flex;
    flex-direction: column;
    gap: 4px;
    min-height: 0;
  }
  .sidebar-following-toggle {
    position: relative;
  }
  .sidebar-following-icon {
    position: relative;
    width: 16px;
    height: 16px;
    flex: 0 0 16px;
    display: inline-flex;
  }
  .sidebar-following-icon svg {
    fill: currentColor;
  }
  .sidebar-following-user-icon {
    width: 16px;
    height: 16px;
  }
  .sidebar-following-check-icon {
    position: absolute;
    right: -4px;
    top: -5px;
    width: 10px;
    height: 10px;
    fill: currentColor;
  }
  .sidebar-following-label {
    min-width: 0;
    flex: 1;
  }
  .sidebar-following-chevron {
    width: 14px;
    height: 14px;
    margin-left: auto;
    fill: currentColor;
    transition: transform 0.2s ease;
  }
  .sidebar-following-section.open .sidebar-following-chevron {
    transform: rotate(180deg);
  }
  .sidebar-following-section.open .sidebar-following-toggle {
    color: var(--text-color);
    background-color: var(--panel-bg);
  }
  .sidebar-following-panel {
    display: none;
    flex-direction: column;
    gap: 8px;
    padding: 0 6px 4px 28px;
  }
  .sidebar-following-section.open .sidebar-following-panel {
    display: flex;
  }
  .sidebar-following-search {
    position: relative;
    flex: 0 0 auto;
  }
  .sidebar-following-search svg {
    position: absolute;
    left: 9px;
    top: 50%;
    width: 12px;
    height: 12px;
    transform: translateY(-50%);
    fill: var(--muted-color);
    pointer-events: none;
  }
  .sidebar-following-search input {
    width: 100%;
    height: 32px;
    padding: 7px 10px 7px 28px;
    border: 1px solid var(--border-color);
    border-radius: 8px;
    background: var(--panel2-bg);
    color: var(--text-color);
    font-size: 12px;
    outline: none;
  }
  .sidebar-following-search input:focus {
    border-color: var(--accent);
  }
  .sidebar-following-list {
    display: flex;
    flex-direction: column;
    gap: 3px;
    max-height: min(280px, 32vh);
    overflow-y: auto;
    padding-right: 2px;
  }
  .sidebar-following-item {
    display: flex;
    align-items: center;
    gap: 10px;
    width: 100%;
    padding: 8px 10px;
    border: 0;
    border-radius: 8px;
    background: transparent;
    color: var(--muted-color);
    cursor: pointer;
    text-align: left;
    transition: background-color 0.2s, color 0.2s;
  }
  .sidebar-following-item:hover {
    background: var(--panel-bg);
    color: var(--text-color);
  }
  .sidebar-following-item img {
    width: 26px;
    height: 26px;
    border-radius: 50%;
    object-fit: cover;
    border: 1px solid var(--border-color);
    flex: 0 0 26px;
  }
  .sidebar-following-meta {
    min-width: 0;
    display: flex;
    flex-direction: column;
    gap: 1px;
  }
  .sidebar-following-meta strong {
    color: var(--text-color);
    font-size: 12px;
    font-weight: 600;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
  }
  .sidebar-following-meta span,
  .sidebar-following-empty {
    color: var(--muted-color);
    font-size: 11px;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
  }
  .sidebar-following-empty {
    padding: 8px 12px;
    line-height: 1.35;
  }
  .nav-item {
    display: flex;
    align-items: center;
    gap: 12px;
    padding: 12px 16px;
    border-radius: 10px;
    color: var(--muted-color);
    font-size: 13px;
    font-weight: 500;
    cursor: pointer;
    text-decoration: none;
    transition: all 0.2s;
    background: transparent;
    border: none;
    width: 100%;
    text-align: left;
  }
  .nav-item svg {
    fill: var(--muted-color);
    width: 16px;
    height: 16px;
    transition: fill 0.2s;
  }
  .nav-item .sidebar-following-icon svg {
    fill: currentColor;
  }
  .nav-item .sidebar-following-user-icon {
    width: 16px;
    height: 16px;
  }
  .nav-item .sidebar-following-check-icon {
    width: 10px;
    height: 10px;
  }
  .nav-item .sidebar-following-chevron {
    width: 14px;
    height: 14px;
    fill: currentColor;
  }
  .nav-item:hover {
    color: var(--text-color);
    background-color: var(--panel-bg);
  }
  .nav-item:hover svg {
    fill: var(--text-color);
  }
  .nav-item.active {
    color: var(--accent-contrast);
    background-color: var(--accent-blue);
  }
  .nav-item.active svg {
    fill: var(--accent-contrast);
  }
  .sidebar-bottom {
    display: flex;
    flex-direction: column;
    gap: 4px;
    padding: 0 12px;
  }

  /* Contenido principal (Zona Derecha) */
  .main-wrapper {
    display: flex;
    flex-direction: column;
    flex-grow: 1;
    height: 100vh;
    overflow: hidden;
  }

  /* Barra superior (Topbar) */
  .topbar {
    height: 70px;
    background-color: var(--sidebar-bg);
    border-bottom: 1px solid var(--border-color);
    display: flex;
    justify-content: space-between;
    align-items: center;
    padding: 0 32px;
    flex-shrink: 0;
  }
  .search-container {
    position: relative;
    width: 100%;
    max-width: 440px;
  }
  .search-container svg {
    position: absolute;
    left: 14px;
    top: 50%;
    transform: translateY(-50%);
    fill: var(--muted-color);
    width: 14px;
    height: 14px;
  }
  .search-input {
    width: 100%;
    background-color: var(--panel2-bg);
    border: 1px solid var(--border-color);
    border-radius: 20px;
    padding: 10px 16px 10px 40px;
    color: var(--text-color);
    font-size: 13px;
    outline: none;
    transition: border-color 0.2s;
  }
  .search-input:focus {
    border-color: var(--accent);
  }
  .search-dropdown {
    display: none;
    position: absolute;
    top: calc(100% + 8px);
    left: 0;
    right: 0;
    max-height: min(480px, calc(100vh - 110px));
    overflow-y: auto;
    background: var(--panel-bg);
    border: 1px solid var(--border-color);
    border-radius: 8px;
    box-shadow: 0 14px 32px rgba(0,0,0,0.32);
    z-index: 30;
    padding: 8px;
  }
  .search-dropdown.open {
    display: block;
  }
  .search-section-title {
    padding: 8px 10px 6px;
    color: var(--muted-color);
    font-family: var(--mono-font);
    font-size: 11px;
    text-transform: uppercase;
  }
  .search-result-item {
    display: flex;
    align-items: center;
    gap: 10px;
    width: 100%;
    border: 0;
    background: transparent;
    color: var(--text-color);
    text-align: left;
    padding: 10px;
    border-radius: 8px;
    cursor: pointer;
  }
  .search-result-item:hover {
    background: var(--panel2-bg);
  }
  .search-result-avatar {
    width: 38px;
    height: 38px;
    border-radius: 50%;
    object-fit: cover;
    border: 1px solid var(--border-color);
    flex: 0 0 38px;
  }
  .search-result-symbol {
    width: 38px;
    height: 38px;
    border-radius: 50%;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    background: var(--accent-blue-soft);
    color: var(--accent-blue);
    border: 1px solid var(--border-color);
    font-family: var(--mono-font);
    font-size: 12px;
    font-weight: 700;
    flex: 0 0 38px;
  }
  .search-result-main {
    min-width: 0;
    flex: 1;
  }
  .search-result-main strong,
  .search-result-main span {
    display: block;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
  }
  .search-result-main span {
    color: var(--muted-color);
    font-size: 12px;
  }
  .search-result-country {
    color: var(--muted-color);
    font-size: 12px;
    flex: 0 0 auto;
    max-width: 110px;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
  }
  .search-result-status {
    color: var(--muted-color);
    padding: 18px 10px;
    text-align: center;
    font-size: 13px;
  }
  .notifications-wrapper {
    position: relative;
  }
  .notifications-dropdown {
    display: none;
    position: absolute;
    top: calc(100% + 14px);
    right: 0;
    width: min(360px, calc(100vw - 32px));
    max-height: min(520px, calc(100vh - 110px));
    overflow-y: auto;
    background: var(--panel-bg);
    border: 1px solid var(--border-color);
    border-radius: 8px;
    box-shadow: 0 14px 32px rgba(0,0,0,0.32);
    z-index: 35;
    padding: 8px;
  }
  .notifications-dropdown.open {
    display: block;
  }
  .notifications-header {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 10px;
    padding: 8px 10px;
  }
  .notifications-header strong {
    font-size: 13px;
  }
  .notifications-header button {
    background: transparent;
    border: 0;
    color: var(--accent-blue);
    cursor: pointer;
    font-size: 12px;
  }
  .notification-item {
    display: flex;
    gap: 10px;
    width: 100%;
    border: 0;
    background: transparent;
    color: var(--text-color);
    text-align: left;
    padding: 10px;
    border-radius: 8px;
    cursor: pointer;
  }
  .notification-item:hover {
    background: var(--panel2-bg);
  }
  .notification-item.unread {
    background: rgba(59,130,246,0.08);
  }
  .notification-item img {
    width: 34px;
    height: 34px;
    border-radius: 50%;
    object-fit: cover;
    border: 1px solid var(--border-color);
  }
  .notification-body {
    min-width: 0;
    flex: 1;
    font-size: 12px;
    line-height: 1.35;
  }
  .notification-body small {
    display: block;
    color: var(--muted-color);
    margin-top: 4px;
  }
  /* Aviso de cartera, no evento social: sin avatar, borde ámbar en vez de "sin leer". */
  .notification-cartera {
    cursor: default;
    background: rgba(245, 158, 11, 0.07);
    border-left: 2px solid var(--warn-color, #f59e0b);
  }
  .notification-cartera:hover {
    background: rgba(245, 158, 11, 0.11);
  }
  .notification-icon-warn {
    flex-shrink: 0;
    width: 34px;
    text-align: center;
    font-size: 15px;
    color: var(--warn-color, #f59e0b);
  }
  /* Informativo, no aviso. Deliberadamente APAGADO: no ha pasado nada malo,
     falta un dato que ningun CSV puede traer. Con el ambar del aviso de cartera
     se leia como un problema, y quien veia «-13.883,93 EUR» creia que lo debia. */
  .notification-info {
    cursor: default;
    background: transparent;
    border-left: 2px solid var(--border-color);
  }
  .notification-info:hover {
    background: var(--panel2-bg);
  }
  .notification-info .notification-body { color: var(--muted-color); }
  .notification-icon-info {
    flex-shrink: 0;
    width: 34px;
    text-align: center;
    font-size: 14px;
    font-style: italic;
    font-weight: 700;
    color: var(--muted-color);
  }
  .notification-acciones {
    display: flex;
    gap: 8px;
    margin-top: 8px;
  }
  .notification-acciones button {
    background: var(--panel2-bg);
    color: var(--text-color);
    border: 1px solid var(--border-color);
    border-radius: 6px;
    padding: 4px 10px;
    font-size: 11px;
    font-weight: 600;
    cursor: pointer;
  }
  .notification-acciones button:hover {
    border-color: var(--accent-blue, #3b82f6);
  }
  .notification-acciones button.ghost:hover {
    border-color: var(--neg-color, #f84960);
    color: var(--neg-color, #f84960);
  }
  .topbar-right {
    display: flex;
    align-items: center;
    gap: 20px;
  }
  .icon-button {
    background: transparent;
    border: none;
    cursor: pointer;
    display: flex;
    align-items: center;
    justify-content: center;
    position: relative;
  }
  .icon-button svg {
    fill: var(--muted-color);
    width: 18px;
    height: 18px;
    transition: fill 0.2s;
  }
  .icon-button:hover svg {
    fill: var(--text-color);
  }
  .icon-badge {
    position: absolute;
    top: -2px;
    right: -2px;
    width: 6px;
    height: 6px;
    background-color: var(--neg-color);
    border-radius: 50%;
  }
  .avatar {
    width: 32px;
    height: 32px;
    border-radius: 50%;
    overflow: hidden;
    border: 1.5px solid var(--border-color);
  }
  .avatar img {
    width: 100%;
    height: 100%;
    object-fit: cover;
  }

  /* Contenedor de la pantalla activa (Scrollable) */
  .content-area {
    flex-grow: 1;
    padding: 16px 32px 32px;
    overflow-y: auto;
    background-color: var(--bg);
    /* Las cajas se miden contra el ancho REAL disponible (unidades `cqw`) y no
       contra el de la ventana: así crecen solas al plegar el menú lateral, que
       con `vw` no se enteraban. */
    container-type: inline-size;
  }

  /* --- ESTILOS DE PANTALLA: PORTFOLIO (DASHBOARD) --- */
  .dashboard-grid {
    display: grid;
    grid-template-columns: 2fr 1fr;
    gap: 24px;
    margin-bottom: 24px;
  }
  /* Un hijo de grid no baja por defecto de su contenido mínimo —el nombre más
     largo de la leyenda, el ancho del canvas—, así que las columnas se pasaban
     de largo y el dashboard se salía por la derecha, dejando la tabla de
     posiciones desalineada con él. Con `min-width: 0` mandan las fracciones y
     el recorte lo absorbe el texto. */
  .dashboard-grid > * {
    min-width: 0;
  }

  /* Por debajo de esto la columna del gráfico se queda tan estrecha que las
     fechas del eje se amontonan. */
  @media (max-width: 1100px) {
    .dashboard-grid {
      grid-template-columns: 1fr;
    }
  }

  .main-chart-card {
    background-color: var(--panel-bg);
    border: 1px solid var(--border-color);
    border-radius: 16px;
    padding: 24px;
    display: flex;
    flex-direction: column;
    /* El gráfico es quien absorbe el espacio sobrante (`flex: 1` abajo). Con
       `space-between` el hueco se repartía en huecos vacíos alrededor. */
    justify-content: flex-start;
  }

  .portfolio-header {
    display: flex;
    justify-content: space-between;
    align-items: flex-start;
    gap: 12px;
    /* Que la cabecera pueda partirse es lo que permite a la tarjeta encoger;
       si no, su ancho mínimo volvía a desbordar la columna. */
    flex-wrap: wrap;
  }
  .portfolio-title-group h2 {
    font-size: 14px;
    font-weight: 500;
    color: var(--muted-color);
    font-family: var(--sans-font);
  }
  .portfolio-value-group {
    display: flex;
    align-items: baseline;
    gap: 12px;
    margin-top: 6px;
    flex-wrap: wrap;
  }
  .portfolio-value {
    font-size: clamp(26px, 2.26cqw, 38px);
    font-weight: 700;
    font-family: var(--sans-font);
    letter-spacing: -0.5px;
  }
  .portfolio-change {
    font-size: 14px;
    font-weight: 600;
    display: inline-flex;
    align-items: center;
    gap: 4px;
  }
  .portfolio-change.pos { color: var(--pos-color); }
  .portfolio-change.neg { color: var(--neg-color); }
  /* Apagada a propósito: acompaña a la cifra sin competir con ella. */
  .portfolio-period-label {
    font-size: 12px;
    color: var(--muted-color);
    font-weight: 500;
  }

  /* --- PANTALLA DE PROYECCIÓN --- */
  .proy-card { margin-bottom: 24px; }

  /* La respuesta arriba del todo, con el mismo reparto que la cabecera de la
     cartera: la cifra grande, su etiqueta apagada al lado, y la segunda medida
     separada por su raya. */
  .proy-cabecera {
    display: flex;
    align-items: baseline;
    flex-wrap: wrap;
    gap: 12px;
    margin-bottom: 20px;
  }
  .proy-valor {
    font-size: clamp(26px, 2.26cqw, 38px);
    font-weight: 700;
    font-family: var(--sans-font);
    letter-spacing: -0.5px;
    color: var(--pos-color);
  }
  .proy-plazo {
    font-size: 12px;
    color: var(--muted-color);
    font-weight: 500;
  }
  .proy-impuesto {
    flex-basis: 100%;
    font-size: 12px;
    color: var(--muted-color);
  }
  .proy-chart-container { height: clamp(240px, 30vh, 400px); }

  /* Los mandos en rejilla: caben dos o tres por fila según el ancho, y el de la
     rentabilidad ocupa la fila entera porque lleva el aviso debajo. */
  .proy-controles {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(230px, 1fr));
    gap: 18px 24px;
    margin-top: 22px;
    padding-top: 20px;
    border-top: 1px solid var(--border-color);
  }
  .proy-control-ancho { grid-column: 1 / -1; }
  .proy-control label {
    display: block;
    font-size: 12px;
    font-weight: 600;
    color: var(--muted-color);
    margin-bottom: 8px;
  }
  .proy-control-fila {
    display: flex;
    align-items: center;
    gap: 12px;
  }
  .proy-control-fila input[type="range"] {
    flex: 1 1 auto;
    min-width: 0;
    accent-color: var(--accent);
    cursor: pointer;
  }
  .proy-control-fila input[type="text"] {
    flex: 0 1 160px;
    background: var(--panel2-bg);
    border: 1px solid var(--border-color);
    border-radius: 8px;
    padding: 8px 10px;
    color: var(--text-color);
    font-family: var(--mono-font);
    font-size: 14px;
  }
  .proy-control-val {
    flex: 0 0 auto;
    min-width: 62px;
    text-align: right;
    font-family: var(--mono-font);
    font-size: 13px;
    font-weight: 600;
    color: var(--text-color);
  }
  .proy-nota {
    margin-top: 6px;
    font-size: 11.5px;
    line-height: 1.45;
    color: var(--muted-color);
  }
  /* El aviso de la rentabilidad histórica no es una nota más: es lo que impide
     que alguien ponga su 20% anual y se crea el resultado. */
  .proy-aviso {
    padding: 8px 10px;
    border-left: 2px solid var(--warn-color, #f59e0b);
    background: var(--panel2-bg);
    border-radius: 0 6px 6px 0;
  }
  .proy-horizontes { display: flex; flex-wrap: wrap; gap: 4px; }

  /* Las dos tarjetas de abajo: de dónde sale el dinero, y qué pasó por el
     camino. Van a la par porque se leen juntas. */
  .proy-columnas {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(320px, 1fr));
    gap: 24px;
    margin-bottom: 24px;
  }
  .proy-titulo {
    font-size: 15px;
    font-weight: 600;
    margin-bottom: 14px;
  }
  /* La barra del desglose: una sola, en tres trozos. Un anillo aquí competiría
     con el de Composición sin decir nada más. */
  .proy-barra {
    display: flex;
    height: 12px;
    border-radius: 6px;
    overflow: hidden;
    background: var(--panel2-bg);
  }
  .proy-barra span { display: block; }
  /* Los tres papeles del dinero. Salen de la paleta categórica de la aplicación
     y están validados sobre las dos superficies: la separación más pobre entre
     dos cualesquiera es ΔE 21 en deuteranopía. Los tres verdes de antes dejaban
     los puntos de la leyenda casi idénticos.

     Viven aquí y en `PROY_COLORES` porque el mismo reparto se cuenta en tres
     sitios —esta barra, el área de la gráfica y las barras año a año— y dos
     códigos de color para lo mismo obligan a aprenderlos dos veces. */
  :root {
    --proy-tienes: #199e70;
    --proy-aportas: #7c5cd6;
    --proy-mercado: #d95926;
  }
  .proy-parte-tienes { background: var(--proy-tienes); }
  .proy-parte-aportas { background: var(--proy-aportas); }
  .proy-parte-mercado { background: var(--proy-mercado); }

  .proy-leyenda {
    list-style: none;
    margin: 14px 0 0;
    padding: 0;
    display: flex;
    flex-direction: column;
    gap: 8px;
    font-size: 12.5px;
  }
  .proy-leyenda li { display: flex; align-items: center; gap: 8px; }
  .proy-leyenda-txt { flex: 1 1 auto; color: var(--muted-color); }
  .proy-leyenda strong { font-family: var(--mono-font); }
  .proy-punto {
    width: 8px;
    height: 8px;
    border-radius: 2px;
    flex-shrink: 0;
  }
  .proy-punto.proy-parte-tienes,
  .proy-punto.proy-parte-aportas,
  .proy-punto.proy-parte-mercado { display: block; }

  #proy-contraste p { font-size: 12.5px; line-height: 1.55; margin: 0 0 10px; }
  #proy-contraste .neg { color: var(--neg-color); }
  .proy-meta #proy-objetivo-respuesta { margin-top: 14px; }
  .proy-meta #proy-objetivo-respuesta p { font-size: 13px; margin: 0 0 8px; }

  /* El selector de vista de la gráfica, pegado a ella. */
  .proy-vistas { margin-bottom: 12px; }

  /* La casilla de un mando escribible: el número y su unidad, con aspecto de
     campo para que se vea que se puede teclear. Ancho fijo para que la barra no
     se mueva al pasar de «6» a «50». */
  .proy-campo {
    display: inline-flex;
    align-items: baseline;
    gap: 3px;
    flex-shrink: 0;
    padding: 4px 8px;
    background: var(--panel2-bg);
    border: 1px solid var(--border-color);
    border-radius: 6px;
    transition: border-color 0.15s ease;
  }
  .proy-campo:focus-within { border-color: var(--accent); }
  .proy-campo input {
    /* El ancho lo manda el `maxlength` del campo, no el máximo del deslizador:
       mientras se escribe el texto no se recorta —recortarlo movería el cursor—
       así que pueden verse más dígitos de los que se van a aplicar, y son esos
       los que tienen que caber. Un carácter de holgura para el cursor: con los
       dígitos justos, el navegador desplaza el texto y se come el último.

       `flex: 0 0 auto` y el `min-width`: como elemento de un contenedor
       flexible, el ancho declarado era solo una preferencia y el campo cedía
       por debajo de él. Ahí es donde se comía la cifra de verdad. */
    flex: 0 0 auto;
    width: 4ch;
    min-width: 4ch;
    border: none;
    background: none;
    padding: 0;
    color: var(--text-color);
    font-family: var(--mono-font);
    font-size: 13px;
    font-weight: 600;
    text-align: right;
  }
  /* La aportación admite cinco dígitos tecleados; la rentabilidad, tres. */
  .proy-campo-largo input { width: 6ch; min-width: 6ch; }
  .proy-campo input:focus { outline: none; }
  .proy-campo-unidad {
    /* Tampoco se encoge: apretada, la unidad se cortaba antes que el número. */
    flex: 0 0 auto;
    color: var(--muted-color);
    font-family: var(--mono-font);
    font-size: 12px;
  }
  /* El interruptor de descontar impuestos: casilla y rótulo en una línea. */
  .proy-interruptor {
    display: flex !important;
    align-items: center;
    gap: 8px;
    cursor: pointer;
    color: var(--text-color) !important;
    font-size: 13px !important;
    margin-bottom: 0 !important;
  }
  .proy-interruptor input { accent-color: var(--accent); width: 15px; height: 15px; cursor: pointer; }
  /* Apagado el interruptor, la retención sigue ahí —la cifra pendiente se
     enseña igual— pero deja de mandar en el número grande. */
  .proy-atenuado { opacity: 0.5; }

  .proy-anual { margin-bottom: 24px; }
  .proy-anual-chart-box {
    height: clamp(200px, 24vh, 320px);
    margin-bottom: 20px;
  }
  /* La tabla completa cabe rara vez: con treinta años se desplaza dentro de su
     caja en vez de estirar la tarjeta. */
  .proy-anual-tabla { max-height: 340px; overflow-y: auto; }
  .proy-anual-tabla thead th {
    position: sticky;
    top: 0;
    background: var(--panel-bg);
    z-index: 1;
  }

  /* --- LA MEDIDA DE UN TRAMO DE LA CURVA ---
   *
   * Aparece al arrastrar sobre la gráfica y se va al soltar. Va arriba a la
   * izquierda y quieta: siguiendo al ratón taparía justo la parte de la curva
   * que se está mirando, y en un rótulo de varias cifras el salto constante
   * cansa más de lo que ayuda.
   */
  .rango-chip {
    position: absolute;
    top: 6px;
    left: 8px;
    z-index: 5;
    display: flex;
    align-items: baseline;
    flex-wrap: wrap;
    gap: 4px 8px;
    max-width: calc(100% - 16px);
    padding: 6px 10px;
    background: var(--panel2-bg);
    border: 1px solid var(--border-color);
    border-radius: 8px;
    box-shadow: 0 4px 14px rgba(0, 0, 0, 0.35);
    font-size: 12px;
    line-height: 1.35;
    /* No se puede pinchar: el ratón está arrastrando por debajo. */
    pointer-events: none;
  }
  .rango-chip[hidden] { display: none; }

  .rango-chip-etiqueta {
    color: var(--muted-color);
    font-weight: 500;
  }
  .rango-chip-pct {
    font-family: var(--mono-font);
    font-weight: 700;
    font-size: 13px;
  }
  .rango-chip-pct.pos { color: var(--pos-color); }
  .rango-chip-pct.neg { color: var(--neg-color); }
  .rango-chip-valor {
    font-family: var(--mono-font);
    color: var(--text-color);
  }
  .rango-chip-fechas {
    color: var(--muted-color);
    /* Separadas del resto con una raya, que son otra clase de dato. */
    padding-left: 8px;
    border-left: 1px solid var(--border-color);
  }

  /* Mientras se mide: la cruz dice que se está apuntando a un punto, y sin
     cortar la selección el arrastre pinta de azul las etiquetas del eje. */
  #portfolio-history-chart.midiendo-rango {
    cursor: crosshair;
    user-select: none;
  }

  /* --- LA EXPLICACIÓN DE CADA CIFRA ---
   *
   * En la cabecera conviven cinco cifras que miden cosas distintas: el valor,
   * el dinero ganado en el tramo, el rendimiento encadenado, lo ya cobrado y el
   * total. Puestas en fila se leen como si fueran la misma cosa —de ahí venía
   * que un «+242,34 € (−18,83 %)» pareciera un error de la aplicación—, y no
   * hay sitio en pantalla para explicarlas a la vista.
   *
   * Al pasar el ratón, cada una cuenta qué es y cómo se calcula. Se abre con
   * `:hover` y con `:focus-within`, así que también se llega con el tabulador.
   */
  .cifra-info {
    position: relative;
    display: inline-block;
    /* El cursor es la única pista de que hay algo que leer. */
    cursor: help;
  }
  /* El grupo del rendimiento ya es un `inline-flex` con su etiqueta dentro;
     esta regla va explícita para que no dependa del orden del fichero. */
  .portfolio-return.cifra-info { display: inline-flex; }

  .cifra-ayuda {
    position: absolute;
    top: calc(100% + 10px);
    left: 0;
    z-index: 30;
    display: flex;
    flex-direction: column;
    gap: 7px;
    /* Ancho de lectura cómoda, y en móvil lo que quepa sin desbordar. */
    width: max-content;
    max-width: min(310px, calc(100vw - 32px));
    padding: 12px 14px;
    background: var(--panel2-bg);
    border: 1px solid var(--border-color);
    border-radius: 10px;
    box-shadow: 0 8px 24px rgba(0, 0, 0, 0.45);
    font-family: var(--sans-font);
    font-size: 12px;
    line-height: 1.5;
    font-weight: 400;
    /* De lo contrario hereda el verde o el rojo de la cifra que la abre. */
    color: var(--text-color);
    text-align: left;
    white-space: normal;
    letter-spacing: normal;
    pointer-events: none;
    opacity: 0;
    transform: translateY(-4px);
    transition: opacity 0.18s ease, transform 0.18s ease;
  }
  /* La punta que la ata a su cifra. */
  .cifra-ayuda::before {
    content: "";
    position: absolute;
    top: -5px;
    left: 14px;
    width: 8px;
    height: 8px;
    background: var(--panel2-bg);
    border-left: 1px solid var(--border-color);
    border-top: 1px solid var(--border-color);
    transform: rotate(45deg);
  }
  .cifra-info:hover .cifra-ayuda,
  .cifra-info:focus-within .cifra-ayuda {
    opacity: 1;
    transform: translateY(0);
  }

  .cifra-ayuda-titulo {
    font-size: 13px;
    font-weight: 700;
    color: var(--text-color);
    line-height: 1.3;
  }
  /* El nombre técnico, para quien lo busque fuera; en pequeño y apagado, que no
     es lo que hay que leer para entender la cifra. */
  .cifra-ayuda-sub {
    font-size: 11px;
    color: var(--muted-color);
    margin-top: -6px;
  }
  .cifra-ayuda-texto { color: var(--text-color); }

  /* «Cómo se mide» y «Ojo» son bloques aparte, con su etiqueta encima: quien
     solo quiere saber qué es la cifra lee la primera frase y para. */
  .cifra-ayuda-cuenta,
  .cifra-ayuda-ojo {
    display: flex;
    flex-direction: column;
    gap: 3px;
    padding-top: 8px;
    border-top: 1px solid var(--border-color);
    font-size: 11.5px;
    color: var(--muted-color);
  }
  .cifra-ayuda-etiqueta {
    font-size: 10px;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: 0.6px;
    color: var(--muted-color);
    opacity: 0.75;
  }
  /* Los operadores de la cuenta, marcados para poder leerla de un vistazo. */
  .cifra-ayuda-cuenta em {
    font-style: normal;
    font-weight: 700;
    color: var(--text-color);
    opacity: 0.7;
  }
  /* El aviso del rendimiento es el que resuelve la duda que trae aquí a la
     gente, así que se distingue del resto. */
  .cifra-ayuda-ojo .cifra-ayuda-etiqueta { color: var(--warn-color, #f59e0b); opacity: 1; }

  /* Quien pidió no ver animaciones tampoco ve esta: aparece y ya. */
  @media (prefers-reduced-motion: reduce) {
    .cifra-ayuda { transition: none; transform: none; }
    .cifra-info:hover .cifra-ayuda,
    .cifra-info:focus-within .cifra-ayuda { transform: none; }
  }

  /* El rendimiento del tramo, separado de los euros.
   *
   * Iba pegado entre paréntesis —«+242,34 € (−18,83 %)»— y se leía como una
   * sola cifra: el porcentaje DE esos euros. No lo es. Los euros son dinero;
   * el porcentaje es un TWR, que encadena el día a día sin mirar cuánto había
   * dentro en cada momento. Pueden llevar signo distinto sin que nada falle, y
   * juntos eso parecía un error de la aplicación.
   *
   * Separados y con etiqueta, cada uno responde a su pregunta. La jerarquía
   * hace el resto: los euros en el sitio grande y coloreado, el rendimiento
   * más pequeño y a un lado. */
  .portfolio-return {
    display: inline-flex;
    align-items: baseline;
    gap: 5px;
    font-size: 12px;
    /* Una raya suave a la izquierda: separa sin meter un punto ni un paréntesis
       más, que es de lo que se venía. */
    padding-left: 12px;
    border-left: 1px solid var(--border-color);
  }
  .portfolio-return-label {
    color: var(--muted-color);
    font-weight: 500;
  }
  .portfolio-return-value {
    font-weight: 600;
    color: var(--muted-color);
  }
  .portfolio-return-value.pos { color: var(--pos-color); }
  .portfolio-return-value.neg { color: var(--neg-color); }

  /* En pantallas estrechas el grupo ya hace `wrap`, y una raya al principio de
     una línea nueva no separa de nada. */
  @media (max-width: 640px) {
    .portfolio-return {
      padding-left: 0;
      border-left: none;
    }
  }
  
  .portfolio-actions {
    display: flex;
    gap: 8px;
    flex-shrink: 0;
  }
  .btn-action-circle {
    width: 36px;
    height: 36px;
    border-radius: 50%;
    background-color: var(--panel2-bg);
    border: 1px solid var(--border-color);
    display: flex;
    align-items: center;
    justify-content: center;
    cursor: pointer;
    transition: background-color 0.2s;
  }
  .btn-action-circle:hover {
    background-color: var(--border-color);
  }
  .btn-action-circle svg {
    fill: var(--text-color);
    width: 16px;
    height: 16px;
  }
  /* Comparación activa: el botón dice que hay algo encendido, que si no solo se
     nota mirando las pastillas del pie de la gráfica. */
  .btn-action-circle.activo {
    background-color: var(--accent-soft);
    border-color: var(--accent);
  }
  .btn-action-circle.activo svg {
    fill: var(--accent);
  }

  /* Filtros y Cuentas */
  .portfolio-sub-actions {
    display: flex;
    /* Centrados bajo el gráfico: son el pie del eje de tiempo, no una acción
       suelta de la esquina. */
    justify-content: center;
    align-items: center;
    margin-top: 16px;
    margin-bottom: 0;
    flex-wrap: wrap;
    gap: 12px;
  }
  .portfolio-accounts {
    display: flex;
    gap: 8px;
    background-color: var(--panel-bg);
  }
  .btn-account {
    background-color: transparent;
    border: 1px solid transparent;
    color: var(--muted-color);
    padding: 6px 14px;
    border-radius: 16px;
    font-size: 12px;
    font-weight: 500;
    cursor: pointer;
    transition: all 0.2s;
  }
  .btn-account:hover {
    color: var(--text-color);
  }
  .btn-account.active {
    color: var(--accent-green);
    background-color: rgba(0, 197, 130, 0.1);
  }
  .btn-add-account {
    border: 1px dashed var(--border-color);
    color: var(--muted-color);
  }
  .btn-add-account:hover {
    border-color: var(--muted-color);
    color: var(--text-color);
  }
  .portfolio-time-filters {
    display: flex;
    background-color: var(--panel2-bg);
    border-radius: 6px;
    padding: 2px;
  }
  .btn-time-filter {
    background: transparent;
    border: none;
    color: var(--muted-color);
    padding: 4px 10px;
    border-radius: 4px;
    font-size: 11px;
    font-weight: 600;
    cursor: pointer;
    font-family: var(--mono-font);
    transition: all 0.2s;
  }
  .btn-time-filter:hover {
    color: var(--text-color);
  }
  .btn-time-filter.active {
    background-color: var(--accent-soft);
    color: var(--accent);
  }

  /* SVG Line Chart */
  .line-chart-container {
    width: 100%;
    position: relative;
    margin-top: 10px;
    /* Base 0, no `auto`: con `auto` la altura sale del canvas, que Chart.js
       dimensiona a partir del contenedor, y esa circularidad hacía crecer el
       gráfico sin parar. */
    flex: 1 1 0;
    /* Anula el mínimo automático de los flex items; escalado con la pantalla
       para no comerse la vista en portátil ni dejar hueco muerto en monitor. */
    min-height: clamp(220px, 34vh, 460px);
    overflow: hidden; /* estructural: que ningún hijo empuje la caja */
  }
  /* Quita el hueco bajo un canvas en línea. El tamaño no se fuerza: Chart.js lo
     calcula del `devicePixelRatio`, y pisarlo con `!important` lo desenfoca. */
  .line-chart-container > canvas {
    display: block;
  }
  .line-chart-container svg {
    width: 100%;
    height: 100%;
  }

  /* Barra lateral derecha (Widgets) */
  .right-widgets {
    display: flex;
    flex-direction: column;
    gap: 24px;
  }
  .widget-card {
    background-color: var(--panel-bg);
    border: 1px solid var(--border-color);
    border-radius: 16px;
    padding: 20px;
    display: flex;
    flex-direction: column;
    /* Reparten entre las dos la altura de la columna, que el grid ya iguala a
       la del gráfico. Sin esto se quedaban en su altura natural y el sobrante
       se acumulaba en un hueco al fondo de la columna. */
    flex: 1 1 auto;
    min-height: 230px;
  }
  /* El reparto de la columna deja de ser mitad y mitad. El mapa necesita alto
     —con poco, las piezas de menos peso se quedan en rayas donde no cabe ni el
     nombre— y las barras de rendimiento se leen igual algo más bajas, que su
     información está en la altura relativa entre ellas y no en su tamaño.
     Va con `flex-grow` y no con alturas fijas para que las dos sigan
     dependiendo del alto que el grid le dé a la columna. */
  .widget-card--composicion {
    flex-grow: 1.55;
    min-height: 280px;
  }
  .widget-card--rendimiento {
    flex-grow: 1;
    min-height: 190px;
  }
  /* El contenido es quien absorbe el alto de más. Antes la tarjeta usaba
     `space-between`, que al estirarse empujaba cabecera y gráfico a los
     extremos y dejaba el hueco en medio en vez de repartirlo. */
  .donut-chart-container,
  .performance-chart-container {
    flex: 1 1 auto;
  }
  .widget-header {
    display: flex;
    justify-content: space-between;
    align-items: center;
    margin-bottom: 14px;
  }
  .widget-header h3 {
    font-size: clamp(15px, 1cqw, 18px);
    font-weight: 600;
  }
  .widget-header a {
    font-size: clamp(11.5px, 0.77cqw, 14px);
    color: var(--accent-green);
    text-decoration: none;
    font-weight: 600;
  }
  .widget-header a:hover {
    text-decoration: underline;
  }

  /* --- SELECTOR DE FORMA DEL WIDGET DE COMPOSICIÓN ---
   *
   * Va en la cabecera y no bajo el gráfico porque el alto es el recurso escaso:
   * la tarjeta reparte con la de Rendimiento la altura que el grid fija para la
   * columna, y una fila de botones debajo se la quitaría al propio gráfico. En
   * la cabecera no cuesta nada, que ahí sobra ancho. */
  .widget-header-acciones {
    display: flex;
    align-items: center;
    gap: clamp(8px, 0.8cqw, 14px);
    flex: 0 0 auto;
  }
  .composicion-formas-widget {
    display: flex;
    gap: 2px;
    padding: 2px;
    border-radius: 8px;
    background-color: var(--bg);
    border: 1px solid var(--border-color);
  }
  .composicion-forma-btn {
    display: grid;
    place-items: center;
    width: 26px;
    height: 24px;
    padding: 0;
    border: none;
    border-radius: 6px;
    background: transparent;
    color: var(--muted-color);
    cursor: pointer;
    transition: background-color 0.15s, color 0.15s;
  }
  .composicion-forma-btn svg {
    display: block;
    width: 15px;
    height: 15px;
    fill: currentColor;
  }
  .composicion-forma-btn:hover {
    color: var(--text-color);
  }
  .composicion-forma-btn.active {
    background-color: var(--accent-soft);
    color: var(--accent);
  }
  /* El icono activo se distingue por color y fondo. El foco necesita su propia
     marca: quien navega con teclado tiene que ver dónde está aunque el botón
     que recorre no sea el que está puesto. */
  .composicion-forma-btn:focus-visible {
    outline: 2px solid var(--accent);
    outline-offset: 1px;
  }

  /* --- CUERPO DEL WIDGET DE COMPOSICIÓN ---
   *
   * Las tres formas conviven en el DOM y se alternan con `hidden`. Este
   * contenedor es quien absorbe el alto sobrante de la tarjeta, el papel que
   * antes hacía `.donut-chart-container` cuando era hijo directo. */
  .composicion-widget-cuerpo {
    flex: 1 1 auto;
    display: flex;
    flex-direction: column;
    min-height: 0;
  }
  .composicion-widget-cuerpo > *:not([hidden]) {
    flex: 1 1 auto;
    min-height: 0;
  }
  /* IMPRESCINDIBLE, y no es redundante con el `hidden` del HTML: el
     `display:none` que el navegador aplica a `[hidden]` sale de su hoja de
     estilos por defecto, así que CUALQUIER regla nuestra que fije `display` lo
     pisa —y `.donut-chart-container` fija `display:flex`—. Sin esto, el anillo
     seguiría dibujado debajo de las barras. */
  .composicion-widget-cuerpo > [hidden] {
    display: none;
  }

  /* Barras y mapa ocupan el ancho completo: la leyenda es cosa del anillo. En
     las barras el nombre y el peso van en el propio eje, y en el mapa dentro de
     cada rectángulo, así que repetirlos al lado sería gastar en duplicar lo que
     hace falta para que se lea el gráfico. */
  .composicion-widget-barras,
  .composicion-widget-mapa {
    position: relative;
    min-height: 0;
  }
  .composicion-widget-mapa {
    border-radius: 8px;
    overflow: hidden;
  }
  .treemap-widget-celda {
    position: absolute;
    display: flex;
    flex-direction: column;
    justify-content: center;
    gap: 1px;
    padding: 5px 7px;
    overflow: hidden;
    border-radius: 4px;
    /* La separación entre piezas se hace con un borde del color del panel, no
       con márgenes: el reparto se escribe en porcentajes del contenedor y un
       margen los descuadraría al cambiar de tamaño la ventana. */
    border: 2px solid var(--panel-bg);
    cursor: default;
    /* El color llega en un segundo tiempo, cuando responden las series. La
       transición convierte ese desfase en algo que se lee como «ha llegado un
       dato» en vez de como un parpadeo. */
    background-color: var(--panel2-bg);
    transition: background-color 0.35s ease;
  }
  .treemap-widget-nombre,
  .treemap-widget-rent {
    color: #fff;
    /* Los peldaños de `colorRentabilidad` están elegidos para que el blanco se
       lea encima, pero el más vivo de la escala se queda justo: la sombra da el
       margen sin tener que apagar los verdes. */
    text-shadow: 0 1px 2px rgba(0, 0, 0, 0.55);
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
    line-height: 1.2;
  }
  .treemap-widget-nombre {
    font-size: clamp(10.5px, 0.72cqw, 12.5px);
    font-weight: 600;
  }
  .treemap-widget-rent {
    font-size: clamp(9.5px, 0.66cqw, 11.5px);
    font-family: var(--mono-font);
    opacity: 0.95;
  }

  /* --- TOOLTIP DE LAS BARRAS DEL WIDGET ---
   *
   * Cuelga de `body` y va `fixed`: la tarjeta tiene `overflow:hidden` por el
   * mapa, y dentro de ella el tooltip de la primera barra saldría recortado.
   *
   * Se muestra con opacidad y desplazamiento, no con `display`: es lo que
   * sustituye a los nombres que se han quitado del eje, así que tiene que
   * entrar de forma que se vea DE DÓNDE sale y no aparecer de golpe. */
  .composicion-widget-tooltip {
    position: fixed;
    z-index: 4000;
    pointer-events: none;
    width: max-content;
    max-width: 260px;
    padding: 9px 11px;
    border-radius: 8px;
    background: var(--panel2-bg);
    border: 1px solid var(--border-color);
    box-shadow: 0 10px 28px rgba(0, 0, 0, 0.45);
    color: var(--text-color);
    font-size: 12px;
    line-height: 1.45;
    opacity: 0;
    transform: translateX(-4px);
    transition: opacity 0.16s ease, transform 0.16s ease;
  }
  .composicion-widget-tooltip.visible {
    opacity: 1;
    transform: translateX(0);
  }
  /* Quien haya pedido menos movimiento en su sistema lo recibe igual de rápido,
     pero sin el desplazamiento. */
  @media (prefers-reduced-motion: reduce) {
    .composicion-widget-tooltip {
      transform: none;
      transition: opacity 0.1s linear;
    }
    .treemap-widget-celda {
      transition: none;
    }
  }
  .composicion-widget-tooltip-titulo {
    display: flex;
    align-items: center;
    gap: 7px;
    font-weight: 700;
    margin-bottom: 3px;
  }
  .composicion-widget-tooltip-color {
    flex: 0 0 auto;
    width: 9px;
    height: 9px;
    border-radius: 2px;
  }
  /* Etiqueta a la izquierda y cifra a la derecha, como el tooltip del mapa
     grande: en tres filas apiladas, alinear los números deja comparar de un
     vistazo en vez de tener que leerlos. */
  .composicion-widget-tooltip-fila {
    display: flex;
    justify-content: space-between;
    align-items: baseline;
    gap: 18px;
    color: var(--muted-color);
    font-size: 11.5px;
  }
  .composicion-widget-tooltip-fila strong {
    color: var(--text-color);
    font-family: var(--mono-font);
    font-weight: 600;
  }
  .composicion-widget-tooltip-fila strong.pos { color: var(--pos-color); }
  .composicion-widget-tooltip-fila strong.neg { color: var(--neg-color); }

  .composicion-widget-vacio {
    display: grid;
    place-items: center;
    height: 100%;
    color: var(--muted-color);
    font-size: 12px;
  }

  /* Donut Chart Widget */
  .analytics-tabs {
    display: flex;
    gap: 12px;
    margin-bottom: 14px;
    border-bottom: 1px solid var(--border-color);
    padding-bottom: 8px;
  }
  .analytics-tab {
    background: transparent;
    border: none;
    color: var(--muted-color);
    font-size: 11px;
    font-weight: 600;
    text-transform: uppercase;
    cursor: pointer;
    padding-bottom: 4px;
    position: relative;
  }
  .analytics-tab:hover {
    color: var(--text-color);
  }
  .analytics-tab.active {
    color: var(--text-color);
  }
  .analytics-tab.active::after {
    content: '';
    position: absolute;
    bottom: -9px;
    left: 0;
    width: 100%;
    height: 2px;
    background-color: var(--accent-blue);
  }
  .donut-chart-container {
    display: flex;
    align-items: center;
    justify-content: center;
    gap: clamp(14px, 1.2cqw, 28px);
  }
  /* Escalado con la pantalla, como `.line-chart-container`: el mínimo protege
     el portátil y el máximo evita que en un monitor grande el anillo se coma
     la tarjeta. El SVG es `viewBox`, así que sigue al contenedor solo.

     El tope era 168 px, y en un monitor normal el anillo estaba SIEMPRE ahí:
     `cqw` se mide contra el área de contenido entera (~2.200 px), así que el
     9,5% daba 216 y la cifra que mandaba era el máximo. Subirlo es lo que hace
     el anillo más grande; el sitio sale de la leyenda, que antes se estiraba
     hasta el borde de la tarjeta dejando 280 px de hueco muerto.

     Puede encoger (`flex-shrink: 1`) hasta el mínimo, que es el tamaño de
     antes: en una ventana estrecha vuelve a lo que había en vez de desbordar. */
  .donut-svg-wrapper {
    position: relative;
    flex: 0 1 auto;
    width: clamp(120px, 13cqw, 250px);
    min-width: 110px;
    /* Cuadrado sin repetir la medida: al encoger, el alto sigue al ancho. */
    aspect-ratio: 1;
    height: auto;
    /* Para que la cifra del centro se mida contra el ANILLO y no contra el área
       de contenido: si no, el anillo crece y el texto del hueco se queda igual
       de pequeño. */
    container-type: inline-size;
  }
  .donut-center-text {
    position: absolute;
    top: 50%;
    left: 50%;
    transform: translate(-50%, -50%);
    text-align: center;
    /* En proporción al anillo, no en píxeles. El hueco mide el 68% del ancho
       (radio 34 de 100 en el `viewBox`), así que con 62% el texto entra con
       aire; con los 122 px fijos de antes se salía del hueco. */
    width: 62%;
  }
  /* `cqw` aquí es porcentaje del ANILLO, por el `container-type` de arriba. */
  .donut-center-text .d-label {
    font-size: clamp(7px, 3.8cqw, 11px);
    text-transform: uppercase;
    color: var(--muted-color);
    letter-spacing: 0.05em;
  }
  .donut-center-text .d-val {
    font-size: clamp(11px, 8cqw, 22px);
    font-weight: 700;
    margin-top: 2px;
  }
  /* Se ajusta a su contenido en vez de estirarse hasta el borde.
   *
   * Antes ocupaba todo el ancho sobrante y el `space-between` de cada fila
   * mandaba el porcentaje al extremo: con los nombres cortos quedaban 280 px de
   * blanco entre «ISHARES MSCI ACWI» y su «50.3%», y había que cruzar la
   * tarjeta con la vista para emparejarlos.
   *
   * Con `fit-content` la caja mide lo que el nombre más largo, y como las filas
   * se estiran a la caja (es una columna flex), los porcentajes SIGUEN
   * alineados en columna. Se acercan sin perder la rejilla, y un nombre más
   * largo ensancha la leyenda sola: no hay ninguna medida fija que ajustar.
   *
   * El tope del 58% y el recorte con puntos suspensivos son el seguro para un
   * nombre desmedido: se corta, no se come el anillo. El completo sigue en el
   * `title` y en la pantalla de Composición. */
  .donut-legend {
    display: flex;
    flex-direction: column;
    justify-content: center;
    gap: clamp(6px, 0.5vh, 11px);
    flex: 0 1 auto;
    width: fit-content;
    max-width: 58%;
    min-width: 0;
  }
  .legend-item {
    display: flex;
    justify-content: space-between;
    align-items: center;
    /* Separación mínima entre el nombre y su porcentaje, que ahora es la real
       en la fila más ancha. */
    gap: 14px;
    font-size: clamp(11px, 0.74cqw, 13.5px);
  }
  /* Solo la leyenda enlazada con el anillo responde al ratón. El relleno va con
     un margen negativo que lo compensa: así el resaltado tiene aire alrededor
     sin mover ni un píxel la posición de las filas. */
  .legend-item[data-serie] {
    cursor: pointer;
    padding: 3px 6px;
    margin: -3px -6px;
    border-radius: 6px;
    transition: background-color 0.18s ease, opacity 0.18s ease;
  }
  .legend-item.activo {
    background: color-mix(in srgb, var(--color-serie) 16%, transparent);
  }
  .legend-item[data-serie]:focus-visible {
    outline: 2px solid var(--color-serie);
    outline-offset: 1px;
  }
  /* Se queda con el ancho que sobre en la tarjeta. Antes tenía un tope fijo de
     110 px, que cortaba los nombres aunque hubiera sitio de sobra. El
     `min-width: 0` es lo que hace que al estrecharse recorte el texto en vez
     de ensanchar la caja. */
  .legend-label-group {
    display: flex;
    align-items: center;
    gap: 6px;
    flex: 1 1 auto;
    min-width: 0;
  }
  .legend-label-group span {
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
  }
  .legend-dot {
    width: 6px;
    height: 6px;
    border-radius: 50%;
    flex-shrink: 0;
  }
  .legend-val {
    font-family: var(--mono-font);
    color: var(--muted-color);
    flex-shrink: 0;
  }

  /* Performance Bars Widget */
  .performance-chart-container {
    /* Sin alto fijo: lo pone el `flex` de arriba, que es lo que hace que las
       barras crezcan con la tarjeta en vez de dejar el hueco encima. */
    min-height: 110px;
    width: 100%;
    display: flex;
    align-items: flex-end;
    justify-content: space-between;
    padding-top: 10px;
  }
  .perf-bar-group {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 8px;
    flex-grow: 1;
    position: relative;
  }
  .perf-bar-wrapper {
    height: 70px;
    width: 14px;
    background-color: var(--panel2-bg);
    border-radius: 3px;
    position: relative;
    overflow: hidden;
    cursor: pointer;
    transition: transform 0.15s ease;
  }
  /* Solo en el widget del dashboard: ahí el carril se estira con la tarjeta.
     La pantalla de Rendimiento completa fija `height` en línea y calcula la
     barra en píxeles contra ese alto, así que estirarla la descuadraría. */
  .performance-chart-container .perf-bar-group {
    height: 100%;
    justify-content: flex-end;
  }
  .performance-chart-container .perf-bar-wrapper {
    flex: 1 1 auto;
    height: auto;
    min-height: 70px;
    width: clamp(14px, 1.3cqw, 24px);
  }
  .perf-bar-wrapper:hover {
    transform: scaleY(1.08);
  }
  .perf-bar {
    width: 100%;
    border-radius: 3px;
    position: absolute;
    bottom: 0;
    transition: height 0.3s ease;
  }
  .perf-bar.pos { background-color: var(--pos-color); }
  .perf-bar.neg { background-color: var(--neg-color); }
  .perf-label {
    font-family: var(--mono-font);
    font-size: clamp(9px, 0.6cqw, 11.5px);
    color: var(--muted-color);
  }
  .perf-tooltip {
    position: absolute;
    bottom: calc(100% + 8px);
    left: 50%;
    transform: translateX(-50%) translateY(4px);
    background: var(--panel2-bg);
    border: 1px solid var(--border-color);
    border-radius: 8px;
    padding: 6px 10px;
    font-family: var(--mono-font);
    font-size: 11px;
    font-weight: 600;
    white-space: nowrap;
    pointer-events: none;
    opacity: 0;
    transition: opacity 0.2s ease, transform 0.2s ease;
    z-index: 10;
    box-shadow: 0 4px 12px rgba(0,0,0,0.4);
  }
  .perf-bar-group:hover .perf-tooltip,
  .perf-col:hover .perf-tooltip,
  .perf-col:focus-visible .perf-tooltip {
    opacity: 1;
    transform: translateX(-50%) translateY(0);
  }
  /* En la pantalla grande el tooltip lleva varias líneas —el periodo con su año,
     la cartera y cada índice—, así que ahí deja de ser una sola cifra. El
     `bottom` va al 100% de la columna, que ahora ocupa todo el carril: pegado
     arriba del todo se salía de la tarjeta. */
  .perf-col .perf-tooltip {
    bottom: auto;
    top: 4px;
    display: flex;
    flex-direction: column;
    gap: 2px;
    align-items: flex-start;
    text-align: left;
  }
  .perf-col .perf-tooltip strong {
    font-family: var(--sans-font);
    font-size: 11px;
    font-weight: 600;
    color: var(--text-color);
  }
  .perf-tooltip-valor.pos { color: var(--pos-color); }
  .perf-tooltip-valor.neg { color: var(--neg-color); }
  .perf-tooltip-ref {
    font-weight: 500;
    color: var(--muted-color);
  }
  .perf-time-filters {
    display: flex;
    gap: 4px;
  }
  /* Los filtros a un lado y la comparación al otro: son dos cosas distintas
     —qué tramo se mira y contra qué se mide— y juntas se leían como un grupo. */
  .perf-toolbar {
    display: flex;
    align-items: center;
    gap: 12px;
    flex-wrap: wrap;
    margin-bottom: 16px;
  }
  .perf-toolbar .btn-columnas { margin-left: auto; }

  /* --- PANTALLA DE RENDIMIENTO: MÉTRICAS --- */
  .perf-metricas {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(150px, 1fr));
    gap: 12px;
    margin-bottom: 20px;
  }
  .perf-metricas:empty { display: none; }
  .perf-metrica {
    display: flex;
    flex-direction: column;
    gap: 2px;
    padding: 12px 14px;
    background: var(--panel2-bg);
    border: 1px solid var(--border-color);
    border-radius: 10px;
  }
  .perf-metrica-titulo {
    font-size: 10px;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: 0.07em;
    color: var(--muted-color);
  }
  .perf-metrica-valor {
    font-family: var(--mono-font);
    font-size: 19px;
    font-weight: 700;
    color: var(--text-color);
  }
  .perf-metrica-valor.pos { color: var(--pos-color); }
  .perf-metrica-valor.neg { color: var(--neg-color); }
  .perf-metrica-detalle { font-size: 11px; color: var(--muted-color); }

  /* --- PANTALLA DE RENDIMIENTO: BARRAS CON CERO --- */
  .perf-vista {
    background-color: var(--panel2-bg);
    border-radius: 12px;
    border: 1px solid var(--border-color);
    padding: 20px 24px;
    margin-bottom: 12px;
  }
  .perf-grafico {
    display: flex;
    gap: 12px;
    height: 300px;
  }
  /* Las tres referencias del eje: el techo, el cero y el suelo. Sin ellas la
     escala real no se puede leer, solo comparar barras entre sí.
     Cada una se posiciona a su altura desde JS —no repartidas a partes iguales—
     porque el cero casi nunca está en el medio. */
  .perf-eje {
    position: relative;
    font-family: var(--mono-font);
    font-size: 10px;
    color: var(--muted-color);
    min-width: 52px;
  }
  .perf-eje-marca {
    position: absolute;
    right: 0;
    /* Centrada en su línea: el rótulo del techo y el del suelo sobresalen media
       línea del carril, que es lo que absorbe el relleno de la tarjeta. */
    transform: translateY(-50%);
    white-space: nowrap;
  }
  .perf-eje-cero { color: var(--text-color); opacity: 0.75; }
  .perf-carril {
    position: relative;
    flex: 1 1 auto;
    min-width: 0;
  }
  /* El cero cae donde le toca según cuánto se pierde y cuánto se gana, no
     siempre en el medio ni siempre abajo. Continua y no discontinua: a 1 px y en
     el color del borde no se veía, y es la referencia de la que cuelga la
     lectura entera del gráfico. */
  .perf-cero {
    position: absolute;
    left: 0;
    right: 0;
    border-top: 1px solid var(--muted-color);
    opacity: 0.32;
    pointer-events: none;
  }
  .perf-columnas {
    display: flex;
    align-items: stretch;
    gap: 6px;
    height: 100%;
  }
  .perf-col {
    position: relative;
    display: flex;
    flex-direction: column;
    flex: 1 1 0;
    min-width: 0;
    cursor: default;
  }
  .perf-col:focus-visible {
    outline: 2px solid var(--accent-blue);
    outline-offset: 2px;
    border-radius: 4px;
  }
  .perf-mitad { position: relative; display: flex; }
  .perf-mitad-alta { align-items: flex-end; }
  .perf-mitad-baja { align-items: flex-start; }
  .perf-barra {
    width: 100%;
    max-width: 34px;
    margin: 0 auto;
    /* Un mes de +0,1% seguiría siendo una barra invisible con la escala real:
       este mínimo lo deja verse sin falsear la comparación. */
    min-height: 3px;
  }
  .perf-mitad-alta .perf-barra {
    border-radius: 4px 4px 0 0;
    background: var(--pos-color);
  }
  .perf-mitad-baja .perf-barra {
    border-radius: 0 0 4px 4px;
    background: var(--neg-color);
  }
  .perf-col:hover .perf-barra { filter: brightness(1.15); }
  /* La marca de un índice: una línea a la altura de SU rentabilidad, para poder
     ver de un vistazo si la barra llega o no llega. */
  .perf-marca {
    position: absolute;
    left: 12%;
    right: 12%;
    height: 2px;
    border-radius: 1px;
  }
  .perf-etiquetas {
    display: flex;
    gap: 6px;
    /* El ancho del eje más su hueco, para que cada etiqueta caiga bajo su
       columna. Si cambia `min-width` en `.perf-eje`, cambia aquí. */
    margin-left: 64px;
    margin-top: 8px;
  }
  .perf-etiqueta {
    flex: 1 1 0;
    min-width: 0;
    display: flex;
    flex-direction: column;
    align-items: center;
    font-family: var(--mono-font);
    font-size: 11px;
    color: var(--muted-color);
  }
  .perf-etiqueta-nombre { font-weight: 600; }
  .perf-etiqueta-anyo { font-size: 9.5px; opacity: 0.7; }

  /* --- PANTALLA DE RENDIMIENTO: MAPA MENSUAL --- */
  .mapa-mensual-caja { width: 100%; overflow-x: auto; }
  .mapa-mensual {
    width: 100%;
    border-collapse: separate;
    border-spacing: 3px;
    font-family: var(--mono-font);
    font-size: 11px;
  }
  .mapa-mensual thead th {
    font-size: 10px;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: 0.06em;
    color: var(--muted-color);
    padding-bottom: 4px;
  }
  .mapa-anyo {
    text-align: right;
    padding-right: 8px;
    font-weight: 700;
    color: var(--text-color);
    white-space: nowrap;
  }
  .mapa-celda {
    text-align: center;
    padding: 9px 4px;
    border-radius: 5px;
    /* Blanco fijo sobre relleno saturado, igual que en el mapa de rentabilidad:
       el color de la celda no cambia con el tema, así que el texto tampoco. */
    color: #fff;
    text-shadow: 0 1px 2px rgba(0, 0, 0, 0.45);
    font-variant-numeric: tabular-nums;
    cursor: default;
  }
  .mapa-celda:hover { filter: brightness(1.18); }
  .mapa-celda-vacia {
    background: transparent;
    color: var(--border-color);
    text-shadow: none;
  }
  .mapa-total-cab { text-align: right; }
  .mapa-total {
    text-align: right;
    padding: 9px 6px 9px 12px;
    font-weight: 700;
    font-variant-numeric: tabular-nums;
    white-space: nowrap;
    border-left: 1px solid var(--border-color);
  }
  .mapa-total.pos { color: var(--pos-color); }
  .mapa-total.neg { color: var(--neg-color); }

  /* --- PANTALLA DE RENDIMIENTO: COMPARACIÓN --- */
  .perf-comparacion {
    display: flex;
    align-items: center;
    flex-wrap: wrap;
    gap: 8px;
    margin-bottom: 24px;
    min-height: 24px;
  }
  .perf-comparacion-vacio {
    font-size: 11.5px;
    color: var(--muted-color);
  }
  .btn-perf-filter {
    background: transparent;
    border: 1px solid var(--border-color);
    color: var(--muted-color);
    padding: 6px 14px;
    border-radius: 8px;
    font-size: 12px;
    font-weight: 600;
    cursor: pointer;
    transition: all 0.2s;
  }
  .btn-perf-filter:hover {
    color: var(--text-color);
    border-color: var(--muted-color);
  }
  .btn-perf-filter.active {
    background-color: var(--accent-blue);
    border-color: var(--accent-blue);
    color: var(--accent-contrast);
  }

  /* --- POSITIONS TABLE CARD --- */
  .positions-card {
    background-color: var(--panel-bg);
    border: 1px solid var(--border-color);
    border-radius: 16px;
    padding: 24px;
  }

  /* --- Activos con precio manual --- */
  .form-hint {
    font-size: 11.5px;
    color: var(--muted-color);
    margin: 6px 0 0;
    line-height: 1.45;
    font-weight: 400;
  }
  /* Mayúsculas monoespaciadas funciona en un rótulo corto, no en una frase. */
  /* `.form-group label` es más específico que una clase suelta, así que hay que
     igualarlo para poder ganarle; si no, la frase sale en mayúsculas igual. */
  .form-group label.check-inline {
    display: flex;
    align-items: flex-start;
    gap: 9px;
    cursor: pointer;
    text-transform: none;
    font-family: var(--sans-font);
    font-size: 13px;
    letter-spacing: normal;
    line-height: 1.45;
    color: var(--text-color);
    margin-bottom: 0;
  }
  .form-group label.check-inline input[type="checkbox"] {
    margin: 2px 0 0;
    width: auto;
    flex-shrink: 0;
    accent-color: var(--pos-color);
  }

  /* --- EL PRECIO QUE LLEVA EL USUARIO, EN SU FILA ---
     Aquí vivían los estilos de «Activos con precio manual», un panel que
     repetía encima de la tabla las mismas posiciones que había debajo. Ahora el
     precio se edita en la celda donde se lee. */

  /* En modo lectura ocupa lo mismo que un precio normal —es la misma línea de
     la celda— pero se distingue: pinchable, y con la marca y la fecha que dicen
     que el número lo puso una persona y cuándo. Sin eso, un precio tecleado se
     lee como una cotización y la cartera parece inventárselos. */
  .precio-manual {
    display: inline-flex;
    align-items: baseline;
    gap: 5px;
    margin-top: 2px;
    padding: 1px 5px;
    margin-right: -5px;
    background: none;
    border: 1px solid transparent;
    border-radius: 6px;
    font-family: var(--mono-font);
    font-variant-numeric: tabular-nums;
    font-size: 11px;
    color: var(--muted-color);
    cursor: pointer;
  }
  .precio-manual:hover,
  .precio-manual:focus-visible {
    border-color: var(--border-color);
    color: var(--text-color);
  }
  .precio-manual-marca { font-size: 10px; opacity: 0.75; }
  .precio-manual-cuando { font-size: 10px; opacity: 0.8; }
  /* En ámbar y no en rojo: no es un error, es algo que falta por hacer. */
  .precio-manual-vacio { color: #f0b90b; font-family: inherit; }

  /* El editor. Alineado a la derecha como el resto de la columna, y con el
     ancho suelto para que quepan el campo, la unidad y los dos botones sin que
     la tabla se descuadre. */
  .precio-editor {
    display: inline-flex;
    flex-direction: column;
    align-items: flex-end;
    gap: 4px;
    margin-top: 4px;
    text-align: right;
  }
  .precio-editor-fila { display: flex; gap: 4px; align-items: stretch; }
  .precio-editor-campo {
    width: 96px;
    padding: 4px 7px;
    background: var(--panel2-bg);
    border: 1px solid var(--accent-blue);
    border-radius: 6px;
    color: var(--text-color);
    font-family: var(--mono-font);
    font-variant-numeric: tabular-nums;
    font-size: 12px;
    text-align: right;
  }
  .precio-editor-modo,
  .precio-editor-ok,
  .precio-editor-no {
    padding: 0 7px;
    background: var(--panel2-bg);
    border: 1px solid var(--border-color);
    border-radius: 6px;
    color: var(--text-color);
    font-size: 11px;
    font-weight: 600;
    cursor: pointer;
    white-space: nowrap;
  }
  .precio-editor-modo:hover,
  .precio-editor-ok:hover { border-color: var(--pos-color); color: var(--pos-color); }
  .precio-editor-no:hover { border-color: var(--neg-color); color: var(--neg-color); }
  .precio-editor-pie {
    display: flex;
    align-items: center;
    justify-content: flex-end;
    gap: 8px;
    font-size: 10.5px;
    color: var(--muted-color);
  }
  /* La cuenta que se está haciendo: es lo que hace comprobable el conmutador
     entre «€/ud» y «€ total» sin tener que fiarse. */
  .precio-editor-eq {
    font-family: var(--mono-font);
    font-variant-numeric: tabular-nums;
  }
  /* Los enlaces del editor: «otra fecha» y «que lo busque el proveedor». Se
     leen como texto y no como botones a propósito —son salidas de uso raro— y
     no ocupan sitio en la fila mientras no se está editando. */
  .precio-editor-enlace {
    padding: 0;
    background: none;
    border: none;
    border-bottom: 1px dotted var(--border-color);
    color: var(--muted-color);
    font-size: 10.5px;
    cursor: pointer;
  }
  .precio-editor-enlace:hover { color: var(--text-color); }
  .precio-editor-fecha {
    padding: 2px 5px;
    background: var(--panel2-bg);
    border: 1px solid var(--border-color);
    border-radius: 6px;
    color: var(--text-color);
    font-size: 10.5px;
  }
  .precio-editor-error {
    margin: 0;
    font-size: 10.5px;
    color: var(--neg-color);
  }

  /* La salida de una posición que el proveedor no reconoce. En ámbar, como el
     resto de lo que falta por hacer, y con aspecto de botón porque es la única
     acción de la fila que resuelve el problema en vez de describirlo. */
  .btn-llevar-precio {
    margin-top: 4px;
    padding: 2px 8px;
    background: none;
    border: 1px solid #f0b90b;
    border-radius: 6px;
    color: #f0b90b;
    font-size: 10.5px;
    font-weight: 600;
    white-space: nowrap;
    cursor: pointer;
  }
  .btn-llevar-precio:hover { background: #f0b90b; color: var(--bg); }

  .sell-asset-head .sell-asset-isin {
    font-family: var(--mono-font);
    font-size: 11px;
    color: var(--muted-color);
  }
  .positions-header {
    display: flex;
    justify-content: space-between;
    align-items: center;
    margin-bottom: 20px;
  }
  /* Barra de ordenación: los botones reutilizan `.btn-time-filter`. */
  .positions-toolbar {
    display: flex;
    align-items: center;
    gap: 10px;
    flex-wrap: wrap;
    margin-bottom: 14px;
  }
  /* El plegable del desglose anual. Va al final de la barra y con `margin-left:
     auto` para que se lea como lo que es: no un criterio de ordenación más, sino
     un interruptor de lo que la tabla ENSEÑA. */
  .btn-columnas {
    margin-left: auto;
    display: inline-flex;
    align-items: center;
    gap: 7px;
    padding: 5px 12px;
    background: transparent;
    border: 1px solid var(--border-color);
    border-radius: 6px;
    color: var(--muted-color);
    font-family: var(--mono-font);
    font-size: 11px;
    font-weight: 600;
    cursor: pointer;
    transition: color 0.2s, border-color 0.2s, background-color 0.2s;
  }
  .btn-columnas:hover {
    color: var(--text-color);
    border-color: var(--muted-color);
  }
  .btn-columnas.active {
    background-color: var(--accent-soft);
    border-color: transparent;
    color: var(--accent);
  }
  .btn-columnas-flecha {
    display: inline-block;
    transition: transform 0.2s ease;
  }
  .btn-columnas.active .btn-columnas-flecha {
    transform: rotate(90deg);
  }
  @media (prefers-reduced-motion: reduce) {
    .btn-columnas-flecha { transition: none; }
  }
  /* Cabecera de subgrupo al ordenar por clase de activo.
   *
   * Era un rótulo suelto con una línea debajo, igual que la línea que separa dos
   * filas cualesquiera: no marcaba dónde empieza un grupo, solo dónde acaba una
   * fila. Ahora es una BANDA, con aire por encima que la despega del grupo
   * anterior y un filo de acento a la izquierda; los grupos se cuentan de un
   * vistazo sin tener que leer. El hueco va en el `td` y la banda en el `div`,
   * porque un `border-radius` sobre un `td` de tabla no se aplica.
   *
   * Con `.positions-table tr` delante y no `.positions-grupo td` a secas: esa
   * forma empata en especificidad con `.positions-table td`, que está MÁS ABAJO
   * en esta hoja y por tanto ganaba. La cabecera venía cogiendo el relleno y la
   * línea de una fila cualquiera, que es justo de lo que se la quiere separar. */
  .positions-table tr.positions-grupo td {
    padding: 26px 0 8px;
    border-bottom: none;
  }
  /* El primero no separa de nada: ese hueco sería un agujero bajo la cabecera. */
  .positions-table tbody tr.positions-grupo:first-child td {
    padding-top: 6px;
  }
  .positions-grupo-fila {
    display: flex;
    justify-content: space-between;
    align-items: center;
    gap: 12px;
    padding: 9px 16px;
    background: var(--panel2-bg);
    border: 1px solid var(--border-color);
    border-left: 3px solid var(--accent-blue);
    border-radius: 8px;
  }
  /* La banda no es una fila de datos: al pasar por encima no se resalta. */
  .positions-table tr.positions-grupo:hover td {
    background-color: transparent;
  }
  .positions-grupo-titulo {
    display: flex;
    align-items: baseline;
    gap: 10px;
    min-width: 0;
  }
  .positions-grupo-nombre {
    font-size: 12px;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: 0.08em;
    color: var(--text-color);
  }
  .positions-grupo-cuenta {
    font-size: 11px;
    color: var(--muted-color);
    white-space: nowrap;
  }
  .positions-grupo-cifras {
    font-family: var(--mono-font);
    font-size: 12px;
    color: var(--muted-color);
    white-space: nowrap;
  }

  /* La cola de la cartera: una fila que se abre. Se distingue de una posición
     normal por el cursor y la flecha, no por el color: sigue siendo dinero de
     verdad y sus cifras cuentan igual que las de arriba. */
  .positions-otras {
    cursor: pointer;
  }
  .positions-otras:hover,
  .positions-otras:focus-visible {
    background-color: var(--panel2-bg);
  }
  .positions-otras h4 {
    display: flex;
    align-items: center;
    gap: 8px;
  }
  .positions-otras-flecha {
    display: inline-block;
    color: var(--muted-color);
    font-size: 11px;
    transition: transform 0.15s ease;
  }
  .positions-otras.abierta .positions-otras-flecha {
    transform: rotate(90deg);
  }
  /* Las de dentro, sangradas: se ve de un vistazo dónde empieza y acaba la
     cola sin necesidad de otra cabecera. */
  .positions-otras-hija > td:first-child {
    padding-left: 26px;
  }
  .positions-otras-hija > td {
    background-color: color-mix(in srgb, var(--panel2-bg) 45%, transparent);
  }

  /* Pie que explica por qué las filas no suman el total de la cabecera. */
  .positions-nota-ocultas td {
    padding: 12px 10px;
    font-size: 12px;
    color: var(--muted-color);
    border-top: 1px dashed var(--border-color);
  }
  .positions-nota-ocultas button {
    background: transparent;
    border: 0;
    padding: 0 0 0 6px;
    color: var(--accent-blue, #3b82f6);
    font-size: 12px;
    font-weight: 600;
    cursor: pointer;
    text-decoration: underline;
  }
  .positions-toolbar-label {
    font-size: 11px;
    font-weight: 600;
    color: var(--muted-color);
    text-transform: uppercase;
    letter-spacing: 0.04em;
  }
  .positions-title-group h2 {
    font-size: 18px;
    font-weight: 600;
  }
  .positions-title-group p {
    font-size: 12px;
    color: var(--muted-color);
    margin-top: 2px;
  }
  .btn-add-transaction {
    background-color: var(--accent-green);
    color: var(--accent-contrast);
    border: none;
    border-radius: 8px;
    padding: 10px 18px;
    font-size: 13px;
    font-weight: 600;
    cursor: pointer;
    display: flex;
    align-items: center;
    gap: 8px;
    transition: background-color 0.2s;
  }
  .btn-add-transaction:hover {
    background-color: var(--accent-green-hover);
  }
  .btn-add-transaction svg {
    fill: var(--accent-contrast);
    width: 12px;
    height: 12px;
  }

  /* Positions Table */
  .positions-table-container {
    width: 100%;
    overflow-x: auto;
  }
  .positions-table {
    width: 100%;
    border-collapse: collapse;
    font-size: 13px;
  }
  /* Los títulos de columna eran del mismo gris apagado que un dato secundario y
     a 10 px: se leían como un pie de página, no como la cabecera que dice qué
     hay debajo. Ahora van a plena luz sobre una banda propia y con un filo
     grueso abajo, para que la tabla tenga un techo claro. */
  .positions-table th {
    font-family: var(--mono-font);
    font-size: 10.5px;
    font-weight: 700;
    color: var(--text-color);
    text-transform: uppercase;
    letter-spacing: 0.09em;
    padding: 13px 16px;
    background: var(--panel2-bg);
    border-bottom: 2px solid var(--border-color);
    text-align: left;
    white-space: nowrap;
  }
  /* LA CABECERA ORDENA.
     El botón hereda entera la tipografía del `th` para que la tabla no cambie
     de aspecto por haberse vuelto pulsable: lo único que se añade es el cursor,
     la flecha y el realce de la columna que manda. */
  .positions-table th .th-orden {
    font: inherit;
    letter-spacing: inherit;
    text-transform: inherit;
    color: inherit;
    background: none;
    border: 0;
    padding: 0;
    cursor: pointer;
    display: inline-flex;
    align-items: center;
    gap: 6px;
    white-space: nowrap;
    transition: color 0.15s ease;
  }
  .positions-table th .th-orden:hover { color: var(--accent); }
  /* `:focus-visible` y no `:focus`: el anillo aparece al llegar con el
     tabulador, no al hacer clic, donde el orden que cambia ya es la respuesta. */
  .positions-table th .th-orden:focus-visible {
    outline: 2px solid var(--accent);
    outline-offset: 3px;
    border-radius: 3px;
  }
  .positions-table th .th-orden.is-active { color: var(--accent); }
  /* La flecha se enseña en la columna que manda, y asoma a media luz al pasar
     por encima de las demás. Con seis flechas fijas, la cabecera pasaba a ser
     una fila de símbolos y ninguno decía nada. */
  .th-flecha {
    font-size: 8px;
    line-height: 1;
  }
  .positions-table th .th-flecha {
    opacity: 0;
    transition: opacity 0.15s ease;
  }
  .positions-table th .th-orden:hover .th-flecha { opacity: 0.5; }
  .positions-table th .th-orden.is-active .th-flecha { opacity: 1; }
  /* Sin transiciones para quien las haya desactivado en su sistema. */
  @media (prefers-reduced-motion: reduce) {
    .positions-table th .th-orden,
    .positions-table th .th-flecha { transition: none; }
  }
  .positions-table thead tr th:first-child { border-top-left-radius: 8px; }
  .positions-table thead tr th:last-child { border-top-right-radius: 8px; }
  /* Los años son cabecera de segundo orden: dicen de qué tramo habla la columna,
     no qué cifra hay en ella. Apagados para que no compitan con las de arriba. */
  .positions-table th.th-anyo {
    font-weight: 600;
    color: var(--muted-color);
    letter-spacing: 0.04em;
  }
  .positions-table td {
    padding: 16px;
    border-bottom: 1px solid var(--border-color);
    vertical-align: middle;
  }
  .positions-table tr:hover td {
    background-color: rgba(255, 255, 255, 0.01);
  }
  .asset-cell {
    display: flex;
    align-items: center;
    gap: 12px;
  }
  .asset-icon-circle {
    width: 32px;
    height: 32px;
    border-radius: 8px;
    display: flex;
    align-items: center;
    justify-content: center;
    font-weight: 700;
    font-size: 13px;
    color: #fff;
  }
  .asset-details h4 {
    font-size: 13px;
    font-weight: 600;
  }
  .asset-details p {
    font-size: 11px;
    color: var(--muted-color);
    margin-top: 1px;
  }
  /* El nombre del producto es el texto PRINCIPAL de la fila —lo que se busca al
     recorrer la tabla—, así que va a plena luz. Iba en el color de acento, y con
     el acento azul sobre el fondo oscuro eso son 2,6:1 de contraste, por debajo
     del mínimo legible: el dato más importante de la tabla era el que peor se
     veía. Encima subrayado en las veinte filas a la vez, que es ruido y no
     información, porque cuando todo está marcado no destaca nada.
     El acento y el subrayado salen al apuntarlo, que es cuando dicen algo. */
  .asset-nombre {
    display: inline-block;
    max-width: 100%;
    color: var(--text-color);
    cursor: pointer;
    text-decoration: underline;
    text-decoration-color: transparent;
    text-decoration-thickness: 1.5px;
    text-underline-offset: 3px;
    transition: text-decoration-color 0.15s ease;
  }
  /* Solo el subrayado toma el color de acento: el texto se queda a plena luz
     para que el resaltado nunca lo haga menos legible de lo que ya era. */
  .asset-nombre:hover,
  .asset-nombre:focus-visible {
    text-decoration-color: var(--accent-blue);
  }
  .asset-nombre:focus-visible {
    outline: 2px solid var(--accent-blue);
    outline-offset: 3px;
    border-radius: 3px;
  }
  /* El ISIN, debajo: identifica el producto sin competir con su nombre. Sin el
     `opacity: 0.7` que llevaba encima del color apagado, que lo dejaba en un
     gris casi ilegible. */
  /* Con `.asset-details` delante porque `.asset-details p` ya fija color y
     tamaño con la misma especificidad: sin esto, el aviso se pintaría gris. */
  .asset-details .asset-isin {
    font-family: var(--mono-font);
    font-size: 11px;
    color: var(--muted-color);
    letter-spacing: 0.03em;
  }
  .asset-details .asset-aviso {
    font-size: 11px;
    color: var(--neg-color);
  }
  .positions-table .right-col {
    text-align: right;
  }
  /* La clase de activo: etiqueta, no cifra. Va a la izquierda y sin crecer, para
     que el nombre del producto siga llevándose el ancho de la fila. */
  .positions-table .col-tipo {
    text-align: left;
    width: 1%;
    white-space: nowrap;
  }
  .tipo-chip {
    display: inline-block;
    padding: 3px 9px;
    border-radius: 999px;
    background: var(--panel2-bg);
    border: 1px solid var(--border-color);
    font-size: 10.5px;
    font-weight: 600;
    letter-spacing: 0.03em;
    color: var(--muted-color);
    white-space: nowrap;
  }
  /* La cola de la cartera mezcla clases: se dice, en vez de elegir una. */
  .tipo-chip-varios {
    border-style: dashed;
    font-style: italic;
  }
  .td-bold-mono {
    font-family: var(--mono-font);
    font-variant-numeric: tabular-nums;
    font-weight: 600;
  }

  /* Cuántas participaciones se tienen, en el detalle del producto. La tabla las
     enseña recortadas para que la columna se lea de un vistazo; el número
     COMPLETO vive aquí, que es donde se viene a mirar el producto de verdad. */
  .detalle-posicion {
    display: inline-flex;
    align-items: baseline;
    gap: 10px;
    margin-bottom: 20px;
    padding: 9px 14px;
    background: var(--panel2-bg);
    border: 1px solid var(--border-color);
    border-radius: 8px;
  }
  .detalle-posicion-etiqueta {
    font-size: 10px;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: 0.08em;
    color: var(--muted-color);
  }
  .detalle-posicion-uds {
    font-family: var(--mono-font);
    font-size: 16px;
    font-weight: 700;
    color: var(--text-color);
  }
  .detalle-posicion-sufijo {
    font-size: 12px;
    color: var(--muted-color);
  }
  .td-sub-mono {
    font-family: var(--mono-font);
    font-variant-numeric: tabular-nums;
    font-size: 11px;
    color: var(--muted-color);
    margin-top: 2px;
  }
  .wl-val {
    font-weight: 600;
  }
  .wl-val.pos { color: var(--pos-color); }
  .wl-val.neg { color: var(--neg-color); }
  /* «sin registrar»: un dato que falta, no una cifra. */
  .wl-val.muted { color: var(--muted-color); font-weight: 400; }
  .btn-table-action {
    background: transparent;
    border: none;
    cursor: pointer;
    padding: 4px 8px;
    color: var(--muted-color);
  }
  .btn-table-action:hover {
    color: var(--neg-color);
  }
  .position-row-actions {
    display: flex;
    gap: 2px;
    justify-content: center;
  }
  .position-row-actions .btn-table-action:hover {
    color: var(--accent-blue);
  }

  /* --- VENTA Y EDICIÓN DE OPERACIONES --- */
  /* --- ALTA DE TRANSACCIÓN: DISPOSICIÓN ---
   *
   * Los campos cortos van en parejas. En una sola columna eran diez filas: el
   * formulario no cabía de una vez y, al desplegarse la lista de sugerencias,
   * tapaba media docena de campos. En parejas cabe entero y la lista solo se
   * superpone a la fila que tiene justo debajo. */
  #transaction-modal .transaction-box { max-width: 520px; }
  .form-fila {
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: 14px;
    margin-bottom: 20px;
  }
  /* El margen lo lleva la fila: sumado al de cada campo, separaba el doble. */
  .form-fila .form-group { margin-bottom: 0; }
  @media (max-width: 520px) {
    .form-fila { grid-template-columns: 1fr; gap: 0; }
    .form-fila .form-group { margin-bottom: 20px; }
  }
  /* Una frase que comenta la fila entera, no uno de sus dos campos. */
  .form-hint-fila { margin: -12px 0 20px; }

  /* --- CAMPO NUMÉRICO CON PASOS ---
   *
   * Las flechas del navegador son diminutas, cambian de forma en cada uno y solo
   * aparecen al pasar por encima. Estos botones ocupan lo que hay que pulsar y se
   * ven siempre. `tabindex="-1"` en el marcado: quien va con el teclado escribe
   * la cifra, y dos paradas más por campo solo estorban. */
  input[type="number"]::-webkit-outer-spin-button,
  input[type="number"]::-webkit-inner-spin-button {
    -webkit-appearance: none;
    margin: 0;
  }
  input[type="number"] { -moz-appearance: textfield; appearance: textfield; }

  .input-numero { display: flex; align-items: stretch; }
  .form-group .input-numero input {
    flex: 1 1 auto;
    min-width: 0;
    width: auto;
    text-align: center;
    border-radius: 0;
    border-left: none;
    border-right: none;
  }
  .btn-paso {
    flex: 0 0 42px;
    background: var(--panel2-bg);
    border: 1px solid var(--border-color);
    color: var(--muted-color);
    font-size: 17px;
    line-height: 1;
    cursor: pointer;
    transition: color 0.15s, border-color 0.15s, background-color 0.15s;
  }
  .input-numero .btn-paso:first-child { border-radius: 8px 0 0 8px; }
  .input-numero .btn-paso:last-child { border-radius: 0 8px 8px 0; }
  .btn-paso:hover {
    color: var(--text-color);
    background: var(--panel-bg);
  }
  .btn-paso:active { color: var(--accent-blue); }
  /* Separa el bloque del activo del de la operación. Un hueco a secas no bastaba
     con los campos ya tan juntos. */
  .form-separador {
    height: 1px;
    background: var(--border-color);
    margin: 4px 0 20px;
  }

  /* --- ALTA DE TRANSACCIÓN: EL BUSCADOR DE ACTIVO --- */
  .activo-buscador { position: relative; }
  .activo-sugerencias {
    display: none;
    position: absolute;
    top: calc(100% + 6px);
    left: 0;
    right: 0;
    z-index: 20;
    max-height: 244px;
    overflow-y: auto;
    padding: 6px;
    background: var(--panel-bg);
    border: 1px solid var(--border-color);
    border-radius: 10px;
    /* Sombra marcada y fondo opaco: está flotando sobre otros campos y tiene que
       leerse como una capa por encima, no como parte del formulario. */
    box-shadow: 0 14px 34px rgba(0, 0, 0, 0.55);
  }
  .activo-sugerencias.abierta { display: block; }
  .activo-sugerencia {
    display: block;
    width: 100%;
    padding: 8px 10px;
    background: transparent;
    border: none;
    border-radius: 7px;
    text-align: left;
    cursor: pointer;
  }
  .activo-sugerencia + .activo-sugerencia { margin-top: 2px; }
  .activo-sugerencia:hover,
  .activo-sugerencia:focus-visible {
    background: var(--panel2-bg);
    outline: none;
  }
  /* En una línea con puntos suspensivos: un nombre largo partido en dos deja las
     filas de distinta altura y la lista se lee como un bloque de texto. */
  .activo-sugerencia-nombre,
  .activo-sugerencia-meta {
    display: block;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
  }
  .activo-sugerencia-nombre {
    font-size: 13px;
    font-weight: 600;
    color: var(--text-color);
    /* Los nombres del proveedor vienen en mayúsculas y a este tamaño cansan. */
    text-transform: none;
    line-height: 1.35;
  }
  .activo-sugerencia-meta {
    margin-top: 1px;
    font-family: var(--mono-font);
    font-size: 10.5px;
    color: var(--muted-color);
  }
  /* El trozo que coincide con lo escrito. Sin fondo amarillo de navegador: aquí
     lo que hace falta es ver POR QUÉ está esa fila en la lista, no subrayar una
     cita. Se marca con el color de acento y un fondo apenas insinuado. */
  .activo-sugerencia mark {
    background: var(--accent-soft);
    color: var(--accent);
    border-radius: 3px;
    padding: 0 1px;
  }

  /* --- BARRAS DE DESPLAZAMIENTO ---
   *
   * Las del sistema son anchas, de otro color y con flechas en los extremos: en
   * una lista de 244 px se comían el borde redondeado y cantaban más que el
   * contenido. Estas van en los tonos de la aplicación y solo se destacan al
   * pasar por encima. Firefox usa `scrollbar-*`; el resto, `::-webkit-*`. */
  .activo-sugerencias,
  .benchmark-list,
  .composicion-sublista,
  .social-list,
  .positions-table-container,
  .mapa-mensual-caja,
  .content-area {
    scrollbar-width: thin;
    scrollbar-color: var(--border-color) transparent;
  }
  .activo-sugerencias::-webkit-scrollbar,
  .benchmark-list::-webkit-scrollbar,
  .composicion-sublista::-webkit-scrollbar,
  .social-list::-webkit-scrollbar,
  .positions-table-container::-webkit-scrollbar,
  .mapa-mensual-caja::-webkit-scrollbar,
  .content-area::-webkit-scrollbar {
    width: 10px;
    height: 10px;
  }
  .activo-sugerencias::-webkit-scrollbar-track,
  .benchmark-list::-webkit-scrollbar-track,
  .composicion-sublista::-webkit-scrollbar-track,
  .social-list::-webkit-scrollbar-track,
  .positions-table-container::-webkit-scrollbar-track,
  .mapa-mensual-caja::-webkit-scrollbar-track,
  .content-area::-webkit-scrollbar-track {
    background: transparent;
  }
  /* El borde transparente con `background-clip` es lo que deja el pulgar fino y
     con aire a los lados sin tener que estrechar la zona sensible al ratón. */
  .activo-sugerencias::-webkit-scrollbar-thumb,
  .benchmark-list::-webkit-scrollbar-thumb,
  .composicion-sublista::-webkit-scrollbar-thumb,
  .social-list::-webkit-scrollbar-thumb,
  .positions-table-container::-webkit-scrollbar-thumb,
  .mapa-mensual-caja::-webkit-scrollbar-thumb,
  .content-area::-webkit-scrollbar-thumb {
    background-color: var(--border-color);
    border: 3px solid transparent;
    background-clip: content-box;
    border-radius: 999px;
  }
  .activo-sugerencias:hover::-webkit-scrollbar-thumb,
  .benchmark-list:hover::-webkit-scrollbar-thumb,
  .composicion-sublista:hover::-webkit-scrollbar-thumb,
  .social-list:hover::-webkit-scrollbar-thumb,
  .positions-table-container:hover::-webkit-scrollbar-thumb,
  .mapa-mensual-caja:hover::-webkit-scrollbar-thumb,
  .content-area:hover::-webkit-scrollbar-thumb {
    background-color: var(--muted-color);
  }
  /* El activo ya elegido ocupa el sitio de sus campos: mientras esté ahí, ni el
     ISIN ni el nombre ni la divisa se pueden contradecir a mano. */
  .activo-elegido {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 12px;
    padding: 11px 14px;
    margin-bottom: 16px;
    background: var(--panel2-bg);
    border: 1px solid var(--border-color);
    border-left: 3px solid var(--accent-blue);
    border-radius: 10px;
  }
  .activo-elegido-id { min-width: 0; }
  .activo-elegido-id strong {
    display: block;
    font-size: 14px;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
  }
  .activo-elegido-id span {
    font-family: var(--mono-font);
    font-size: 11px;
    color: var(--muted-color);
  }
  .activo-elegido .btn-inline-action { padding: 6px 12px; }

  /* El aviso y el botón de añadir, en la misma línea. */
  .position-tx-intro {
    display: flex;
    align-items: flex-start;
    justify-content: space-between;
    gap: 16px;
    margin-bottom: 14px;
  }
  .position-tx-intro .form-hint { margin: 0; }
  .position-tx-intro .btn-inline-action { padding: 6px 12px; white-space: nowrap; }

  .sell-asset-head {
    padding-bottom: 14px;
    margin-bottom: 16px;
    border-bottom: 1px solid var(--border-color);
  }
  .sell-asset-head strong { display: block; font-size: 15px; }
  .sell-asset-head .form-hint { margin-top: 6px; }
  .input-with-action {
    display: flex;
    gap: 8px;
    align-items: stretch;
  }
  .input-with-action input { flex: 1; min-width: 0; }
  .btn-inline-action {
    flex-shrink: 0;
    padding: 0 12px;
    font-size: 12px;
    font-weight: 600;
    color: var(--text-color);
    background: var(--panel2-bg);
    border: 1px solid var(--border-color);
    border-radius: 8px;
    cursor: pointer;
  }
  .btn-inline-action:hover { border-color: var(--accent-blue); color: var(--accent-blue); }
  .sell-estimate {
    margin: 4px 0 14px;
    font-size: 12.5px;
    color: var(--muted-color);
    line-height: 1.5;
  }
  .sell-estimate.pos { color: var(--pos-color); }
  .sell-estimate.neg { color: var(--neg-color); }
  .position-tx-row {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 16px;
    flex-wrap: wrap;
    padding: 12px 0;
    border-bottom: 1px solid var(--border-color);
  }
  .position-tx-row:last-child { border-bottom: none; }
  .position-tx-row.editing { display: block; }
  .position-tx-main { display: flex; flex-direction: column; gap: 3px; min-width: 220px; }
  .position-tx-detail { font-family: var(--mono-font); font-size: 12.5px; }
  .position-tx-meta { font-size: 11px; color: var(--muted-color); }
  .position-tx-actions { display: flex; gap: 8px; flex-wrap: wrap; }
  .confirm-box {
    max-width: 460px;
  }
  .confirm-text {
    color: var(--muted-color);
    font-size: 14px;
    line-height: 1.55;
    margin-bottom: 20px;
  }
  .confirm-actions {
    justify-content: flex-end;
  }
  .position-tx-editor-grid {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(140px, 1fr));
    gap: 10px;
    margin-bottom: 12px;
  }
  .position-tx-editor-grid label {
    display: flex;
    flex-direction: column;
    gap: 4px;
    font-size: 11.5px;
    color: var(--muted-color);
  }
  .btn-danger { background: var(--neg-color); color: #fff; }
  .btn-neutral {
    background: var(--panel2-bg);
    border: 1px solid var(--border-color);
    color: var(--text-color);
  }
  /* La usa el detalle del modal de purga. */
  .closed-position-label {
    font-size: 10.5px;
    text-transform: uppercase;
    letter-spacing: 0.04em;
    color: var(--muted-color);
  }
  /* --- COMPOSICIÓN: BARRA DE MANDOS ---
     La forma a un lado y el tramo del mapa al otro: son preguntas distintas
     —cómo se dibuja y de qué periodo— y juntas se leían como un solo grupo. */
  .composicion-toolbar {
    display: flex;
    align-items: center;
    gap: 12px;
    flex-wrap: wrap;
    margin-bottom: 20px;
    /* Reserva el alto de los botones aunque no haya ninguno, para que el
       gráfico no suba y baje al cambiar de eje. */
    min-height: 28px;
  }
  .composicion-toolbar #treemap-time-filters { margin-left: auto; }

  /* --- COMPOSICIÓN: OBJETIVO Y DESVIACIÓN --- */
  .objetivo-cabecera {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 16px;
    flex-wrap: wrap;
    margin-bottom: 18px;
  }
  .objetivo-cabecera .form-hint { margin: 0; }

  .objetivo-filas { display: flex; flex-direction: column; gap: 4px; }
  /* Nombre | barra | cifras. La barra se lleva el ancho sobrante porque es lo
     que se compara de una fila a otra. */
  .objetivo-fila {
    display: grid;
    grid-template-columns: minmax(120px, 190px) 1fr minmax(150px, auto);
    align-items: center;
    gap: 16px;
    padding: 11px 14px;
    border-radius: 10px;
    border: 1px solid transparent;
  }
  .objetivo-fila:hover { background: var(--panel2-bg); }
  /* Solo las que se salen del plan llevan marco: si se marcaran todas, la
     marca dejaría de señalar nada. */
  .objetivo-fila.fuera {
    background: var(--panel2-bg);
    border-color: var(--border-color);
  }
  .objetivo-id { display: flex; align-items: center; gap: 9px; min-width: 0; }
  .objetivo-punto {
    flex: 0 0 auto;
    width: 9px;
    height: 9px;
    border-radius: 50%;
  }
  .objetivo-nombre {
    font-size: 13px;
    font-weight: 600;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
  }

  .objetivo-barra {
    position: relative;
    height: 10px;
    min-width: 0;
    background: var(--panel-bg);
    border: 1px solid var(--border-color);
    border-radius: 999px;
  }
  .objetivo-fila:hover .objetivo-barra,
  .objetivo-fila.fuera .objetivo-barra { background: var(--bg); }
  .objetivo-real {
    height: 100%;
    border-radius: 999px;
    transition: width 0.25s ease;
  }
  /* La marca del objetivo, ENCIMA de la barra real: lo que se lee de un vistazo
     es si la barra llega o se pasa de ella. */
  .objetivo-marca {
    position: absolute;
    top: -3px;
    bottom: -3px;
    width: 2px;
    margin-left: -1px;
    background: var(--text-color);
    border-radius: 1px;
  }

  .objetivo-cifras {
    display: flex;
    flex-direction: column;
    align-items: flex-end;
    gap: 1px;
    text-align: right;
    white-space: nowrap;
  }
  .objetivo-pct { font-family: var(--mono-font); font-size: 12.5px; }
  .objetivo-pct-obj { color: var(--muted-color); font-size: 11px; }
  .objetivo-mover { font-size: 11.5px; color: var(--muted-color); }
  /* Verde lo que hay que aportar, rojo lo que sobra: el mismo idioma de signo
     que el resto de la aplicación. */
  .objetivo-mover.pos { color: var(--pos-color); }
  .objetivo-mover.neg { color: var(--neg-color); }

  /* Sin plan todavía: se explica para qué sirve antes de pedir que se rellene. */
  .objetivo-vacio {
    max-width: 520px;
    margin: 0 auto;
    padding: 44px 20px;
    text-align: center;
  }
  .objetivo-vacio h4 { font-size: 15px; font-weight: 600; margin-bottom: 8px; }
  .objetivo-vacio p {
    font-size: 13px;
    line-height: 1.6;
    color: var(--muted-color);
    margin-bottom: 20px;
  }
  .objetivo-vacio .btn-submit { width: auto; padding: 10px 22px; }

  /* --- EL EDITOR DEL PLAN --- */
  .objetivo-lista {
    display: flex;
    flex-direction: column;
    gap: 8px;
    max-height: 46vh;
    overflow-y: auto;
    padding-right: 4px;
  }
  .objetivo-campo {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 14px;
    padding: 8px 12px;
    background: var(--panel2-bg);
    border: 1px solid var(--border-color);
    border-radius: 8px;
  }
  .objetivo-campo-nombre {
    display: flex;
    flex-direction: column;
    gap: 1px;
    font-size: 13px;
    font-weight: 600;
  }
  .objetivo-campo-real {
    font-family: var(--mono-font);
    font-size: 10.5px;
    font-weight: 500;
    color: var(--muted-color);
  }
  .objetivo-campo-entrada {
    display: flex;
    align-items: center;
    gap: 6px;
    color: var(--muted-color);
    font-size: 12px;
  }
  .objetivo-campo-entrada input {
    width: 84px;
    background: var(--panel-bg);
    border: 1px solid var(--border-color);
    border-radius: 7px;
    padding: 8px 10px;
    color: var(--text-color);
    font-family: var(--mono-font);
    font-size: 13px;
    text-align: right;
    outline: none;
  }
  .objetivo-campo-entrada input:focus { border-color: var(--accent-blue); }

  .objetivo-pie {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 16px;
    margin-top: 18px;
  }
  /* El contador vive en rojo hasta que cuadra: es la única condición para poder
     guardar, así que tiene que verse mientras se teclea. */
  .objetivo-suma {
    font-family: var(--mono-font);
    font-size: 12px;
    font-weight: 600;
    color: var(--neg-color);
  }
  .objetivo-suma.cuadra { color: var(--pos-color); }
  .objetivo-pie .btn-submit { width: auto; padding: 10px 20px; }
  .objetivo-pie .btn-submit:disabled {
    opacity: 0.45;
    cursor: not-allowed;
  }
  @media (prefers-reduced-motion: reduce) {
    .objetivo-real { transition: none; }
  }

  /* --- COMPOSICIÓN: DERIVA ---
     Alto fijo y generoso: son bandas apiladas, y aplastadas no se distingue
     cuál engorda y cuál adelgaza, que es justo lo que se viene a ver. */
  .composicion-deriva {
    position: relative;
    width: 100%;
    height: 380px;
  }
  .composicion-deriva-nota {
    max-width: 720px;
    margin: 14px auto 0;
    text-align: center;
  }

  /* --- EFECTIVO ---
     Debajo de las posiciones y con la MISMA cabecera que la tabla: versalitas,
     monoespaciada, sobre su propia banda y con el filo grueso abajo. Así se lee
     como lo que es —otro apartado de la misma pantalla— y no como una tarjeta
     suelta que alguien dejó ahí debajo. */
  .efectivo-panel {
    margin-top: 24px;
    border: 1px solid var(--border-color);
    border-radius: 8px;
    overflow: hidden;
  }
  .efectivo-head {
    display: flex;
    align-items: center;
    gap: 10px;
    width: 100%;
    padding: 13px 16px;
    font-family: var(--mono-font);
    font-size: 10.5px;
    font-weight: 700;
    color: var(--text-color);
    text-transform: uppercase;
    letter-spacing: 0.09em;
    text-align: left;
    background: var(--panel2-bg);
    border: 0;
    border-bottom: 2px solid var(--border-color);
    cursor: pointer;
  }
  .efectivo-head:focus-visible {
    outline: 2px solid var(--accent);
    outline-offset: -3px;
  }
  .efectivo-titulo { flex: 1; }
  /* El total NO va en versalitas ni al tamaño de la cabecera: es la cifra, y
     plegado es lo único que queda a la vista. */
  .efectivo-total {
    font-size: 15px;
    font-weight: 700;
    letter-spacing: 0;
    text-transform: none;
    font-variant-numeric: tabular-nums;
  }
  .efectivo-panel[data-abierto] .composicion-flecha,
  .efectivo-head[aria-expanded="true"] .composicion-flecha {
    transform: rotate(90deg);
  }

  .efectivo-fila {
    display: flex;
    align-items: center;
    gap: 12px;
    padding: 10px 16px;
    border-bottom: 1px solid var(--border-color);
    font-size: 13px;
  }
  .efectivo-lista > :last-child { border-bottom: 0; }
  .efectivo-cuenta { flex: 1; min-width: 0; }
  /* LA CIFRA ES EL CONTROL. Se pincha y se convierte en campo: lo que se quiere
     hacer con un saldo es cambiarlo, y un botón de «editar» al lado solo añade
     un clic a la única acción que hay. El subrayado punteado al pasar por
     encima es lo que dice que se puede tocar sin pintarlo como un botón. */
  .efectivo-cifra {
    padding: 3px 6px;
    margin: -3px -6px;
    font-family: var(--mono-font);
    font-size: 13px;
    font-variant-numeric: tabular-nums;
    color: var(--text-color);
    background: none;
    border: 0;
    border-radius: 6px;
    cursor: text;
    transition: background-color 0.15s ease;
  }
  .efectivo-cifra:hover {
    background: var(--panel2-bg);
    box-shadow: inset 0 -1px 0 var(--muted-color);
  }
  .efectivo-cifra:focus-visible {
    outline: 2px solid var(--accent);
    outline-offset: 0;
  }
  .efectivo-campo {
    width: 120px;
    padding: 3px 6px;
    margin: -3px -6px;
    font-family: var(--mono-font);
    font-size: 13px;
    text-align: right;
    color: var(--text-color);
    background: var(--panel2-bg);
    border: 1px solid var(--accent);
    border-radius: 6px;
  }
  /* Quitar un saldo asoma al pasar por la fila: es lo que menos se hace de
     todo lo que hay aquí, y a la vista compite con la cifra. */
  .efectivo-quitar {
    flex-shrink: 0;
    width: 22px;
    height: 22px;
    font-size: 15px;
    line-height: 1;
    color: var(--muted-color);
    background: none;
    border: 0;
    border-radius: 6px;
    cursor: pointer;
    opacity: 0;
    transition: opacity 0.15s ease, color 0.15s ease;
  }
  .efectivo-fila:hover .efectivo-quitar,
  .efectivo-quitar:focus-visible { opacity: 1; }
  .efectivo-quitar:hover { color: var(--neg-color); }

  .efectivo-anadir {
    display: block;
    width: 100%;
    padding: 10px 16px;
    font: inherit;
    font-size: 12.5px;
    color: var(--muted-color);
    text-align: left;
    background: none;
    border: 0;
    cursor: pointer;
  }
  .efectivo-anadir:hover { color: var(--accent); }
  .efectivo-nueva select,
  .efectivo-nueva input {
    flex: 1 1 100px;
    min-width: 0;
    padding: 6px 9px;
    font-size: 12.5px;
    color: var(--text-color);
    background: var(--panel2-bg);
    border: 1px solid var(--border-color);
    border-radius: 8px;
  }
  .efectivo-nueva .efectivo-campo { margin: 0; width: auto; border-color: var(--accent); }
  .efectivo-vacio {
    padding: 14px 16px;
    font-size: 12px;
    color: var(--muted-color);
  }

  /* --- COMPOSICIÓN: EL DESGLOSE DE UNA FILA ---
     Una fila de la leyenda decía «6 activos» y no había forma de ver cuáles:
     ni «Otros», ni una clase de activo, ni una divisa. */
  .composicion-item.desplegable { cursor: pointer; }
  .composicion-flecha {
    display: inline-block;
    margin-left: 6px;
    font-size: 10px;
    color: var(--muted-color);
    transition: transform 0.18s ease;
  }
  .composicion-item.abierta .composicion-flecha { transform: rotate(90deg); }
  .composicion-sublista {
    display: none;
    margin: -2px 0 8px;
    padding: 6px 16px 8px 30px;
    background: var(--panel2-bg);
    border: 1px solid var(--border-color);
    border-top: none;
    border-radius: 0 0 12px 12px;
    /* Trece criptos abiertas empujaban el resto de la leyenda fuera de la
       pantalla y la separaban del anillo con el que se compara. Ocho filas
       caben; el resto se desplaza, con la barra fina del resto de la aplicación. */
    max-height: 232px;
    overflow-y: auto;
  }
  /* Sin aire lateral en la caja: lo llevan las filas. Es lo que deja que sus
     bandas lleguen de borde a borde en vez de flotar en un carril estrecho. */
  .composicion-sublista { padding-left: 0; padding-right: 0; }
  /* Se despliega con la misma entrada que usan las filas de la leyenda al
     dibujarse: es el mismo gesto —algo que aparece— y no hacía falta inventarle
     otro. Una transición de altura no serviría aquí: se parte de `display:none`,
     que no anima. */
  .composicion-sublista.abierta {
    display: block;
    animation: entraFilaLeyenda 180ms var(--curva-salida) backwards;
  }
  .composicion-subitem {
    display: flex;
    align-items: baseline;
    justify-content: space-between;
    gap: 14px;
    padding: 6px 16px 6px 30px;
    font-size: 12.5px;
    line-height: 1.35;
    color: var(--text-color);
  }
  /* BANDAS ALTERNAS.
     Trece filas seguidas de nombre a la izquierda y cifra a la derecha se leen
     en diagonal, y es fácil acabar cruzando el nombre de una con el porcentaje
     de la de al lado. La banda ata cada nombre a su número sin tener que dibujar
     una línea entre ellos.

     Del color de su clase y muy diluido, no de un gris neutro: así la lista
     sigue diciendo de qué parte del anillo habla, que es lo mismo que hacen la
     franja de la fila y el punto de la leyenda. `color-mix` sobre `transparent`
     y no un color fijo, para que valga igual en los cuatro temas. */
  .composicion-subitem:nth-child(even) {
    background: color-mix(in srgb, var(--color-serie) 7%, transparent);
  }
  /* Seguir la fila hasta su cifra al otro lado del ancho es justo donde se
     pierde el ojo; el realce la acompaña. */
  .composicion-subitem:hover {
    background: color-mix(in srgb, var(--color-serie) 15%, transparent);
  }
  /* La cola de la clase, apagada: es un cajón de sastre y no un activo, igual
     que «Otros» va gris en el anillo y en la leyenda. En el mismo tono que su
     cifra, que es lo que dice que ahí no hay nada que mirar de cerca. */
  .composicion-subitem.agrupada { color: var(--muted-color); }
  .composicion-subitem.agrupada > span:first-child { font-weight: 400; }
  .composicion-subitem > span:first-child {
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    /* Medio punto de grosor sobre el texto corriente: el nombre es lo que se
       busca al recorrer la lista, y en regular se hundía en el fondo. */
    font-weight: 500;
    letter-spacing: 0.005em;
  }
  .composicion-subitem-cifras {
    flex: 0 0 auto;
    /* Ancho mínimo y a la derecha: sin él, «78.5%» y «0.1%» empiezan en sitios
       distintos y la columna deja de poder leerse de un vistazo. */
    min-width: 54px;
    text-align: right;
    font-family: var(--mono-font);
    font-size: 11.5px;
    /* Lo que alinea de verdad las comas: en la fuente proporcional un 1 ocupa
       menos que un 8 y los decimales quedan en diagonal. */
    font-variant-numeric: tabular-nums;
    color: var(--muted-color);
  }
  @media (prefers-reduced-motion: reduce) {
    .composicion-flecha { transition: none; }
    .composicion-sublista.abierta { animation: none; }
  }

  /* --- COMPOSICIÓN: BARRAS --- */
  .composicion-bars {
    position: relative;
    width: 100%;
    min-height: 240px;
  }

  /* --- COMPOSICIÓN: MAPA DE RENTABILIDAD --- */
  .treemap-wrap {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 14px;
  }
  /* Doble de ancho que de alto, y con tope: a lo ancho de la tarjeta en una
     pantalla panorámica el mapa salía en tira y todas las piezas se leían como
     lonchas del mismo grosor. El tope va en `min()` para que en un monitor
     grande el mapa no se coma la pantalla entera y en uno pequeño no se salga
     de ella; por debajo de ese punto manda el 92 % del ancho disponible, en
     `cqw` y no en `vw` para que la cuenta salga contra el ancho REAL (sin el
     menú lateral), como el resto de cajas que se miden solas.
     El `max-height` es para una ventana baja: ahí el 2:1 cede y el mapa se
     queda algo más apaisado antes que obligar a desplazar la página. */
  .treemap {
    position: relative;
    width: 100%;
    max-width: min(1360px, 92cqw);
    aspect-ratio: 2 / 1;
    max-height: 78vh;
    min-height: 280px;
    border-radius: 10px;
    overflow: hidden;
    background: var(--panel-bg);
  }
  /* El «calculando…» y el «sin posiciones», centrados en el mapa: sueltos se
     quedaban pegados al borde de arriba con todo el hueco debajo. */
  .treemap > .public-profile-empty,
  .treemap > div:only-child:not(.treemap-grupo) {
    position: absolute;
    inset: 0;
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 8px;
  }
  /* Una caja por clase de activo: rótulo arriba y sus piezas debajo. Se dibuja
     como una tarjeta con esquinas redondeadas para que la clase se lea como una
     región y no como un conjunto de piezas que resulta que van juntas. */
  .treemap-grupo {
    position: absolute;
    display: flex;
    flex-direction: column;
    border-radius: 8px;
    overflow: hidden;
    background: var(--panel-bg);
  }
  /* El marco va en un `::after` y no en un `box-shadow: inset` del propio grupo:
     una sombra interior se pinta DEBAJO de los hijos, y las piezas —que van
     posicionadas— la tapaban entera, así que la separación entre clases no se
     veía. El pseudoelemento es el último hijo, así que queda por encima.
     Y va por dentro, no como borde real: un borde sumaría al tamaño de la caja
     y los grupos dejarían de sumar el 100 % del área. */
  .treemap-grupo::after {
    content: "";
    position: absolute;
    inset: 0;
    pointer-events: none;
    border: 3px solid var(--treemap-hueco);
    border-radius: 8px;
    box-shadow: inset 0 0 0 1px var(--treemap-marco);
  }
  .treemap-grupo-cabecera {
    /* Cuadra con `ALTO_CABECERA_GRUPO` en charts.js, que descuenta este alto
       antes de repartir las piezas del grupo. */
    flex: 0 0 24px;
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 8px;
    padding: 0 11px;
    background: var(--treemap-cabecera);
    border-bottom: 1px solid var(--treemap-marco);
    font-size: 10.5px;
    font-weight: 700;
    letter-spacing: 0.08em;
    text-transform: uppercase;
    overflow: hidden;
    white-space: nowrap;
  }
  /* El nombre de la clase, a plena luz: es el rótulo de la región. El peso se
     queda apagado, que es dato de apoyo. */
  .treemap-grupo-nombre {
    color: var(--text-color);
    overflow: hidden;
    text-overflow: ellipsis;
  }
  .treemap-grupo-peso {
    color: var(--muted-color);
    font-family: var(--mono-font);
    flex: 0 0 auto;
  }
  .treemap-grupo-cuerpo { position: relative; flex: 1 1 auto; }
  .treemap-celda {
    position: absolute;
    display: flex;
    flex-direction: column;
    justify-content: center;
    align-items: center;
    gap: 1px;
    padding: 4px;
    overflow: hidden;
    box-shadow: inset 0 0 0 1px rgba(0, 0, 0, 0.32);
    text-align: center;
    cursor: default;
    /* Blanco fijo y no `--text-color`: el relleno de la pieza es el mismo en
       tema claro y oscuro, así que el texto de encima también tiene que serlo.
       La sombra es la que salva el peldaño más vivo de la escala. */
    color: #fff;
    text-shadow: 0 1px 2px rgba(0, 0, 0, 0.45);
    transition: filter 120ms ease;
  }
  .treemap-celda:hover { filter: brightness(1.18); }
  .treemap-ticker {
    font-family: var(--mono-font);
    font-weight: 700;
    line-height: 1.2;
    max-width: 100%;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
  }
  .treemap-rent { font-weight: 700; font-variant-numeric: tabular-nums; line-height: 1.25; }
  .treemap-peso { opacity: 0.75; font-variant-numeric: tabular-nums; line-height: 1.2; }

  /* El detalle de la pieza sobre la que está el ratón: en un mapa así hay
     siempre piezas en las que no cabe ni el nombre. */
  .treemap-tooltip {
    position: fixed;
    z-index: 4000;
    display: none;
    pointer-events: none;
    /* `max-content` acotado: sin él, un tooltip colocado cerca del borde derecho
       se encoge contra la ventana y lo que se mide para decidir si hay que
       voltearlo ya no es su ancho real. */
    width: max-content;
    max-width: 280px;
    padding: 10px 12px;
    border-radius: 8px;
    background: var(--panel2-bg);
    border: 1px solid var(--border-color);
    box-shadow: 0 10px 28px rgba(0, 0, 0, 0.45);
    color: var(--text-color);
    font-size: 12px;
    line-height: 1.5;
  }
  .treemap-tooltip-nombre { font-weight: 700; margin-bottom: 2px; }
  .treemap-tooltip-sub {
    color: var(--muted-color);
    font-size: 10.5px;
    text-transform: uppercase;
    letter-spacing: 0.04em;
    margin-bottom: 6px;
  }
  .treemap-tooltip-fila {
    display: flex;
    justify-content: space-between;
    gap: 18px;
  }
  .treemap-tooltip-fila span { color: var(--muted-color); }
  .treemap-tooltip-fila strong { font-family: var(--mono-font); font-weight: 600; }
  .treemap-tooltip-fila strong.pos { color: var(--pos-color); }
  .treemap-tooltip-fila strong.neg { color: var(--neg-color); }

  /* --- COMPOSICIÓN: ESCALA DEL MAPA --- */
  .treemap-leyenda {
    display: flex;
    align-items: center;
    justify-content: center;
    flex-wrap: wrap;
    gap: 8px;
    font-size: 11px;
    color: var(--muted-color);
  }
  .treemap-leyenda-texto { display: inline-flex; align-items: center; gap: 5px; }
  .treemap-leyenda-aparte {
    padding-left: 10px;
    margin-left: 2px;
    border-left: 1px solid var(--border-color);
  }
  .treemap-leyenda-escala { display: inline-flex; gap: 2px; }
  .treemap-leyenda i,
  .treemap-leyenda-escala i {
    display: block;
    width: 20px;
    height: 11px;
    border-radius: 2px;
  }
  .treemap-leyenda-nota {
    max-width: 640px;
    margin: 8px auto 0;
    text-align: center;
    font-size: 11px;
    line-height: 1.5;
    color: var(--muted-color);
  }

  /* --- PESTAÑAS DE NIVEL DE PANTALLA ---
   *
   * Las comparten las cuentas de origen del Portfolio y los dos apartados del
   * Historial. Las de bróker solo se diferencian en que arrancan ocultas: con
   * un solo bróker, la global y la suya enseñan lo mismo. */
  .screen-tabs, .broker-tabs {
    position: relative;
    display: flex;
    gap: 2px;
    /* En UNA fila con desplazamiento lateral, no en varias. Al envolver, la
       segunda fila empujaba el gráfico hacia abajo: abrir la ventana un poco
       más estrecha movía media pantalla, y con seis cuentas eso pasaba en
       cualquier portátil. */
    flex-wrap: nowrap;
    overflow-x: auto;
    overscroll-behavior-x: contain;
    scrollbar-width: none;
    margin-bottom: 18px;
    border-bottom: 1px solid var(--border-color);
    /* Los bordes se difuminan SOLO cuando queda algo por ese lado; lo mide
       `midePestanyas` y lo escribe en estas dos variables. Con las dos a cero
       la máscara es opaca de punta a punta y no se nota que existe. */
    --desvanecido-izq: 0px;
    --desvanecido-der: 0px;
    mask-image: linear-gradient(
      to right,
      transparent 0,
      #000 var(--desvanecido-izq),
      #000 calc(100% - var(--desvanecido-der)),
      transparent 100%
    );
  }
  .screen-tabs::-webkit-scrollbar,
  .broker-tabs::-webkit-scrollbar { display: none; }

  /* El subrayado es UNO y se desplaza, en vez de uno por pestaña que se
     enciende y se apaga. La diferencia no es decorativa: el trazo que viaja
     dice de dónde vienes y a dónde vas, y en un conmutador de cuentas —donde
     todo lo de debajo se reemplaza— ese hilo es lo que evita que el cambio se
     lea como una pantalla nueva.

     Va en el contenedor y no en los botones para poder animarlo: dos elementos
     distintos no se pueden interpolar entre sí. Su sitio lo escribe
     `midePestanyas` en `--indicador-x` y `--indicador-ancho`. */
  .screen-tabs::after, .broker-tabs::after {
    content: "";
    position: absolute;
    left: 0;
    bottom: 0;
    height: 2px;
    width: var(--indicador-ancho, 0);
    transform: translateX(var(--indicador-x, 0));
    background: var(--accent);
    border-radius: 2px 2px 0 0;
    /* La misma curva que las cifras que corren y que el resto de la pantalla:
       arranca rápido y frena al llegar. */
    transition: transform 0.34s var(--curva-salida), width 0.34s var(--curva-salida);
    pointer-events: none;
  }
  /* La primera colocación no se anima: un trazo que entra deslizándose desde el
     margen izquierdo al abrir la página se lee como un fallo, no como un
     conmutador. */
  .screen-tabs.sin-transicion::after,
  .broker-tabs.sin-transicion::after { transition: none; }

  .broker-tabs { display: none; }
  .screen-tab, .broker-tab {
    position: relative;
    flex: 0 0 auto;
    padding: 9px 14px;
    font-size: 13px;
    font-weight: 500;
    /* Son nombres propios de cuentas, así que van en la tipografía de texto y
       no en la mono de los controles: «Interactive Brokers» no es una etiqueta
       de periodo, es el nombre de un sitio. El apretado leve es el mismo que
       lleva la marca. */
    letter-spacing: -0.01em;
    color: var(--muted-color);
    background: transparent;
    border: none;
    border-radius: 7px 7px 0 0;
    cursor: pointer;
    white-space: nowrap;
    transition: color 0.18s ease, background-color 0.18s ease;
  }
  /* Un fantasma en negrita que reserva el ancho de la pestaña ACTIVA aunque no
     lo esté. Sin esto, pasar de 500 a 600 al activarla la ensanchaba unos
     píxeles y empujaba a las de su derecha: el grupo entero temblaba en cada
     clic, y el subrayado deslizante perseguía un objetivo en movimiento. */
  .screen-tab::before, .broker-tab::before {
    content: attr(data-etiqueta);
    display: block;
    height: 0;
    overflow: hidden;
    visibility: hidden;
    font-weight: 600;
    pointer-events: none;
  }
  .screen-tab:hover, .broker-tab:hover {
    color: var(--text-color);
    background: var(--panel2-bg);
  }
  /* El teclado tiene que ver dónde está: antes el foco no se marcaba de ninguna
     manera y recorrer las cuentas con el tabulador era a ciegas. */
  .screen-tab:focus-visible, .broker-tab:focus-visible {
    outline: 2px solid var(--accent);
    outline-offset: -2px;
    border-radius: 7px;
  }

  /* Cambio a una cuenta que todavía no está descargada.
     Se atenúa lo que va a ser reemplazado, pero NO las pestañas: la que se acaba
     de pulsar ya está marcada y es la respuesta al clic. Los datos de la cuenta
     anterior siguen ahí en vez de vaciarse, para que la vista no dé un salto en
     blanco y vuelva; atenuados se leen como «esto ya no es lo que miras».
     La transición de vuelta es más larga que la de ida: apagar tiene que ser
     inmediato y encender, un desvanecido. */
  #screen-portfolio .main-chart-card > *:not(.broker-tabs),
  #screen-portfolio .right-widgets,
  #screen-portfolio .positions-card {
    transition: opacity 0.28s ease;
  }
  #screen-portfolio.cambiando-cuenta .main-chart-card > *:not(.broker-tabs),
  #screen-portfolio.cambiando-cuenta .right-widgets,
  #screen-portfolio.cambiando-cuenta .positions-card {
    opacity: 0.45;
    transition: opacity 0.12s ease;
    /* Nada que pulsar mientras se reemplaza: un clic en «vender» de la cuenta
       anterior abriría el modal de una posición que ya no se está mirando. */
    pointer-events: none;
  }

  @media (prefers-reduced-motion: reduce) {
    #screen-portfolio .main-chart-card > *:not(.broker-tabs),
    #screen-portfolio .right-widgets,
    #screen-portfolio .positions-card {
      transition: none;
    }
    /* El subrayado sigue estando donde toca; lo que se quita es el viaje. */
    .screen-tabs::after, .broker-tabs::after,
    .screen-tab, .broker-tab {
      transition: none;
    }
  }
  /* La cuenta abierta se marca por PESO y por el subrayado, no por color: el
     verde de la marca ya está repartido por la cabecera —la cifra, la línea del
     gráfico, el botón de añadir— y una pestaña verde más competía con ellos en
     vez de destacar. En negro sobre el gris de las demás se lee antes. */
  .screen-tab.active, .broker-tab.active {
    color: var(--text-color);
    font-weight: 600;
  }
  .screen-tab.active:hover, .broker-tab.active:hover {
    background: transparent;
  }

  /* --- AJUSTES DEL GRÁFICO (PANEL DE LA TUERCA) --- */
  .chart-settings-wrapper {
    position: relative;
  }
  .chart-settings-dropdown {
    display: none;
    position: absolute;
    top: calc(100% + 10px);
    right: 0;
    width: max(240px, 16rem);
    background: var(--panel-bg);
    border: 1px solid var(--border-color);
    border-radius: 8px;
    box-shadow: 0 14px 32px rgba(0,0,0,0.32);
    z-index: 35;
    padding: 6px;
  }
  .chart-settings-dropdown.open {
    display: block;
  }
  .chart-settings-group {
    padding: 6px;
  }
  .chart-settings-group + .chart-settings-group {
    border-top: 1px solid var(--border-color);
    margin-top: 2px;
  }
  .chart-settings-title {
    display: block;
    font-size: 10px;
    font-weight: 700;
    letter-spacing: 0.06em;
    text-transform: uppercase;
    color: var(--muted-color);
    padding: 2px 6px 8px;
  }
  /* Una sola línea por opción: la descripción vive en `title`. */
  .chart-settings-option {
    display: flex;
    align-items: center;
    gap: 9px;
    padding: 7px 6px;
    border-radius: 6px;
    font-size: 13px;
    cursor: pointer;
  }
  .chart-settings-option:hover {
    background: var(--panel2-bg);
  }
  .chart-settings-option input {
    accent-color: var(--accent-blue, #3b82f6);
    cursor: pointer;
  }
  /* La única serie encendida no se puede apagar: el mando se ve, pero inerte. */
  .chart-settings-option:has(input:disabled) {
    opacity: 0.55;
    cursor: default;
  }
  .chart-settings-option:has(input:disabled):hover {
    background: transparent;
  }

  /* --- PUNTOS DE REFERENCIA (COMPARAR CON UN ÍNDICE) --- */

  /* Las pastillas son la leyenda de la gráfica: la muestra reproduce el color Y
     el trazo de la línea —dos referencias pueden compartir color—, y el texto se
     queda con la tinta del tema para poder leerse. */
  .benchmark-chips {
    display: flex;
    flex-wrap: wrap;
    justify-content: center;
    gap: 8px;
    margin-top: 12px;
  }
  .benchmark-chip {
    display: inline-flex;
    align-items: center;
    gap: 7px;
    padding: 4px 6px 4px 10px;
    border: 1px solid var(--border-color);
    border-radius: 999px;
    background: var(--panel2-bg);
    color: var(--text-color);
    font-size: 12px;
    font-weight: 500;
  }
  .benchmark-chip-trazo {
    width: 22px;
    height: 6px;
    flex-shrink: 0;
    overflow: visible;
  }
  .benchmark-chip-quitar {
    background: transparent;
    border: none;
    color: var(--muted-color);
    font-size: 15px;
    line-height: 1;
    padding: 0 4px;
    cursor: pointer;
    border-radius: 4px;
  }
  .benchmark-chip-quitar:hover {
    color: var(--text-color);
    background: var(--panel-bg);
  }

  .benchmark-intro {
    color: var(--muted-color);
    font-size: 12px;
    line-height: 1.5;
    margin: -4px 0 14px;
  }
  /* Alto acotado y scroll propio: el catálogo crece al añadir referencias y el
     modal no puede crecer con él hasta salirse de la pantalla. */
  .benchmark-list {
    max-height: 300px;
    overflow-y: auto;
    border: 1px solid var(--border-color);
    border-radius: 8px;
  }
  .benchmark-option {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 12px;
    padding: 10px 12px;
    cursor: pointer;
  }
  .benchmark-option + .benchmark-option {
    border-top: 1px solid var(--border-color);
  }
  .benchmark-option:hover {
    background: var(--panel2-bg);
  }
  .benchmark-option-id {
    display: flex;
    flex-direction: column;
    gap: 2px;
    min-width: 0;
  }
  .benchmark-option-id strong {
    font-size: 13px;
    font-weight: 600;
  }
  .benchmark-option-id span {
    font-size: 11px;
    color: var(--muted-color);
    font-family: var(--mono-font);
  }
  .benchmark-option input {
    accent-color: var(--accent);
    cursor: pointer;
    flex-shrink: 0;
  }
  /* La muestra va en la propia lista: al elegir se ve con qué línea va a salir
     el índice, sin tener que aplicar y mirar la gráfica. `margin-left: auto`
     la empuja junto a la casilla, lejos del nombre. */
  .benchmark-option .benchmark-chip-trazo {
    margin-left: auto;
  }
  /* Sin serie todavía, o con el cupo lleno: se ve, con el motivo en `title`. */
  .benchmark-option.no-disponible {
    opacity: 0.45;
    cursor: default;
  }
  .benchmark-option.no-disponible:hover {
    background: transparent;
  }
  .benchmark-footer {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 12px;
    margin-top: 16px;
  }
  .benchmark-count {
    font-size: 12px;
    color: var(--muted-color);
  }
  .benchmark-count strong {
    color: var(--text-color);
    font-family: var(--mono-font);
  }

  /* Periodo que pide más historia de la que hay: se ve, pero no se pulsa. */
  .btn-time-filter.no-disponible {
    opacity: 0.35;
    cursor: not-allowed;
  }
  .btn-time-filter.no-disponible:hover {
    background: transparent;
    color: inherit;
  }

  /* --- GRÁFICA DE BARRAS SIN DATOS --- */
  .empty-bars {
    display: flex;
    flex-direction: column;
    justify-content: flex-end;
    align-items: center;
    gap: 14px;
    width: 100%;
    min-height: 90px;
    padding-bottom: 4px;
    /* El contenedor alinea al fondo; sin esto el estado vacío se quedaba
       pegado abajo con el hueco encima, igual que las barras. */
    flex: 1 1 auto;
    align-self: stretch;
  }
  .empty-bars-msg {
    margin: auto 0;
    font-size: 12.5px;
    color: var(--muted-color);
    text-align: center;
  }
  /* La línea base es lo único que hace de eje en este widget: sin ella el hueco
     se lee como un fallo de carga en vez de como una gráfica sin serie. */
  .empty-bars-axis {
    width: 100%;
    height: 1px;
    background: var(--border-color);
  }

  /* --- CLASE DE ACTIVO (modal) --- */
  .category-options {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(170px, 1fr));
    gap: 8px;
    margin: 16px 0 4px;
  }
  .category-option {
    display: flex;
    align-items: center;
    gap: 9px;
    padding: 10px 12px;
    border: 1px solid var(--border-color);
    border-radius: 8px;
    font-size: 13px;
    cursor: pointer;
  }
  .category-option:hover { background: var(--panel2-bg); }
  .category-option.activa {
    border-color: var(--accent-blue, #3b82f6);
    background: var(--panel2-bg);
  }
  .category-option input {
    accent-color: var(--accent-blue, #3b82f6);
    cursor: pointer;
  }

  /* --- BORRADO DEFINITIVO --- */
  .btn-purge:hover { color: var(--neg-color); }
  .purge-lead {
    font-size: 13.5px;
    line-height: 1.55;
    margin-bottom: 16px;
  }
  .purge-details {
    padding: 12px 14px;
    margin-bottom: 14px;
    border: 1px solid var(--border-color);
    border-radius: 8px;
    background: var(--panel2-bg);
  }
  .purge-detail-row {
    display: flex;
    align-items: baseline;
    justify-content: space-between;
    gap: 16px;
    padding: 5px 0;
  }
  .purge-warning {
    font-size: 12.5px;
    line-height: 1.5;
    color: var(--neg-color);
    margin-bottom: 18px;
  }
  .danger-zone { border: 1px solid var(--neg-color); }
  .danger-zone-row {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 20px;
    flex-wrap: wrap;
    margin-top: 18px;
    padding-top: 16px;
    border-top: 1px solid var(--border-color);
  }
  .danger-zone-row strong { font-size: 14px; }
  .danger-zone-row p {
    margin-top: 4px;
    max-width: 560px;
    font-size: 12.5px;
    line-height: 1.5;
    color: var(--muted-color);
  }

  .portfolio-realized {
    display: flex;
    align-items: baseline;
    gap: 8px;
    margin-top: 6px;
    font-size: 12.5px;
    color: var(--muted-color);
  }
  .portfolio-realized-total { font-size: 12px; }
  .portfolio-realized-total.pos { color: var(--pos-color); }
  .portfolio-realized-total.neg { color: var(--neg-color); }

  /* --- OTRAS PANTALLAS (OCULTAS POR DEFECTO) --- */
  .screen-view {
    display: none;
    animation: rise 0.3s ease both;
  }
  .screen-view.active {
    display: block;
  }
  .screen-header {
    margin-bottom: 24px;
  }
  .screen-header h1 {
    font-size: 24px;
    font-weight: 600;
    margin-bottom: 4px;
  }
  .screen-header p {
    font-size: 13px;
    color: var(--muted-color);
  }

  /* Formulario modal/caja agregar transacción */
  /* El fondo es el que se desplaza, no la caja: un `overflow` en la caja
     recortaría la lista de sugerencias, que se sale de ella a propósito.
     Y `margin: auto` en vez de `align-items: center` porque centrar un hijo más
     alto que su contenedor lo recorta por ARRIBA —y por arriba está el aspa—;
     con el margen automático se centra cuando cabe y se desplaza cuando no. */
  .transaction-modal {
    display: none; /* JS controla esto */
    position: fixed;
    top: 0; left: 0;
    width: 100vw; height: 100vh;
    overflow-y: auto;
    background-color: rgba(0,0,0,0.6);
    z-index: 1000;
    align-items: flex-start;
    justify-content: center;
    padding: 20px;
  }
  .transaction-box {
    background: var(--panel-bg);
    border: 1px solid var(--border-color);
    border-radius: 16px;
    padding: 30px;
    width: 100%;
    max-width: 440px;
    margin: auto;
    box-shadow: 0 10px 30px rgba(0, 0, 0, 0.5);
  }
  .transaction-box-header {
    display: flex;
    justify-content: space-between;
    align-items: center;
    margin-bottom: 20px;
  }
  .transaction-box-header h3 {
    font-size: 18px;
    font-weight: 600;
  }
  .btn-close-modal {
    background: transparent;
    border: none;
    color: var(--muted-color);
    cursor: pointer;
    font-size: 18px;
  }
  .btn-close-modal:hover {
    color: var(--text-color);
  }

  /* Estilos de carga y spinner */
  .spinner-small {
    display: inline-block;
    width: 12px;
    height: 12px;
    border: 2px solid rgba(255, 255, 255, 0.3);
    border-radius: 50%;
    border-top-color: #ffffff;
    animation: spin 0.8s linear infinite;
    margin-right: 6px;
    vertical-align: middle;
  }
  @keyframes spin {
    to { transform: rotate(360deg); }
  }

  /* Estilos para el contenedor de la gráfica de Analítica */
  /* La leyenda se lleva algo más de columna que el anillo: es la que tiene
     nombres largos que recortar, y al anillo le sobraba sitio a los lados. */
  .analytics-chart-layout {
    display: grid;
    grid-template-columns: minmax(0, 1fr) minmax(0, 1.15fr);
    gap: 40px;
    align-items: center;
    width: 100%;
    margin-top: 20px;
  }
  @media (max-width: 768px) {
    .analytics-chart-layout {
      grid-template-columns: 1fr;
      gap: 24px;
    }
  }

  /* Crece con su columna en vez de quedarse en 300 px fijos: en una pantalla
     ancha el anillo se quedaba flotando en medio de un hueco vacío del tamaño de
     él mismo. El tope evita el otro extremo, un anillo enorme y hueco. */
  .analytics-donut-wrapper {
    position: relative;
    width: 100%;
    max-width: 480px;
    aspect-ratio: 1 / 1;
    margin: 0 auto;
    display: flex;
    align-items: center;
    justify-content: center;
  }
  .analytics-donut-center {
    position: absolute;
    top: 50%;
    left: 50%;
    transform: translate(-50%, -50%);
    text-align: center;
    pointer-events: none;
  }
  /* El texto del centro crece con el anillo, o en uno de 480 px se queda como
     una nota al pie en mitad de un agujero. */
  .analytics-donut-center .d-label {
    font-size: clamp(11px, 0.85cqw, 13px);
    color: var(--muted-color);
    text-transform: uppercase;
    letter-spacing: 0.08em;
    font-weight: 500;
  }
  .analytics-donut-center .d-val {
    font-size: clamp(22px, 1.95cqw, 32px);
    font-weight: 700;
    margin-top: 2px;
    font-family: var(--sans-font);
  }
  .analytics-legend {
    display: flex;
    flex-direction: column;
    gap: 8px;
    width: 100%;
    padding-right: 4px;
  }
  .analytics-legend-item {
    display: flex;
    align-items: center;
    justify-content: space-between;
    padding: 12px 16px;
    background-color: var(--panel2-bg);
    border-radius: 12px;
    border: 1px solid var(--border-color);
    transition: transform 0.2s, border-color 0.2s;
  }
  .analytics-legend-item:hover {
    transform: translateX(4px);
    border-color: var(--muted-color);
  }

  /* --- COMPOSICIÓN: ANILLO Y LEYENDA ENLAZADOS --- */
  .donut-seg {
    /* Tres transiciones sobre la misma porción, y cada una a lo suyo:
       - el grosor y la opacidad son el RESALTADO al pasar el ratón, cortas;
       - el trazo es el BARRIDO de entrada, y su duración y su retraso los pone
         `donutGrande` porción a porción para que la aguja recorra el anillo una
         sola vez. Sin barrido, los dos valores por defecto son cero y la
         declaración no hace nada. */
    transition:
      stroke-width 0.18s ease,
      opacity 0.18s ease,
      stroke-dasharray var(--barrido-dur, 0ms) var(--curva-salida) var(--barrido-retraso, 0ms);
  }
  /* Las filas de la leyenda entran detrás del anillo, en cascada.
     `backwards` y no `both`: con `both` el fotograma final se quedaría fijado
     sobre el elemento y ganaría al `opacity` con el que la leyenda se atenúa al
     resaltar una porción. */
  .composicion-item {
    animation: entraFilaLeyenda 210ms var(--curva-salida) backwards;
  }
  @keyframes entraFilaLeyenda {
    from { opacity: 0; transform: translateY(6px); }
    to { opacity: 1; transform: none; }
  }
  .legend-item {
    animation: entraFilaLeyenda 210ms var(--curva-salida) backwards;
  }
  @media (prefers-reduced-motion: reduce) {
    .composicion-item,
    .legend-item { animation: none; }
  }
  /* El anillo entero es zona sensible: 9 unidades de un viewBox de 100 sobre
     300px son ~27px reales, por encima del mínimo de 24 para un objetivo táctil.
     El SVG no recibe eventos para que el círculo de fondo —que está debajo de
     las porciones y no es ninguna serie— no apague el resaltado al pasar por
     encima de un hueco. */
  .analytics-donut-wrapper svg,
  .donut-svg-wrapper svg { pointer-events: none; }
  .donut-seg[data-serie] { pointer-events: stroke; cursor: pointer; }

  /* Sin acotar a una pantalla: la misma regla vale para el anillo grande de
     Composición y para el widget del panel principal, que ahora comparten el
     mecanismo de resaltado. */
  .con-foco .donut-seg:not(.activo) { opacity: 0.3; }
  .con-foco .composicion-item:not(.activo),
  .con-foco .composicion-sublista:not(.activo),
  .con-foco .legend-item:not(.activo) { opacity: 0.45; }
  .donut-seg.activo { stroke-width: 11.5; }
  .composicion-item.activo {
    border-color: var(--color-serie);
    background: color-mix(in srgb, var(--color-serie) 14%, var(--panel2-bg));
  }
  .composicion-item:focus-visible {
    outline: 2px solid var(--color-serie);
    outline-offset: 2px;
  }
  /* El anillo del widget es más fino (trazo 8 frente a 9), así que su porción
     resaltada crece menos: con el 11,5 del grande, la porción activa se salía
     de la circunferencia de las demás. */
  .donut-chart-container .donut-seg.activo { stroke-width: 10.5; }

  /* --- LEYENDA DE COMPOSICIÓN --- */
  .composicion-item {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 16px;
    padding: 12px 16px;
    background: var(--panel2-bg);
    border: 1px solid var(--border-color);
    /* La franja del color de la porción hace de puente con el anillo, y deja el
       punto y el texto libres de tener que cargar con la identidad ellos solos. */
    border-left: 3px solid var(--color-serie);
    border-radius: 10px;
    transition: border-color 0.2s, background-color 0.2s;
  }
  .composicion-item:hover { background: var(--panel-bg); }
  .composicion-item.principal {
    background: color-mix(in srgb, var(--color-serie) 10%, var(--panel2-bg));
  }
  .composicion-item-id { min-width: 0; }
  .composicion-badge {
    display: block;
    margin-bottom: 4px;
    font-size: 9.5px;
    font-weight: 700;
    letter-spacing: 0.09em;
    text-transform: uppercase;
    color: var(--color-serie);
  }
  .composicion-item-nombre {
    display: flex;
    align-items: center;
    gap: 10px;
    min-width: 0;
    font-size: 13.5px;
    font-weight: 600;
    color: var(--text-color);
  }
  .composicion-item-nombre span {
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
  }
  .composicion-punto {
    flex-shrink: 0;
    width: 9px;
    height: 9px;
    border-radius: 50%;
    background: var(--color-serie);
  }
  .composicion-item-meta {
    display: block;
    margin-top: 3px;
    margin-left: 19px;
    font-size: 11px;
    color: var(--muted-color);
    font-family: var(--mono-font);
  }
  .composicion-item-cifras {
    flex-shrink: 0;
    text-align: right;
    /* Los porcentajes se leen en columna: aquí sí interesa que los dígitos
       ocupen lo mismo para que las comas queden alineadas. */
    font-variant-numeric: tabular-nums;
  }
  .composicion-item-peso {
    display: block;
    font-size: 15px;
    font-weight: 700;
    color: var(--text-color);
  }
  .composicion-item-valor {
    display: block;
    margin-top: 2px;
    font-size: 11.5px;
    color: var(--muted-color);
  }
  .analytics-donut-center .d-delta {
    margin-top: 4px;
    font-size: 13px;
    font-weight: 600;
  }
  .analytics-donut-center .d-delta.pos { color: var(--pos-color); }
  .analytics-donut-center .d-delta.neg { color: var(--neg-color); }

  /* Estilos de OAuth (Google & Microsoft) */
  .oauth-divider {
    display: flex;
    align-items: center;
    text-align: center;
    color: var(--muted-color);
    font-size: 11px;
    margin: 20px 0;
    font-family: var(--mono-font);
    text-transform: uppercase;
    letter-spacing: 0.05em;
  }
  .oauth-divider::before, .oauth-divider::after {
    content: '';
    flex: 1;
    border-bottom: 1px solid var(--border-color);
  }
  .oauth-divider:not(:empty)::before {
    margin-right: .5em;
  }
  .oauth-divider:not(:empty)::after {
    margin-left: .5em;
  }
  .oauth-buttons-container {
    display: flex;
    flex-direction: column;
    gap: 10px;
    margin-top: 15px;
    align-items: center;
    width: 100%;
  }
  .btn-oauth {
    display: flex;
    align-items: center;
    justify-content: center;
    width: 100%;
    background-color: var(--panel2-bg);
    border: 1px solid var(--border-color);
    color: var(--text-color);
    border-radius: 8px;
    padding: 10px 14px;
    font-size: 13.5px;
    font-weight: 500;
    cursor: pointer;
    transition: all 0.2s;
    outline: none;
  }
  .btn-oauth:hover {
    background-color: var(--border-color);
    border-color: var(--muted-color);
  }

  /* Estilos de Ajustes del Perfil */
  .settings-grid {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(320px, 1fr));
    gap: 20px;
    margin-top: 20px;
  }
  .settings-single-grid {
    grid-template-columns: minmax(0, 860px);
  }
  .settings-panel {
    max-width: 860px;
    width: 100%;
  }
  .settings-config-stack {
    display: flex;
    flex-direction: column;
    gap: 16px;
  }
  .settings-card {
    height: 100%;
  }
  .settings-section-card {
    padding: 20px;
  }
  .settings-section-card h3 {
    margin-bottom: 16px;
  }
  .settings-fields-stack {
    display: flex;
    flex-direction: column;
    gap: 16px;
  }
  /* El desplegable de formato de número enseña cifras, no palabras: en
     monoespaciada los separadores se distinguen a simple vista, que es
     justamente lo que hay que comparar para elegir. */
  #settings-number-format {
    font-family: var(--mono-font);
    letter-spacing: 0.02em;
  }
  .settings-field-hint {
    display: block;
    margin-top: 6px;
    font-size: 12px;
    color: var(--muted-color);
  }
  .settings-switch-group {
    display: flex;
    flex-direction: column;
  }
  .settings-actions-row {
    display: flex;
    gap: 12px;
    flex-wrap: wrap;
    justify-content: flex-start;
  }
  .settings-switch-row {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 16px;
    padding: 12px 0;
    border-bottom: 1px solid var(--border-color);
  }
  .settings-switch-row:last-child {
    border-bottom: 0;
  }
  .settings-switch-label {
    display: flex;
    flex-direction: column;
    gap: 4px;
  }
  .settings-switch-label span {
    font-size: 14px;
    font-weight: 600;
    color: var(--text-color);
  }
  .settings-switch-label small {
    font-size: 12px;
    color: var(--muted-color);
  }
  .settings-switch {
    position: relative;
    width: 44px;
    height: 24px;
    flex: 0 0 44px;
  }
  .settings-switch input {
    opacity: 0;
    width: 0;
    height: 0;
  }
  .settings-switch-slider {
    position: absolute;
    cursor: pointer;
    inset: 0;
    background: var(--border-color);
    border-radius: 999px;
    transition: background-color 0.2s;
  }
  .settings-switch-slider:before {
    content: "";
    position: absolute;
    width: 18px;
    height: 18px;
    left: 3px;
    top: 3px;
    background: #fff;
    border-radius: 50%;
    transition: transform 0.2s;
  }
  .settings-switch input:checked + .settings-switch-slider {
    background: var(--accent);
  }
  .settings-switch input:checked + .settings-switch-slider:before {
    transform: translateX(20px);
  }
  .settings-theme-control {
    display: flex;
    align-items: center;
    gap: 10px;
    color: var(--muted-color);
    font-size: 12px;
    font-weight: 600;
    white-space: nowrap;
  }
  .accent-color-picker {
    position: relative;
  }
  .settings-choice-button {
    display: inline-flex;
    align-items: center;
    gap: 8px;
    min-width: 120px;
    justify-content: space-between;
    padding: 9px 12px;
    border: 1px solid var(--border-color);
    border-radius: 8px;
    background: var(--panel2-bg);
    color: var(--text-color);
    font-size: 13px;
    font-weight: 600;
    cursor: pointer;
    transition: border-color 0.2s, background-color 0.2s, color 0.2s;
  }
  .settings-choice-button:hover,
  .settings-choice-button:focus {
    border-color: var(--accent);
    outline: none;
  }
  .accent-dot {
    width: 12px;
    height: 12px;
    border-radius: 999px;
    background: var(--accent);
    border: 1px solid rgba(255, 255, 255, 0.35);
    flex: 0 0 12px;
  }
  .accent-green { background: #00c582; }
  .accent-orange { background: #f59e0b; }
  .accent-blue { background: #2563eb; }
  .accent-color-popover {
    display: none;
    position: absolute;
    right: 0;
    top: calc(100% + 8px);
    min-width: 160px;
    padding: 6px;
    border: 1px solid var(--border-color);
    border-radius: 8px;
    background: var(--panel-bg);
    box-shadow: 0 18px 36px rgba(0, 0, 0, 0.32);
    z-index: 1500;
  }
  .accent-color-popover.open {
    display: flex;
    flex-direction: column;
    gap: 4px;
  }
  .accent-color-popover button {
    display: flex;
    align-items: center;
    gap: 8px;
    width: 100%;
    padding: 9px 10px;
    border: 1px solid transparent;
    border-radius: 6px;
    background: transparent;
    color: var(--text-color);
    text-align: left;
    font-size: 13px;
    font-weight: 600;
    cursor: pointer;
  }
  .accent-color-popover button:hover,
  .accent-color-popover button.selected {
    background: var(--accent-soft);
    border-color: var(--accent);
  }
  .public-profile-top-row {
    display: grid;
    grid-template-columns: minmax(0, 3fr) minmax(260px, 1fr);
    gap: 20px;
    align-items: start;
  }
  .public-profile-top-row:not(.has-follow-requests) {
    grid-template-columns: 1fr;
  }
  .public-profile-info-card,
  .public-follow-requests-card {
    min-width: 0;
  }
  .public-follow-requests-card .portfolio-header {
    margin-bottom: 12px;
  }
  .public-profile-hero {
    display: flex;
    align-items: center;
    gap: 24px;
    flex-wrap: wrap;
  }
  .public-profile-avatar {
    width: 112px;
    height: 112px;
    border-radius: 50%;
    object-fit: cover;
    border: 2px solid var(--border-color);
    flex: 0 0 112px;
  }
  .public-profile-main {
    flex: 1;
    min-width: 240px;
  }
  .public-profile-main h2 {
    margin: 0 0 4px;
    font-size: 26px;
  }
  .public-profile-username {
    color: var(--muted-color);
    font-family: var(--mono-font);
    font-size: 13px;
  }
  .public-profile-bio {
    margin: 14px 0 0;
    color: var(--text-color);
    line-height: 1.55;
  }
  .public-profile-meta {
    display: flex;
    gap: 14px;
    flex-wrap: wrap;
    margin-top: 14px;
    color: var(--muted-color);
    font-size: 13px;
  }
  .public-profile-stats {
    display: flex;
    gap: 18px;
    margin-top: 16px;
    flex-wrap: wrap;
  }
  .public-profile-stat {
    font-family: var(--mono-font);
    color: var(--muted-color);
    font-size: 12px;
  }
  .public-profile-stat strong {
    color: var(--text-color);
    font-size: 16px;
    margin-right: 4px;
  }
  .public-profile-actions {
    display: flex;
    gap: 10px;
    flex-wrap: wrap;
    margin-top: 18px;
    position: relative;
  }
  .public-profile-stat {
    cursor: pointer;
  }
  .public-profile-stat:hover strong {
    color: var(--accent-blue);
  }
  .profile-actions-menu {
    display: none;
    position: absolute;
    top: calc(100% + 6px);
    left: 0;
    min-width: 160px;
    padding: 8px;
    border: 1px solid var(--border-color);
    border-radius: 8px;
    background: var(--panel-bg);
    box-shadow: 0 12px 28px rgba(0,0,0,0.28);
    z-index: 25;
  }
  .profile-actions-menu.open {
    display: block;
  }
  .profile-actions-menu button {
    width: 100%;
    border: 0;
    background: transparent;
    color: var(--text-color);
    text-align: left;
    padding: 10px 12px;
    border-radius: 6px;
    cursor: pointer;
    font-size: 13px;
  }
  .profile-actions-menu button:hover {
    background: var(--panel2-bg);
  }
  .public-profile-badge {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    width: fit-content;
    border: 1px solid var(--border-color);
    border-radius: 999px;
    padding: 6px 10px;
    color: var(--muted-color);
    font-size: 12px;
    margin-top: 14px;
  }
  .public-portfolio-title-row {
    display: flex;
    align-items: center;
    gap: 10px;
    flex-wrap: wrap;
  }
  .public-portfolio-title-row .public-profile-badge {
    margin-top: 0;
  }
  .public-portfolio-visibility {
    color: var(--text-color);
    background: var(--panel2-bg);
  }
  .public-portfolio-visibility.is-private {
    color: var(--muted-color);
  }
  .public-portfolio-visibility svg {
    width: 13px;
    height: 13px;
    fill: currentColor;
  }
  .public-portfolio-value-group {
    flex-wrap: wrap;
  }
  .public-portfolio-chart-container {
    min-height: clamp(260px, 36vh, 430px);
  }
  .public-portfolio-sub-actions {
    justify-content: space-between;
  }
  .public-profile-empty {
    color: var(--muted-color);
    text-align: center;
    padding: 28px;
  }
  @media (max-width: 960px) {
    .public-profile-top-row,
    .public-profile-top-row:not(.has-follow-requests) {
      grid-template-columns: 1fr;
    }
  }
  .follow-request-list {
    display: flex;
    flex-direction: column;
    gap: 12px;
  }
  .follow-request-item {
    display: flex;
    align-items: center;
    justify-content: space-between;
    flex-wrap: wrap;
    gap: 14px;
    padding: 12px;
    border: 1px solid var(--border-color);
    border-radius: 8px;
    background: var(--panel2-bg);
  }
  .follow-request-user {
    display: flex;
    align-items: center;
    gap: 12px;
    flex: 1;
    min-width: 0;
  }
  .follow-request-user img {
    width: 44px;
    height: 44px;
    border-radius: 50%;
    object-fit: cover;
    border: 1px solid var(--border-color);
    flex: 0 0 44px;
  }
  .follow-request-user strong,
  .follow-request-user span {
    display: block;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
  }
  .follow-request-user span {
    color: var(--muted-color);
    font-family: var(--mono-font);
    font-size: 12px;
  }
  .follow-request-actions {
    display: flex;
    gap: 8px;
    flex-wrap: wrap;
    justify-content: flex-end;
  }
  .social-list {
    display: flex;
    flex-direction: column;
    gap: 10px;
    max-height: 60vh;
    overflow-y: auto;
  }
  .social-list-item {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 12px;
    padding: 10px;
    border: 1px solid var(--border-color);
    border-radius: 8px;
    background: var(--panel2-bg);
  }
  .social-list-user {
    display: flex;
    align-items: center;
    gap: 10px;
    min-width: 0;
    flex: 1;
    cursor: pointer;
    padding: 6px;
    border-radius: 8px;
    transition: background-color 0.15s ease;
  }
  .social-list-user:hover {
    background: var(--accent-blue-soft);
  }
  .social-list-user img {
    width: 42px;
    height: 42px;
    border-radius: 50%;
    object-fit: cover;
    border: 1px solid var(--border-color);
    flex: 0 0 42px;
  }
  .social-list-user strong,
  .social-list-user span {
    display: block;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
  }
  .social-list-user span {
    color: var(--muted-color);
    font-size: 12px;
  }
  .social-list-actions {
    display: flex;
    gap: 8px;
    flex-wrap: wrap;
    justify-content: flex-end;
  }
  .social-list-actions .btn-compact {
    min-width: 96px;
  }
  .btn-compact {
    width: auto;
    min-width: 86px;
    padding: 8px 12px;
    font-size: 12px;
  }
  .nav-settings-wrapper {
    position: relative;
  }
  .settings-menu {
    display: none;
    position: absolute;
    left: 0;
    bottom: calc(100% + 8px);
    min-width: 190px;
    padding: 8px;
    border: 1px solid var(--border-color);
    border-radius: 8px;
    background: var(--panel-bg);
    box-shadow: 0 12px 28px rgba(0,0,0,0.28);
    z-index: 20;
  }
  .settings-menu.open {
    display: block;
  }
  .settings-menu button {
    width: 100%;
    border: 0;
    background: transparent;
    color: var(--text-color);
    text-align: left;
    padding: 10px 12px;
    border-radius: 6px;
    cursor: pointer;
    font-size: 13px;
  }
  .settings-menu button:hover {
    background: var(--panel2-bg);
  }
  .avatar-upload-section {
    display: flex;
    align-items: center;
    gap: 20px;
    margin-bottom: 24px;
    padding-bottom: 20px;
    border-bottom: 1px solid var(--border-color);
  }
  .settings-avatar-container {
    position: relative;
    width: 80px;
    height: 80px;
  }
  .settings-avatar-container img {
    width: 80px;
    height: 80px;
    border-radius: 50%;
    object-fit: cover;
    border: 2px solid var(--border-color);
  }
  .avatar-upload-label {
    position: absolute;
    bottom: 0;
    right: 0;
    width: 28px;
    height: 28px;
    background-color: var(--accent-green);
    border-radius: 50%;
    display: flex;
    align-items: center;
    justify-content: center;
    cursor: pointer;
    box-shadow: 0 2px 4px rgba(0,0,0,0.3);
    transition: transform 0.2s;
  }
  .avatar-upload-label:hover {
    transform: scale(1.1);
  }
  .avatar-upload-label svg {
    width: 14px;
    height: 14px;
  }
  .avatar-upload-info {
    display: flex;
    flex-direction: column;
    gap: 4px;
  }
  .avatar-upload-title {
    font-size: 14px;
    font-weight: 600;
    color: var(--text-color);
  }
  .avatar-upload-subtitle {
    font-size: 11px;
    color: var(--muted-color);
  }
  .profile-indicator-avatar-container {
    width: 40px;
    height: 40px;
    border-radius: 50%;
    overflow: hidden;
    border: 2px solid var(--border-color);
    flex-shrink: 0;
  }
  .sidebar-avatar {
    width: 100%;
    height: 100%;
    object-fit: cover;
  }

  /* ── Bandeja de valores sin identificar ─────────────────────────────────
     Cada símbolo es una tarjeta, no una fila de tabla: lleva dentro una lista
     de candidatos y cuatro acciones, y eso no cabe en una celda. */
  .nav-badge {
    margin-left: auto;
    min-width: 20px;
    padding: 2px 6px;
    border-radius: 10px;
    background-color: var(--neg-color);
    color: #fff;
    font-size: 11px;
    font-weight: 600;
    text-align: center;
  }
  .unresolved-card {
    border: 1px solid var(--border-color);
    border-radius: 10px;
    padding: 18px;
    margin-bottom: 14px;
    background-color: var(--panel2-bg);
  }
  .unresolved-head {
    display: flex;
    justify-content: space-between;
    align-items: baseline;
    gap: 12px;
    flex-wrap: wrap;
    margin-bottom: 4px;
  }
  .unresolved-symbol {
    font-family: var(--mono-font);
    font-size: 15px;
    font-weight: 600;
    color: var(--text-color);
  }
  .unresolved-meta {
    font-size: 12.5px;
    color: var(--muted-color);
  }
  .unresolved-impact {
    font-size: 12.5px;
    color: var(--neg-color);
    white-space: nowrap;
  }
  .unresolved-candidates {
    display: flex;
    flex-direction: column;
    gap: 8px;
    margin: 14px 0 4px;
  }
  .candidate-row {
    display: flex;
    justify-content: space-between;
    align-items: center;
    gap: 12px;
    flex-wrap: wrap;
    padding: 10px 12px;
    border: 1px solid var(--border-color);
    border-radius: 8px;
    background-color: var(--panel-bg);
  }
  .candidate-name {
    font-size: 13px;
    color: var(--text-color);
  }
  .candidate-detail {
    font-family: var(--mono-font);
    font-size: 11.5px;
    color: var(--muted-color);
  }
  .unresolved-actions {
    display: flex;
    gap: 8px;
    flex-wrap: wrap;
    align-items: center;
    margin-top: 14px;
    padding-top: 14px;
    border-top: 1px solid var(--border-color);
  }
  .unresolved-actions input {
    font-family: var(--mono-font);
    text-transform: uppercase;
    padding: 8px 10px;
    border-radius: 8px;
    border: 1px solid var(--border-color);
    background-color: var(--panel-bg);
    color: var(--text-color);
    font-size: 12.5px;
    width: 160px;
  }
  .btn-unresolved {
    padding: 8px 12px;
    border-radius: 8px;
    border: 1px solid var(--border-color);
    background-color: var(--panel-bg);
    color: var(--text-color);
    font-size: 12.5px;
    font-weight: 500;
    cursor: pointer;
    transition: all 0.2s;
  }
  .btn-unresolved:hover:not(:disabled) {
    border-color: var(--accent-blue);
  }
  .btn-unresolved:disabled {
    opacity: 0.5;
    cursor: default;
  }
  .btn-unresolved.primary {
    background-color: var(--accent-green);
    border-color: var(--accent-green);
    color: var(--accent-contrast);
  }
  .btn-unresolved.ghost {
    color: var(--muted-color);
  }
  .unresolved-note {
    margin-top: 10px;
    font-size: 12px;
    color: var(--muted-color);
  }
  .unresolved-note.error { color: var(--neg-color); }
  .unresolved-note.ok { color: var(--pos-color); }
