Files
colibre/src/assets/css/style.css
T
2026-07-13 23:48:54 +02:00

1116 lines
22 KiB
CSS

@import url(https://fonts.bunny.net/css?family=fira-code:400|inter:400,600|akshar:500);
/* ==========================================================================
Variables
========================================================================== */
:root {
--main-font: "Inter", sans-serif;
--bs-font-monospace: "Fira Code";
--primary-color: rgb(179, 56, 33);
--primary-color-text: #b33821;
/* Dash 4 utilise cette variable pour l'état actif/focus des composants
dcc (Dropdown, Input, Tabs, DatePicker...) ; défaut violet remplacé
par notre couleur primaire. */
--Dash-Fill-Interactive-Strong: var(--primary-color);
/* Override AG Grid */
--ag-font-family: var(--main-font);
}
/* ==========================================================================
Base & Reset
========================================================================== */
body {
font-family: "Inter", sans-serif;
font-weight: 400;
background-color: rgb(255 240 240 / 40%);
-moz-osx-font-smoothing: grayscale;
-webkit-font-smoothing: antialiased;
font-smooth: always;
font-display: swap;
}
strong,
b {
font-weight: 600 !important;
}
h1,
h2,
h3,
h4,
h5 {
font-weight: 600;
}
h3 {
margin: 36px 0 20px 0;
}
/* ==========================================================================
Boutons — charte à 3 rôles (couleur = fonction, remplissage = emphase)
Voir docs/superpowers/specs/2026-06-30-charte-boutons-design.md
Override scopé aux classes .btn-* uniquement (n'affecte pas les alertes,
badges, ni text-danger qui héritent de la sémantique Simplex).
========================================================================== */
:root {
--btn-terracotta: #b33821;
--btn-terracotta-text: #fff;
--btn-secondary-text: #344054;
--btn-secondary-border: #5a6570;
--btn-secondary-hover-bg: #f1f3f5;
--btn-danger: #c0392b;
--btn-danger-text: #fff;
}
/* Base commune : rayon + typo */
.btn {
border-radius: 3px;
font-family: "Inter", sans-serif;
font-weight: 400;
}
/* --- PRIMARY plein : action principale validante (1 par contexte) --- */
button.btn.btn-primary,
a.btn.btn-primary,
button.show-hide {
display: block;
outline: 0;
color: var(--btn-terracotta-text);
border: 0;
height: 30px;
padding-top: 2px;
background-image: linear-gradient(
rgb(209, 96, 73),
rgb(179, 56, 33) 26%,
rgb(159, 36, 22)
);
}
button.btn.btn-primary:hover,
a.btn.btn-primary:hover,
button.show-hide:hover {
color: var(--btn-terracotta-text);
background-image: linear-gradient(
rgb(239, 126, 103),
rgb(209, 86, 63) 26%,
rgb(189, 66, 52)
);
}
/* --- PRIMARY outline : action affirmative de moindre emphase --- */
.btn.btn-outline-primary {
color: var(--btn-terracotta);
border: 1px solid var(--btn-terracotta);
background-color: transparent;
background-image: none;
}
.btn.btn-outline-primary:hover,
.btn.btn-outline-primary:focus-visible {
color: var(--btn-terracotta-text);
background-color: var(--btn-terracotta);
border-color: var(--btn-terracotta);
}
/* --- SECONDARY : action neutre / alternative (gris ardoise) --- */
.btn.btn-secondary,
.btn.btn-outline-secondary {
color: var(--btn-secondary-text);
border: 1px solid var(--btn-secondary-border);
background-color: transparent;
background-image: none;
}
.btn.btn-secondary:hover,
.btn.btn-secondary:focus-visible,
.btn.btn-outline-secondary:hover,
.btn.btn-outline-secondary:focus-visible {
color: var(--btn-secondary-text);
background-color: var(--btn-secondary-hover-bg);
border-color: var(--btn-secondary-border);
}
/* --- DANGER outline : action destructive dans le flux courant --- */
.btn.btn-outline-danger {
color: var(--btn-danger);
border: 1px solid var(--btn-danger);
background-color: transparent;
background-image: none;
}
.btn.btn-outline-danger:hover,
.btn.btn-outline-danger:focus-visible {
color: var(--btn-danger-text);
background-color: var(--btn-danger);
border-color: var(--btn-danger);
}
/* --- DANGER plein : confirmation finale destructive (modale) --- */
.btn.btn-danger {
color: var(--btn-danger-text);
border: 1px solid var(--btn-danger);
background-color: var(--btn-danger);
background-image: none;
}
.btn.btn-danger:hover,
.btn.btn-danger:focus-visible {
color: var(--btn-danger-text);
background-color: #a93226;
border-color: #a93226;
}
/* --- État désactivé commun (conserve l'existant) --- */
.btn[disabled],
button[disabled] {
border-color: #ccc;
color: #666;
background-image: none;
}
@media (prefers-reduced-motion: no-preference) {
.btn {
transition: background-color 0.15s ease, color 0.15s ease,
border-color 0.15s ease;
}
}
/* ==========================================================================
Layout
========================================================================== */
#_pages_content {
padding: 28px 24px 0 24px;
}
#header > * {
margin: 0 0 20px 0px;
}
/* ==========================================================================
Components
========================================================================== */
/* --- Navigation & Header --- */
a.logo {
color: black;
text-decoration: none;
}
a.logo > h1 {
font-weight: 400;
margin: 0;
line-height: 1;
}
.logo-wrapper {
display: flex;
align-items: baseline;
}
p.version {
margin: 0 0 0 12px;
font-family: "Fira Code";
font-size: 0.9rem;
}
p.version > a {
text-decoration: none;
margin-top: 10px;
}
.navbar-brand {
margin-right: 2px;
}
.navbar-nav .nav-link.active {
font-weight: 600;
}
.account-nav .nav-link {
color: inherit;
padding-left: 10px;
border-left: 3px solid transparent;
border-radius: 0;
}
.account-nav .nav-link:hover {
background-color: rgba(255, 240, 240, 0.9);
}
.account-nav .nav-link.active {
color: #d9230f;
font-weight: 600;
border-left-color: #d9230f;
background-color: transparent;
}
#announcements {
margin: 25px 40px 0 60px;
font-size: 90%;
max-width: 900px;
}
#announcements p {
margin-bottom: 0.2rem;
}
.seeBorder {
border: dotted 1px green;
}
/* --- Search Page --- */
.tagline {
text-align: center;
font-size: 120%;
display: block;
margin-top: 50px;
}
#search {
margin: 30px auto 0px auto;
width: 500px;
font-size: 16px;
height: 30px;
display: block;
}
.search_options {
margin: 16px auto;
width: 450px;
}
.search_options input {
margin-right: 12px;
}
#search_results td[data-dash-column="Département"] {
text-wrap: wrap;
}
/* Account form */
input[type="email"] {
max-width: 400px;
}
/* --- Dashboard inputs --- */
#filters .row > * {
margin-bottom: 6px;
}
#filters input[type="text"],
#filters input[type="number"] {
border: 1px #ccc solid;
border-radius: 3px;
padding-left: 8px;
}
/* --- Tables (Dash & Custom) --- */
/* Table Menu (Exports etc) */
.table-menu {
font-size: 16px;
margin: 12px 0 12px 0;
display: flex;
align-items: center;
flex-wrap: wrap;
}
.table-menu > * {
margin: 8px 16px 8px 0;
}
/* Barre d'outils du tableau (/tableau) : une rangée d'actions compactes
au-dessus d'une ligne d'infos discrète. .table-menu (autres pages) intacte. */
.table-toolbar {
display: flex;
flex-wrap: wrap;
align-items: center;
margin: 14px 0 6px 0;
}
.table-toolbar > * {
margin: 0 12px 8px 0;
}
/* Mode d'emploi : aide auxiliaire, rejetée en fin de barre sans toucher au DOM */
.table-toolbar #tableau_help_open {
order: 1;
}
.table-meta {
margin: 0 0 16px 0;
color: #666;
font-size: 14px;
}
/* Raison du téléchargement bloqué : visible (pas une infobulle), mise en avant
sobrement avec la couleur terracotta de la marque. */
.table-meta .dl-hint {
color: #b33821;
}
/* Légende des boutons en tête du mode d'emploi : boutons reproduits à
l'identique mais inertes, alignés en face de leur fonction. */
.help-legend-table {
border-collapse: collapse;
}
.help-legend-table td {
padding: 4px 16px 4px 0;
vertical-align: middle;
}
.help-legend-btn {
white-space: nowrap;
}
.help-legend .btn {
pointer-events: none;
}
#source_table {
margin-bottom: 25px;
}
#source_table p {
line-height: 1.5;
}
/* Dash Table Overrides */
.column-header--sort {
margin-left: 3px;
}
dash-table-container dash-spreadsheet-menu table.cell-table {
margin-right: 8px;
margin-lef: 8px;
}
table.cell-table,
table.cell-table tr {
border-color: #fff;
padding: 0;
border-collapse: separate !important;
/* Required for border-radius */
border-spacing: 0;
}
table.cell-table th {
border-collapse: separate !important;
border-spacing: 0;
}
.dash-table-container p {
margin-bottom: 0;
}
.dash-table-container
.dash-spreadsheet-container
.dash-spreadsheet-inner
th.dash-header,
.dash-table-container
.dash-spreadsheet-container
.dash-spreadsheet-inner
th.dash-select-header {
margin: 0;
color: white;
font-family: "Inter", sans-serif;
text-align: left;
font-weight: 600;
padding: 2px 12px 4px 2px;
border: 1px solid rgb(179, 56, 33) !important;
background-color: rgb(179, 56, 33);
border-bottom: none !important;
height: 32px;
}
.dash-table-container
.dash-spreadsheet-container
.dash-spreadsheet-inner
table.cell-table
tr:first-of-type
th.dash-header:first-of-type,
.dash-table-container
.dash-spreadsheet-container
.dash-spreadsheet-inner
table.cell-table
tr:first-of-type
th.dash-select-header:first-of-type {
border-top-left-radius: 3px !important;
}
.dash-table-container
.dash-spreadsheet-container
.dash-spreadsheet-inner
table.cell-table
tr:first-of-type
th.dash-header:last-of-type {
border-top-right-radius: 3px !important;
}
/* Dash Filters */
.dash-table-container
.dash-spreadsheet-container
.dash-spreadsheet-inner
.cell-table
.dash-filter
input[type="text"] {
border-color: #ccc;
border-style: solid;
border-width: 1px;
border-radius: 3px;
height: 28px;
font-family: "Fira Code";
caret-color: #000;
background-color: rgb(250 250 250);
text-align: left !important;
padding: 1px 2px 0 2px;
vertical-align: center;
}
.dash-table-container
.dash-spreadsheet-container
.dash-spreadsheet-inner
.cell-table
.dash-filter
input[type="text"]::placeholder {
color: #999;
}
.dash-filter--case {
display: none;
}
.dash-table-container
.dash-spreadsheet-container
.dash-spreadsheet-inner
.cell-table
th.dash-filter {
background-color: #ccc;
}
/* Custom Marches Table */
.dash-table-container
.dash-spreadsheet-container
.dash-spreadsheet-inner
.cell-table
td {
padding-left: 5px;
padding-right: 5px;
}
.dash-table-container
.dash-spreadsheet-container
.dash-spreadsheet-inner
td
div.dash-cell-value.cell-markdown {
font-family: "Inter", sans-serif !important;
font-weight: 400;
}
/* Bootstrap's CSS cascade defeats dash_table's own inline `display: none`
toggle on dropdown-cell menus (react-select v1 renders the menu hidden
first to measure it, then flips to visible — Bootstrap's reset wins that
fight, so the menu never becomes visible even though the cell's "open"
state is correct). Applies to every editable dropdown column in every
DataTable, not just one table. See:
https://github.com/plotly/dash-table/issues/956 */
.Select-menu-outer {
display: block !important;
}
.marches_table.stuck {
position: relative;
right: 200px;
}
/* ===== Tableaux : en-têtes collants + scroll horizontal (#82) ===== */
/* Contenir le scroll horizontal dans le conteneur Dash (élimine la scrollbar native en bas de page) */
/* overflow-y:clip évite la conversion CSS visible→auto qui ajouterait une scrollbar verticale */
.marches_table .dash-spreadsheet-container {
overflow-x: hidden !important;
overflow-y: clip !important;
}
/* L'inner reste visible pour que le tableau se déploie librement en largeur */
.marches_table .dash-spreadsheet-inner {
overflow: visible !important;
}
.marches_table .cell-table tr:nth-child(even) td {
background-color: rgb(255 240 240 / 40%);
}
/* Colonne "Marché" : lien loupe centré et sans soulignement */
table.cell-table td[data-dash-column="marche"] .dash-cell-value {
text-align: center !important;
}
td[data-dash-column="marche"] a {
text-decoration: none;
}
th[data-dash-column="marche"].dash-filter input {
display: none;
}
/* Barre de défilement horizontale, collée en haut du tableau */
.marches_table .dt-hscroll {
position: sticky;
top: 0;
z-index: 11;
height: 12px;
background-color: #e0e0e0;
overflow: hidden;
cursor: pointer;
}
.marches_table .dt-hscroll.is-hidden {
display: none;
}
/* Thumb custom — toujours visible, draggable */
.marches_table .dt-hscroll-thumb {
position: absolute;
top: 2px;
height: calc(100% - 4px);
min-width: 40px;
background-color: orange;
border-radius: 8px;
cursor: grab;
user-select: none;
}
.marches_table .dt-hscroll-thumb:active {
cursor: grabbing;
}
/* Column Visibility Menu */
.column-actions {
margin-right: 8px;
}
.column-header--hide {
display: none;
}
button.show-hide {
position: relative;
width: 180px;
margin: 0 0 10px 0;
display: none;
}
/*
.show-hide::before {
background: inherit;
content: "Colonnes affichées";
position: absolute;
left: 5px;
right: 5px;
#column_list .show-hide,
#table .show-hide {
display: none;
}
.show-hide-menu-item > input {
margin-right: 10px;
} */
/* Override des styles AG Grid */
/* La ligne de filtres flottants reprend le fond des lignes paires (rosé),
distinct du fond rouge brique appliqué à la ligne d'en-têtes (theme
params AG Grid n'exposant pas de couleur de fond dédiée à cette ligne). */
.marches_table .ag-floating-filter {
background-color: var(--ag-odd-row-background-color);
}
.ag-row {
--ag-internal-content-line-height: 20px;
}
.ag-cell {
padding-top: 3px;
}
.ag-header-cell-text {
font-family: "Akshar", sans-serif;
font-size: 18px;
}
/* Lien "voir le marché" (loupe) : pas de soulignement, c'est une icône. */
.ag-cell[col-id="marche"] a {
text-decoration: none;
}
/* Numéro de ligne sous la loupe : repère de position pendant le défilement,
discret pour ne pas concurrencer le lien. */
.ag-cell[col-id="marche"] {
text-align: center;
}
.marche-row-number {
color: #bbb;
font-size: 12px;
line-height: 1.4;
}
/* Infobulle : largeur bornée avec retour à la ligne plutôt qu'une largeur
qui suit tout le texte. .ag-tooltip = infobulle native (ex. colonne
"objet" tronquée) ; .ag-tooltip-custom = infobulle rendue par un
tooltipComponent personnalisé (ex. en-têtes de colonnes, cf.
grid_column_defs) — AG Grid n'ajoute PAS la classe .ag-tooltip dans ce
cas, il faut donc cibler les deux. */
.ag-tooltip,
.ag-tooltip-custom {
max-width: 400px;
white-space: normal;
word-wrap: break-word;
background-color: #fdd;
}
/* .ag-tooltip-custom n'a, contrairement à .ag-tooltip, aucun style visuel
par défaut côté AG Grid (voir dash_ag_grid.min.js : seuls position/z-index
sont posés) — on reprend ici les mêmes variables de thème que .ag-tooltip
pour un rendu identique (bordure grise, padding, coins arrondis). */
.ag-tooltip-custom {
border: var(--ag-tooltip-border);
border-radius: var(--ag-border-radius);
color: var(--ag-tooltip-text-color);
padding: var(--ag-widget-container-vertical-padding)
var(--ag-widget-container-horizontal-padding);
}
/* fin overrides AG Grid*/
#btn-copy-url:before {
}
/* Dropdowns */
/* Bootstrap 5.3 redéfinit les variables --bs-dropdown-* SUR le sélecteur
.dropdown-menu : un override sur :root est masqué (déclaration composant plus
spécifique). On pose donc la surcharge sur .dropdown-menu. */
.dropdown-menu {
--bs-dropdown-link-hover-bg: rgba(255, 240, 240, 1);
--bs-dropdown-link-active-bg: rgba(255, 240, 240, 1);
}
.Select-placeholder {
color: #333 !important;
}
/* Checkboxes */
input[type="checkbox"] {
height: 17px;
width: 17px;
}
/* Tooltips */
.dash-tooltip,
.dash-table-tooltip {
color: #333;
width: 400px !important;
max-width: 400px !important;
height: 150px !important;
max-height: 150px !important;
overflow: hidden;
}
.dash-tooltip pre,
.dash-tooltip code {
overflow: hidden;
height: 150px;
text-wrap: wrap;
font-family: "Inter", sans-serif;
}
/* --- Organization Cards (Grid Items) --- */
#cards .card {
margin-bottom: 16px;
}
.org_infos > p {
margin: 8px 0;
}
/* --- About Page (A Propos) --- */
.a-propos-container {
display: flex;
flex-wrap: wrap;
align-items: flex-start;
position: relative;
max-width: 1200px;
margin: 0 auto;
}
.a-propos-content {
flex: 1 1 70%;
max-width: 75%;
padding-right: 40px;
}
.a-propos-toc {
flex: 0 0 25%;
max-width: 25%;
/* Keeps it from growing too large */
position: sticky;
top: 40px;
/* Sticks 40px from the top of the viewport */
border-left: 2px solid #333;
/* Dark vertical line like hedgedoc */
padding-left: 15px;
margin-top: 40px;
background-color: #fff;
/* Aligns visually with the first header */
}
/* TOC Links */
.toc-link {
display: block;
color: #666;
text-decoration: none;
font-size: 0.9em;
padding: 2px 0;
transition: color 0.2s, font-weight 0.2s;
line-height: 1.4;
}
.toc-link:hover {
color: #000;
text-decoration: none;
}
.toc-active {
color: #000;
font-weight: bold;
}
.toc-level-2 {
margin-left: 15px;
font-size: 0.85em;
}
.toc-header {
font-weight: bold;
margin-bottom: 10px;
display: block;
color: #333;
}
/* --- Misc & Utility --- */
#instructions {
max-width: 1000px;
}
details > div {
padding-top: 24px;
}
summary > h4 {
margin: 0;
display: inline;
}
/* ==========================================================================
Media Queries
========================================================================== */
@media (max-width: 992px) {
/* Navigation */
#announcements-nav {
display: none !important;
}
/* About Page */
.a-propos-content {
max-width: 100%;
padding-right: 0;
flex: 1 1 100%;
}
.a-propos-toc {
display: none;
}
}
input[type="number"]::-webkit-outer-spin-button,
input[type="number"]::-webkit-inner-spin-button {
-webkit-appearance: none;
margin: 0;
}
input[type="number"] {
-moz-appearance: textfield;
}
/* Dash 4 ajoute des boutons +/- (steppers) sur les dcc.Input type="number" ;
inutiles ici (pas d'incrémentation pertinente pour des montants), on les
masque pour que le champ récupère l'espace (flex: 1 1 0 sur l'input). */
.dash-input-stepper {
display: none;
}
/* ===== Page /etapes : graphique données par étape et par seuil ===== */
.etapes-chart-scroll {
overflow-x: auto;
margin: 1rem 0;
}
.etapes-chart {
min-width: 720px;
background: #fff;
border: 1px solid #d0d5dd;
border-radius: 8px;
overflow: hidden;
font-size: 13px;
display: grid;
grid-template-columns: 150px repeat(5, 1fr);
}
.etapes-corner {
border-bottom: 2px solid #344054;
}
.etapes-xhead {
grid-column: 2 / -1;
display: grid;
grid-template-columns: repeat(5, 1fr);
border-bottom: 2px solid #344054;
}
.etapes-xcell {
text-align: center;
padding: 6px 2px;
font-size: 11px;
color: #475467;
border-left: 1px dashed #d0d5dd;
}
.etapes-xcell strong {
display: block;
color: #101828;
font-size: 12px;
}
.etapes-stage {
padding: 14px 10px;
font-weight: 600;
color: #101828;
border-bottom: 1px solid #eaecf0;
display: flex;
align-items: center;
}
.etapes-stage small {
font-weight: 400;
color: #667085;
}
.etapes-lane {
grid-column: 2 / -1;
position: relative;
border-bottom: 1px solid #eaecf0;
min-height: 52px;
}
.etapes-segs {
position: absolute;
inset: 0;
display: grid;
grid-template-columns: repeat(5, 1fr);
}
.etapes-segs > div {
border-left: 1px dashed #eaecf0;
}
.etapes-bar {
position: absolute;
top: 9px;
height: 32px;
border-radius: 6px;
color: #fff;
font-size: 11px;
font-weight: 600;
display: flex;
align-items: center;
padding: 0 10px;
box-shadow: 0 1px 2px rgba(0, 0, 0, 0.12);
white-space: nowrap;
overflow: hidden;
cursor: pointer;
transition: filter 0.15s, box-shadow 0.15s;
}
.etapes-bar:hover {
filter: brightness(1.12);
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.22);
}
.etapes-empty {
color: #98a2b3;
font-style: italic;
padding: 14px;
display: flex;
align-items: center;
}
.etapes-note {
margin-top: 8px;
color: #667085;
font-size: 13px;
}
/* --- Vue mobile (liste par étape) : masquée par défaut --- */
.etapes-mobile {
display: none;
margin: 1rem 0;
}
.etapes-m-block {
border: 1px solid #d0d5dd;
border-radius: 8px;
margin-bottom: 12px;
overflow: hidden;
}
.etapes-m-header {
display: flex;
align-items: center;
justify-content: space-between;
background: #f9fafb;
border-bottom: 1px solid #eaecf0;
}
.etapes-m-stage {
margin: 0;
padding: 10px 12px;
font-size: 15px;
color: #101828;
}
.etapes-m-link {
background: none;
border: none;
color: #1570ef;
font-size: 12px;
font-weight: 600;
cursor: pointer;
padding: 0 12px;
white-space: nowrap;
}
.etapes-m-link:hover {
text-decoration: underline;
}
.etapes-m-item {
display: flex;
align-items: baseline;
gap: 8px;
padding: 8px 12px;
border-bottom: 1px solid #f2f4f7;
font-size: 13px;
}
.etapes-m-item:last-child {
border-bottom: none;
}
.etapes-m-item i {
width: 12px;
height: 12px;
border-radius: 3px;
flex: 0 0 auto;
position: relative;
top: 2px;
}
.etapes-m-label {
font-weight: 600;
color: #101828;
}
.etapes-m-seuil {
color: #667085;
}
.etapes-m-empty {
color: #98a2b3;
font-style: italic;
}
.etapes-detail {
margin: 1rem 0;
padding: 1rem 1.25rem;
border: 1px solid #d0d5dd;
border-radius: 8px;
background: #f9fafb;
}
.etapes-detail:empty {
display: none;
}
/* Roadmap */
.roadmap-vote-list input[type="text"] {
}
/* --- Bascule desktop / mobile au point de rupture 768 px --- */
@media (max-width: 768px) {
.etapes-chart-scroll {
display: none;
}
.etapes-mobile {
display: block;
}
}
/* Écran de chargement initial (avant hydratation de l'app Dash) */
._dash-loading {
position: fixed;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
font-size: 0;
}
._dash-loading::after {
content: "Chargement...";
font-size: 1.1rem;
color: #ccc;
}
.plan-selectable {
cursor: pointer;
}
.plan-selectable .card {
transition: background-color 0.15s, border-color 0.15s;
}
.plan-selectable.selected .card {
background-color: var(--bs-primary-bg-subtle);
border-color: var(--bs-primary);
}
/* Lien de partage affiché en texte (span) mais stylé comme un champ :
bordure gris clair, coins arrondis, texte légèrement plus petit. */
.share-url-text {
font-size: 90%;
padding: 0.2rem 0.5rem;
border: 1px solid var(--bs-border-color);
border-radius: 3px;
background-color: var(--bs-body-bg);
}