[ADD] interface: colour tokens, two themes, checked palette, marks
The plan's colours carry meaning — a conflict, a reservation, a mode — so
they must stay readable for every reader and in both themes. jetons.css
defines the tokens for the light and dark themes, set by data-theme on the
root; palette.js reads them from the stylesheet text and checks, by
computation, contrast to WCAG and separation under the three
dichromacies, keeping the conflict hue reserved. The theme follows the
system at each start and the operator's choice lasts the session.
Checked: 1709 node and 43 browser tests.
--- FR ---
[ADD] interface : jetons de couleur, deux thèmes, palette, marques
Les couleurs du plan portent un sens — un conflit, une réservation, un mode
— et doivent rester lisibles pour tout lecteur et dans les deux thèmes.
jetons.css définit les jetons des thèmes clair et sombre, posés par
data-theme sur la racine ; palette.js les lit dans le texte de la feuille
et contrôle, par calcul, le contraste au sens des WCAG et la séparation
sous les trois dichromaties, la teinte du conflit restant réservée. Le
thème suit le système à chaque démarrage ; le choix de l'opérateur vaut
pour la séance.
Vérifié : 1709 node et 43 navigateur.
Assisted-by: Claude Opus 5.5
2026-10-07 02:33:12 -04:00
// © 2026 TechnoLibre (http://www.technolibre.ca)
// License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl)
// Le registre des marques porteuses d'information et des textes (§ 14.5,
// § 7.5, § 7.6, § 7.7), et la palette de jetons.css validée par calcul sur
// lui (§ 12.7) : chaque entrée tient son seuil sur chacun de ses fonds, dans
// les deux thèmes, en couleurs d'origine puis sous les trois dichromaties.
import assert from 'node:assert/strict' ;
import { readFileSync } from 'node:fs' ;
import { describe , test } from '../../test/lanceur.js' ;
[ADD] interface: visual foundations, pills, cards, icons, navy header
Screens need colour that separates information without ever carrying it
alone. Tokens gain state, membership and status tints whose marks hold
3:1 and texts 4.5:1 in both themes and under three dichromacies, and
every hue stays 30 degrees from the reserved conflict hues. Commands get
three levels; Pastille, Carte and an icon module join the primitives;
memberships map to six stable tints over sorted names. A pill label
wraps and never truncates, and keeps one line beside a nowrap neighbour.
Checked: node 3949; browser 767, only the walkthrough captures differ.
--- FR ---
[ADD] interface : fondations, pastilles, cartes, icônes, bandeau marine
Les écrans ont besoin d'une couleur qui distingue l'information sans
jamais la porter seule. Les jetons gagnent des teintes d'état,
d'appartenance et de statut dont les marques tiennent 3:1 et les textes
4,5:1 dans les deux thèmes et sous trois dichromaties, chaque teinte à
30 degrés des teintes de conflit réservées. Les commandes ont trois
niveaux ; Pastille, Carte et un module d'icônes rejoignent les
primitives ; les appartenances reçoivent six teintes stables sur les
noms triés. Un libellé de pastille se replie, jamais tronqué.
Vérifié : node 3949 ; navigateur 767, seules les captures du parcours.
Assisted-by: Claude Opus 5.5
2026-10-10 22:59:51 -04:00
import { CONFLITS , JETONS _CONFLIT , MARQUES , SEPARATIONS , SIGNES , TEINTES _APPARTENANCE , TEXTES } from './marques.js' ;
import { lireBlocs , lireJetons , teinte , verifierClartes , verifierPalette , verifierSeparation } from './palette.js' ;
[ADD] interface: colour tokens, two themes, checked palette, marks
The plan's colours carry meaning — a conflict, a reservation, a mode — so
they must stay readable for every reader and in both themes. jetons.css
defines the tokens for the light and dark themes, set by data-theme on the
root; palette.js reads them from the stylesheet text and checks, by
computation, contrast to WCAG and separation under the three
dichromacies, keeping the conflict hue reserved. The theme follows the
system at each start and the operator's choice lasts the session.
Checked: 1709 node and 43 browser tests.
--- FR ---
[ADD] interface : jetons de couleur, deux thèmes, palette, marques
Les couleurs du plan portent un sens — un conflit, une réservation, un mode
— et doivent rester lisibles pour tout lecteur et dans les deux thèmes.
jetons.css définit les jetons des thèmes clair et sombre, posés par
data-theme sur la racine ; palette.js les lit dans le texte de la feuille
et contrôle, par calcul, le contraste au sens des WCAG et la séparation
sous les trois dichromaties, la teinte du conflit restant réservée. Le
thème suit le système à chaque démarrage ; le choix de l'opérateur vaut
pour la séance.
Vérifié : 1709 node et 43 navigateur.
Assisted-by: Claude Opus 5.5
2026-10-07 02:33:12 -04:00
const JETONS = readFileSync ( new URL ( './jetons.css' , import . meta . url ) , 'utf8' ) ;
const THEMES = [ 'clair' , 'sombre' ] ;
const NOMS _MARQUES = [
'cadenasFerme' , 'cadenasOuvert' , 'anneau' , 'hachure' , 'remplissagePlein' ,
[ADD] plan: one hue and pattern per conflict rule, legend, appartenance
The plan drew every conflict in one hue, so a table that seats colleagues
together looked like one where people meet again. Each active rule now has
its own reserved hue and pattern: same appartenance hatched one way, met
again hatched the other, back at a table dotted; rules on one table
overlap, the badge keeps the total. A legend from the view bar shows each
active rule's sample. A table's tooltip names the appartenance that brings
a pair together. The hues are validated by computation in both themes and
the spec (7.5, 12.7) follows. Checked: 2848 node, 580 browser tests.
--- FR ---
[ADD] plan : une teinte et une trame par règle, légende, appartenance
Le plan dessinait tout conflit d'une seule teinte : une table qui réunit
des collègues ressemblait à une table où des gens se revoient. Chaque
règle active a sa teinte réservée et sa trame : même appartenance hachurée
dans un sens, voisins revus dans l'autre, table revue en pointillé ; les
règles d'une table se superposent, la pastille garde le total. Une légende
dans la barre de vue montre l'échantillon de chaque règle active.
L'infobulle nomme l'appartenance qui réunit une paire. Teintes validées
par calcul dans les deux thèmes ; spec § 7.5, § 12.7. Vérifié : 2848, 580.
Assisted-by: Claude Opus 5.5
2026-10-08 04:33:43 -04:00
'contourConflit' , 'trameAppartenance' , 'trameVoisins' , 'trameTable' , 'pastille' , 'poignee' , 'gel' , 'miseEnEvidence' ,
[ADD] interface: colour tokens, two themes, checked palette, marks
The plan's colours carry meaning — a conflict, a reservation, a mode — so
they must stay readable for every reader and in both themes. jetons.css
defines the tokens for the light and dark themes, set by data-theme on the
root; palette.js reads them from the stylesheet text and checks, by
computation, contrast to WCAG and separation under the three
dichromacies, keeping the conflict hue reserved. The theme follows the
system at each start and the operator's choice lasts the session.
Checked: 1709 node and 43 browser tests.
--- FR ---
[ADD] interface : jetons de couleur, deux thèmes, palette, marques
Les couleurs du plan portent un sens — un conflit, une réservation, un mode
— et doivent rester lisibles pour tout lecteur et dans les deux thèmes.
jetons.css définit les jetons des thèmes clair et sombre, posés par
data-theme sur la racine ; palette.js les lit dans le texte de la feuille
et contrôle, par calcul, le contraste au sens des WCAG et la séparation
sous les trois dichromaties, la teinte du conflit restant réservée. Le
thème suit le système à chaque démarrage ; le choix de l'opérateur vaut
pour la séance.
Vérifié : 1709 node et 43 navigateur.
Assisted-by: Claude Opus 5.5
2026-10-07 02:33:12 -04:00
'selection' , 'cadreLecture' , 'cadreEcriture' , 'cadreBloque' , 'focus' ,
[ADD] print: preview screen, printable sheet, paper question
Printed pages must show exactly what will come out of the printer. An
Imprimer button in the event header opens a preview screen where each page
is a sheet at paper size, light whatever the theme, with its footer and,
under the strict draft rule, BROUILLON in outline; a proposal shown on a
retained plan prints as a draft. The paper is asked once per machine and
can be changed there. The table sheets offer one sheet per round. A failed
print shows IMPRESSION_ECHEC. The captures are republished with the button.
Checked: red first; 3651 node, 707 browser and 101 long tests green from
the index alone.
--- FR ---
[ADD] impression : aperçu, feuille imprimable, question du papier
Une page imprimée doit montrer exactement ce que l'imprimante rendra. Un
bouton Imprimer de la tête de l'événement ouvre un aperçu où chaque page
est une feuille au format du papier, claire quel que soit le thème, avec
son pied et, sous la règle stricte, BROUILLON au trait ; une proposition
montrée sur un plan retenu s'imprime en brouillon. Le papier se demande une
fois par machine et s'y change. Les feuilles par table offrent une feuille
par tour. Une impression échouée affiche IMPRESSION_ECHEC. Les captures
sont republiées avec le bouton.
Vérifié : rouge d'abord ; 3651 node, 707 navigateur et 101 longues vertes
depuis l'index seul.
Assisted-by: Claude Opus 5.5
2026-10-09 17:09:29 -04:00
'contourTable' , 'contourChaise' , 'echelle' , 'fantome' , 'chargement' , 'filigrane' ,
[ADD] interface: colour tokens, two themes, checked palette, marks
The plan's colours carry meaning — a conflict, a reservation, a mode — so
they must stay readable for every reader and in both themes. jetons.css
defines the tokens for the light and dark themes, set by data-theme on the
root; palette.js reads them from the stylesheet text and checks, by
computation, contrast to WCAG and separation under the three
dichromacies, keeping the conflict hue reserved. The theme follows the
system at each start and the operator's choice lasts the session.
Checked: 1709 node and 43 browser tests.
--- FR ---
[ADD] interface : jetons de couleur, deux thèmes, palette, marques
Les couleurs du plan portent un sens — un conflit, une réservation, un mode
— et doivent rester lisibles pour tout lecteur et dans les deux thèmes.
jetons.css définit les jetons des thèmes clair et sombre, posés par
data-theme sur la racine ; palette.js les lit dans le texte de la feuille
et contrôle, par calcul, le contraste au sens des WCAG et la séparation
sous les trois dichromaties, la teinte du conflit restant réservée. Le
thème suit le système à chaque démarrage ; le choix de l'opérateur vaut
pour la séance.
Vérifié : 1709 node et 43 navigateur.
Assisted-by: Claude Opus 5.5
2026-10-07 02:33:12 -04:00
] ;
// Les remplissages d'une chaise : fond, pleine, et les deux couleurs de la
// hachure — ses traits sur le fond de la chaise.
const REMPLISSAGES _CHAISE = [ '--couleur-chaise-fond' , '--couleur-chaise-pleine' , '--couleur-hachure' ] ;
// Fonds minimaux des marques de désignation et du fantôme. « chaise » vaut
// chacun des remplissages d'une chaise : la marque se pose sur une chaise
// vide, pourvue ou à pourvoir.
const c = ( nom ) => ` --couleur- ${ nom } ` ;
const FONDS _REQUIS = {
focus : [ ... [ 'page-fond' , 'bandeau-fond' , 'sol' , 'table-fond' ] . map ( c ) , ... REMPLISSAGES _CHAISE ] ,
selection : [ ... [ 'page-fond' , 'sol' , 'table-fond' ] . map ( c ) , ... REMPLISSAGES _CHAISE ] ,
miseEnEvidence : [ ... [ 'page-fond' , 'sol' , 'table-fond' ] . map ( c ) , ... REMPLISSAGES _CHAISE ] ,
fantome : [ ... [ 'sol' , 'table-fond' ] . map ( c ) , ... REMPLISSAGES _CHAISE ] ,
} ;
const parNom = ( registre , nom ) => registre . find ( ( e ) => e . nom === nom ) ;
describe ( 'registre des marques' , ( ) => {
[ADD] print: preview screen, printable sheet, paper question
Printed pages must show exactly what will come out of the printer. An
Imprimer button in the event header opens a preview screen where each page
is a sheet at paper size, light whatever the theme, with its footer and,
under the strict draft rule, BROUILLON in outline; a proposal shown on a
retained plan prints as a draft. The paper is asked once per machine and
can be changed there. The table sheets offer one sheet per round. A failed
print shows IMPRESSION_ECHEC. The captures are republished with the button.
Checked: red first; 3651 node, 707 browser and 101 long tests green from
the index alone.
--- FR ---
[ADD] impression : aperçu, feuille imprimable, question du papier
Une page imprimée doit montrer exactement ce que l'imprimante rendra. Un
bouton Imprimer de la tête de l'événement ouvre un aperçu où chaque page
est une feuille au format du papier, claire quel que soit le thème, avec
son pied et, sous la règle stricte, BROUILLON au trait ; une proposition
montrée sur un plan retenu s'imprime en brouillon. Le papier se demande une
fois par machine et s'y change. Les feuilles par table offrent une feuille
par tour. Une impression échouée affiche IMPRESSION_ECHEC. Les captures
sont republiées avec le bouton.
Vérifié : rouge d'abord ; 3651 node, 707 navigateur et 101 longues vertes
depuis l'index seul.
Assisted-by: Claude Opus 5.5
2026-10-09 17:09:29 -04:00
test ( 'les vingt-quatre marques du contrat, noms uniques, seuil 3, au moins un fond chacune' , ( ) => {
[ADD] interface: colour tokens, two themes, checked palette, marks
The plan's colours carry meaning — a conflict, a reservation, a mode — so
they must stay readable for every reader and in both themes. jetons.css
defines the tokens for the light and dark themes, set by data-theme on the
root; palette.js reads them from the stylesheet text and checks, by
computation, contrast to WCAG and separation under the three
dichromacies, keeping the conflict hue reserved. The theme follows the
system at each start and the operator's choice lasts the session.
Checked: 1709 node and 43 browser tests.
--- FR ---
[ADD] interface : jetons de couleur, deux thèmes, palette, marques
Les couleurs du plan portent un sens — un conflit, une réservation, un mode
— et doivent rester lisibles pour tout lecteur et dans les deux thèmes.
jetons.css définit les jetons des thèmes clair et sombre, posés par
data-theme sur la racine ; palette.js les lit dans le texte de la feuille
et contrôle, par calcul, le contraste au sens des WCAG et la séparation
sous les trois dichromaties, la teinte du conflit restant réservée. Le
thème suit le système à chaque démarrage ; le choix de l'opérateur vaut
pour la séance.
Vérifié : 1709 node et 43 navigateur.
Assisted-by: Claude Opus 5.5
2026-10-07 02:33:12 -04:00
assert . equal ( MARQUES . length , NOMS _MARQUES . length ) ;
assert . deepEqual ( MARQUES . map ( ( m ) => m . nom ) , NOMS _MARQUES ) ;
assert . equal ( new Set ( MARQUES . map ( ( m ) => m . nom ) ) . size , MARQUES . length ) ;
for ( const marque of MARQUES ) {
assert . deepEqual ( Object . keys ( marque ) . sort ( ) , [ 'fonds' , 'jeton' , 'nom' , 'seuil' ] , marque . nom ) ;
assert . equal ( marque . seuil , 3 , marque . nom ) ;
assert . ok ( marque . fonds . length > 0 , marque . nom ) ;
assert . equal ( new Set ( marque . fonds ) . size , marque . fonds . length , ` ${ marque . nom } : fond en double ` ) ;
}
} ) ;
test ( 'le registre est figé' , ( ) => {
assert . ok ( Object . isFrozen ( MARQUES ) && Object . isFrozen ( TEXTES ) ) ;
assert . ok ( MARQUES . every ( ( m ) => Object . isFrozen ( m ) && Object . isFrozen ( m . fonds ) ) ) ;
assert . ok ( TEXTES . every ( ( m ) => Object . isFrozen ( m ) && Object . isFrozen ( m . fonds ) ) ) ;
} ) ;
test ( 'le focus, la sélection, la mise en évidence et le fantôme se mesurent sur chaque fond où ils se peignent, chaque remplissage de chaise compris' , ( ) => {
for ( const nom of [ 'focus' , 'selection' , 'miseEnEvidence' , 'fantome' ] ) {
const marque = parNom ( MARQUES , nom ) ;
assert . notEqual ( marque , undefined , nom ) ;
for ( const fond of FONDS _REQUIS [ nom ] ) {
assert . ok ( marque . fonds . includes ( fond ) , ` ${ nom } : ${ fond } ` ) ;
}
}
} ) ;
test ( 'une marque posée sur une chaise se mesure sur chacun de ses remplissages' , ( ) => {
const surChaise = [ 'cadenasFerme' , 'cadenasOuvert' , 'anneau' ] ;
for ( const nom of surChaise ) {
for ( const fond of REMPLISSAGES _CHAISE ) {
assert . ok ( parNom ( MARQUES , nom ) . fonds . includes ( fond ) , ` ${ nom } : ${ fond } ` ) ;
}
}
assert . deepEqual ( parNom ( MARQUES , 'hachure' ) . fonds , [ '--couleur-chaise-fond' ] ) ;
} ) ;
test ( 'chaque jeton et chaque fond du registre existe dans les deux thèmes' , ( ) => {
[ADD] interface: visual foundations, pills, cards, icons, navy header
Screens need colour that separates information without ever carrying it
alone. Tokens gain state, membership and status tints whose marks hold
3:1 and texts 4.5:1 in both themes and under three dichromacies, and
every hue stays 30 degrees from the reserved conflict hues. Commands get
three levels; Pastille, Carte and an icon module join the primitives;
memberships map to six stable tints over sorted names. A pill label
wraps and never truncates, and keeps one line beside a nowrap neighbour.
Checked: node 3949; browser 767, only the walkthrough captures differ.
--- FR ---
[ADD] interface : fondations, pastilles, cartes, icônes, bandeau marine
Les écrans ont besoin d'une couleur qui distingue l'information sans
jamais la porter seule. Les jetons gagnent des teintes d'état,
d'appartenance et de statut dont les marques tiennent 3:1 et les textes
4,5:1 dans les deux thèmes et sous trois dichromaties, chaque teinte à
30 degrés des teintes de conflit réservées. Les commandes ont trois
niveaux ; Pastille, Carte et un module d'icônes rejoignent les
primitives ; les appartenances reçoivent six teintes stables sur les
noms triés. Un libellé de pastille se replie, jamais tronqué.
Vérifié : node 3949 ; navigateur 767, seules les captures du parcours.
Assisted-by: Claude Opus 5.5
2026-10-10 22:59:51 -04:00
const entrees = [ ... MARQUES , ... TEXTES , ... SIGNES ] ;
[ADD] interface: colour tokens, two themes, checked palette, marks
The plan's colours carry meaning — a conflict, a reservation, a mode — so
they must stay readable for every reader and in both themes. jetons.css
defines the tokens for the light and dark themes, set by data-theme on the
root; palette.js reads them from the stylesheet text and checks, by
computation, contrast to WCAG and separation under the three
dichromacies, keeping the conflict hue reserved. The theme follows the
system at each start and the operator's choice lasts the session.
Checked: 1709 node and 43 browser tests.
--- FR ---
[ADD] interface : jetons de couleur, deux thèmes, palette, marques
Les couleurs du plan portent un sens — un conflit, une réservation, un mode
— et doivent rester lisibles pour tout lecteur et dans les deux thèmes.
jetons.css définit les jetons des thèmes clair et sombre, posés par
data-theme sur la racine ; palette.js les lit dans le texte de la feuille
et contrôle, par calcul, le contraste au sens des WCAG et la séparation
sous les trois dichromaties, la teinte du conflit restant réservée. Le
thème suit le système à chaque démarrage ; le choix de l'opérateur vaut
pour la séance.
Vérifié : 1709 node et 43 navigateur.
Assisted-by: Claude Opus 5.5
2026-10-07 02:33:12 -04:00
assert . ok ( entrees . length > 20 ) ;
for ( const theme of THEMES ) {
const jetons = lireJetons ( JETONS , theme ) ;
for ( const entree of entrees ) {
for ( const nom of [ entree . jeton , ... entree . fonds ] ) {
assert . ok ( jetons . has ( nom ) , ` ${ theme } : ${ entree . nom } → ${ nom } ` ) ;
}
}
}
} ) ;
} ) ;
[ADD] print: preview screen, printable sheet, paper question
Printed pages must show exactly what will come out of the printer. An
Imprimer button in the event header opens a preview screen where each page
is a sheet at paper size, light whatever the theme, with its footer and,
under the strict draft rule, BROUILLON in outline; a proposal shown on a
retained plan prints as a draft. The paper is asked once per machine and
can be changed there. The table sheets offer one sheet per round. A failed
print shows IMPRESSION_ECHEC. The captures are republished with the button.
Checked: red first; 3651 node, 707 browser and 101 long tests green from
the index alone.
--- FR ---
[ADD] impression : aperçu, feuille imprimable, question du papier
Une page imprimée doit montrer exactement ce que l'imprimante rendra. Un
bouton Imprimer de la tête de l'événement ouvre un aperçu où chaque page
est une feuille au format du papier, claire quel que soit le thème, avec
son pied et, sous la règle stricte, BROUILLON au trait ; une proposition
montrée sur un plan retenu s'imprime en brouillon. Le papier se demande une
fois par machine et s'y change. Les feuilles par table offrent une feuille
par tour. Une impression échouée affiche IMPRESSION_ECHEC. Les captures
sont republiées avec le bouton.
Vérifié : rouge d'abord ; 3651 node, 707 navigateur et 101 longues vertes
depuis l'index seul.
Assisted-by: Claude Opus 5.5
2026-10-09 17:09:29 -04:00
describe ( 'le filigrane BROUILLON sur le papier (§ 11.7, § 14.5)' , ( ) => {
test ( 'une marque du registre, peinte de --couleur-filigrane sur le papier, à 3:1' , ( ) => {
const filigrane = parNom ( MARQUES , 'filigrane' ) ;
assert . deepEqual ( { ... filigrane , fonds : [ ... filigrane . fonds ] } , {
nom : 'filigrane' ,
jeton : '--couleur-filigrane' ,
fonds : [ '--couleur-papier' ] ,
seuil : 3 ,
} ) ;
} ) ;
test ( 'le papier est clair dans les deux thèmes : le filigrane et le papier gardent leur valeur d’ un thème à l’ autre, et le papier est celle du clair' , ( ) => {
const [ clair , sombre ] = THEMES . map ( ( theme ) => lireJetons ( JETONS , theme ) ) ;
for ( const nom of [ '--couleur-filigrane' , '--couleur-papier' ] ) {
assert . notEqual ( clair . get ( nom ) , undefined , nom ) ;
assert . deepEqual ( sombre . get ( nom ) , clair . get ( nom ) , nom ) ;
}
assert . deepEqual ( clair . get ( '--couleur-papier' ) , [ 255 , 255 , 255 , 1 ] ) ;
} ) ;
} ) ;
[ADD] plan: one hue and pattern per conflict rule, legend, appartenance
The plan drew every conflict in one hue, so a table that seats colleagues
together looked like one where people meet again. Each active rule now has
its own reserved hue and pattern: same appartenance hatched one way, met
again hatched the other, back at a table dotted; rules on one table
overlap, the badge keeps the total. A legend from the view bar shows each
active rule's sample. A table's tooltip names the appartenance that brings
a pair together. The hues are validated by computation in both themes and
the spec (7.5, 12.7) follows. Checked: 2848 node, 580 browser tests.
--- FR ---
[ADD] plan : une teinte et une trame par règle, légende, appartenance
Le plan dessinait tout conflit d'une seule teinte : une table qui réunit
des collègues ressemblait à une table où des gens se revoient. Chaque
règle active a sa teinte réservée et sa trame : même appartenance hachurée
dans un sens, voisins revus dans l'autre, table revue en pointillé ; les
règles d'une table se superposent, la pastille garde le total. Une légende
dans la barre de vue montre l'échantillon de chaque règle active.
L'infobulle nomme l'appartenance qui réunit une paire. Teintes validées
par calcul dans les deux thèmes ; spec § 7.5, § 12.7. Vérifié : 2848, 580.
Assisted-by: Claude Opus 5.5
2026-10-08 04:33:43 -04:00
describe ( 'les trois sortes de conflit (§ 7.5, § 12.7)' , ( ) => {
test ( 'une par règle localisable, dans l’ ordre du moteur : sa règle, la marque de sa trame, le jeton de sa teinte, la forme de son motif' , ( ) => {
assert . deepEqual (
CONFLITS . map ( ( c ) => [ c . regle , c . marque , c . jeton , c . forme ] ) ,
[
[ 'separerAppartenances' , 'trameAppartenance' , '--couleur-conflit-appartenance' , 'hachuresDescendantes' ] ,
[ 'nouveauxVoisins' , 'trameVoisins' , '--couleur-conflit-voisins' , 'hachuresMontantes' ] ,
[ 'nouvelleTable' , 'trameTable' , '--couleur-conflit-table' , 'points' ] ,
] ,
) ;
assert . ok ( CONFLITS . every ( ( c ) => Object . keys ( c ) . sort ( ) . join ( ) === 'forme,jeton,marque,regle' ) ) ;
assert . ok ( Object . isFrozen ( CONFLITS ) && CONFLITS . every ( ( c ) => Object . isFrozen ( c ) ) ) ;
assert . deepEqual ( JETONS _CONFLIT , CONFLITS . map ( ( { jeton } ) => jeton ) ) ;
assert . ok ( Object . isFrozen ( JETONS _CONFLIT ) ) ;
// Les seuils d'écart perçu : entre deux teintes de conflit, et d'une
// teinte de conflit à une autre marque du plan.
[ADD] interface: visual foundations, pills, cards, icons, navy header
Screens need colour that separates information without ever carrying it
alone. Tokens gain state, membership and status tints whose marks hold
3:1 and texts 4.5:1 in both themes and under three dichromacies, and
every hue stays 30 degrees from the reserved conflict hues. Commands get
three levels; Pastille, Carte and an icon module join the primitives;
memberships map to six stable tints over sorted names. A pill label
wraps and never truncates, and keeps one line beside a nowrap neighbour.
Checked: node 3949; browser 767, only the walkthrough captures differ.
--- FR ---
[ADD] interface : fondations, pastilles, cartes, icônes, bandeau marine
Les écrans ont besoin d'une couleur qui distingue l'information sans
jamais la porter seule. Les jetons gagnent des teintes d'état,
d'appartenance et de statut dont les marques tiennent 3:1 et les textes
4,5:1 dans les deux thèmes et sous trois dichromaties, chaque teinte à
30 degrés des teintes de conflit réservées. Les commandes ont trois
niveaux ; Pastille, Carte et un module d'icônes rejoignent les
primitives ; les appartenances reçoivent six teintes stables sur les
noms triés. Un libellé de pastille se replie, jamais tronqué.
Vérifié : node 3949 ; navigateur 767, seules les captures du parcours.
Assisted-by: Claude Opus 5.5
2026-10-10 22:59:51 -04:00
assert . deepEqual ( SEPARATIONS , { entreConflits : 12 , autresMarques : 5 , entreAppartenances : 10 , clarteAppartenances : 10 } ) ;
[ADD] plan: one hue and pattern per conflict rule, legend, appartenance
The plan drew every conflict in one hue, so a table that seats colleagues
together looked like one where people meet again. Each active rule now has
its own reserved hue and pattern: same appartenance hatched one way, met
again hatched the other, back at a table dotted; rules on one table
overlap, the badge keeps the total. A legend from the view bar shows each
active rule's sample. A table's tooltip names the appartenance that brings
a pair together. The hues are validated by computation in both themes and
the spec (7.5, 12.7) follows. Checked: 2848 node, 580 browser tests.
--- FR ---
[ADD] plan : une teinte et une trame par règle, légende, appartenance
Le plan dessinait tout conflit d'une seule teinte : une table qui réunit
des collègues ressemblait à une table où des gens se revoient. Chaque
règle active a sa teinte réservée et sa trame : même appartenance hachurée
dans un sens, voisins revus dans l'autre, table revue en pointillé ; les
règles d'une table se superposent, la pastille garde le total. Une légende
dans la barre de vue montre l'échantillon de chaque règle active.
L'infobulle nomme l'appartenance qui réunit une paire. Teintes validées
par calcul dans les deux thèmes ; spec § 7.5, § 12.7. Vérifié : 2848, 580.
Assisted-by: Claude Opus 5.5
2026-10-08 04:33:43 -04:00
assert . ok ( Object . isFrozen ( SEPARATIONS ) ) ;
} ) ;
test ( 'chaque trame est au registre, peinte de son jeton sur le fond du plateau' , ( ) => {
for ( const { marque , jeton } of CONFLITS ) {
const entree = parNom ( MARQUES , marque ) ;
assert . notEqual ( entree , undefined , marque ) ;
assert . equal ( entree . jeton , jeton , marque ) ;
assert . deepEqual ( entree . fonds , [ '--couleur-table-fond' ] , marque ) ;
}
} ) ;
test ( 'teinte réservée au registre : une teinte de conflit ne peint que sa trame, aucune autre marque ni aucun texte' , ( ) => {
[ADD] interface: visual foundations, pills, cards, icons, navy header
Screens need colour that separates information without ever carrying it
alone. Tokens gain state, membership and status tints whose marks hold
3:1 and texts 4.5:1 in both themes and under three dichromacies, and
every hue stays 30 degrees from the reserved conflict hues. Commands get
three levels; Pastille, Carte and an icon module join the primitives;
memberships map to six stable tints over sorted names. A pill label
wraps and never truncates, and keeps one line beside a nowrap neighbour.
Checked: node 3949; browser 767, only the walkthrough captures differ.
--- FR ---
[ADD] interface : fondations, pastilles, cartes, icônes, bandeau marine
Les écrans ont besoin d'une couleur qui distingue l'information sans
jamais la porter seule. Les jetons gagnent des teintes d'état,
d'appartenance et de statut dont les marques tiennent 3:1 et les textes
4,5:1 dans les deux thèmes et sous trois dichromaties, chaque teinte à
30 degrés des teintes de conflit réservées. Les commandes ont trois
niveaux ; Pastille, Carte et un module d'icônes rejoignent les
primitives ; les appartenances reçoivent six teintes stables sur les
noms triés. Un libellé de pastille se replie, jamais tronqué.
Vérifié : node 3949 ; navigateur 767, seules les captures du parcours.
Assisted-by: Claude Opus 5.5
2026-10-10 22:59:51 -04:00
const peintes = [ ... MARQUES , ... TEXTES , ... SIGNES ] . filter ( ( e ) => JETONS _CONFLIT . includes ( e . jeton ) || e . fonds . some ( ( f ) => JETONS _CONFLIT . includes ( f ) ) ) ;
[ADD] plan: one hue and pattern per conflict rule, legend, appartenance
The plan drew every conflict in one hue, so a table that seats colleagues
together looked like one where people meet again. Each active rule now has
its own reserved hue and pattern: same appartenance hatched one way, met
again hatched the other, back at a table dotted; rules on one table
overlap, the badge keeps the total. A legend from the view bar shows each
active rule's sample. A table's tooltip names the appartenance that brings
a pair together. The hues are validated by computation in both themes and
the spec (7.5, 12.7) follows. Checked: 2848 node, 580 browser tests.
--- FR ---
[ADD] plan : une teinte et une trame par règle, légende, appartenance
Le plan dessinait tout conflit d'une seule teinte : une table qui réunit
des collègues ressemblait à une table où des gens se revoient. Chaque
règle active a sa teinte réservée et sa trame : même appartenance hachurée
dans un sens, voisins revus dans l'autre, table revue en pointillé ; les
règles d'une table se superposent, la pastille garde le total. Une légende
dans la barre de vue montre l'échantillon de chaque règle active.
L'infobulle nomme l'appartenance qui réunit une paire. Teintes validées
par calcul dans les deux thèmes ; spec § 7.5, § 12.7. Vérifié : 2848, 580.
Assisted-by: Claude Opus 5.5
2026-10-08 04:33:43 -04:00
assert . deepEqual ( peintes . map ( ( e ) => e . nom ) , CONFLITS . map ( ( { marque } ) => marque ) ) ;
// Le contour épaissi d'une table en conflit est commun aux trois règles :
// il ne porte aucune de leurs teintes.
assert . ok ( ! JETONS _CONFLIT . includes ( parNom ( MARQUES , 'contourConflit' ) . jeton ) ) ;
} ) ;
} ) ;
[ADD] interface: colour tokens, two themes, checked palette, marks
The plan's colours carry meaning — a conflict, a reservation, a mode — so
they must stay readable for every reader and in both themes. jetons.css
defines the tokens for the light and dark themes, set by data-theme on the
root; palette.js reads them from the stylesheet text and checks, by
computation, contrast to WCAG and separation under the three
dichromacies, keeping the conflict hue reserved. The theme follows the
system at each start and the operator's choice lasts the session.
Checked: 1709 node and 43 browser tests.
--- FR ---
[ADD] interface : jetons de couleur, deux thèmes, palette, marques
Les couleurs du plan portent un sens — un conflit, une réservation, un mode
— et doivent rester lisibles pour tout lecteur et dans les deux thèmes.
jetons.css définit les jetons des thèmes clair et sombre, posés par
data-theme sur la racine ; palette.js les lit dans le texte de la feuille
et contrôle, par calcul, le contraste au sens des WCAG et la séparation
sous les trois dichromaties, la teinte du conflit restant réservée. Le
thème suit le système à chaque démarrage ; le choix de l'opérateur vaut
pour la séance.
Vérifié : 1709 node et 43 navigateur.
Assisted-by: Claude Opus 5.5
2026-10-07 02:33:12 -04:00
describe ( 'registre des textes' , ( ) => {
[ADD] interface: visual foundations, pills, cards, icons, navy header
Screens need colour that separates information without ever carrying it
alone. Tokens gain state, membership and status tints whose marks hold
3:1 and texts 4.5:1 in both themes and under three dichromacies, and
every hue stays 30 degrees from the reserved conflict hues. Commands get
three levels; Pastille, Carte and an icon module join the primitives;
memberships map to six stable tints over sorted names. A pill label
wraps and never truncates, and keeps one line beside a nowrap neighbour.
Checked: node 3949; browser 767, only the walkthrough captures differ.
--- FR ---
[ADD] interface : fondations, pastilles, cartes, icônes, bandeau marine
Les écrans ont besoin d'une couleur qui distingue l'information sans
jamais la porter seule. Les jetons gagnent des teintes d'état,
d'appartenance et de statut dont les marques tiennent 3:1 et les textes
4,5:1 dans les deux thèmes et sous trois dichromaties, chaque teinte à
30 degrés des teintes de conflit réservées. Les commandes ont trois
niveaux ; Pastille, Carte et un module d'icônes rejoignent les
primitives ; les appartenances reçoivent six teintes stables sur les
noms triés. Un libellé de pastille se replie, jamais tronqué.
Vérifié : node 3949 ; navigateur 767, seules les captures du parcours.
Assisted-by: Claude Opus 5.5
2026-10-10 22:59:51 -04:00
test ( 'page, secondaire, bandeau, refus, avis, listes du plan, pastille, puis les textes des cartes, des étiquettes, de la bande de mode, du bandeau, de l’ action et des messages ; seuil 4,5' , ( ) => {
assert . deepEqual ( TEXTES . map ( ( t ) => t . nom ) , [
'page' , 'secondaire' , 'bandeau' , 'refus' , 'avis' , 'listes' , 'pastille' ,
'carte' , 'secondaireCarte' , 'etiquette' , 'bandeMode' , 'bandeauSecondaire' , 'bandeauChoisi' , 'action' , 'lien' , 'information' ,
] ) ;
[ADD] interface: colour tokens, two themes, checked palette, marks
The plan's colours carry meaning — a conflict, a reservation, a mode — so
they must stay readable for every reader and in both themes. jetons.css
defines the tokens for the light and dark themes, set by data-theme on the
root; palette.js reads them from the stylesheet text and checks, by
computation, contrast to WCAG and separation under the three
dichromacies, keeping the conflict hue reserved. The theme follows the
system at each start and the operator's choice lasts the session.
Checked: 1709 node and 43 browser tests.
--- FR ---
[ADD] interface : jetons de couleur, deux thèmes, palette, marques
Les couleurs du plan portent un sens — un conflit, une réservation, un mode
— et doivent rester lisibles pour tout lecteur et dans les deux thèmes.
jetons.css définit les jetons des thèmes clair et sombre, posés par
data-theme sur la racine ; palette.js les lit dans le texte de la feuille
et contrôle, par calcul, le contraste au sens des WCAG et la séparation
sous les trois dichromaties, la teinte du conflit restant réservée. Le
thème suit le système à chaque démarrage ; le choix de l'opérateur vaut
pour la séance.
Vérifié : 1709 node et 43 navigateur.
Assisted-by: Claude Opus 5.5
2026-10-07 02:33:12 -04:00
assert . ok ( TEXTES . every ( ( t ) => t . seuil === 4.5 && t . fonds . length > 0 ) ) ;
[ADD] interface: visual foundations, pills, cards, icons, navy header
Screens need colour that separates information without ever carrying it
alone. Tokens gain state, membership and status tints whose marks hold
3:1 and texts 4.5:1 in both themes and under three dichromacies, and
every hue stays 30 degrees from the reserved conflict hues. Commands get
three levels; Pastille, Carte and an icon module join the primitives;
memberships map to six stable tints over sorted names. A pill label
wraps and never truncates, and keeps one line beside a nowrap neighbour.
Checked: node 3949; browser 767, only the walkthrough captures differ.
--- FR ---
[ADD] interface : fondations, pastilles, cartes, icônes, bandeau marine
Les écrans ont besoin d'une couleur qui distingue l'information sans
jamais la porter seule. Les jetons gagnent des teintes d'état,
d'appartenance et de statut dont les marques tiennent 3:1 et les textes
4,5:1 dans les deux thèmes et sous trois dichromaties, chaque teinte à
30 degrés des teintes de conflit réservées. Les commandes ont trois
niveaux ; Pastille, Carte et un module d'icônes rejoignent les
primitives ; les appartenances reçoivent six teintes stables sur les
noms triés. Un libellé de pastille se replie, jamais tronqué.
Vérifié : node 3949 ; navigateur 767, seules les captures du parcours.
Assisted-by: Claude Opus 5.5
2026-10-10 22:59:51 -04:00
assert . equal ( new Set ( TEXTES . map ( ( t ) => t . nom ) ) . size , TEXTES . length ) ;
[ADD] interface: colour tokens, two themes, checked palette, marks
The plan's colours carry meaning — a conflict, a reservation, a mode — so
they must stay readable for every reader and in both themes. jetons.css
defines the tokens for the light and dark themes, set by data-theme on the
root; palette.js reads them from the stylesheet text and checks, by
computation, contrast to WCAG and separation under the three
dichromacies, keeping the conflict hue reserved. The theme follows the
system at each start and the operator's choice lasts the session.
Checked: 1709 node and 43 browser tests.
--- FR ---
[ADD] interface : jetons de couleur, deux thèmes, palette, marques
Les couleurs du plan portent un sens — un conflit, une réservation, un mode
— et doivent rester lisibles pour tout lecteur et dans les deux thèmes.
jetons.css définit les jetons des thèmes clair et sombre, posés par
data-theme sur la racine ; palette.js les lit dans le texte de la feuille
et contrôle, par calcul, le contraste au sens des WCAG et la séparation
sous les trois dichromaties, la teinte du conflit restant réservée. Le
thème suit le système à chaque démarrage ; le choix de l'opérateur vaut
pour la séance.
Vérifié : 1709 node et 43 navigateur.
Assisted-by: Claude Opus 5.5
2026-10-07 02:33:12 -04:00
assert . deepEqual ( parNom ( TEXTES , 'listes' ) . fonds , [ '--couleur-sol' ] ) ;
assert . deepEqual ( parNom ( TEXTES , 'pastille' ) . fonds , [ '--couleur-pastille-fond' ] ) ;
} ) ;
[ADD] interface: visual foundations, pills, cards, icons, navy header
Screens need colour that separates information without ever carrying it
alone. Tokens gain state, membership and status tints whose marks hold
3:1 and texts 4.5:1 in both themes and under three dichromacies, and
every hue stays 30 degrees from the reserved conflict hues. Commands get
three levels; Pastille, Carte and an icon module join the primitives;
memberships map to six stable tints over sorted names. A pill label
wraps and never truncates, and keeps one line beside a nowrap neighbour.
Checked: node 3949; browser 767, only the walkthrough captures differ.
--- FR ---
[ADD] interface : fondations, pastilles, cartes, icônes, bandeau marine
Les écrans ont besoin d'une couleur qui distingue l'information sans
jamais la porter seule. Les jetons gagnent des teintes d'état,
d'appartenance et de statut dont les marques tiennent 3:1 et les textes
4,5:1 dans les deux thèmes et sous trois dichromaties, chaque teinte à
30 degrés des teintes de conflit réservées. Les commandes ont trois
niveaux ; Pastille, Carte et un module d'icônes rejoignent les
primitives ; les appartenances reçoivent six teintes stables sur les
noms triés. Un libellé de pastille se replie, jamais tronqué.
Vérifié : node 3949 ; navigateur 767, seules les captures du parcours.
Assisted-by: Claude Opus 5.5
2026-10-10 22:59:51 -04:00
test ( 'le texte d’ une étiquette est l’ encre de la page, sur chaque fond teinté d’ une pastille (§ 12.7) ; celui d’ un message, l’ encre de son message sur son fond' , ( ) => {
const etiquette = parNom ( TEXTES , 'etiquette' ) ;
assert . equal ( etiquette . jeton , '--couleur-page-texte' ) ;
const fondsTeintes = [
'neutre' , 'etat-brouillon' , 'etat-propose' , 'etat-retenu' , 'etat-bloque' , 'avis' , 'refus' , 'information' ,
... TEINTES _APPARTENANCE . map ( ( { rang } ) => ` appartenance- ${ rang } ` ) ,
] . map ( ( teinte ) => ` --couleur- ${ teinte } -fond ` ) ;
for ( const fond of fondsTeintes ) assert . ok ( etiquette . fonds . includes ( fond ) , fond ) ;
assert . deepEqual ( parNom ( TEXTES , 'bandeMode' ) . fonds , [ 'ecriture' , 'lecture' , 'bloque' ] . map ( ( m ) => ` --couleur-mode- ${ m } -fond ` ) ) ;
for ( const message of [ 'refus' , 'avis' , 'information' ] ) {
const entree = parNom ( TEXTES , message ) ;
assert . equal ( entree . jeton , ` --couleur- ${ message } ` , message ) ;
for ( const fond of [ ` --couleur- ${ message } -fond ` , '--couleur-page-fond' , '--couleur-carte-fond' ] ) assert . ok ( entree . fonds . includes ( fond ) , ` ${ message } : ${ fond } ` ) ;
}
} ) ;
} ) ;
describe ( 'les signes des pastilles, des messages, de la bande de mode et de l’ action' , ( ) => {
const NOMS _SIGNES = [
'etatBrouillon' , 'etatPropose' , 'etatRetenu' , 'etatBloque' , 'neutre' ,
'appartenance1' , 'appartenance2' , 'appartenance3' , 'appartenance4' , 'appartenance5' , 'appartenance6' ,
'signeAvis' , 'signeRefus' , 'signeInformation' , 'bandeEcriture' , 'bandeLecture' , 'bandeBloque' , 'actionPrincipale' ,
] ;
test ( 'le registre des signes : noms uniques, hors de MARQUES, seuil 3, figé' , ( ) => {
assert . deepEqual ( SIGNES . map ( ( s ) => s . nom ) , NOMS _SIGNES ) ;
assert . ok ( Object . isFrozen ( SIGNES ) && SIGNES . every ( ( s ) => Object . isFrozen ( s ) && Object . isFrozen ( s . fonds ) ) ) ;
assert . ok ( SIGNES . every ( ( s ) => s . seuil === 3 && s . fonds . length > 0 ) ) ;
const marques = new Set ( MARQUES . map ( ( m ) => m . nom ) ) ;
assert . deepEqual ( SIGNES . filter ( ( s ) => marques . has ( s . nom ) ) . map ( ( s ) => s . nom ) , [ ] ) ;
} ) ;
test ( 'le signe d’ un état, du neutre ou d’ une appartenance se mesure sur son fond teinté, la carte, son fond sourd et la page' , ( ) => {
const teintes = [
[ 'etatBrouillon' , 'etat-brouillon' ] , [ 'etatPropose' , 'etat-propose' ] , [ 'etatRetenu' , 'etat-retenu' ] , [ 'etatBloque' , 'etat-bloque' ] , [ 'neutre' , 'neutre' ] ,
... TEINTES _APPARTENANCE . map ( ( { rang } ) => [ ` appartenance ${ rang } ` , ` appartenance- ${ rang } ` ] ) ,
] ;
for ( const [ nom , teinte ] of teintes ) {
const signe = parNom ( SIGNES , nom ) ;
assert . equal ( signe . jeton , ` --couleur- ${ teinte } -marque ` , nom ) ;
assert . deepEqual ( signe . fonds , [ ` --couleur- ${ teinte } -fond ` , '--couleur-carte-fond' , '--couleur-carte-fond-sourd' , '--couleur-page-fond' ] , nom ) ;
}
// La bande de mode reprend la teinte du cadre de mode, sur son propre fond.
for ( const mode of [ 'Ecriture' , 'Lecture' , 'Bloque' ] ) {
const signe = parNom ( SIGNES , ` bande ${ mode } ` ) ;
assert . deepEqual ( [ signe . jeton , ... signe . fonds ] , [ ` --couleur-cadre- ${ mode . toLowerCase ( ) } ` , ` --couleur-mode- ${ mode . toLowerCase ( ) } -fond ` ] ) ;
}
} ) ;
test ( 'chaque signe tient 3:1 sur chacun de ses fonds, dans les deux thèmes, sous les trois simulations' , ( ) => {
assert . deepEqual ( verifierPalette ( JETONS , SIGNES ) , [ ] ) ;
} ) ;
test ( 'le focus se mesure aussi sur la carte et son fond sourd' , ( ) => {
for ( const fond of [ '--couleur-carte-fond' , '--couleur-carte-fond-sourd' ] ) assert . ok ( parNom ( MARQUES , 'focus' ) . fonds . includes ( fond ) , fond ) ;
} ) ;
} ) ;
describe ( 'la palette des appartenances (listes seulement)' , ( ) => {
test ( 'six teintes au plus, rangées de 1 à n, chacune un fond et une marque' , ( ) => {
assert . ok ( TEINTES _APPARTENANCE . length > 0 && TEINTES _APPARTENANCE . length <= 6 ) ;
assert . ok ( Object . isFrozen ( TEINTES _APPARTENANCE ) && TEINTES _APPARTENANCE . every ( Object . isFrozen ) ) ;
TEINTES _APPARTENANCE . forEach ( ( entree , i ) => {
assert . deepEqual ( entree , { rang : i + 1 , marque : ` --couleur-appartenance- ${ i + 1 } -marque ` , fond : ` --couleur-appartenance- ${ i + 1 } -fond ` } ) ;
} ) ;
} ) ;
const marques = ( ) => TEINTES _APPARTENANCE . map ( ( { marque } ) => marque ) ;
test ( 'chaque marque est chromatique dans les deux thèmes : la teinte la porte, avec le nom' , ( ) => {
for ( const theme of THEMES ) {
const jetons = lireJetons ( JETONS , theme ) ;
for ( const nom of marques ( ) ) assert . notEqual ( teinte ( jetons . get ( nom ) ) , null , ` ${ theme } : ${ nom } ` ) ;
}
} ) ;
test ( ` les marques se séparent deux à deux de ${ SEPARATIONS . entreAppartenances } au moins (OKLab × 100), dans les deux thèmes, en couleurs d’ origine et sous les trois simulations ` , ( ) => {
assert . deepEqual ( verifierSeparation ( JETONS , marques ( ) , [ ] , SEPARATIONS . entreAppartenances ) , [ ] ) ;
} ) ;
test ( ` deux marques de teintes voisines se distinguent aussi en clarté, de ${ SEPARATIONS . clarteAppartenances } au moins (L d’ OKLab × 100) ` , ( ) => {
assert . deepEqual ( verifierClartes ( JETONS , marques ( ) , SEPARATIONS . clarteAppartenances ) , [ ] ) ;
} ) ;
[ADD] interface: colour tokens, two themes, checked palette, marks
The plan's colours carry meaning — a conflict, a reservation, a mode — so
they must stay readable for every reader and in both themes. jetons.css
defines the tokens for the light and dark themes, set by data-theme on the
root; palette.js reads them from the stylesheet text and checks, by
computation, contrast to WCAG and separation under the three
dichromacies, keeping the conflict hue reserved. The theme follows the
system at each start and the operator's choice lasts the session.
Checked: 1709 node and 43 browser tests.
--- FR ---
[ADD] interface : jetons de couleur, deux thèmes, palette, marques
Les couleurs du plan portent un sens — un conflit, une réservation, un mode
— et doivent rester lisibles pour tout lecteur et dans les deux thèmes.
jetons.css définit les jetons des thèmes clair et sombre, posés par
data-theme sur la racine ; palette.js les lit dans le texte de la feuille
et contrôle, par calcul, le contraste au sens des WCAG et la séparation
sous les trois dichromaties, la teinte du conflit restant réservée. Le
thème suit le système à chaque démarrage ; le choix de l'opérateur vaut
pour la séance.
Vérifié : 1709 node et 43 navigateur.
Assisted-by: Claude Opus 5.5
2026-10-07 02:33:12 -04:00
} ) ;
describe ( 'palette de jetons.css validée par calcul (§ 12.7, § 14.5)' , ( ) => {
test ( 'aucun jeton de texte ou de marque, ni aucun de leurs fonds, n’ a de canal alpha' , ( ) => {
[ADD] interface: visual foundations, pills, cards, icons, navy header
Screens need colour that separates information without ever carrying it
alone. Tokens gain state, membership and status tints whose marks hold
3:1 and texts 4.5:1 in both themes and under three dichromacies, and
every hue stays 30 degrees from the reserved conflict hues. Commands get
three levels; Pastille, Carte and an icon module join the primitives;
memberships map to six stable tints over sorted names. A pill label
wraps and never truncates, and keeps one line beside a nowrap neighbour.
Checked: node 3949; browser 767, only the walkthrough captures differ.
--- FR ---
[ADD] interface : fondations, pastilles, cartes, icônes, bandeau marine
Les écrans ont besoin d'une couleur qui distingue l'information sans
jamais la porter seule. Les jetons gagnent des teintes d'état,
d'appartenance et de statut dont les marques tiennent 3:1 et les textes
4,5:1 dans les deux thèmes et sous trois dichromaties, chaque teinte à
30 degrés des teintes de conflit réservées. Les commandes ont trois
niveaux ; Pastille, Carte et un module d'icônes rejoignent les
primitives ; les appartenances reçoivent six teintes stables sur les
noms triés. Un libellé de pastille se replie, jamais tronqué.
Vérifié : node 3949 ; navigateur 767, seules les captures du parcours.
Assisted-by: Claude Opus 5.5
2026-10-10 22:59:51 -04:00
const noms = new Set ( [ ... MARQUES , ... TEXTES , ... SIGNES ] . flatMap ( ( e ) => [ e . jeton , ... e . fonds ] ) ) ;
[ADD] interface: colour tokens, two themes, checked palette, marks
The plan's colours carry meaning — a conflict, a reservation, a mode — so
they must stay readable for every reader and in both themes. jetons.css
defines the tokens for the light and dark themes, set by data-theme on the
root; palette.js reads them from the stylesheet text and checks, by
computation, contrast to WCAG and separation under the three
dichromacies, keeping the conflict hue reserved. The theme follows the
system at each start and the operator's choice lasts the session.
Checked: 1709 node and 43 browser tests.
--- FR ---
[ADD] interface : jetons de couleur, deux thèmes, palette, marques
Les couleurs du plan portent un sens — un conflit, une réservation, un mode
— et doivent rester lisibles pour tout lecteur et dans les deux thèmes.
jetons.css définit les jetons des thèmes clair et sombre, posés par
data-theme sur la racine ; palette.js les lit dans le texte de la feuille
et contrôle, par calcul, le contraste au sens des WCAG et la séparation
sous les trois dichromaties, la teinte du conflit restant réservée. Le
thème suit le système à chaque démarrage ; le choix de l'opérateur vaut
pour la séance.
Vérifié : 1709 node et 43 navigateur.
Assisted-by: Claude Opus 5.5
2026-10-07 02:33:12 -04:00
assert . ok ( noms . size > 20 ) ;
const blocs = lireBlocs ( JETONS ) ;
for ( const theme of THEMES ) {
const selecteur = ` :root[data-theme=' ${ theme } '] ` ;
const brutes = new Map (
blocs . filter ( ( b ) => b . selecteurs . includes ( selecteur ) ) . flatMap ( ( b ) => [ ... b . declarations ] ) ,
) ;
const jetons = lireJetons ( JETONS , theme ) ;
for ( const nom of noms ) {
assert . equal ( jetons . get ( nom ) [ 3 ] , 1 , ` ${ theme } : ${ nom } ` ) ;
assert . doesNotMatch (
brutes . get ( nom ) ,
/rgba|hsla|transparent|#[0-9a-f]{8}\b|#[0-9a-f]{4}\b|\/\s*[\d.]+%?\s*\)/i ,
` ${ theme } : ${ nom } ` ,
) ;
}
}
} ) ;
test ( 'chaque marque tient 3:1 sur chacun de ses fonds, dans les deux thèmes, sous les trois simulations' , ( ) => {
assert . deepEqual ( verifierPalette ( JETONS , MARQUES ) , [ ] ) ;
} ) ;
test ( 'chaque texte tient 4,5:1 sur chacun de ses fonds, dans les deux thèmes, sous les trois simulations' , ( ) => {
assert . deepEqual ( verifierPalette ( JETONS , TEXTES ) , [ ] ) ;
} ) ;
[ADD] plan: one hue and pattern per conflict rule, legend, appartenance
The plan drew every conflict in one hue, so a table that seats colleagues
together looked like one where people meet again. Each active rule now has
its own reserved hue and pattern: same appartenance hatched one way, met
again hatched the other, back at a table dotted; rules on one table
overlap, the badge keeps the total. A legend from the view bar shows each
active rule's sample. A table's tooltip names the appartenance that brings
a pair together. The hues are validated by computation in both themes and
the spec (7.5, 12.7) follows. Checked: 2848 node, 580 browser tests.
--- FR ---
[ADD] plan : une teinte et une trame par règle, légende, appartenance
Le plan dessinait tout conflit d'une seule teinte : une table qui réunit
des collègues ressemblait à une table où des gens se revoient. Chaque
règle active a sa teinte réservée et sa trame : même appartenance hachurée
dans un sens, voisins revus dans l'autre, table revue en pointillé ; les
règles d'une table se superposent, la pastille garde le total. Une légende
dans la barre de vue montre l'échantillon de chaque règle active.
L'infobulle nomme l'appartenance qui réunit une paire. Teintes validées
par calcul dans les deux thèmes ; spec § 7.5, § 12.7. Vérifié : 2848, 580.
Assisted-by: Claude Opus 5.5
2026-10-08 04:33:43 -04:00
// Les autres marques du plan : celles qui se peignent sur le sol, le
// plateau ou une chaise, trames de conflit exceptées, chaque jeton une fois.
const FONDS _DU _PLAN = new Set ( [ '--couleur-sol' , '--couleur-table-fond' , ... REMPLISSAGES _CHAISE ] ) ;
const autresMarquesDuPlan = ( ) => [
... new Set ( MARQUES . filter ( ( m ) => ! JETONS _CONFLIT . includes ( m . jeton ) && m . fonds . some ( ( f ) => FONDS _DU _PLAN . has ( f ) ) ) . map ( ( m ) => m . jeton ) ) ,
] ;
test ( ` les trois teintes de conflit se séparent deux à deux de ${ SEPARATIONS . entreConflits } au moins (OKLab × 100), dans les deux thèmes, en couleurs d’ origine et sous les trois simulations ` , ( ) => {
assert . equal ( JETONS _CONFLIT . length , 3 ) ;
assert . deepEqual ( verifierSeparation ( JETONS , JETONS _CONFLIT , [ ] , SEPARATIONS . entreConflits ) , [ ] ) ;
} ) ;
test ( ` chaque teinte de conflit se sépare de ${ SEPARATIONS . autresMarques } au moins de chaque autre marque du plan, dans les deux thèmes, sous les trois simulations ` , ( ) => {
const autres = autresMarquesDuPlan ( ) ;
assert . ok ( autres . length >= 10 , ` ${ autres . length } autres marques ` ) ;
for ( const jeton of [ '--couleur-gel' , '--couleur-mise-en-evidence' , '--couleur-selection' , '--couleur-focus' , '--couleur-fantome' , '--couleur-pastille-fond' ] ) {
assert . ok ( autres . includes ( jeton ) , jeton ) ;
}
assert . deepEqual ( verifierSeparation ( JETONS , JETONS _CONFLIT , autres , SEPARATIONS . autresMarques ) , [ ] ) ;
} ) ;
[ADD] interface: colour tokens, two themes, checked palette, marks
The plan's colours carry meaning — a conflict, a reservation, a mode — so
they must stay readable for every reader and in both themes. jetons.css
defines the tokens for the light and dark themes, set by data-theme on the
root; palette.js reads them from the stylesheet text and checks, by
computation, contrast to WCAG and separation under the three
dichromacies, keeping the conflict hue reserved. The theme follows the
system at each start and the operator's choice lasts the session.
Checked: 1709 node and 43 browser tests.
--- FR ---
[ADD] interface : jetons de couleur, deux thèmes, palette, marques
Les couleurs du plan portent un sens — un conflit, une réservation, un mode
— et doivent rester lisibles pour tout lecteur et dans les deux thèmes.
jetons.css définit les jetons des thèmes clair et sombre, posés par
data-theme sur la racine ; palette.js les lit dans le texte de la feuille
et contrôle, par calcul, le contraste au sens des WCAG et la séparation
sous les trois dichromaties, la teinte du conflit restant réservée. Le
thème suit le système à chaque démarrage ; le choix de l'opérateur vaut
pour la séance.
Vérifié : 1709 node et 43 navigateur.
Assisted-by: Claude Opus 5.5
2026-10-07 02:33:12 -04:00
} ) ;