/* neurostim.css : the stylesheet of the whole site, besides one per game (public/assets/games/<code>.css, prefixed classes).
   The pink and slate theme of the 2008 site (its main.css), modernised in 2026: v2/CHARTE.md, every component shown on
   /admin/charte. Five sections: 1 tokens, 2 bare elements, 3 components (the charte head tile's), 4 page frame (the
   gabarit tile's), 5 modules (each tile its own block). A game asks the head tile for a missing token instead of
   writing a colour in its own CSS. */

/* 1. Tokens (v2/CHARTE.md §2, contrast ratios there) */
:root {
    --ns-bg: #f4f1f3;
    --ns-page: #ffffff;
    --ns-tint: #faf7f9;
    --ns-ink: #2a2124;
    --ns-ink-2: #3b2c36;
    --ns-on-ink: #ffffff;
    --ns-on-ink-muted: #d9cfd5;
    --ns-text: #36403f;
    --ns-text-strong: #2a2124;
    --ns-muted: #5d6867;
    --ns-title: #4c6664;
    --ns-box-text: #2a5052;
    --ns-border: #e6dfe3;
    --ns-border-strong: #7f8c8b;
    --ns-accent: #ff3399;
    --ns-accent-dark: #cc0066;
    --ns-accent-darker: #a3004f;
    --ns-accent-soft: #fff0f6;
    --ns-accent-light: #ffe0ef;
    --ns-on-accent: #ffffff;
    --ns-line: #ffc2df;
    --ns-nav: #cc0066;
    --ns-link: #2a2124;
    --ns-hover: #a3004f;
    --ns-focus: #cc0066;
    --ns-off: #8c9493;
    --ns-ok: #2e7d32;
    --ns-ok-soft: #edf7ed;
    --ns-ok-line: #a5d6a7;
    --ns-error: #c62828;
    --ns-error-soft: #fdecea;
    --ns-error-line: #ef9a9a;
    --ns-warn: #9a5800;
    --ns-warn-soft: #fff8e1;
    --ns-warn-line: #ffe082;
    --ns-info: #3c5553;
    --ns-info-soft: #eef4f3;
    --ns-info-line: #cfdad9;

    /* No system-ui: Windows may take a font of another language with it, Linux takes DejaVu Sans. */
    --ns-font: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Inter, "Helvetica Neue", Arial, "Noto Sans", sans-serif;
    --ns-font-mono: ui-monospace, "SF Mono", Menlo, Consolas, "DejaVu Sans Mono", "Liberation Mono", monospace;
    --ns-size-xs: 0.8125rem;
    --ns-size-sm: 0.875rem;
    --ns-size-md: 1rem;
    --ns-size-lg: 1.125rem;
    --ns-size-xl: 1.25rem;
    --ns-size-2xl: 1.75rem;
    --ns-space-1: 0.25rem;
    --ns-space-2: 0.5rem;
    --ns-space-3: 0.75rem;
    --ns-space-4: 1rem;
    --ns-space-5: 1.5rem;
    --ns-space-6: 2rem;
    --ns-space-7: 3rem;
    --ns-radius-sm: 6px;
    --ns-radius: 10px;
    --ns-radius-lg: 14px;
    --ns-radius-pill: 999px;
    --ns-shadow-sm: 0 1px 2px rgb(42 33 36 / 0.06);
    --ns-shadow: 0 1px 2px rgb(42 33 36 / 0.05), 0 4px 16px rgb(42 33 36 / 0.06);
    /* A touch target (WCAG 2.5.5): every control at 640 px and less, or under a finger (section 3, end). */
    --ns-target: 44px;
}

/* 2. Bare elements */
*, *::before, *::after { box-sizing: border-box; }
html { -webkit-text-size-adjust: 100%; text-size-adjust: 100%; accent-color: var(--ns-accent-dark); }
body {
    margin: 0;
    font-family: var(--ns-font);
    font-size: var(--ns-size-md);
    line-height: 1.55;
    color: var(--ns-text);
    background: var(--ns-bg);
}
img { max-width: 100%; height: auto; }
/* Links: ink, half bold. A link of a text (paragraph, list, cell…) without a class of its own is underlined in pink: it is
   told apart otherwise than by its colour. An empty class is none: x-nav-link writes class="" off its own page.
   :where() keeps that rule under any class: a menu, a tab, a game's button. */
a { color: var(--ns-link); font-weight: 600; text-decoration: none; }
:where(p, li, dd, td, th, figcaption, blockquote, label, .flash, .form-error, .field-help) a:where(:not([class]), [class=""]) {
    text-decoration: underline;
    text-decoration-color: var(--ns-accent);
    text-decoration-thickness: 0.1em;
    text-underline-offset: 0.22em;
}
a:hover { color: var(--ns-hover); text-decoration: underline; text-decoration-color: currentColor; }
:focus-visible { outline: 3px solid var(--ns-focus); outline-offset: 2px; }
p { margin: 0 0 var(--ns-space-4); }
/* A paragraph under a form keeps apart from its button (« Mot de passe oublié ? » under « Se connecter »). */
form + p { margin-top: var(--ns-space-4); }
ul, ol { padding-left: 1.4em; }
ul > li::marker { color: var(--ns-accent); }
h1, h2, h3, h4 { color: var(--ns-title); font-weight: 700; line-height: 1.25; text-wrap: balance; }
h1 { margin: 0 0 var(--ns-space-5); font-size: var(--ns-size-2xl); letter-spacing: -0.01em; }
/* The pink line under a title, as the dotted one of 2008. */
h2 { margin: var(--ns-space-6) 0 var(--ns-space-3); padding-bottom: var(--ns-space-2); font-size: var(--ns-size-xl); border-bottom: 2px solid var(--ns-line); }
h3 { margin: var(--ns-space-5) 0 var(--ns-space-2); font-size: var(--ns-size-lg); }
h4 { margin: var(--ns-space-4) 0 var(--ns-space-2); font-size: var(--ns-size-md); }
/* A title that is a link (the cards of /jeux) keeps the title's colour and weight. */
:is(h1, h2, h3, h4) a { color: inherit; font-weight: inherit; }
small { font-size: var(--ns-size-sm); }
code, kbd, samp { font-family: var(--ns-font-mono); font-size: 0.9em; }
hr { margin: var(--ns-space-5) 0; border: 0; border-top: 1px solid var(--ns-border); }
table { font-variant-numeric: tabular-nums; }
::selection { color: var(--ns-text-strong); background: var(--ns-accent-light); }
@media (min-width: 961px) { h1 { font-size: 2rem; } }

/* 3. Components (v2/CHARTE.md §3) */

/* Buttons: tonal by default; .button-primary for the one main action of a screen. */
button, .button {
    padding: 0.5rem 1rem;
    font: inherit;
    font-weight: 600;
    line-height: 1.25;
    color: var(--ns-accent-dark);
    background: var(--ns-accent-soft);
    border: 1px solid var(--ns-line);
    border-radius: var(--ns-radius);
    text-decoration: none;
    cursor: pointer;
}
.button { display: inline-flex; align-items: center; justify-content: center; gap: var(--ns-space-2); }
button:hover, .button:hover { color: var(--ns-accent-darker); background: var(--ns-accent-light); border-color: var(--ns-accent); text-decoration: none; }
button:disabled, button:disabled:hover, button[aria-disabled="true"], .button[aria-disabled="true"] { color: var(--ns-off); background: var(--ns-tint); border-color: var(--ns-border); cursor: not-allowed; }
.button-primary { color: var(--ns-on-accent); background: var(--ns-accent-dark); border-color: var(--ns-accent-dark); }
.button-primary:hover { color: var(--ns-on-accent); background: var(--ns-accent-darker); border-color: var(--ns-accent-darker); }
.button-danger { color: var(--ns-error); background: var(--ns-error-soft); border-color: var(--ns-error-line); }
.button-danger:hover { color: var(--ns-on-accent); background: var(--ns-error); border-color: var(--ns-error); }
/* A form button read as a link (Déconnecter, Annuler). */
.link-button {
    padding: 0;
    font: inherit;
    font-weight: 600;
    color: var(--ns-link);
    background: none;
    border: 0;
    border-radius: 0;
    text-decoration: underline;
    text-decoration-color: var(--ns-accent);
    text-decoration-thickness: 0.1em;
    text-underline-offset: 0.22em;
    cursor: pointer;
}
.link-button:hover { color: var(--ns-hover); background: none; text-decoration: underline; text-decoration-color: currentColor; }
@media (prefers-reduced-motion: no-preference) {
    button, .button, .topnav a, .menu a, .tabs a { transition: color 0.12s, background-color 0.12s, border-color 0.12s; }
}

/* Fields: 16 px (iOS no longer zooms), a border at 3.5:1, the error of x-form-error under the field. */
input:not([type]), input[type=text], input[type=password], input[type=email], input[type=number], input[type=search],
input[type=tel], input[type=url], input[type=date], input[type=datetime-local], input[type=time], select, textarea {
    max-width: 100%;
    padding: 0.5rem 0.75rem;
    font: inherit;
    line-height: 1.25;
    color: var(--ns-text-strong);
    background: var(--ns-page);
    border: 1px solid var(--ns-border-strong);
    border-radius: var(--ns-radius-sm);
}
textarea { line-height: 1.55; }
input:focus-visible, select:focus-visible, textarea:focus-visible { outline-offset: 1px; border-color: var(--ns-focus); }
/* A field in error (x-form-error): a red border, besides the message that names it. */
:is(input, select, textarea)[aria-invalid="true"] { border-color: var(--ns-error); }
::placeholder { color: var(--ns-muted); opacity: 1; }
input[type=checkbox], input[type=radio] { width: 1.125rem; height: 1.125rem; margin: 0 0.4rem 0 0; vertical-align: -0.2em; }
label { display: block; margin-bottom: var(--ns-space-1); }
.field { margin: 0 0 var(--ns-space-4); }
.field > label { font-weight: 600; color: var(--ns-text-strong); }
label.inline { display: inline; font-weight: 400; }
/* The help of a field (.field-help, or the p.muted of the socle's forms), under it. */
.field-help, .field > p.muted { margin: var(--ns-space-1) 0 0; font-size: var(--ns-size-sm); color: var(--ns-muted); }
.form-error { margin: var(--ns-space-1) 0 0; font-size: var(--ns-size-sm); font-weight: 600; color: var(--ns-error); }
fieldset { min-width: 0; margin: 0 0 var(--ns-space-4); padding: var(--ns-space-3) var(--ns-space-4) var(--ns-space-4); border: 1px solid var(--ns-border); border-radius: var(--ns-radius); }
legend { padding: 0 var(--ns-space-1); font-weight: 600; color: var(--ns-title); }

/* Cards; .card-accent takes the pink line of the content on top. */
.card { margin: 0 0 var(--ns-space-4); padding: var(--ns-space-4) var(--ns-space-5); background: var(--ns-page); border: 1px solid var(--ns-border); border-radius: var(--ns-radius-lg); box-shadow: var(--ns-shadow-sm); }
.card-accent { border-top: 3px solid var(--ns-accent); }
.card > :first-child { margin-top: 0; }
.card > :last-child { margin-bottom: 0; }

/* Tables. A wide table scrolls in its box instead of widening the page (390 px). */
table.list { width: 100%; border-collapse: collapse; }
table.list caption { padding: 0 0 var(--ns-space-2); font-weight: 600; text-align: left; color: var(--ns-title); }
table.list th, table.list td { padding: var(--ns-space-2) var(--ns-space-3); text-align: left; border-bottom: 1px solid var(--ns-border); }
table.list th { font-size: var(--ns-size-sm); font-weight: 600; color: var(--ns-title); background: var(--ns-tint); border-bottom: 2px solid var(--ns-line); }
table.list tbody th { font-size: inherit; background: none; border-bottom: 1px solid var(--ns-border); }
table.list .num { text-align: right; }
/* A wide table in its frame, which scrolls sideways. position: relative keeps a hidden text of a cell out of the frame
   (.visually-hidden is absolute) inside what scrolls, instead of widening the page (/numerank/mes-parties, jeux A). The
   scroll padding brings a half-shown link with the focus into the frame, as for the tabs (below, at 640 px). */
.scroll-x { position: relative; max-width: 100%; overflow-x: auto; scroll-padding-inline: 40%; }

/* Messages: the colour of the state on a 4 px left border, the text at 4.5:1 or more on its background. */
.flash { margin: 0 0 var(--ns-space-4); padding: var(--ns-space-3) var(--ns-space-4); border: 1px solid; border-left-width: 4px; border-radius: var(--ns-radius-sm); }
.flash > :last-child { margin-bottom: 0; }
.flash-ok { color: var(--ns-ok); background: var(--ns-ok-soft); border-color: var(--ns-ok-line); border-left-color: var(--ns-ok); }
.flash-error { color: var(--ns-error); background: var(--ns-error-soft); border-color: var(--ns-error-line); border-left-color: var(--ns-error); }
.flash-warn { color: var(--ns-warn); background: var(--ns-warn-soft); border-color: var(--ns-warn-line); border-left-color: var(--ns-warn); }
.flash-info { color: var(--ns-info); background: var(--ns-info-soft); border-color: var(--ns-info-line); border-left-color: var(--ns-info); }

/* Badges */
.badge { display: inline-block; padding: 0.125rem 0.5rem; font-size: var(--ns-size-xs); font-weight: 700; line-height: 1.4; color: var(--ns-accent-darker); white-space: nowrap; vertical-align: 0.1em; background: var(--ns-accent-light); border-radius: var(--ns-radius-pill); }
.badge-ok { color: var(--ns-ok); background: var(--ns-ok-soft); }
.badge-error { color: var(--ns-error); background: var(--ns-error-soft); }
.badge-warn { color: var(--ns-warn); background: var(--ns-warn-soft); }
.badge-muted { color: var(--ns-info); background: var(--ns-info-soft); }
.badge-solid { color: var(--ns-on-accent); background: var(--ns-accent-dark); }

/* Tabs and sub-menus: nav.tabs > ul > li > a, the page in progress by aria-current (or .active), one line at 390 px. */
.tabs { margin: 0 0 var(--ns-space-5); }
.tabs ul { display: flex; flex-wrap: wrap; gap: 0 var(--ns-space-1); margin: 0; padding: 0; list-style: none; border-bottom: 1px solid var(--ns-border); }
.tabs li > * { display: flex; align-items: center; min-height: 2.5rem; margin-bottom: -1px; padding: 0 var(--ns-space-3); font-weight: 600; white-space: nowrap; text-decoration: none; border-bottom: 3px solid transparent; }
.tabs a { color: var(--ns-muted); }
.tabs a:hover { color: var(--ns-accent-dark); border-bottom-color: var(--ns-line); }
/* The page in progress: a link (x-nav-link) or a strong, aria-current="page" either way. */
.tabs [aria-current="page"], .tabs a.active { color: var(--ns-accent-dark); border-bottom-color: var(--ns-accent-dark); }

/* Pages of a list */
.pager { display: flex; flex-wrap: wrap; align-items: center; gap: var(--ns-space-2); margin: var(--ns-space-4) 0; }
.pager a, .pager span { display: inline-flex; align-items: center; justify-content: center; min-width: 2.5rem; min-height: 2.5rem; padding: 0 var(--ns-space-3); text-decoration: none; border: 1px solid var(--ns-border); border-radius: var(--ns-radius-sm); }
.pager a:hover { background: var(--ns-accent-soft); border-color: var(--ns-line); }
.pager [aria-current="page"] { color: var(--ns-on-accent); background: var(--ns-accent-dark); border-color: var(--ns-accent-dark); }
/* A line of links out of a sentence, after a text (« Retour », « Toutes les règles »): p.links for one link, ul.links for
   several, side by side without « | » (a screen reader reads « barre verticale »). Under a finger, each link a target
   of 44 px; CSS cannot tell a lone link of a paragraph from a link inside a sentence. Baseline: a button of 44 px in the
   line keeps its text on the links' line. */
ul.links { display: flex; flex-wrap: wrap; align-items: baseline; gap: 0 var(--ns-space-4); margin: 0 0 var(--ns-space-4); padding: 0; list-style: none; }
/* The links of a cell (« Voir », « Rejeu »): the list without its margin, the row spaces it. Under a form, apart from
   its button, like a paragraph (form + p). */
:where(td, th) > ul.links { margin: 0; }
form + ul.links { margin-top: var(--ns-space-4); }

/* Icons of the games (x-game-icon, GameIcons): inline SVG, stroke in the colour of the text around, one detail in
   var(--ns-icon-accent, var(--ns-accent)). Their margins stay with their places: the left menu (section 4), the page
   Les jeux (section 5). */
.game-icon { flex: none; vertical-align: middle; }

/* Details */
summary { font-weight: 600; color: var(--ns-link); cursor: pointer; }
summary:hover { color: var(--ns-hover); }
details[open] > summary { margin-bottom: var(--ns-space-2); }

/* Utilities */
.muted { color: var(--ns-muted); }
.lead { font-size: var(--ns-size-lg); color: var(--ns-text-strong); }
.visually-hidden { position: absolute; width: 1px; height: 1px; margin: -1px; padding: 0; overflow: hidden; clip: rect(0 0 0 0); clip-path: inset(50%); white-space: nowrap; border: 0; }
.inline { display: inline; }
.nowrap { white-space: nowrap; }
/* Free text that can be long without spaces (an email address, a URL, a reason, JSON) may break anywhere: on its cell
   only, one cell per row, never on a whole table (every cell would then shrink to a letter, numbers broken first). In a
   cell, a floor of 9em: the table's automatic layout squeezes first the column whose minimum is a letter. Not on a
   login, which stays whole, its table scrolling in its .scroll-x when it must: the utility cut a short login
   (« Cassiope|e »), its floor made a table of short logins scroll for nothing. */
.wrap-anywhere { overflow-wrap: anywhere; }
td.wrap-anywhere, th.wrap-anywhere { min-width: 9em; }
.num { font-variant-numeric: tabular-nums; }
.chrono { font-size: 1.5rem; font-weight: 700; color: var(--ns-accent-dark); font-variant-numeric: tabular-nums; }
.link-off { font-weight: 600; color: var(--ns-off); cursor: default; }

/* Under a finger, or at 640 px and less: every control a target of 44 px (WCAG 2.5.5). Never on a bare label (the cells
   of a board can be labels); a board of buttons on an image keeps its size with min-height: 0 in its own rule. */
@media (max-width: 640px), (pointer: coarse) {
    button, .button,
    input:not([type]), input[type=text], input[type=password], input[type=email], input[type=number], input[type=search],
    input[type=tel], input[type=url], input[type=date], input[type=datetime-local], input[type=time], select { min-height: var(--ns-target); }
    label.inline { display: inline-flex; align-items: center; min-width: var(--ns-target); min-height: var(--ns-target); }
    /* Its box keeps its size when the text of the label goes to the line (flex-shrink took it from 18 to 10 px). */
    label.inline > input:is([type=checkbox], [type=radio]) { flex: none; }
    summary { padding-block: 0.625rem; }
    .tabs li > *, .pager a, .pager span { min-height: var(--ns-target); }
    .pager a, .pager span { min-width: var(--ns-target); }
    .tabs li > * { justify-content: center; min-width: var(--ns-target); }
    /* A short link (« # », « 0 », a number of credits) 44 px wide too, like a page of the pager. */
    .links a { display: inline-flex; align-items: center; justify-content: center; min-width: var(--ns-target); min-height: var(--ns-target); }
    /* A plain list of links in the content (the home page's): each link a target. Inline flex keeps the text after it on
       its line and the bullet on its first line (an inline block puts it on its last). */
    .content ul:not([class]) > li > a:only-child { display: inline-flex; align-items: center; min-height: var(--ns-target); }
}
/* Tabs on one line that scrolls sideways (v2/CHARTE.md, mobile 3); closer cells in a table. The row cuts what passes
   its edges: the focus ring inside the tab (4 px in, the tab's last pixel being under the row's line). Chromium scrolls
   a tab with the focus into the row only when none of it shows: the scroll padding makes a tab outside the middle fifth
   count as hidden, so it comes to the middle. A tab wider than the padding can stay across the band's edge, cut by the
   row: 40 % leaves none from 320 to 640 px, 25 % some at 320 and 360 px (v2/captures-charte/onglets/, gabarit/topnav/). */
@media (max-width: 640px) {
    .tabs ul { flex-wrap: nowrap; overflow-x: auto; scrollbar-width: none; scroll-padding-inline: 40%; }
    .tabs li > :focus-visible { outline-offset: -4px; }
    table.list th, table.list td { padding: var(--ns-space-2); }
}

/* 4. Page frame: header, top navigation, three columns, footer (the gabarit tile's after the GO) */
/* Skip link, the first element of the body (Numerank's review, 23/10): off screen until it gets the keyboard focus. */
.skip-link { position: absolute; top: 0.5em; left: -999em; z-index: 10; padding: 0.625rem var(--ns-space-4); font-weight: 700; color: var(--ns-on-accent); text-decoration: none; background: var(--ns-accent-dark); border-radius: var(--ns-radius-pill); }
.skip-link:focus { left: 0.5em; color: var(--ns-on-accent); outline-color: var(--ns-on-ink); }
.container { display: flex; flex-direction: column; min-height: 100vh; }

/* The dark band of header.jpg, now a gradient (one request less), and a pink line under it. Its background runs the
   whole width of the window, its content stays in the 1 280 px of the page. */
.site-header {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    justify-content: space-between;
    gap: var(--ns-space-3) var(--ns-space-5);
    padding: var(--ns-space-5) max(var(--ns-space-5), calc(50% - 640px + var(--ns-space-5)));
    color: var(--ns-on-ink);
    background: linear-gradient(180deg, var(--ns-ink-2), var(--ns-ink) 70%);
    border-bottom: 3px solid var(--ns-accent);
}
.site-header a { color: var(--ns-on-ink); }
.site-header :focus-visible { outline-color: var(--ns-on-ink); }
.site-logo { display: flex; flex-direction: column; gap: 6px; text-decoration: none; }
.site-logo img { display: block; }
/* Who is there and the notifications, side by side (no « | » read by a screen reader). */
.site-header-status { display: flex; flex-wrap: wrap; align-items: center; justify-content: flex-end; gap: 0 var(--ns-space-4); font-size: var(--ns-size-sm); color: var(--ns-on-ink-muted); text-align: right; }

.topnav { position: relative; padding: 0 max(var(--ns-space-4), calc(50% - 640px + var(--ns-space-4))); background: var(--ns-page); border-bottom: 1px solid var(--ns-border); }
.topnav ul { display: flex; flex-wrap: wrap; gap: var(--ns-space-1); margin: 0; padding: var(--ns-space-2) 0; list-style: none; }
.topnav a, .topnav .link-off { display: flex; align-items: center; min-height: 2.5rem; padding: 0 var(--ns-space-3); font-size: var(--ns-size-sm); font-weight: 700; letter-spacing: 0.04em; text-transform: uppercase; white-space: nowrap; text-decoration: none; border-radius: var(--ns-radius-pill); }
.topnav a { color: var(--ns-nav); }
.topnav a:hover { color: var(--ns-accent-darker); background: var(--ns-accent-soft); }
/* The page in progress, marked otherwise than by its colour (aria-current: x-nav-link). */
.topnav a[aria-current="page"] { color: var(--ns-accent-darker); background: var(--ns-accent-light); text-decoration: underline; text-decoration-thickness: 2px; text-underline-offset: 0.35em; }

.layout {
    flex: 1;
    display: grid;
    grid-template-columns: 14rem minmax(0, 1fr) 15rem;
    /* The content comes first in the page (layouts/app), the menu is placed on its left. */
    grid-template-areas: "left content right";
    /* Each column as tall as its own content. */
    align-items: start;
    gap: var(--ns-space-5);
    width: 100%;
    max-width: 1280px;
    margin: 0 auto;
    padding: var(--ns-space-5);
}
.layout > .left { grid-area: left; }
.layout > .content { grid-area: content; }
.layout > .right { grid-area: right; }
.left, .right { min-width: 0; }
.content { min-width: 0; padding: var(--ns-space-5) var(--ns-space-6) var(--ns-space-6); background: var(--ns-page); border: 1px solid var(--ns-border); border-top: 3px solid var(--ns-accent); border-radius: var(--ns-radius-lg); box-shadow: var(--ns-shadow); }
.content > :first-child { margin-top: 0; }
/* A page without the layout (errors 500 and 503, whose cause may be the layout): the band, then the message alone. */
.page-alone { flex: 1; width: 100%; max-width: 48rem; margin: 0 auto; padding: var(--ns-space-5); }
/* The ways in of the home page, as buttons side by side. */
.home-actions { display: flex; flex-wrap: wrap; gap: var(--ns-space-2) var(--ns-space-3); margin: var(--ns-space-5) 0; padding: 0; list-style: none; }

/* The copyright then its links, on one line when it fits. */
.footer { display: flex; flex-wrap: wrap; align-items: center; justify-content: center; gap: 0 var(--ns-space-4); padding: var(--ns-space-5) var(--ns-space-4); font-size: var(--ns-size-sm); color: var(--ns-muted); text-align: center; background: var(--ns-page); border-top: 1px solid var(--ns-border); }
.footer p { margin: 0; }
/* Its links: a ul.links (section 3), centred like the copyright. */
.footer .links { justify-content: center; margin: 0; }

/* Boxes of the columns (x-box, old .h9): white cards, their title in small capitals. */
.box { margin: 0 0 var(--ns-space-4); padding: var(--ns-space-4); background: var(--ns-page); border: 1px solid var(--ns-border); border-radius: var(--ns-radius-lg); box-shadow: var(--ns-shadow-sm); }
.box > h2 { margin: 0 0 var(--ns-space-3); padding: 0; font-size: var(--ns-size-xs); letter-spacing: 0.08em; text-transform: uppercase; border: 0; }
.box-body > :first-child { margin-top: 0; }
/* A box that ends on a form (the login of the left column) ends on the form's last element. */
.box-body > :last-child, .box-body > form:last-child > :last-child { margin-bottom: 0; }
.box-body input[type=text], .box-body input[type=password] { width: 100%; }
/* A box in the content (the home page's Fast Count): tinted, a title of the page's own size. */
.content .box { background: var(--ns-tint); box-shadow: none; }
.content .box > h2 { font-size: var(--ns-size-lg); letter-spacing: 0; text-transform: none; }
/* A link of the menu fills its line; the text of a line without a link stays on the line of the box's title. */
.menu { margin: 0; padding: 0; list-style: none; }
.menu li { margin: 0; }
.menu a, .menu .link-off { display: flex; align-items: center; min-height: 2rem; margin: 0 calc(-1 * var(--ns-space-2)); padding: var(--ns-space-1) var(--ns-space-2); text-decoration: none; border-radius: var(--ns-radius-sm); }
.menu a { color: var(--ns-text-strong); }
.menu a:hover { color: var(--ns-accent-darker); background: var(--ns-accent-soft); }
.menu a[aria-current="page"] { color: var(--ns-accent-darker); background: var(--ns-accent-light); box-shadow: inset 3px 0 0 var(--ns-accent-dark); }
/* The icon of a game before its name (x-game-icon, 24 px). */
.menu .game-icon { margin-right: 0.3em; }
/* A long box folded under its summary at 640 px and less (x-box fold: the menu, more than twelve entries, v2/CHARTE.md
   §4.3), open without its summary wider: ::details-content shows the body of a closed details. A browser without it
   keeps the summary at every width. */
@supports selector(::details-content) {
    @media (min-width: 641px) {
        .box-fold > summary { display: none; }
        .box-fold::details-content { display: block; content-visibility: visible; }
    }
}
.status dl { display: grid; grid-template-columns: auto 1fr; gap: var(--ns-space-1) var(--ns-space-3); margin: 0; }
.status dt { color: var(--ns-muted); }
.status dd { margin: 0; font-weight: 700; color: var(--ns-text-strong); font-variant-numeric: tabular-nums; }

/* Under a finger, each link of the header's status is a target (those of the boxes and the footer: .links, section 3). */
@media (max-width: 640px), (pointer: coarse) {
    .site-header-status a { display: inline-flex; align-items: center; min-height: var(--ns-target); }
}

@media (max-width: 960px) {
    .layout { grid-template-columns: 13rem minmax(0, 1fr); grid-template-areas: "left content" "right right"; }
}

@media (max-width: 640px) {
    .site-header { gap: var(--ns-space-2); padding: var(--ns-space-4); }
    .site-header-status { justify-content: flex-start; text-align: left; }
    /* The top navigation on one line that scrolls sideways (v2/CHARTE.md §4), a fade on its right edge as a hint. */
    .topnav { padding: 0 var(--ns-space-2); }
    /* With the keyboard, as the tabs (section 3): the ring inside the link, a link out of the middle fifth comes to the
       middle; the end padding (the 24 px the fade covers) leaves the last link out of the fade (gabarit/topnav/). */
    .topnav ul { flex-wrap: nowrap; overflow-x: auto; scrollbar-width: none; scroll-padding-inline: 40%; padding-inline-end: 1.5rem; }
    .topnav li > :focus-visible { outline-offset: -4px; }
    .topnav::after { content: ""; position: absolute; top: 0; right: 0; bottom: 1px; width: 2rem; pointer-events: none; background: linear-gradient(to right, rgb(255 255 255 / 0), var(--ns-page)); }
    /* One column in the order of the page: the focus follows the screen. */
    .layout { grid-template-columns: minmax(0, 1fr); grid-template-areas: "content" "left" "right"; gap: var(--ns-space-4); padding: var(--ns-space-3); }
    .page-alone { padding: var(--ns-space-3); }
    /* A wide table not yet in its .scroll-x (v2/CHARTE.md, mobile 1) scrolls inside the content, never the page; so does
       the hidden text of one of its cells (.visually-hidden, absolute), the content being its containing block. */
    .content { position: relative; padding: var(--ns-space-4) var(--ns-space-4) var(--ns-space-5); overflow-x: auto; border-radius: var(--ns-radius); }
    /* The menu of the left column on two columns: 22 links on 11 lines. */
    .left .menu { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 0 var(--ns-space-5); }
}

@media (max-width: 640px), (pointer: coarse) {
    .topnav li > *, .menu a, .menu .link-off { min-height: var(--ns-target); }
}

/* 5. Modules, each tile its own block */
/* module games-autres : Compteur, Color clavier, Test global, coach */
.ga-target { font-size: 1.2rem; }
.ga-grid { display: grid; grid-template-columns: repeat(10, minmax(0, 1fr)); gap: 3px; max-width: 520px; }
.ga-grid button { min-width: 0; padding: 0.45em 0; font-size: 0.95rem; }
.ga-keypad { display: flex; flex-wrap: wrap; gap: 6px; }
.ga-keypad button { min-width: 3em; font-size: 1.1rem; }
.ga-squares { display: flex; flex-wrap: wrap; gap: 10px; margin: 0.6em 0 1em; padding: 0; list-style: none; }
.ga-square { width: 48px; height: 48px; border: 1px solid var(--ns-border-strong); border-radius: var(--ns-radius-sm); }
.ga-bars { margin: 0; padding: 0; list-style: none; max-width: 420px; }
.ga-bars li { display: flex; align-items: center; gap: 0.5em; margin: 2px 0; }
.ga-bar { display: inline-block; height: 0.9em; min-width: 2px; background: var(--ns-accent); }
.ga-bar-label { font-size: 0.85rem; }
.ga-coach .box-body { overflow: hidden; }
.ga-coach-img { float: left; margin: 0 0.8em 0.4em 0; }
.ga-progress, .ga-meter { display: inline-block; width: 100%; max-width: 320px; height: 0.9em; vertical-align: middle; border: 1px solid var(--ns-accent); }
.ga-meter { width: 140px; }
.ga-progress span, .ga-meter span { display: block; height: 100%; background: var(--ns-accent); }
.ga-steps li { margin: 0.2em 0; }
.ga-abandon { margin-top: 1.5em; }

/* module games-fastcount : menu Entraînement, Fast Count, Patrons, fins de partie, statistiques */
.gf-menu { margin: 0; padding: 0; list-style: none; }
.gf-menu h2 { margin-left: 0; margin-right: 0; }
.gf-progress { font-weight: bold; color: var(--ns-title); }
.gf-question { margin: 0.6em 0 0.8em; font-size: 1.5rem; color: var(--ns-accent-dark); }
.gf-keypad { display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: 6px; max-width: 20em; }
.gf-keypad button { padding: 0.7em 0; font-size: 1.2rem; }
.gf-net { margin: 0 0 1em; }
.gf-net svg { display: block; width: 220px; max-width: 100%; height: auto; }
.gf-net figcaption, .gf-chart figcaption { font-size: 0.85rem; color: var(--ns-muted); }
.gf-figures { display: flex; flex-wrap: wrap; gap: 8px; }
.gf-figures button { display: flex; flex-direction: column; align-items: center; gap: 4px; padding: 6px; background: var(--ns-page); }
.gf-figures svg { display: block; width: 96px; height: 96px; }
.gf-net polygon, .gf-figures polygon { stroke: var(--ns-text); }
.gf-chart { margin: 0.5em 0 1em; }
.gf-chart svg { display: block; width: 100%; max-width: 40em; height: 120px; border-bottom: 1px solid var(--ns-border-strong); }
/* Bars of the recent games (partials/score-chart): the slate of the titles, the pink of the site for the game shown. */
.gf-chart rect { fill: var(--ns-title); }
.gf-chart rect.gf-current { fill: var(--ns-accent); }
.gf-score { font-size: 1.1rem; }
.gf-abandon { margin-top: 1.5em; }
/* The titles of the training menu: 44 px under a finger (its lines of links are the site's p.links). */
@media (max-width: 640px), (pointer: coarse) {
    .gf-menu h2 a { display: inline-flex; align-items: center; min-height: var(--ns-target); }
}
/* module accounts : compte, membres, fiche */
.ac-member { white-space: nowrap; }
.ac-presence { margin-right: var(--ns-space-1); vertical-align: middle; }
.ac-profile { display: flex; align-items: flex-start; gap: var(--ns-space-4); margin: 0 0 var(--ns-space-4); }
.ac-profile .ac-avatar { flex: none; border-radius: var(--ns-radius-sm); }
.ac-facts { display: grid; grid-template-columns: max-content minmax(0, 1fr); gap: var(--ns-space-2) var(--ns-space-4); margin: 0 0 var(--ns-space-5); }
.ac-facts dt { font-weight: 600; color: var(--ns-title); }
.ac-facts dd { margin: 0; }
/* The avatars and the coaches in the fieldset frame of the base; the chosen avatar in pink. */
.ac-avatars { display: flex; flex-wrap: wrap; gap: var(--ns-space-3); }
.ac-avatars legend { margin-bottom: var(--ns-space-2); }
.ac-avatars label { display: inline-flex; flex-direction: column; align-items: center; gap: var(--ns-space-1); margin: 0; padding: var(--ns-space-2); border: 1px solid var(--ns-border); border-radius: var(--ns-radius); cursor: pointer; }
.ac-avatars label:has(:checked) { background: var(--ns-accent-soft); border-color: var(--ns-accent-dark); }
.ac-coach { overflow: hidden; margin: 0 0 var(--ns-space-4); }
.ac-coach:last-child { margin-bottom: 0; }
.ac-coach img { float: left; max-width: 120px; margin: 0 var(--ns-space-3) var(--ns-space-2) 0; border-radius: var(--ns-radius-sm); }
.ac-plus { color: var(--ns-ok); }
.ac-minus { color: var(--ns-error); }
/* The JSON of the admin journal (/admin/membres/{id}) may break anywhere (.wrap-anywhere), in a column of 15 rem at
   least: the table then scrolls in its frame instead of squeezing the JSON to a letter a line (CHARTE §4.1). */
.ac-meta { min-width: 15rem; font-family: var(--ns-font-mono); font-size: var(--ns-size-sm); }
@media (max-width: 640px) { .ac-facts { grid-template-columns: minmax(0, 1fr); gap: 0; } .ac-facts dd { margin-bottom: var(--ns-space-3); } }

/* Social, module social-messages (sm-): messages, contacts, warnings, notifications, forum, static pages. Tabs and pages are
   the charte's nav.tabs and .pager, inline forms its .inline, lines of links its .links. */
table.list tr.sm-unread td { font-weight: 700; color: var(--ns-text-strong); }
/* One message of a conversation (or of the reports' moderation): a light card. */
.sm-message { margin: 0 0 var(--ns-space-3); padding: var(--ns-space-3) var(--ns-space-4); background: var(--ns-page); border: 1px solid var(--ns-border); border-radius: var(--ns-radius); }
.sm-message header, .sm-message footer { font-size: var(--ns-size-sm); color: var(--ns-muted); }
.sm-message-body { margin: var(--ns-space-2) 0; color: var(--ns-text); white-space: pre-line; overflow-wrap: anywhere; }
/* The actions of a message, a line of links at the foot of its card, with no margin under them. */
.sm-message footer .links { margin: 0; }
/* The bar of the new messages and warnings, a box at the top of the content, framed in pink. */
.sm-warnings { border-color: var(--ns-accent-dark); }
.sm-warnings p { margin: var(--ns-space-1) 0; }
.sm-warnings .button, .sm-warnings button { display: inline-block; white-space: nowrap; }
.sm-warning + .sm-warning { margin-top: var(--ns-space-3); padding-top: var(--ns-space-3); border-top: 1px solid var(--ns-border); }
.sm-warning-actions { display: flex; flex-wrap: wrap; align-items: center; gap: var(--ns-space-2) var(--ns-space-3); margin: var(--ns-space-2) 0 0; }
.sm-warning-moderation { color: var(--ns-error); }
.sm-events { margin: 0; padding: 0; list-style: none; font-size: var(--ns-size-sm); }
.sm-events li { margin: 0 0 var(--ns-space-2); }
.sm-actions { margin: 0 0 var(--ns-space-3); padding-left: var(--ns-space-5); }
/* The notifications (/notifications): one line each, the unread ones in pink. */
.sm-notices { margin: 0 0 var(--ns-space-4); padding: 0; list-style: none; border-top: 1px solid var(--ns-border); }
.sm-notices li { padding: 0 0 var(--ns-space-3); border-bottom: 1px solid var(--ns-border); }
/* The link of a notice a target of 44 px (16 px on 1.55, plus 2 × 0.625rem), as the plain lists of the charte. */
.sm-notices a { display: block; padding-block: 0.625rem; }
.sm-notices .sm-unread a { color: var(--ns-accent-dark); }
/* The news of the site (/news). */
.sm-news dt { font-weight: 700; color: var(--ns-title); }
.sm-news dd { margin: 0 0 var(--ns-space-4); }
/* Under a finger: the link of the messages bar and those of a member's actions, targets of 44 px as the plain lists of
   the charte (the buttons and .link-button of these blocks already are). */
@media (max-width: 640px), (pointer: coarse) {
    .sm-warnings p > a, .sm-actions li > a { display: inline-block; padding-block: 0.625rem; }
}

/* module rankings (rk-): bar charts of /statistiques (x-rankings.bars), in the tokens of the site. A chart keeps the size
   of its drawing, its texts at 13 px: narrower than it (390 px, two columns), its frame scrolls sideways. */
.rk-chart { margin: 0 0 var(--ns-space-5); }
.rk-chart svg { display: block; }
.rk-chart figcaption { margin-top: var(--ns-space-2); font-size: var(--ns-size-sm); }
.rk-axis { stroke: var(--ns-accent-dark); }
.rk-bar { fill: var(--ns-accent); }
.rk-value, .rk-label { font-size: var(--ns-size-xs); }
.rk-value { fill: var(--ns-text); }
.rk-label { fill: var(--ns-title); }
/* Lists of a box that are not menus (counters of « En direct », ranks of « Mes classements »): no bullets. With the top
   of the mini ranking (.rk-top, numbered), the link of a line stays in its line, a target of 44 px under a finger (as
   the links of a list of the content). */
.rk-list { margin: 0; padding: 0; list-style: none; }
@media (max-width: 640px), (pointer: coarse) {
    .rk-list a, .rk-top a { display: inline-block; padding-block: 0.625rem; }
}

/* module tournaments (tn-): bracket of a tournament to elimination, its rounds side by side on a wide screen, one under the other at 390 px;
   each match a .card, closer than a page's, the reader's on the pink tint. */
.tn-bracket { display: grid; grid-template-columns: repeat(auto-fit, minmax(15rem, 1fr)); gap: 0 var(--ns-space-5); }
.tn-round h2 { margin-top: var(--ns-space-2); }
.tn-matches { margin: 0 0 var(--ns-space-4); }
.tn-match { margin: 0 0 var(--ns-space-3); padding: var(--ns-space-3); overflow-wrap: anywhere; }
.tn-mine { background: var(--ns-accent-soft); border-color: var(--ns-line); }
.tn-players { font-weight: 700; color: var(--ns-text-strong); }
/* The label of a filter of /tournois (Mise, Jeu), over its tabs. */
.tn-filter { margin: 0 0 var(--ns-space-1); font-weight: 600; color: var(--ns-title); }

/* page Les jeux (gc-): one card per game, side by side on a wide screen, one under the other at 390 px. The whole card
   is the link of its title, its only link (GamesPageTest): a target of the card's size, icon included; the card, its
   only positioned ancestor, shows the hover and the focus ring (v2/CHARTE.md §3, clickable cards). */
.gc-cards { display: grid; grid-template-columns: repeat(auto-fill, minmax(15rem, 1fr)); gap: var(--ns-space-4); margin: 0 0 var(--ns-space-5); padding: 0; list-style: none; }
.gc-card { position: relative; padding: var(--ns-space-4); background: var(--ns-page); border: 1px solid var(--ns-border); border-top: 3px solid var(--ns-accent); border-radius: var(--ns-radius-lg); box-shadow: var(--ns-shadow-sm); overflow-wrap: anywhere; }
.gc-card:hover { border-color: var(--ns-line); border-top-color: var(--ns-accent); }
.gc-card h2 { margin: 0 0 var(--ns-space-2); padding: 0; font-size: var(--ns-size-lg); border: 0; }
/* The radius of the card itself (inherit would take the link's, 0): the ring follows the card's corners. */
.gc-card h2 a::after { content: ""; position: absolute; inset: 0; border-radius: var(--ns-radius-lg); }
.gc-card h2 a:focus-visible { outline: none; }
.gc-card h2 a:focus-visible::after { outline: 3px solid var(--ns-focus); outline-offset: 2px; }
@media (prefers-reduced-motion: no-preference) {
    .gc-card { transition: border-color 0.12s; }
}
.gc-card .game-icon { margin-right: 0.5em; }
.gc-card p { margin: var(--ns-space-1) 0; }
.gc-does { color: var(--ns-title); }
.gc-trainings { padding-left: 0; list-style: none; }
.gc-trainings li { margin: 0.3em 0; }
.gc-trainings .game-icon { margin-right: 0.3em; }
