/* Copyright (c) 2025-2026 kwargs SRL, Bruxelles. Tous droits reserves.
   Styles communs aux pages "Revue" (/composer/revue/) et "Composition
   publique" (/composition/<uuid>/) : feuille CV. */

.compose-kicker {
    text-transform: uppercase;
    letter-spacing: .1em;
    font-size: .82rem;
    opacity: .65;
    font-weight: 600;
}


/* ── Feuille CV ────────────────────────────────────────────────────
   Anciennement carte (background + bordure + ombre) qui enveloppait
   l'ensemble Formation/Langues/Compétences. Formation et Langues
   ayant été extraites en row col-md-6, l'article ne porte plus que
   les Compétences et les autres sections sont nues. On retire la
   carte pour homogénéiser : reste juste l'espace au-dessus des
   indicateurs. */
.skills-sheet {
    margin-top: 1.5rem;
}

.cv-header {
    padding-bottom: 1rem;
    border-bottom: 2px solid var(--ks-emerald);
    margin-bottom: 1.6rem;
}
.cv-header .cv-kicker {
    text-transform: uppercase;
    letter-spacing: .15em;
    font-size: .72rem;
    font-weight: 700;
    opacity: .55;
    margin-bottom: .25rem;
}
.cv-header h2 {
    font-size: 1.6rem;
    font-weight: 700;
    margin: 0 0 .3rem 0;
}
.cv-header .cv-secondary {
    font-size: .9rem;
    opacity: .7;
}

.compose-section { margin-bottom: 1.6rem; }
.compose-section:last-child { margin-bottom: 0; }
.compose-section-title {
    display: flex;
    align-items: center;
    gap: .5rem;
    font-size: .78rem;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: .1em;
    padding-bottom: .4rem;
    margin-bottom: .7rem;
    border-bottom: 1px solid var(--bs-border-color);
}
.compose-section-title i { font-size: 1rem; }
.compose-edit {
    margin-left: auto;
    font-size: .75rem;
    text-transform: none;
    font-weight: 400;
    letter-spacing: 0;
    opacity: .55;
    text-decoration: none;
    color: inherit;
}
.compose-edit:hover { opacity: 1; }

.qualifications-list { list-style: none; padding: 0; margin: 0; }
.qualifications-list li {
    padding: .3rem 0;
    display: flex;
    align-items: baseline;
    gap: .7rem;
}
/* En dessous de lg (991.98px), le badge EQF + main sont empiles
   verticalement : la colonne Qualifications devient etroite des md
   (col-md-8 sur ecran moyen) et la mise en ligne ecraserait le
   libelle. Sur sm/xs, idem, lecture plus confortable en colonne. */
@media (max-width: 991.98px) {
    .qualifications-list li {
        flex-direction: column;
        align-items: flex-start;
        gap: .25rem;
    }
}
.qualifications-list .qualification-badge {
    flex: 0 0 auto;
    min-width: 3.4rem;
    padding: .15rem .4rem;
    font-size: .7rem;
    font-weight: 700;
    border-radius: .25rem;
    text-align: center;
    background: var(--ks-gold);
    color: var(--ks-navy);
}
/* Couleurs EQF graduées, alignées sur les chips de l'étape Qualification
   (cf. compose-chips.css). Ne se chargent pas via compose-chips.css ici,
   donc dupliquées avec scope .qualification-badge pour rester locales. */
.qualifications-list .qualification-badge.eqf-1 { background: #cbd5e1; color: #1e293b; }
.qualifications-list .qualification-badge.eqf-2 { background: #94a3b8; color: #ffffff; }
.qualifications-list .qualification-badge.eqf-3 { background: #7fb069; color: #ffffff; }
.qualifications-list .qualification-badge.eqf-4 { background: #2a9d5c; color: #ffffff; }
.qualifications-list .qualification-badge.eqf-5 { background: #56ACE0; color: #ffffff; }
.qualifications-list .qualification-badge.eqf-6 { background: #194F82; color: #ffffff; }
.qualifications-list .qualification-badge.eqf-7 { background: #FFC10D; color: #1e293b; }
.qualifications-list .qualification-badge.eqf-8 { background: #d6336c; color: #ffffff; }
.qualifications-list .qualification-main { flex: 1; font-size: .95rem; }
.qualifications-list .qualification-meta { opacity: .55; font-size: .82rem; }
.qualifications-list .qualification-sub {
    display: block;
    opacity: .55;
    font-size: .78rem;
    font-style: italic;
    margin-top: .1rem;
}

.languages-list { list-style: none; padding: 0; margin: 0; }
.languages-list li {
    display: flex;
    justify-content: space-between;
    align-items: baseline;
    padding: .35rem 0;
    border-bottom: 1px dotted var(--bs-border-color);
}
.languages-list li:last-child { border-bottom: none; }
.language-label-wrap {
    display: inline-flex;
    align-items: baseline;
    gap: .5rem;
    min-width: 0;
}
.language-flag {
    font-size: 1.05rem;
    line-height: 1;
    flex-shrink: 0;
}
.language-name { font-size: .95rem; font-weight: 500; }
.language-level {
    font-size: .82rem;
    opacity: .7;
    font-style: italic;
}
/* Niveau rendu en grille de 6 etoiles (A1=1 ... C2=6). Etoile
   pleine en or, etoile vide attenuee. Tooltip via data-tt
   (cf. app-tooltip.js) revele le libelle CEFR au survol. */
.language-stars {
    display: inline-flex;
    gap: .1rem;
    font-style: normal;
    font-size: .8rem;
    opacity: 1;
    color: var(--ks-gold);
    line-height: 1;
}
.language-stars .bi-star { opacity: .25; }
/* Niveau "langue maternelle" : meme grille de 6 etoiles gold que
   pour C2 (la maitrise est plenaire) mais chaque etoile recoit un
   lisere coral via -webkit-text-stroke pour marquer le statut
   hors-CEFR de langue maternelle. */
.language-native {
    display: inline-flex;
    gap: .1rem;
    font-style: normal;
    font-size: .8rem;
    opacity: 1;
    color: var(--ks-gold);
    line-height: 1;
}
.language-native .bi-star-fill {
    -webkit-text-stroke: 1.5px var(--ks-coral);
}

.cv-occupations { list-style: none; padding: 0; margin: 0; }
.cv-occupations li {
    padding: .3rem 0;
    font-size: .95rem;
}
.cv-occupations .isco-code {
    font-size: .72rem;
    opacity: .55;
    font-family: monospace;
    margin-left: .4rem;
}

/* Légende compacte au-dessus de la liste : explicite le code
   couleur (S savoir / C compétence) et les marqueurs corail
   (aptitude commune) et doré (aptitude phare). Rendue uniquement
   sur la page de revue (editable=True), pas sur les pages
   publiques où les chips parlent d'elles-mêmes. */
.skills-legend {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: .35rem .9rem;
    margin: 0 0 .9rem 0;
    font-size: .78rem;
    opacity: .8;
}
.skills-legend .legend-label {
    text-transform: uppercase;
    letter-spacing: .08em;
    font-weight: 700;
    opacity: .65;
    margin-right: .15rem;
}
.skills-legend .legend-label::after { content: " :"; }
.skills-legend .legend-item {
    display: inline-flex;
    align-items: center;
    gap: .35rem;
}
.skills-legend .legend-star {
    color: var(--ks-gold);
    font-size: .85rem;
    line-height: 1;
}

/* Liste des compétences sur les pages de revue / composition
   publique / CV / Offre : flex-wrap simple, identique au layout
   de #selected-list dans step_skills.html (« Ma sélection »).
   Pas de grille à colonnes : les chips s'enchaînent à largeur
   naturelle et passent à la ligne quand la rangée est pleine. */
.skills-list {
    list-style: none;
    padding: 0;
    margin: 0;
    display: flex;
    flex-wrap: wrap;
    gap: .5rem;
}

/* Chips des aptitudes : pill blanc avec bordure gris léger + tag
   S/C coloré à gauche. Style aligné sur la classe .chip de
   step_skills.html. Largeur naturelle (inline-flex) : la chip
   prend la place de son contenu. */
.skill-badge {
    display: inline-flex;
    align-items: center;
    gap: .4rem;
    padding: .4rem .75rem;
    border-radius: 2rem;
    background: var(--bs-body-bg);
    border: 1px solid var(--bs-border-color);
    color: var(--bs-body-color);
    font-size: .86rem;
    line-height: 1.2;
    font-weight: 400;
}

/* Tag S/C (Savoir vs Compétence) : badge mini coloré en début de
   chaque chip. Dupliqué de step_skills.html pour servir aussi sur
   les pages revue / composition publique / CV / Offre. Bleu
   profond pour les savoirs, émeraude pour les compétences. */
.skill-type-tag {
    font-size: .62rem;
    text-transform: uppercase;
    letter-spacing: .04em;
    padding: .1rem .4rem;
    border-radius: .25rem;
    color: #fff;
    font-weight: 600;
    flex-shrink: 0;
}
.skill-type-tag.knowledge { background: var(--ks-deep-blue); }
.skill-type-tag.competence { background: var(--ks-emerald); }
[data-bs-theme="dark"] .skill-type-tag.knowledge {
    background: var(--ks-sky);
    color: var(--ks-navy);
}

/* Aptitudes communes à plusieurs métiers de la composition :
   badge ×N corail à droite du label, signale le nombre
   d'occupations qui requièrent l'aptitude. */
.skill-shared-count {
    display: inline-block;
    font-size: .65rem;
    font-weight: 700;
    color: var(--ks-coral);
    background: rgba(var(--ks-danger-rgb), .15);
    border-radius: .4rem;
    padding: .1rem .35rem;
    line-height: 1;
    cursor: help;
    flex-shrink: 0;
}

/* Bouton étoile à droite des chips Compétences. Toggle entre vide
   (bi-star, opacité .35) et plein doré (bi-star-fill, opacité 1
   couleur gold). Cf. compose.toggle_featured_skill et JS
   compose-featured.js. */
.chip-star {
    background: transparent;
    border: 0;
    color: inherit;
    opacity: .35;
    cursor: pointer;
    padding: 0;
    font-size: .9rem;
    line-height: 1;
    margin-left: .15rem;
}
.chip-star:hover,
.chip-star:focus {
    opacity: 1;
    color: var(--ks-gold);
}
.chip-star[aria-pressed="true"] {
    opacity: 1;
    color: var(--ks-gold);
}

/* Variante non-éditable (pages publiques) : étoile pleine dorée
   purement décorative à la place du bouton. */
.chip-star-static {
    color: var(--ks-gold);
    margin-left: .15rem;
    font-size: .9rem;
    line-height: 1;
}

/* Chip phare : bordure dorée + fond légèrement teinté gold.
   Suffisamment marqué en mode clair (background body blanc) sans
   etre criard, et boost en mode sombre via le sélecteur dédié. */
.skill-badge.is-featured {
    border-color: var(--ks-gold);
    background: rgba(var(--ks-warning-rgb), .14);
}
[data-bs-theme="dark"] .skill-badge.is-featured {
    background: rgba(var(--ks-warning-rgb), .22);
}

/* Chip partagée (aptitude commune à >= 2 metiers de la composition) :
   bordure et fond corail subtil. Signal d'opportunité (le candidat
   joue sur plusieurs casquettes via cette aptitude).
   Defini APRES .is-featured dans le fichier : la cascade fait gagner
   coral pour une chip a la fois phare et commune. C'est volontaire,
   le bucket Phares signale deja le statut « phare » via la position
   et l'etoile, on garde la couleur coral pour ne pas perdre le
   signal « commune ». */
.skill-badge.is-shared {
    border-color: rgba(var(--ks-danger-rgb), .55);
    background: rgba(var(--ks-danger-rgb), .10);
}
[data-bs-theme="dark"] .skill-badge.is-shared {
    background: rgba(var(--ks-danger-rgb), .18);
}

.compose-empty {
    opacity: .5;
    font-size: .88rem;
    font-style: italic;
    margin: 0;
}

/* ── Cartes de regroupement des compétences ────────────────────────
   Les compétences sont scindées en 3 buckets pour faire ressortir
   la hiérarchie sémantique : Phares (choix candidat) | Communes
   (agrégat ESCO) | Autres. Pas de doublons : chaque chip apparaît
   dans une seule carte. Bordure gauche colorée comme accent
   discret pour distinguer les buckets sans charger visuellement. */
.skills-bucket {
    padding: .9rem 1.1rem;
    border: 1px solid var(--bs-border-color);
    border-left-width: 3px;
    border-radius: .55rem;
    background: var(--bs-body-bg);
    display: flex;
    flex-direction: column;
}
[data-bs-theme="dark"] .skills-bucket {
    background: var(--bs-tertiary-bg);
}
.skills-bucket-title {
    display: flex;
    align-items: center;
    gap: .45rem;
    font-size: .78rem;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: .08em;
    margin: 0 0 .7rem 0;
    padding-bottom: .4rem;
    border-bottom: 1px dashed var(--bs-border-color);
}
.skills-bucket-title i { font-size: .95rem; }
.skills-bucket-empty {
    margin: 0;
    font-size: .82rem;
    font-style: italic;
    opacity: .55;
}
/* Le partial _skills.html rend toujours <ul.skills-list> et
   <p.skills-bucket-empty> pour offrir au JS (compose-featured.js)
   des cibles stables quand il deplace une chip d'un bucket a
   l'autre. On masque le message d'empty des que la liste se
   peuple (et inversement). */
.skills-bucket:has(.skills-list > li) .skills-bucket-empty {
    display: none;
}

/* Les cartes Phares et Communes ne s'affichent pas tant qu'aucune
   chip ne s'y trouve. La col reste dans le DOM (cible stable pour
   la migration JS) mais est cachee jusqu'a ce qu'une chip y soit
   appendChild, moment ou :has(.skills-list > li) la revele.
   Communes peut etre vide si aucune skill n'est partagee ou si
   toutes les partagees sont marquees phares (donc migrees vers
   Phares). */
.phares-slot:not(:has(.skills-list > li)),
.communes-slot:not(:has(.skills-list > li)) {
    display: none;
}

/* Strategie inverse : par defaut Phares et Communes prennent toute
   la largeur (override du col-lg-6 de Bootstrap). Elles ne se
   reduisent a 50% que si la row contient les DEUX cartes peuplees
   simultanement. Plus robuste qu'un :not(:has(...)) qui peut etre
   capricieux selon les browsers. */
.phares-slot,
.communes-slot {
    width: 100%;
    max-width: 100%;
}
@media (min-width: 992px) {
    .row:has(.phares-slot:has(.skills-list > li)):has(.communes-slot:has(.skills-list > li)) > .phares-slot,
    .row:has(.phares-slot:has(.skills-list > li)):has(.communes-slot:has(.skills-list > li)) > .communes-slot {
        width: 50%;
        max-width: 50%;
    }
}

.skills-bucket-featured { border-left-color: var(--ks-gold); }
.skills-bucket-featured .skills-bucket-title i { color: var(--ks-gold); }

.skills-bucket-shared { border-left-color: var(--ks-coral); }
.skills-bucket-shared .skills-bucket-title i { color: var(--ks-coral); }

.skills-bucket-other .skills-bucket-title i { opacity: .5; }

/* Slot du toast d'erreur (limite phares atteinte) : rendue dans
   le template comme col-12 entre la rangee Phares/Communes et la
   carte Autres. Cachee tant qu'aucun message n'a ete pose, sinon
   le row gap est preserve par le retrait du flow. */
.chip-star-toast:empty {
    display: none;
}

/* ── Bandeau d'identité du candidat (page de revue) ──────────────
   Apparaît uniquement quand l'utilisateur est connecté, en tête de
   /composer/revue/. Deux colonnes : identité (avatar + nom + email +
   bouton Modifier) à gauche, critères de recherche poussés à droite.
   Pas de duplication sur /composition/<uuid>/ : la page publique reste
   anonyme par design. */
.cv-identity {
    display: flex;
    align-items: flex-start;
    justify-content: space-between;
    gap: 1.25rem;
    padding: 1.1rem 1.25rem;
    border: 1px solid var(--bs-border-color);
    border-radius: .6rem;
    background: var(--bs-body-bg);
    margin-top: 1.5rem;
}
[data-bs-theme="dark"] .cv-identity {
    background: var(--bs-tertiary-bg);
}
.cv-identity-card {
    display: flex;
    flex-direction: column;
    align-items: flex-start;
    gap: .5rem;
    flex: 0 0 auto;
}
.cv-identity-row {
    display: flex;
    align-items: center;
    gap: 1rem;
}
.cv-identity-avatar {
    width: 56px;
    height: 56px;
    border-radius: 50%;
    object-fit: cover;
    flex-shrink: 0;
    background: var(--bs-tertiary-bg);
}
.cv-identity-info {
    min-width: 0;
    line-height: 1.25;
    display: flex;
    flex-direction: column;
    gap: .15rem;
}
.cv-identity-name {
    font-weight: 700;
    font-size: 1.05rem;
}
.cv-identity-city {
    font-weight: 400;
    font-size: .85rem;
    opacity: .65;
    margin-left: .25rem;
}
.cv-identity-headline {
    font-size: .9rem;
    color: var(--ks-brand-accent);
    font-weight: 500;
    margin-top: .1rem;
}
.cv-identity-email {
    font-size: .82rem;
    opacity: .7;
    word-break: break-all;
}
.cv-identity-links {
    display: flex;
    gap: .35rem;
    margin-top: .25rem;
    font-size: 1rem;
}
.cv-identity-link {
    color: var(--bs-body-color);
    opacity: .55;
    transition: opacity .12s, color .12s;
    text-decoration: none;
    display: inline-flex;
    align-items: center;
}
.cv-identity-link:hover,
.cv-identity-link:focus-visible {
    opacity: 1;
    color: var(--ks-brand-accent);
}
.cv-identity-edit {
    /* Annule le margin-left:auto hérité de .compose-edit (qui pousse à
       droite quand utilisé dans un compose-section-title). Ici on veut le
       lien aligné sous le bloc identité. */
    align-self: flex-start;
    margin: .35rem 0 0 0;
}
.cv-identity-criteria {
    margin: 0;
    flex: 0 0 auto;
    display: flex;
    flex-direction: column;
    gap: .2rem;
    font-size: .82rem;
    text-align: right;
    min-width: 0;
}
.cv-criteria-row {
    display: flex;
    gap: .5rem;
    align-items: baseline;
    justify-content: flex-end;
}
.cv-criteria-row dt {
    font-weight: 600;
    opacity: .65;
    flex: 0 0 auto;
}
.cv-criteria-row dd {
    margin: 0;
    flex: 0 0 auto;
    overflow-wrap: anywhere;
}
@media (max-width: 767.98px) {
    .cv-identity {
        flex-direction: column;
    }
    .cv-criteria-row dt { min-width: 6rem; }
}

/* ── Tableau de bord de la composition ─────────────────────────────
   4 indicateurs synthétiques affichés à la fois sur /composer/revue/
   (avant la finalisation, comme aperçu) et sur /composition/<uuid>/
   (signal objectif pour les recruteurs). */

/* Bande des 6 indicateurs sous la constellation : 2 colonnes (mobile),
   3 (≥576px), 6 en ligne (≥992px). */
.composition-dashboard {
    display: grid;
    grid-template-columns: repeat(2, minmax(0, 1fr));
    gap: .65rem;
    margin-top: 1.25rem;
}
@media (min-width: 576px) {
    .composition-dashboard { grid-template-columns: repeat(3, minmax(0, 1fr)); }
}
@media (min-width: 992px) {
    .composition-dashboard { grid-template-columns: repeat(6, minmax(0, 1fr)); }
}
/* Revue : constellation (col-lg-6) + 4 KPI en grille 2×2 (col-lg-6). La
   spécificité .composition-split (0,2,0) bat les media queries de la bande
   (0,1,0), donc les cartes restent en 2×2 dans la demi-ligne. */
.composition-split .composition-dashboard {
    grid-template-columns: repeat(2, minmax(0, 1fr));
    margin-top: 0;
}
.composition-split .constellation-hero {
    max-width: 100%;
    /* La constellation (carrée) ne doit pas dépasser la hauteur des deux
       lignes de KPI : on plafonne sa hauteur à celle de la grille 2×2
       (2 cartes min-height 130px + l'écart .65rem). Elle reste centrée. */
    max-height: calc(130px * 2 + 0.65rem);
}
.dash-card {
    padding: 0;
    display: flex;
    flex-direction: column;
    min-height: 130px;
}
.dash-card-head {
    font-size: .72rem;
    font-weight: 600;
    opacity: .75;
    display: flex;
    align-items: center;
    gap: .3rem;
    margin-bottom: .35rem;
    line-height: 1.2;
}
.dash-card-head > .bi:first-child {
    font-size: .9rem;
    opacity: .8;
}
.dash-card-info {
    margin-left: auto;
    font-size: .8rem;
    opacity: .45;
    cursor: help;
}
.dash-card-info:hover { opacity: .9; }

/* Jauge SVG (Alignement) : compactée à 80px. */
.dash-gauge-wrap {
    display: flex;
    justify-content: center;
    align-items: center;
    flex: 1;
}
.dash-gauge { width: 100%; max-width: 80px; height: auto; }
.dash-gauge-track { stroke: var(--bs-tertiary-bg); }
[data-bs-theme="dark"] .dash-gauge-track { stroke: rgba(255,255,255,.08); }
.dash-gauge-fill {
    stroke: var(--ks-emerald);
    transition: stroke-dasharray .5s ease-in-out;
}
.dash-gauge-text {
    font-size: 1.7rem;
    font-weight: 700;
    fill: var(--bs-body-color);
    font-variant-numeric: tabular-nums;
}

/* Split bar mini (Compétences/Savoirs) : barre fine + 2 chiffres en
   ligne avec dot couleur. Plus compact que l'ancienne legende sur
   2 colonnes. */
.dash-split-mini {
    display: flex;
    flex-direction: column;
    justify-content: center;
    flex: 1;
    gap: .45rem;
}
.dash-split-bar {
    display: flex;
    height: .65rem;
    border-radius: .4rem;
    overflow: hidden;
    background: var(--bs-tertiary-bg);
}
[data-bs-theme="dark"] .dash-split-bar { background: rgba(255,255,255,.08); }
.dash-split-seg { transition: width .5s ease-in-out; }
.dash-split-pcts {
    list-style: none;
    margin: 0;
    padding: 0;
    display: flex;
    justify-content: space-between;
    gap: .25rem;
    font-size: .85rem;
    font-weight: 600;
    font-variant-numeric: tabular-nums;
}
.dash-split-pcts li {
    display: inline-flex;
    align-items: center;
    gap: .3rem;
}
.dash-split-dot {
    display: inline-block;
    width: .55rem;
    height: .55rem;
    border-radius: 50%;
    flex-shrink: 0;
}

/* Histogramme mini (Transférabilité) : 4 colonnes verticales, barre
   colorée qui monte selon le %, chiffre en bas. Plus visuel que les
   4 lignes horizontales avec libellés tronqués. */
.dash-reuse-mini {
    display: grid;
    grid-template-columns: repeat(4, 1fr);
    gap: .4rem;
    flex: 1;
    align-items: end;
    padding-top: .25rem;
}
.dash-reuse-col {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: .25rem;
    height: 100%;
}
.dash-reuse-track {
    width: 100%;
    flex: 1;
    background: var(--bs-tertiary-bg);
    border-radius: .25rem;
    overflow: hidden;
    display: flex;
    align-items: flex-end;
    min-height: 35px;
}
[data-bs-theme="dark"] .dash-reuse-track { background: rgba(255,255,255,.08); }
.dash-reuse-fill {
    width: 100%;
    background: var(--ks-emerald);
    border-radius: .25rem .25rem 0 0;
    min-height: 2px;
    transition: height .5s ease-in-out;
}
.dash-reuse-pct {
    font-size: .65rem;
    font-weight: 600;
    font-variant-numeric: tabular-nums;
    opacity: .75;
}
.dash-reuse-key {
    font-size: .7rem;
    font-weight: 700;
    color: var(--bs-body-color);
    opacity: .55;
    cursor: help;
    line-height: 1;
}
.dash-reuse-col[data-tt]:hover .dash-reuse-key {
    opacity: 1;
}

/* Grille ISCO 5×2 : emojis miniaturisés, libellé n/total dans le
   header pour gagner de la hauteur. */
.dash-isco-count {
    margin-left: .25rem;
    font-weight: 700;
    color: var(--ks-emerald);
    font-variant-numeric: tabular-nums;
}
.dash-isco-grid {
    display: grid;
    grid-template-columns: repeat(5, 1fr);
    gap: .25rem;
    flex: 1;
    align-content: center;
}
.dash-isco-cell {
    aspect-ratio: 1;
    display: flex;
    align-items: center;
    justify-content: center;
    border-radius: .3rem;
    font-size: 1rem;
    line-height: 1;
    background: var(--bs-tertiary-bg);
    cursor: help;
    transition: transform .12s ease-in-out;
    filter: grayscale(.85);
    opacity: .5;
}
.dash-isco-cell.is-on {
    background: var(--cell-color);
    filter: none;
    opacity: 1;
    box-shadow: 0 1px 3px rgba(0, 0, 0, .12);
}
.dash-isco-cell:hover { transform: translateY(-1px); }
[data-bs-theme="dark"] .dash-isco-cell:not(.is-on) {
    background: rgba(255, 255, 255, .06);
}
