/* css/main/design-tokens.css — part 1/30 of the app styles (was css/main.css; loaded in this order by index.html). */
      /* ==================================================================
         ⛔ TOKENS COMUNES · GENERADO by scripts/tokens-build.py — DO NOT EDIT BY HAND.
         Source: scripts/design-tokens.json · Guard: scripts/tokens-check.py
      
         These values are IDENTICAL in the app and in Score.
         If one of them needs another value, it is NOT changed here: it is
         defined afterwards, in the product's own :root, with the reason beside it.
         ================================================================== */
      :root {
        /* Page background */
        --bg: #0d0d0d;
        /* Dimmed text
           ⛔ In DARK it has the same value as --text, and it is not an oversight: it is halation.
           Light text on a dark background bleeds outwards and mid grey is the worst case. In
           LIGHT it is grey, because there is no halation there and it measures 12:1. See
           UX-UI-normas.md §2.
           ⚠️ A token that exists in one theme and not in the other gives NO error: it inherits
           the other theme's value. It happened to this very one on 2026-08-19 and its 11 uses
           were invisible.
         */
        --text-dim: #f0ede8;
        /* Brand gold
           --accent-fg is the colour of TEXT on a gold background, not a shade of gold.
           ⚠️ Measured on 2026-08-20: white on the light gold gave 4.80:1 (#8a6f1f), not the
           ~6.5 this comment claimed; with #846b1e (#107, 2026-09-19) it measures 5.12:1.
           Any lightening of the gold in the light theme brings it closer to 4.5. In dark,
           #0d0d0d on #c8a84b measures 8.48:1 and there is plenty of margin.
         */
        --accent-fg:  #0d0d0d;
        --accent-dim: rgba(200, 168, 75, 0.12);
        /* Semantic layers
           Subtle surfaces over the background. In dark they are white at 4-8 %; in light they
           become black at 4-9 % to achieve the same visual effect, not the same value.
         */
        --hover-soft:   rgba(255, 255, 255, 0.04);
        --hover-strong: rgba(255, 255, 255, 0.08);
        --surface-soft: rgba(255, 255, 255, 0.06);
        /* Counter badge (unread)
           The little red circle with the number. The directory introduced it on 2026-08-23 and
           on 2026-08-25 it also moved to the app with the news channel (card #121): from then on
           it applies in two products, and what applies in more than one lives here.
           It is not the error red (#ef4444 in dark): that gives 3.76:1 with white text and does
           not reach the 4.5 required by UX rule 2. These two values are measured in both themes.
         */
        --badge: #dc2626;
        /* Each discipline, its colour
           ⛔ Wherever something is filtered, grouped or labelled by discipline, THESE tokens are
           used, not one gold for everything. Three roles each: -bd the border, -bg the
           translucent background, -fg the text. The colour stripe is also shown when OFF, so the
           association is learnt before touching anything. What is NOT a discipline does not get
           one of these four. Santi's rule, 2026-08-20. See UX-UI-normas.md §8-bis c-bis.
         */
        --cv-type-aire-bd:  #378ADD;
        --cv-type-aire-bg:  rgba(55,138,221,0.16);
        --cv-type-aire-fg:  #6cb6f0;
        --cv-type-fuego-bd: #D85A30;
        --cv-type-fuego-bg: rgba(216,90,48,0.16);
        --cv-type-fuego-fg: #f0997b;
        --cv-type-aahh-bd:  #BA7517;
        --cv-type-aahh-bg:  rgba(186,117,23,0.18);
        --cv-type-aahh-fg:  #efb968;
        --cv-type-plato-bd: #639922;
        --cv-type-plato-bg: rgba(99,153,34,0.16);
        --cv-type-plato-fg: #97c459;
        /* Each entity type, its colour
           ⛔ The second family of the same system, used the same way: wherever something is
           listed, filtered or labelled by entity type, THESE tokens are used. Same three roles
           as the disciplines: -bd the stripe, -bg the translucent background, -fg the text.
           Santi's rule, 2026-08-27. See UX-UI-normas.md §8-bis c-ter.
           
           WHY THESE THREE HUES AND NOT OTHERS: the wheel was already taken — blue (air), orange
           (fire), amber (historic arms), green (clay), gold (brand) and red (unread badge).
           Violet, raspberry and teal are the arc that was left free, so none of the three can be
           confused with a discipline, which is exactly the mistake that would make marking the
           type useless.
           
           ⚠️ MEASURED, not picked by eye (2026-08-27), on the real background they are painted
           on: the text gives between 6.2 and 8.3 on its own chip in both themes, and the stripe
           between 4.3 and 7.7 on the card. The same band as the four discipline ones, which were
           already accepted. The minimum of rule §2 is 4.5 for text and 3 for a graphic element.
         */
        --tl-ent-club-bd:  #8B6FD8;
        --tl-ent-club-bg:  rgba(139,111,216,0.18);
        --tl-ent-club-fg:  #bda6f2;
        --tl-ent-fed-bd:   #D4589B;
        --tl-ent-fed-bg:   rgba(212,88,155,0.18);
        --tl-ent-fed-fg:   #f0a4c9;
        --tl-ent-campo-bd: #2DA39B;
        --tl-ent-campo-bg: rgba(45,163,155,0.18);
        --tl-ent-campo-fg: #6ed2ca;
        /* Simulated competition
           The mark of SIMULATED COMPETITIONS (plan-competiciones-prueba.md, S6 and S7): Santi
           asked for them to be told apart «with absolute clarity», with a colour that stands out.
           
           ⛔ THE WHEEL WAS ALREADY FULL — disciplines, brand, red and the three entity types —,
           so COLOUR IS NOT THE MAIN SIGNAL. The signal is the DIAGONAL STRIPED BAND
           (`--sim-stripe` over `--sim-bg`), which nothing else in TiroLog uses and which reads as
           «this is not real» without knowing the colour code; with icon and text on top, as rule
           §2 requires (never colour as the only indicator). The hue is a cobalt between the air
           blue and the club violet, chosen to match neither.
           
           ⚠️ The contrast of the text over the band is measured in both themes before accepting
           it (minimum 4.5).
         */
        --sim-bd:     #7C8CFF;
        --sim-bg:     rgba(124,140,255,0.14);
        --sim-stripe: rgba(124,140,255,0.10);
        --sim-fg:     #b3bcff;
      }
      :root[data-theme="light"] {
        /* Page background */
        --bg: #f5f3ee;
        /* Dimmed text */
        --text-dim: #3a3631;
        /* Brand gold */
        --accent-fg:  #ffffff;
        --accent-dim: rgba(138, 111, 31, 0.14);
        /* Semantic layers */
        --hover-soft:   rgba(0, 0, 0, 0.05);
        --hover-strong: rgba(0, 0, 0, 0.09);
        --surface-soft: rgba(0, 0, 0, 0.04);
        /* Counter badge (unread) */
        --badge: #b91c1c;
        /* Each discipline, its colour */
        --cv-type-aire-bd:  #185FA5;
        --cv-type-aire-bg:  rgba(55,138,221,0.12);
        --cv-type-aire-fg:  #0C447C;
        --cv-type-fuego-bd: #993C1D;
        --cv-type-fuego-bg: rgba(216,90,48,0.12);
        --cv-type-fuego-fg: #712B13;
        --cv-type-aahh-bd:  #854F0B;
        --cv-type-aahh-bg:  rgba(186,117,23,0.14);
        --cv-type-aahh-fg:  #633806;
        --cv-type-plato-bd: #3B6D11;
        --cv-type-plato-bg: rgba(99,153,34,0.14);
        --cv-type-plato-fg: #27500A;
        /* Each entity type, its colour */
        --tl-ent-club-bd:  #5B3FA8;
        --tl-ent-club-bg:  rgba(91,63,168,0.14);
        --tl-ent-club-fg:  #472B93;
        --tl-ent-fed-bd:   #9E2E68;
        --tl-ent-fed-bg:   rgba(158,46,104,0.14);
        --tl-ent-fed-fg:   #7E1F52;
        --tl-ent-campo-bd: #0F6E68;
        --tl-ent-campo-bg: rgba(15,110,104,0.14);
        --tl-ent-campo-fg: #0A544F;
        /* Simulated competition */
        --sim-bd:     #2F3AA8;
        --sim-bg:     rgba(47,58,168,0.10);
        --sim-stripe: rgba(47,58,168,0.07);
        --sim-fg:     #232c8c;
      }
      /* ⛔ fin TOKENS COMUNES */

      :root {
        --surface: #1a1a1a;
        --card: #1e1e1e;
        /* ⛔ THE BORDER IS TRANSLUCENT GOLD, and it is the most noticeable change of
           the whole design review (Santi, 2026-08-20). It was `#2e2e2e`, a neutral
           gray, while Score had carried this same value all along — and that
           is the main reason Score looked «more elaborate» and the app
           «flat». Shadows weren't missing: what was missing was the edge of each piece
           saying something.
           ⚠️ `--border` is the OUTER border (cards, fields, buttons). For
           the separators INSIDE —list rows, lines between blocks—
           use `--border-soft`: if everything carries gold, gold stops signaling. */
        --border: rgba(200, 168, 75, 0.18);
        --border-soft: rgba(255, 255, 255, 0.06);
        --accent: #c8a84b;
        --accent-2: #56beb0;
        --accent-2-dim: rgba(86, 190, 176, 0.12);
        /* ── EACH AUTHOR'S COLOR IN THE CHAT ────────────────────────────
           ⛔ SEVEN COLORS AND NOT ONE, and it is what Santi asked for looking at the chat:
           "WhatsApp puts it in a more eye-catching color, it's easier to identify
           who sent the message". With a single color, twenty different names
           read the same and you have to READ them to know whose each
           message is; with one per person, it's recognized without reading.
           ⛔ Color is NOT the only indicator (norm §2): the name is
           written beside it, always. This speeds things up, it doesn't inform.
           ⛔ AND THE SEVEN ARE MEASURED on --bg, --surface and --card in BOTH
           themes, with the same arithmetic as `unit-contraste-tokens.test.js`, which
           also watches them. The teal of `--accent-2` —the one used until
           now— does NOT make it: in light theme it measures 4.15:1, below the minimum.
           ⚠️ Seven and not eight: with a prime number, two consecutive authors of
           the same batch hardly ever fall on the same color. */
        --chat-au1: #7fb3ff;
        --chat-au2: #f0a3c8;
        --chat-au3: #9dd67a;
        --chat-au4: #f2b45c;
        --chat-au5: #c3a6f0;
        --chat-au6: #f59a86;
        --chat-au7: #6fd0d6;
        --text: #f0ede8;
        /* ⛔ IN DARK THERE IS NO GRAY TEXT, and it isn't a preference: it is halation.
           Light text on a dark background bleeds outward and astigmatism
           multiplies it — the letter's edge stops being defined—, and it gets worse
           the closer the text is to mid gray. The old #999 was the
           worst possible case: light enough to glow and not light enough to
           be crisp. It measured 5.85:1, i.e. it MET the 4.5 norm and still
           couldn't be read: WCAG's 4.5:1 is calibrated for 16 px and here there are 302
           rules at 13 px and below.
           ⛔ Hierarchy is NOT made by lowering contrast. It is made with size, with
           weight (600 versus 400) and with HUE —gold and teal, which measure 7.3:1 and
           7.5:1, MORE than the gray they replace—.
           📌 In LIGHT they stay gray on purpose: there is no halation there and they measure
           12:1. The rule isn't «gray is forbidden», it is «secondary text has to
           be legible at its size». See Documentos/UX-UI-normas.md §2. */
        --muted: #f0ede8;
        --text-muted: #f0ede8; /* compat alias — multiple views use var(--text-muted) */
        --surface2: #2a2a2a; /* slightly lighter tone than --surface; used in bars/gauges */
        /* ⛔ RAISED from #c0392b to #ec7063 on 2026-08-22 (ticket #109). The old value
           measured 3.07:1 on --card and 3.57:1 on --bg, against the 4.5 required by
           norm §2 — and its 10 uses as TEXT are nearly all form error messages
           at 12-14 px: the 12 words, naming and authorizing a device,
           the identity transfer, Tiro Rápido's sound test. That is, the
           moment when text is needed MOST.
           ⛔ It also contradicted the policy written twelve lines above: in dark
           contrast is NOT lowered, «hierarchy is NOT made by lowering contrast».
           MEASURED the new value on the four backgrounds where it lives, and the worst rules:
             --card #1e1e1e 5.61:1 · --bg #0d0d0d 6.54:1 · --surface #1a1a1a 5.85:1
             and on its OWN tint —rgba(192,57,43,.12) composited over --card,
             giving #312120— 5.16:1. That last one is what ruled out #e35d4f (4.34:1):
             a red on a red background raises the floor, and there are two such components
             (.settings-banner-danger and .settings-inline-warn).
           ⚠️ It was checked BEFORE raising it that the token is NEVER a background with text
           on top: the app's solid red backgrounds (.swipe-bg, .log-entry.is-comp)
           are LITERAL #c0392b, not this token. As a token it is only text, border and the
           chart legend dot — and that one is read by `_chartCol('--danger')`
           (js/views/evolucion.js:329), so legend and bars stay in sync.
           ⚠️ It sits very close to --alerta (#ff5a4d), and in LIGHT theme both already
           equal #b3271a exactly. Having too many reds is real, but it is taste and Santi
           decides: ticket #107. */
        --danger: #ec7063;
        --success: #27ae60;
        /* WARNING — neither error nor success: «you should take a look at this». There was no
           counterpart for this and the first place that needed it (the
           «unused» badge in Devices) resorted to a fixed hex that in dark was
           brown on black. Measured: 9:1 in dark, 7:1 in light. */
        --warn: #d9a83a;
        --warn-dim: rgba(217, 168, 58, 0.14);
        /* ALERT — a step above `--warn`: «this must be read», not
           «you should look at this». Measured: 5.42:1 in dark and 5.88:1 in light.
           ⚠️ It WAS BORN as a contrast patch —`--danger` was #c0392b and couldn't be
           read—, and that reason NO LONGER EXISTS: since 2026-08-22 `--danger` is
           legible as text in both themes. What remains of `--alerta` is its
           semantic role, sounding louder. In LIGHT theme both equal
           #b3271a, so today they only differ in dark. If it's redundant, it gets
           removed — but it is taste and Santi decides: ticket #107. */
        --alerta: #ff5a4d;
        --alerta-dim: rgba(255, 90, 77, 0.14);

        /* ══ ELEVATION — three planes, and not one more ═════════════════
           ⛔ WHY IT EXISTS (Santi, 2026-08-20): "I don't see shadows anywhere…
           I see everything very flat". And he was right at the root: it wasn't that
           shadows were missing, it's that **there was no system saying when there
           are any**. Everything lived on a single plane —same background, same 1 px border,
           same corner—, so a card, a notice and a field looked
           equally important and the eye didn't know where to look.

           THE THREE PLANES, and each component lives on ONE:
             0 · the page background. No shadow. Sections and inline
                 notices live here: they don't float, they belong to the text.
             1 · what rests on top: cards, rows, primary button.
             2 · what truly floats: dialogs, sheets, menus.

           ⛔ AND IN DARK THE SHADOW IS BARELY VISIBLE. On #0d0d0d a black
           shadow separates nothing, so here depth is given by the TONE —the
           `--bg` → `--card` step that already existed— and the shadow only rounds off
           the effect. That is why the values of the two themes are not the same with
           another opacity: they are different things.

           ⚠️ Subtle on purpose. The rule he himself quoted —"don't
           overdo it, make them very subtle"— is the right one: as soon as a
           shadow reads as a shadow, the interface looks like a toy. */
        --elev-1: 0 1px 2px rgba(0, 0, 0, 0.45);
        --elev-2: 0 6px 18px rgba(0, 0, 0, 0.55);
        --elev-3: 0 -6px 28px rgba(0, 0, 0, 0.6);
        --shadow-modal: 0 12px 28px rgba(0, 0, 0, 0.55);
        /* Semantic filters of the History (precision/plato/train/comp) */
        --filter-prec-fg: #e0e0e0;
        --filter-prec-bg: rgba(224, 224, 224, 0.12);
        --filter-train-bg: rgba(39, 174, 96, 0.18);
        --filter-comp-bg: rgba(192, 57, 43, 0.18);
        /* Payment status banners in CV (pending / authorized / issue) */
        --banner-pay-bg: #2a0a0a;
        --banner-pay-bd: #e57373;
        --banner-pay-fg: #fca5a5;
        --banner-cta-fg: #1a0a0a;
        --banner-auth-bg: #2a1c00;
        --banner-auth-bd: #d4a017;
        --banner-auth-fg: #fcd34d;
        --banner-issue-bg: #3a0505;
        --banner-issue-bd: #ef4444;
        --banner-issue-fg: #fecaca;
        /* Badges of the CV listing */
        --cv-badge-paid-bg: #1f4d2b;
        --cv-badge-paid-fg: #86efac;
        --cv-badge-fin-bg: #7f1d1d;
        --cv-badge-fin-fg: #fca5a5;
        --cv-badge-arb-bg: rgba(127, 119, 221, 0.18);
        --cv-badge-arb-fg: #b3a9f0;
        --cv-badge-esp-bg: rgba(255, 255, 255, 0.08);
        --cv-badge-esp-fg: #aaa;
        /* Charts (canvas: axes and grids) */
        --chart-grid: #2a2a2a;
        --chart-text: #888;
        /* Help chat — user / bot (AI) bubbles */
        --chat-user-bg: #2a5f3f;
        --chat-user-fg: #f0ede8;
        --chat-leido: #9ad9ff;   /* ✓✓ de un privado, sobre --chat-user-bg */
        --chat-bot-bg: #1d1d1d;
        --chat-bot-fg: #e8e6e0;
      }
      :root[data-theme="light"] {
        --surface: #ffffff;
        --card: #ffffff;
        /* The same border gold, in its light-theme version (see dark). */
        --border: rgba(138, 111, 31, 0.28);
        --border-soft: rgba(0, 0, 0, 0.08);
        --accent: #846b1e;
        --accent-2: #2a7a6f;
        --accent-2-dim: rgba(42, 122, 111, 0.12);
        /* The seven chat ones in light: the same hues, darkened until
           passing 4.5:1 on white (see the dark palette's note). */
        --chat-au1: #1f5fb0;
        --chat-au2: #a3316c;
        --chat-au3: #3f7a1f;
        --chat-au4: #8a5a12;
        --chat-au5: #6b3fb5;
        --chat-au6: #a53f24;
        --chat-au7: #12706f;
        --text: #1a1a1a;
        --muted: #3a3631;
        --text-muted: #3a3631;
        --surface2: #ebe7dd;
        /* In light the shadow DOES do the work: two layers, a short tight one
           that draws the edge, and a long very faint one that gives the air. A
           single big shadow reads as a gray smudge. */
        --elev-1: 0 1px 2px rgba(31, 26, 15, 0.06), 0 1px 3px rgba(31, 26, 15, 0.05);
        --elev-2: 0 2px 4px rgba(31, 26, 15, 0.06), 0 8px 20px rgba(31, 26, 15, 0.08);
        --elev-3: 0 -2px 6px rgba(31, 26, 15, 0.06), 0 -10px 34px rgba(31, 26, 15, 0.12);
        --danger: #b3271a;
        /* ⛔ Darkened from #1f8a4a on 2026-08-20: with white text on top
           —which is what the «Entrenamiento» chip does when activated— it measured
           **4.38:1**, below the 4.5 of norm §2. Now 5.17:1. In
           dark it wasn't needed: the pair #0d0d0d on #27ae60 measures 6.77:1. */
        --success: #1b7d43;
        --warn: #7a5a06;
        --warn-dim: rgba(122, 90, 6, 0.14);
        --alerta: #b3271a;
        --alerta-dim: rgba(179, 39, 26, 0.12);
        --shadow-modal: 0 12px 28px rgba(0, 0, 0, 0.18);
        --filter-prec-fg: #5e5a52;
        --filter-prec-bg: rgba(0, 0, 0, 0.06);
        --filter-train-bg: rgba(31, 138, 74, 0.16);
        --filter-comp-bg: rgba(179, 39, 26, 0.14);
        /* Banners in light mode: pale backgrounds, dark borders and text */
        --banner-pay-bg: #fef2f2;
        --banner-pay-bd: #b91c1c;
        --banner-pay-fg: #7f1d1d;
        --banner-cta-fg: #ffffff;
        --banner-auth-bg: #fffbeb;
        --banner-auth-bd: #b45309;
        --banner-auth-fg: #78350f;
        --banner-issue-bg: #fef2f2;
        --banner-issue-bd: #b91c1c;
        --banner-issue-fg: #7f1d1d;
        --cv-badge-paid-bg: #d1fae5;
        --cv-badge-paid-fg: #065f46;
        --cv-badge-fin-bg: #fee2e2;
        --cv-badge-fin-fg: #7f1d1d;
        --cv-badge-arb-bg: rgba(83, 74, 183, 0.14);
        --cv-badge-arb-fg: #3C3489;
        --cv-badge-esp-bg: rgba(0, 0, 0, 0.06);
        --cv-badge-esp-fg: #5e5a52;
        /* Charts in light: very faint grid, near-black values */
        --chart-grid: #e2dccf;
        --chart-text: #1a1a1a;
        /* Chat in light: user pale green, bot/AI white with border */
        --chat-user-bg: #d8f0e0;
        --chat-user-fg: #163a23;
        --chat-leido: #0b5cad;
        --chat-bot-bg: #ffffff;
        --chat-bot-fg: #1a1a1a;
      }
