/* ==========================================================================
   NewsBox — design tokens
   Direction A · graphite + cyan-teal
   --------------------------------------------------------------------------
   Load this BEFORE any other stylesheet. Nothing below this file should
   contain a raw hex value, a raw px font-size, or a raw px radius.

   Scale values were derived from the measured computed-CSS inventory across
   57 pages of the running app — they are the values you already use most,
   not invented ones. Everything else collapses into the nearest token.

   Chart colors live in js/newsbox-charts.js and are mirrored here as
   --viz-* so HTML marks (progress bars, stance strips, legends) match the
   canvas-rendered charts exactly.
   ========================================================================== */

:root {
  color-scheme: light;

  /* ---------------------------------------------------------------- type */
  --font-sans: Inter, -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif;
  --font-mono: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
  --font-icon: "Material Symbols Outlined";

  /* 6 sizes. Your measured distribution: 14px was 5286 uses — that is the base. */
  --fs-xs:    11px;   /* table headers, badges, meta, nav group labels        */
  --fs-sm:    12px;   /* secondary text, dense table cells                    */
  --fs-base:  14px;   /* body — the default for everything unless stated      */
  --fs-lg:    16px;   /* card titles, section headings                        */
  --fs-xl:    20px;   /* subsection headings                                  */
  --fs-2xl:   32px;   /* page titles                                          */

  /* Ratios, not px. This alone collapses 26 measured line-heights into 3. */
  --lh-tight: 1.25;
  --lh-base:  1.5;
  --lh-loose: 1.7;

  --fw-regular: 400;
  --fw-medium:  500;
  --fw-bold:    700;
  /* NOTE: 600 is deliberately absent. You had 500, 600 and 700 all in play;
     600 and 700 were doing the same job. Map every 600 to --fw-bold. */

  --ls-caps:   0.06em;  /* the ONLY letter-spacing. Replaces 13 measured values. */
  --ls-tight: -0.02em;  /* large display text only (--fs-2xl)                    */

  /* -------------------------------------------------------------- brand */
  /* One hue, four steps. Used for: primary buttons, active nav, focus,
     links. NOT for status — see semantic below. That separation is the fix
     for "CON FALLAS" currently rendering in the same green as "SALUDABLES". */
  --brand-900: #08424d;
  --brand-800: #0a5763;
  --brand-700: #0e8a9c;   /* primary */
  --brand-600: #22a2b7;   /* hover   */
  --brand-200: #a9dde5;
  --brand-100: #d6eff3;
  --brand-050: #eef7f9;

  /* ----------------------------------------------------------- semantic */
  /* Reserved. Never reuse these as a chart series or a decorative accent. */
  --ok-700:    #0d7a44;
  --ok-100:    #d9f2e4;
  --warn-700:  #8f5408;
  --warn-100:  #fdf0d5;
  --error-700: #b3261e;
  --error-100: #fbe0dd;
  --info-700:  #4a5a60;
  --info-100:  #e7edee;

  /* ----------------------------------------------------------- neutrals */
  --ink-900:   #10171a;   /* primary text                                  */
  --ink-700:   #3b474c;   /* secondary text                                */
  --ink-500:   #6b797f;   /* muted text, placeholders, table headers       */
  --ink-300:   #a4b0b4;   /* disabled                                      */
  --line:      #dbe3e5;   /* borders, dividers                             */
  --line-soft: #e7edee;   /* table row separators                          */
  --surface:   #ffffff;   /* cards, tables, menus                          */
  --surface-2: #eef3f4;   /* table headers, subtle fills                   */
  --canvas:    #f6f8f8;   /* page background                               */

  /* Sidebar is its own dark surface even in light mode — that contrast is
     what separates chrome from content and lets the data carry the color. */
  --nav-bg:        #101619;
  --nav-fg:        #c3ced2;
  --nav-fg-muted:  #7d8a8f;
  --nav-active-bg: var(--brand-700);
  --nav-active-fg: #ffffff;
  --nav-hover-bg:  #1a2327;

  /* ------------------------------------------------------------- radius */
  --r-sm:   6px;    /* inputs, buttons, small controls                     */
  --r-md:  12px;    /* cards, tables, modals                              */
  --r-full: 9999px; /* badges and avatars ONLY — never buttons.           */
  /* Your app currently mixes 9999px pills with 12px cards. Pills read
     consumer; boxy cards read tool. Pick one language: buttons get --r-sm. */

  /* ---------------------------------------------------------- elevation */
  --sh-1: 0 1px 2px rgba(16, 23, 26, .05);
  --sh-2: 0 4px 20px rgba(16, 23, 26, .06);
  --sh-3: 0 8px 30px rgba(16, 23, 26, .10);

  /* ------------------------------------------------------------ spacing */
  --s-1:  4px;
  --s-2:  8px;
  --s-3: 12px;
  --s-4: 16px;
  --s-5: 20px;
  --s-6: 24px;
  --s-8: 32px;
  --s-12: 48px;

  /* --------------------------------------------------------------- misc */
  --focus-ring: 0 0 0 3px var(--brand-200);
  --dur-fast: 120ms;
  --dur-base: 200ms;
  --ease: cubic-bezier(.2, 0, .2, 1);

  /* ------------------------------------------------- viz (see charts.js) */
  /* Categorical — fixed order, assigned in sequence, NEVER cycled.
     A 9th series folds into "Otros" or becomes small multiples. */
  --viz-cat-1: #0e9cb0;
  --viz-cat-2: #eb6834;
  --viz-cat-3: #4a3aa7;
  --viz-cat-4: #eda100;
  --viz-cat-5: #e87ba4;
  --viz-cat-6: #008300;
  --viz-cat-7: #2a78d6;
  --viz-cat-8: #e34948;

  /* Sequential — magnitude, volumes, dates. One hue, light → dark. */
  --viz-seq-1: #45b8cc;
  --viz-seq-2: #22a2b7;
  --viz-seq-3: #0e8a9c;
  --viz-seq-4: #0a7181;
  --viz-seq-5: #095763;
  --viz-seq-6: #083f48;

  /* Diverging — stance/sentiment. Two poles through a NEUTRAL GREY middle.
     Replaces the current 5 arbitrary hues where `neutral` was orange. */
  --viz-div-neg-2: #8f5408;   /* muy en contra */
  --viz-div-neg-1: #d18a24;   /* en contra     */
  --viz-div-mid:   #9aa4a8;   /* neutral       */
  --viz-div-pos-1: #22a2b7;   /* a favor       */
  --viz-div-pos-2: #0a7181;   /* muy a favor   */

  /* Outside the stance scale — these are not polarity values. */
  --viz-informativo: #4a3aa7;
  --viz-mixto:       #e87ba4;
  --viz-sin-datos:   #b8c2c5;   /* "sin clasificar" — NEUTRAL, never red.  */

  --viz-surface: var(--surface);
  --viz-grid:    #e7edee;
  --viz-axis:    var(--ink-500);
}

/* ============================================================ dark mode ==
   Selected, not flipped. These are their own steps validated against the
   dark surface — an automatic inversion fails the contrast checks.
   ======================================================================== */
/* Two scopes, same values. The media query covers the OS setting; the
   data-theme scope covers an in-app toggle. The :not() guard lets an
   explicit light stamp beat OS-dark; :where() keeps specificity at 0 so
   the toggle scope below always wins. */
@media (prefers-color-scheme: dark) {
  :root:where(:not([data-theme="light"])) {
    color-scheme: dark;

    --ink-900: #e6edef;
    --ink-700: #b3c0c4;
    --ink-500: #8b989d;
    --ink-300: #5c686d;
    --line:      #253034;
    --line-soft: #1c2427;
    --surface:   #12171a;
    --surface-2: #1a2226;
    --canvas:    #0d1214;

    --nav-bg:       #090d0f;
    --nav-fg:       #8b989d;
    --nav-hover-bg: #151d21;

    --brand-700: #22a2b7;
    --brand-600: #45b8cc;
    /* brand-800 had no dark step, so --primary-container and
       --on-secondary-container stayed a deep teal on a near-black surface:
       2.20:1, effectively invisible. Lifted above the same 4.5 bar the rest
       of the scale clears (5.07:1 on --surface). */
    --brand-800: #1795a8;
    --brand-100: #0f3d47;
    --brand-050: #0c2f37;

    --ok-700:    #3fae72;  --ok-100:    #103523;
    --warn-700:  #dc9c35;  --warn-100:  #3a2a0c;
    --error-700: #f2938a;  --error-100: #3d1a17;
    --info-700:  #9aa8ad;  --info-100:  #1d2528;

    --sh-1: 0 1px 2px rgba(0,0,0,.4);
    --sh-2: 0 4px 20px rgba(0,0,0,.45);
    --sh-3: 0 8px 30px rgba(0,0,0,.55);

    --viz-cat-1: #1aa3b8; --viz-cat-2: #d95926; --viz-cat-3: #9085e9;
    --viz-cat-4: #c98500; --viz-cat-5: #d55181; --viz-cat-6: #008300;
    --viz-cat-7: #3987e5; --viz-cat-8: #e66767;

    --viz-seq-1: #7fd4e2; --viz-seq-2: #4dbdd0; --viz-seq-3: #26a3b8;
    --viz-seq-4: #12889c; --viz-seq-5: #0c6d7e; --viz-seq-6: #0a5460;

    --viz-div-neg-2: #9c610c; --viz-div-neg-1: #dc9c35;
    --viz-div-mid:   #8b989d;
    --viz-div-pos-1: #26a3b8; --viz-div-pos-2: #12889c;

    --viz-informativo: #9085e9;
    --viz-mixto:       #d55181;
    --viz-sin-datos:   #5c686d;
    --viz-grid:        #1f282c;
  }
}

:root[data-theme="dark"] {
  --ink-900: #e6edef; --ink-700: #b3c0c4; --ink-500: #8b989d; --ink-300: #5c686d;
  --line: #253034; --line-soft: #1c2427;
  --surface: #12171a; --surface-2: #1a2226; --canvas: #0d1214;
  --nav-bg: #090d0f; --nav-fg: #8b989d; --nav-hover-bg: #151d21;
  --brand-700: #22a2b7; --brand-600: #45b8cc; --brand-100: #0f3d47; --brand-050: #0c2f37;
  --ok-700: #3fae72; --ok-100: #103523;
  --warn-700: #dc9c35; --warn-100: #3a2a0c;
  --error-700: #f2938a; --error-100: #3d1a17;
  --info-700: #9aa8ad; --info-100: #1d2528;
  --sh-1: 0 1px 2px rgba(0,0,0,.4);
  --sh-2: 0 4px 20px rgba(0,0,0,.45);
  --sh-3: 0 8px 30px rgba(0,0,0,.55);
  --viz-cat-1: #1aa3b8; --viz-cat-2: #d95926; --viz-cat-3: #9085e9;
  --viz-cat-4: #c98500; --viz-cat-5: #d55181; --viz-cat-6: #008300;
  --viz-cat-7: #3987e5; --viz-cat-8: #e66767;
  --viz-seq-1: #7fd4e2; --viz-seq-2: #4dbdd0; --viz-seq-3: #26a3b8;
  --viz-seq-4: #12889c; --viz-seq-5: #0c6d7e; --viz-seq-6: #0a5460;
  --viz-div-neg-2: #9c610c; --viz-div-neg-1: #dc9c35; --viz-div-mid: #8b989d;
  --viz-div-pos-1: #26a3b8; --viz-div-pos-2: #12889c;
  --viz-informativo: #9085e9; --viz-mixto: #d55181; --viz-sin-datos: #5c686d;
  --viz-grid: #1f282c;
}

/* ======================================================================== */
/* THE RESET THAT MATTERS                                                   */
/* ------------------------------------------------------------------------ */
/* The audit found 435 elements rendering in Arial, plus monospace and bare  */
/* sans-serif, plus fractional font-sizes (13.6px, 18.72px, 13.3333px) that  */
/* nobody chose. Every one of them is an unstyled form control or an element */
/* that escaped styling and fell back to a browser default.                  */
/*                                                                          */
/* These few rules delete that entire class of defect in one commit. Do this */
/* before touching any individual page.                                      */
/* ======================================================================== */

html {
  font-family: var(--font-sans);
  font-size: var(--fs-base);
  line-height: var(--lh-base);
  color: var(--ink-900);
  background: var(--canvas);
  -webkit-font-smoothing: antialiased;
}

input, select, textarea, button, optgroup {
  font: inherit;              /* ← kills Arial, monospace, and the fractional sizes */
  color: inherit;
  letter-spacing: inherit;
}

/* Native selects are the single strongest "unfinished" signal in the app.
   This makes every <select> match your custom inputs with no markup change. */
select {
  appearance: none;
  -webkit-appearance: none;
  background-color: var(--surface);
  background-image: url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='8' viewBox='0 0 12 8'%3E%3Cpath d='M1 1.5 6 6.5l5-5' fill='none' stroke='%236b797f' stroke-width='1.75' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E");
  background-repeat: no-repeat;
  background-position: right var(--s-3) center;
  border: 1px solid var(--line);
  border-radius: var(--r-sm);
  padding: var(--s-2) var(--s-8) var(--s-2) var(--s-3);
  min-width: 12ch;            /* ← fixes "Todos los estado" truncating mid-word */
  width: auto;
}

input[type="text"], input[type="search"], input[type="email"],
input[type="date"], input[type="number"], textarea {
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: var(--r-sm);
  padding: var(--s-2) var(--s-3);
}

:is(input, select, textarea, button, a):focus-visible {
  outline: 2px solid var(--brand-700);
  outline-offset: 1px;
  box-shadow: var(--focus-ring);
}

::placeholder { color: var(--ink-500); opacity: 1; }

/* ======================================================================== */
/* PRIMITIVES                                                               */
/* ======================================================================== */

/* --- buttons: three variants, ONE size scale, radius --r-sm (not pills) --- */
.btn {
  display: inline-flex; align-items: center; gap: var(--s-2);
  font-size: var(--fs-base); font-weight: var(--fw-medium);
  padding: var(--s-2) var(--s-4);
  border-radius: var(--r-sm);
  border: 1px solid transparent;
  cursor: pointer;
  transition: background var(--dur-fast) var(--ease), border-color var(--dur-fast) var(--ease);
}
.btn--primary   { background: var(--brand-700); color: #fff; }
.btn--primary:hover { background: var(--brand-600); }
.btn--secondary { background: var(--surface); color: var(--ink-700); border-color: var(--line); }
.btn--secondary:hover { background: var(--surface-2); }
.btn--ghost     { background: transparent; color: var(--ink-700); }
.btn--ghost:hover { background: var(--surface-2); }
.btn--sm { font-size: var(--fs-sm); padding: var(--s-1) var(--s-3); }

/* There is no .btn--danger. Destructive actions live inside a kebab menu or
   a confirm dialog — never as a coloured button in a table row or a toolbar.
   The audit found ~23 red delete outlines stacked down one page. */
.menu__item--danger { color: var(--error-700); }

/* --- status badge: ONE component, replaces 3 different treatments -------- */
.badge {
  display: inline-flex; align-items: center; gap: var(--s-1);
  font-size: var(--fs-xs); font-weight: var(--fw-bold);
  letter-spacing: var(--ls-caps); text-transform: uppercase;
  padding: 2px var(--s-2);
  border-radius: var(--r-full);
}
.badge--ok    { background: var(--ok-100);    color: var(--ok-700); }
.badge--warn  { background: var(--warn-100);  color: var(--warn-700); }
.badge--error { background: var(--error-100); color: var(--error-700); }
.badge--info  { background: var(--info-100);  color: var(--info-700); }
/* Status colour must never be the brand colour. "Con fallas" is --badge--error,
   never the mint green it renders in today. Always ship an icon or the word —
   colour alone is not an accessible signal. */

/* --- page header: ONE shell, replaces 3 different page layouts ---------- */
.page-header { display: flex; align-items: flex-start; justify-content: space-between;
               gap: var(--s-4); margin-bottom: var(--s-6); }
.page-header__title { font-size: var(--fs-2xl); font-weight: var(--fw-bold);
                      letter-spacing: var(--ls-tight); margin: 0; }
.page-header__subtitle { font-size: var(--fs-base); color: var(--ink-500); margin: var(--s-1) 0 0; }
.page-header__actions { display: flex; gap: var(--s-2); flex-shrink: 0; }

/* Filters belong attached to what they filter, not floating in whitespace. */
.toolbar { display: flex; align-items: center; gap: var(--s-3); flex-wrap: wrap;
           padding: var(--s-3) var(--s-4);
           background: var(--surface); border: 1px solid var(--line);
           border-radius: var(--r-md) var(--r-md) 0 0; border-bottom: 0; }
.toolbar + .table-wrap { border-radius: 0 0 var(--r-md) var(--r-md); }

/* --- tabs: for navigating between views of ONE record ------------------- */
/* This is what replaces four of the nine buttons on the KoI detail page.
   Resultados / Datos / Análisis / Lotes are routes, not actions. */
.tabs { display: flex; gap: var(--s-1); border-bottom: 1px solid var(--line);
        margin-bottom: var(--s-5); }
.tabs__item { padding: var(--s-3) var(--s-4); font-size: var(--fs-base);
              font-weight: var(--fw-medium); color: var(--ink-500);
              border-bottom: 2px solid transparent; margin-bottom: -1px; }
.tabs__item:hover { color: var(--ink-700); }
.tabs__item--active { color: var(--brand-700); border-bottom-color: var(--brand-700); }

/* --- table ------------------------------------------------------------- */
.table-wrap { background: var(--surface); border: 1px solid var(--line);
              border-radius: var(--r-md); overflow: hidden; }
table { width: 100%; border-collapse: collapse; }
th { font-size: var(--fs-xs); font-weight: var(--fw-bold);
     letter-spacing: var(--ls-caps); text-transform: uppercase;
     color: var(--ink-500); text-align: left;
     padding: var(--s-3) var(--s-4); background: var(--surface-2); }
td { padding: var(--s-3) var(--s-4); font-size: var(--fs-base);
     border-top: 1px solid var(--line-soft); }
tbody tr:hover { background: var(--surface-2); }

/* --- card -------------------------------------------------------------- */
.card { background: var(--surface); border: 1px solid var(--line);
        border-radius: var(--r-md); padding: var(--s-5); box-shadow: var(--sh-1); }

/* --- stat tile --------------------------------------------------------- */
/* No category badge. The audit found the badge repeated the title in 8 of 8
   cases ("Cuentas de Interés" + a badge reading "CUENTAS"). If the badge
   can't carry a delta or a timeframe the title lacks, delete it. */
.stat { background: var(--surface); border: 1px solid var(--line);
        border-radius: var(--r-md); padding: var(--s-4); }
.stat__label { font-size: var(--fs-xs); letter-spacing: var(--ls-caps);
               text-transform: uppercase; color: var(--ink-500); }
.stat__value { font-size: var(--fs-2xl); font-weight: var(--fw-bold);
               letter-spacing: var(--ls-tight); margin-top: var(--s-1); }
.stat__meta  { font-size: var(--fs-sm); color: var(--ink-500); margin-top: var(--s-1); }
.stat-grid { display: grid; gap: var(--s-3);
             grid-template-columns: repeat(auto-fill, minmax(200px, 1fr)); }
/* auto-fill with a fixed minimum keeps card widths equal across rows —
   the dashboard currently has 5 narrow cards over 3 wide ones. */

/* --- empty state ------------------------------------------------------- */
.empty { text-align: center; padding: var(--s-12) var(--s-5); color: var(--ink-500); }
.empty__title { font-size: var(--fs-lg); color: var(--ink-700); margin: 0 0 var(--s-1); }
/* Copy rule: describe the user's world, not the system's.
   "No hay claves API almacenadas en la base de datos" → "Aún no hay claves API." */
