/* ==============================================================================
   DESIGN TOKENS — the default skin and the dark-mode variant every skin
   redefines the same way.

   Derecho a la Vivienda Lanzarote (2026-10-13): the default skin
   ("sobria" by name, kept so the admin's skin setting and the tests keep
   working) is the style of the «Enyesque popular» poster by @pepahdzm,
   Juan's choice that day after the three teal trials: an aquamarine page,
   violet ink, and nothing red or gold. Colours measured on the poster's
   PNG as the median of plain patches: background #cce8eb, violet ink
   #5a4065, apple green #d8e8c0. Dark mode turns it round: a deep violet
   page with aquamarine text. Every pair below was measured for WCAG AA
   against the page, the paper and the secondary paper, and the ratios sit
   in the comment of each token (doc/03-FRONTEND-AND-SKINS.md); nobody
   changes a colour here without measuring it again. The "calida" and
   "noche" skins in skins.css are only reachable with DEMO_SKINS, which
   this site leaves empty.

   Three blocks, in this order, is the whole no-flash mechanism (see the
   drolosoft-theming/drolosoft-tema-oscuro skills): :root carries the LIGHT
   values, which is also skin "sobria" and theme "light" without needing an
   attribute at all; :root[data-theme="dark"] wins unconditionally, whatever
   the OS says, the moment a visitor picked dark explicitly; the
   @media(prefers-color-scheme:dark) block is scoped to
   :root:not([data-theme="light"]) so it only ever affects "auto" (the
   default) or a missing attribute, never an explicit light choice. A bare
   :root{} inside that media query would be the one defect this shape
   exists to avoid — it would leak dark mode onto a visitor who chose light.

   skins.css does the same thing again under [data-skin="calida"] and
   [data-skin="noche"], linked after this file in layout.html so it wins
   the cascade on the equal-specificity ties with the blocks below.
   ============================================================================== */

:root {
  /* --------------------------------------------------------------------
     Spacing: 4-8-12-16-24-32-48-64, the scale every future component
     should reach for directly. --spacing-xs..xl are the names the
     existing layout/component sheets already call var() with (task 5);
     they alias the numbered scale instead of duplicating it, so neither
     set of names can drift from the other.
     -------------------------------------------------------------------- */
  --space-1: 0.25rem; /* 4px */
  --space-2: 0.5rem;  /* 8px */
  --space-3: 0.75rem; /* 12px */
  --space-4: 1rem;    /* 16px */
  --space-5: 1.5rem;  /* 24px */
  --space-6: 2rem;    /* 32px */
  --space-7: 3rem;    /* 48px */
  --space-8: 4rem;    /* 64px */

  --spacing-xs: var(--space-1);
  --spacing-sm: var(--space-2);
  --spacing-md: var(--space-4);
  --spacing-lg: var(--space-5);
  --spacing-xl: var(--space-6);

  /* Radii: 4/inputs/chips, 8/buttons/cards, 12/large cards, pill for
     anything meant to read as fully round (the slideshow's dot and
     prev/next/toggle controls, all already square, so a large radius
     rounds them exactly like 50% would). */
  --radius-sm: 4px;
  --radius-md: 8px;
  --radius-lg: 12px;
  --radius-full: 9999px;

  /* Typography: system stacks only, zero bytes downloaded. --font-title
     is what skins.css actually varies per skin (a distinctive trait
     without a webfont); --font-text stays the same everywhere so body
     copy never changes rhythm when the skin does. */
  --font-title: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
  --font-text: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, sans-serif;
  /* The "serious" title face for the closed list of headings Juan marked
     on 13 October 2026 (hero h1, the h2 of card and gallery blocks, event
     and milestone titles, the month markers of the timeline; ADR-034):
     Source Serif 4 SemiBold, declared in fonts.css with a size-adjusted
     Georgia to stand in while it downloads. The book serifs behind them
     are for the admin, which does not load fonts.css, and for systems
     without Georgia. Every other heading keeps the hand-lettered
     --font-title. */
  --font-title-serious: 'Source Serif 4', 'Source Serif 4 Fallback', 'Iowan Old Style', 'Palatino Linotype', Georgia, serif;

  /* A fluid scale so headline sizes never jump at a breakpoint; the base
     size stays a plain rem; the browser's own root font-size still drives
     it, so a visitor's zoom or font preference is respected. */
  --font-size-base: 1rem;
  --font-size-lg: clamp(1.05rem, 1rem + 0.3vw, 1.15rem);
  --font-size-hero: clamp(1.75rem, 1.4rem + 2vw, 2.75rem);

  /* Color roles: background, surface, text, muted text, accent, border,
     focus, the things a skin actually has to redefine. Ratios are WCAG 2
     relative luminance, "worst" being the lowest of page, paper and
     secondary paper (scratch script contrast.py, 2026-10-13). */

  /* The poster's own background is the page; the paper is a step lighter
     so cards read as cards, the secondary paper (call-to-action band,
     slideshow frame) a step deeper. */
  --page-bg: #cce8eb;
  --paper-bg: #e3f2f3;
  --paper-secondary-bg: #bcdfe2;

  /* The poster's violet ink, exactly: 6.9:1 on the page, 6.3:1 at worst. */
  --text-primary: #5a4065;
  /* Between the ink and the muted text, 5.4:1 on the secondary paper. */
  --text-secondary: #634a70;
  /* The muted grey-violet is the tight one: #7d6a88 gave 3.5:1 on the
     secondary paper, so it went darker until 4.7:1 there (5.2:1 page). */
  --text-muted: #685574;

  /* Both borders need 3:1, because both draw controls: the strong one
     (3.4:1 at worst), and the light one, which besides separating cards
     is the only edge of the contact and login fields, painted on the
     paper (contact.css). #b9a9c4 gave those fields 1.9:1; this lilac
     gives 3.0:1 on the paper. */
  --border-color: #7f6b8c;
  --border-light: #9483a3;

  /* The accent keeps the template's --accent-blue name so every component
     sheet picks it up unchanged. Content links take the ink one step
     darker, which sets them a step apart from the body text: 8.6:1 on
     the page, 7.8:1 at worst. Solid buttons left it for the slate
     (--button-bg, below) on 13 October 2026. */
  --accent-blue: #4a3356;
  /* The poster's apple green #d8e8c0 is a background colour, not a text
     one; darkened until it clears 4.5:1 for the success notices (5.0:1 at
     worst). */
  --accent-green: #3a6235;
  /* The ring every :focus-visible outline uses; same value as the accent
     so a keyboard user learns one colour for "this is interactive/focused"
     across the whole site (8.6:1 on the page). */
  --focus-ring: var(--accent-blue);
  /* Text on anything painted ON the accent (the admin's counters and
     its primary buttons in other skins): an off-white with a hint of the
     page's aqua, 10.3:1 on the violet and 11.5:1 on the hover. */
  --accent-contrast: #f3f8f8;
  /* Form errors (.form-error/.form-alert text, the [aria-invalid] border)
     and the admin's notices: a plum, not a red, so the page keeps no red
     at all; 6.3:1 at worst. */
  --color-danger: #7a2f4f;
  --color-error: var(--color-danger);
  --color-success: var(--accent-green);

  /* The third tone (Juan, 13 October 2026: «demasiado soso, solo dos
     tonos»): the grey-blue slate of the tent in the «Transformamos la
     protesta» poster. It paints the chrome (header and footer bands), the
     solid buttons and the calendars; text, headings and content links stay
     violet. The poster's own slate, #59798c, gave the off-white only
     4.3:1, so it went darker until it cleared AA: #4f6d7f, 5.1:1 with the
     off-white on it. */
  --chrome-bg: #4f6d7f;
  --chrome-text: #f3f8f8;

  /* The admin bar and the header still read the --action-bar-* names;
     they alias the chrome so both bands can never drift apart. The muted
     links take the off-white at 92 % (4.6:1): at 85 % they fell to 4.2:1
     on the slate. Hover and the current page DARKEN the band with black
     at 12 % / 20 % (6.2:1 / 7.1:1): white on top, as on the violet, drops
     the text to 3.8:1 / 3.4:1 on a mid-tone like this one. */
  --action-bar-bg: var(--chrome-bg);
  --action-bar-text: var(--chrome-text);
  --action-bar-text-muted: rgba(243, 248, 248, 0.92);
  --action-bar-hover-bg: rgba(0, 0, 0, 0.12);
  --action-bar-active-bg: rgba(0, 0, 0, 0.2);

  /* The violet ring is 2.0:1 on the slate, lost against it; inside the
     header and footer bands the ring takes the chrome's text instead,
     5.1:1 (02-layout/header.css, footer.css, admin.css). */
  --chrome-focus-ring: var(--chrome-text);

  /* Solid buttons and the calendar band: the same slate and off-white as
     the chrome (5.1:1; 4.7:1 under the hover's brightness(0.88), which
     darkens the text with the slate). The slate is also
     the colour of the small labels by an event (time, «Por venir», the
     months of the timeline), painted on the paper: 4.8:1 there. */
  --button-bg: var(--chrome-bg);
  --button-text: var(--chrome-text);

  /* A ghost button's hover on a light page is a whisper of the ink. */
  --button-bg-hover: rgba(90, 64, 101, 0.08);

  /* On a light page a black shadow looks dirty; these are a violet-grey
     and softer than the dark mode's. */
  --shadow-sm: 0 1px 3px rgba(60, 40, 70, 0.15);
  --shadow-md: 0 2px 8px rgba(60, 40, 70, 0.18);
  --shadow-lg: 0 4px 16px rgba(60, 40, 70, 0.22);

  --transition-normal: 0.3s ease;

  --z-toast: 1100;

  /* Reading width the header, the page's blocks and the footer all
     share, so a paragraph of body copy never stretches wider than is
     comfortable to read on a desktop screen. */
  --content-max-width: 72rem;
}

/* Explicit dark: wins over the OS unconditionally. The poster turned
   round: a deep violet page, the poster's aquamarine as the text and the
   accent, and its apple green as is for success. Worst of page, paper and
   secondary paper: text 9.1:1, secondary 7.5:1, muted 5.9:1, accent
   8.0:1, success 9.0:1, danger (a light orchid) 7.3:1, strong border
   3.5:1, light border (the fields' edge) 3.2:1 on the paper. The
   slate turns round too: the chrome is a deep slate with the aquamarine
   on it, 7.7:1 (6.1:1 muted, 6.5:1 / 5.4:1 on hover and the current
   page), and the aqua focus ring stays visible there (6.8:1). Buttons
   are a lighter slate with a dark slate ink, 6.1:1 and 5.1:1 under the
   hover's brightness(0.88); #6f93a8, the first try, gave the ink 4.50:1
   and the event labels 4.1:1 on the paper, which now get 5.6:1. */
:root[data-theme="dark"] {
  --page-bg: #2a2033;
  --paper-bg: #352a40;
  --paper-secondary-bg: #3f3350;

  --text-primary: #cce8eb;
  --text-secondary: #b3d6da;
  --text-muted: #9bbfc4;

  --border-color: #9686a4;
  --border-light: #857598;

  --accent-blue: #a8e0da;
  --accent-green: #d8e8c0;
  --focus-ring: var(--accent-blue);
  --accent-contrast: #2a2033;
  --color-danger: #eebfdc;
  --color-success: var(--accent-green);

  --chrome-bg: #2f4654;
  --chrome-text: #cce8eb;
  --action-bar-bg: var(--chrome-bg);
  --action-bar-text: var(--chrome-text);
  --action-bar-text-muted: rgba(204, 232, 235, 0.85);
  --action-bar-hover-bg: rgba(255, 255, 255, 0.06);
  --action-bar-active-bg: rgba(255, 255, 255, 0.12);
  --chrome-focus-ring: var(--accent-blue);

  --button-bg: #8aabbe;
  --button-text: #1b2a33;

  --button-bg-hover: rgba(255, 255, 255, 0.06);

  --shadow-sm: 0 1px 3px rgba(0, 0, 0, 0.4);
  --shadow-md: 0 2px 8px rgba(0, 0, 0, 0.5);
  --shadow-lg: 0 4px 16px rgba(0, 0, 0, 0.7);
}

/* "auto" (the default) or no attribute at all follows the OS; an explicit
   light choice is excluded by :not([data-theme="light"]) so it can never
   be overridden here, and an explicit dark choice already got its values,
   unconditionally, from the block above regardless of what the OS says. */
@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) {
    --page-bg: #2a2033;
    --paper-bg: #352a40;
    --paper-secondary-bg: #3f3350;

    --text-primary: #cce8eb;
    --text-secondary: #b3d6da;
    --text-muted: #9bbfc4;

    --border-color: #9686a4;
    --border-light: #857598;

    --accent-blue: #a8e0da;
    --accent-green: #d8e8c0;
    --focus-ring: var(--accent-blue);
    --accent-contrast: #2a2033;
    --color-danger: #eebfdc;
    --color-success: var(--accent-green);

    --chrome-bg: #2f4654;
    --chrome-text: #cce8eb;
    --action-bar-bg: var(--chrome-bg);
    --action-bar-text: var(--chrome-text);
    --action-bar-text-muted: rgba(204, 232, 235, 0.85);
    --action-bar-hover-bg: rgba(255, 255, 255, 0.06);
    --action-bar-active-bg: rgba(255, 255, 255, 0.12);
    --chrome-focus-ring: var(--accent-blue);

    --button-bg: #8aabbe;
    --button-text: #1b2a33;

    --button-bg-hover: rgba(255, 255, 255, 0.06);

    --shadow-sm: 0 1px 3px rgba(0, 0, 0, 0.4);
    --shadow-md: 0 2px 8px rgba(0, 0, 0, 0.5);
    --shadow-lg: 0 4px 16px rgba(0, 0, 0, 0.7);
  }
}
