/* =====================================================================
   AikidoKai Sakura — couche design par-dessus Bootstrap 5
   Registre visuel : sobriété martiale, encre + papier, accent sakura.
   ===================================================================== */

:root {
    /* Palette : encre japonaise, papier washi, rose cerisier */
    --aks-ink:        #16181d;
    --aks-ink-soft:   #3a3f4a;
    --aks-paper:      #faf8f5;
    --aks-paper-warm: #f2ede6;
    --aks-line:       #e2dbd2;
    --aks-sakura:     #dd6169;
    --aks-sakura-dk:  #b04d54;
    --aks-sakura-lt:  #f8e4e5;
    --aks-indigo:     #2b3a55;
    --aks-indigo-lt:  #e8ecf3;

    --aks-radius:     4px;   /* angles quasi droits : rigueur du dojo */
    --aks-shadow:     0 1px 2px rgba(22, 24, 29, .06), 0 8px 24px rgba(22, 24, 29, .05);

    --bs-primary:      var(--aks-indigo);
    --bs-body-color:   var(--aks-ink);
    --bs-body-bg:      var(--aks-paper);
    --bs-body-font-family: 'Inter', system-ui, -apple-system, 'Segoe UI', sans-serif;
    --bs-border-radius: var(--aks-radius);
}

body {
    background-color: var(--aks-paper);
    color: var(--aks-ink);
    font-family: var(--bs-body-font-family);
    line-height: 1.65;
    -webkit-font-smoothing: antialiased;
}

h1, h2, h3, .display-title {
    font-family: 'Cormorant Garamond', Georgia, serif;
    font-weight: 600;
    letter-spacing: .01em;
    color: var(--aks-ink);
}

/* Échelle nettement plus tranchée : le titre porte la page, le corps
   reste sobre. C'est le contraste, pas la couleur, qui donne l'énergie. */
h1 { font-size: clamp(2.6rem, 7.5vw, 5.25rem); line-height: 1.02; letter-spacing: -.015em; }
h2 { font-size: clamp(1.9rem, 4.4vw, 3rem);   line-height: 1.08; letter-spacing: -.01em; }
h3 { font-size: clamp(1.15rem, 2vw, 1.5rem); }

a { color: var(--aks-indigo); text-underline-offset: .18em; }
a:hover { color: var(--aks-sakura-dk); }

.skip-link {
    position: absolute; top: .5rem; left: .5rem; z-index: 2000;
    background: var(--aks-ink); color: #fff; padding: .5rem 1rem; border-radius: var(--aks-radius);
}

/* ---------- En-tête ---------- */
.site-header {
    background: rgba(250, 248, 245, .94);
    backdrop-filter: blur(8px);
    border-bottom: 1px solid var(--aks-line);
    position: sticky; top: 0; z-index: 1030;
}
.sakura-mark { color: var(--aks-sakura); flex: 0 0 auto; }
.brand-text { display: flex; flex-direction: column; line-height: 1.1; }
.brand-title {
    font-family: 'Cormorant Garamond', serif; font-size: 1.3rem; font-weight: 600;
    letter-spacing: .04em; color: var(--aks-ink);
}
.brand-sub { font-size: .68rem; letter-spacing: .22em; text-transform: uppercase; color: var(--aks-ink-soft); }

.navbar-nav .nav-link {
    color: var(--aks-ink-soft); font-size: .93rem; font-weight: 500;
    padding-inline: .85rem; position: relative;
}
.navbar-nav .nav-link:hover,
.navbar-nav .nav-link.active { color: var(--aks-ink); }
.navbar-nav .nav-link::after {
    content: ''; position: absolute; left: .85rem; right: .85rem; bottom: .35rem;
    height: 1px; background: var(--aks-sakura); transform: scaleX(0);
    transform-origin: left; transition: transform .22s ease;
}
.navbar-nav .nav-link:hover::after { transform: scaleX(1); }

/* ---------- Boutons ---------- */
.btn { border-radius: var(--aks-radius); font-weight: 500; letter-spacing: .01em; }
/* Texte à l'encre et non en blanc : blanc sur sakura ne donne que 2,74:1,
   très en deçà des 4,5:1 exigés par le WCAG AA — et c'est le bouton
   d'adhésion, le seul que tout le site cherche à faire cliquer. L'encre sur
   le même rose monte à 6,49:1 sans rien perdre de la couleur. */
.btn-sakura {
    background: var(--aks-sakura); border: 1px solid var(--aks-sakura); color: var(--aks-ink);
    padding-inline: 1.35rem; font-weight: 600;
}
.btn-sakura:hover, .btn-sakura:focus {
    background: var(--aks-sakura-dk); border-color: var(--aks-sakura-dk); color: #fff;
}
.btn-ink { background: var(--aks-ink); border-color: var(--aks-ink); color: #fff; }
.btn-ink:hover { background: #000; border-color: #000; color: #fff; }
.btn-outline-ink { border: 1px solid var(--aks-ink); color: var(--aks-ink); background: transparent; }
.btn-outline-ink:hover { background: var(--aks-ink); color: #fff; }

/* ---------- Hero ---------- */
.hero {
    position: relative;
    padding: clamp(4rem, 11vw, 8.5rem) 0 clamp(3.5rem, 8vw, 6rem);
    background:
        radial-gradient(ellipse at 82% 8%, var(--aks-sakura-lt) 0%, transparent 58%),
        linear-gradient(180deg, var(--aks-paper) 0%, var(--aks-paper-warm) 100%);
    overflow: hidden;
}
.hero > .container { position: relative; z-index: 2; }
.hero-eyebrow {
    text-transform: uppercase; letter-spacing: .3em; font-size: .72rem;
    color: var(--aks-sakura-dk); font-weight: 600; margin-bottom: 1.25rem;
}
.hero h1 .hero-accent {
    color: var(--aks-sakura-dk);
    font-style: italic;
}
.hero-lead { font-size: clamp(1.05rem, 1.6vw, 1.22rem); color: var(--aks-ink-soft); max-width: 44ch; }
.hero-figure { position: relative; }

/* Bandeau de chiffres sous le hero : ancre le club dans le réel. */
.hero-stats {
    display: flex; flex-wrap: wrap; gap: clamp(1.5rem, 5vw, 3.5rem);
    margin-top: clamp(2.5rem, 5vw, 3.5rem);
    padding-top: 1.75rem;
    border-top: 1px solid var(--aks-line);
}
.hero-stat-value {
    font-family: 'Cormorant Garamond', Georgia, serif;
    font-size: clamp(2rem, 3.6vw, 2.9rem); line-height: 1;
    color: var(--aks-ink); display: block;
}
.hero-stat-label {
    text-transform: uppercase; letter-spacing: .18em; font-size: .68rem;
    color: var(--aks-ink-soft); margin-top: .45rem; display: block;
}

/* ---------- Sections ---------- */
.section { padding: clamp(3.5rem, 8vw, 6.5rem) 0; position: relative; overflow: hidden; }
.section-alt { background: var(--aks-paper-warm); }

/* Section encre : le contrepoint sombre qui rythme la page. */
.section-ink {
    background: var(--aks-ink);
    color: #e7e9ee;
}
.section-ink h1, .section-ink h2, .section-ink h3 { color: var(--aks-paper); }
.section-ink .text-muted { color: #a9b0bd !important; }
.section-ink .eyebrow { color: var(--aks-sakura); }
.section-ink .card-aks {
    background: rgba(255, 255, 255, .04);
    border-color: rgba(255, 255, 255, .12);
    box-shadow: none;
}
.section-ink .card-aks:hover { box-shadow: 0 18px 40px rgba(0, 0, 0, .35); }
.section-ink .plan-price { color: var(--aks-paper); }
.section-ink .plan-price small { color: #a9b0bd; }
.section-ink /* Vignette de liste, back-office : même fabrique que le grand portrait, au
   format d'une ligne de tableau. */
.avatar-mini {
    width: 38px; height: 38px; border-radius: 50%; overflow: hidden;
    background: var(--aks-paper-warm); color: var(--aks-ink-soft);
    display: grid; place-items: center;
    font-family: 'Cormorant Garamond', serif; font-size: 1rem; line-height: 1;
}
.avatar-mini img, .avatar-mini picture { width: 100%; height: 100%; object-fit: cover; display: block; }

.grade-badge { background: var(--aks-sakura); color: var(--aks-ink); }
.section-ink hr { border-color: rgba(255, 255, 255, .16); }
.section-ink dt { color: var(--aks-sakura-lt); }
/* :not(.btn) est indispensable : une ancre stylée en bouton se trouve
   sinon repeinte en rose clair sur rose, et « Choisir cette formule »
   devient illisible (1,6:1) au beau milieu de la page des tarifs. */
.section-ink a:not(.btn) { color: var(--aks-sakura-lt); }
.section-ink a:not(.btn):hover { color: #fff; }
.section-ink .btn-outline-ink { border-color: rgba(255, 255, 255, .55); color: var(--aks-paper); }
.section-ink .btn-outline-ink:hover { background: var(--aks-paper); color: var(--aks-ink); }
.section-ink > .container { position: relative; z-index: 2; }

.section-title { margin-bottom: clamp(2rem, 4vw, 3rem); }
.section-title .eyebrow {
    text-transform: uppercase; letter-spacing: .24em; font-size: .7rem;
    color: var(--aks-sakura-dk); font-weight: 600;
}
.rule-sakura { width: 44px; height: 2px; background: var(--aks-sakura); border: 0; opacity: 1; margin: 1rem 0 0; }

/* ---------- Cartes ---------- */
/* Pas de `height: 100%` ici. Sur la page Contact, deux cartes empilées dans
   la même colonne : la première prenait toute la hauteur de la colonne — calée
   sur celle du formulaire — et poussait la seconde hors du flux, où elle se
   faisait couper par le pied de page. Une carte qui doit remplir sa colonne le
   demande explicitement avec la classe `h-100` de Bootstrap. */
.card-aks {
    background: #fff; border: 1px solid var(--aks-line); border-radius: var(--aks-radius);
    box-shadow: var(--aks-shadow); transition: transform .2s ease, box-shadow .2s ease;
}
.card-aks:hover { transform: translateY(-2px); box-shadow: 0 4px 8px rgba(22,24,29,.07), 0 16px 40px rgba(22,24,29,.07); }
.card-aks .card-body { padding: 1.75rem; }

.plan-card { border-top: 3px solid var(--aks-sakura); }
.plan-price { font-family: 'Cormorant Garamond', serif; font-size: 2.6rem; line-height: 1; color: var(--aks-ink); }
.plan-price small { font-size: .9rem; font-family: var(--bs-body-font-family); color: var(--aks-ink-soft); }

/* ---------- Publics : enfants / adultes ----------
   Les deux cours n'ont ni le même horaire ni le même encadrement, et l'œil
   doit faire la différence avant de lire. Une seule variable de couleur par
   public, déclarée ici et consommée partout — horaires comme enseignants :
   les deux sections se répondent au lieu de se ressembler. */
.audience            { --audience: var(--aks-indigo);    --audience-lt: var(--aks-indigo-lt); }
.audience--enfants   { --audience: var(--aks-sakura-dk); --audience-lt: var(--aks-sakura-lt); }

/* Bandeau de tête : c'est lui qui porte la couleur, donc la distinction. */
.audience-head {
    display: flex; align-items: baseline; gap: .75rem;
    margin: -1.5rem -1.5rem 1.25rem; padding: .85rem 1.5rem;
    background: var(--audience-lt); border-bottom: 1px solid var(--aks-line);
    border-radius: var(--aks-radius) var(--aks-radius) 0 0;
}
.audience-head h3 { margin: 0; font-size: 1.3rem; color: var(--audience); }
.audience-head .audience-tag {
    margin-left: auto; font-size: .68rem; letter-spacing: .14em; text-transform: uppercase;
    color: var(--audience); opacity: .8; white-space: nowrap;
}

/* Titre de groupe, pour les listes d'enseignants : le trait prolonge le nom
   jusqu'au bord et sépare les deux encadrements sans ajouter de cadre. */
.audience-title { display: flex; align-items: center; gap: 1rem; margin: 0 0 1.6rem; }
.audience-title h3 {
    margin: 0; font-size: 1.35rem; color: var(--audience); white-space: nowrap;
}
.audience-title .audience-tag {
    font-size: .68rem; letter-spacing: .14em; text-transform: uppercase;
    color: var(--audience); opacity: .8; white-space: nowrap;
}
.audience-title::after { content: ''; flex: 1; height: 1px; background: var(--aks-line); }

/* ---------- Horaires ---------- */
.schedule-day {
    background: #fff; border: 1px solid var(--aks-line); border-left: 3px solid var(--audience, var(--aks-indigo));
    border-radius: var(--aks-radius); padding: 1.5rem;
}
.schedule-day h3 { font-size: 1.25rem; margin-bottom: 1rem; }
.slot-row { display: flex; justify-content: space-between; gap: 1rem; padding: .6rem 0; border-bottom: 1px dashed var(--aks-line); }
.slot-row:last-child { border-bottom: 0; }
.slot-time { font-variant-numeric: tabular-nums; font-weight: 600; }

/* ---------- Enseignants ---------- */
.teacher-card { text-align: center; }
/* Portrait d'enseignant. La taille suit la largeur de la carte plutôt qu'une
   valeur fixe : sur trois colonnes le visage reste lisible, et sur mobile il
   ne mange pas l'écran. Le plafond évite qu'il ne s'étale sur une carte seule. */
.teacher-avatar {
    width: min(180px, 62%); aspect-ratio: 1; height: auto;
    border-radius: 50%; margin: 0 auto 1.15rem;
    background: var(--audience-lt, var(--aks-sakura-lt));
    color: var(--audience, var(--aks-sakura-dk));
    display: grid; place-items: center;
    font-family: 'Cormorant Garamond', serif; font-size: clamp(2rem, 6vw, 3.2rem);
}
.grade-badge {
    display: inline-block; font-size: .72rem; letter-spacing: .12em; text-transform: uppercase;
    background: var(--aks-ink); color: #fff; padding: .18rem .6rem; border-radius: 2px;
}

/* ---------- Tunnel d'inscription ---------- */
.funnel-steps { display: flex; gap: .5rem; list-style: none; padding: 0; margin: 0 0 2.5rem; flex-wrap: wrap; }
.funnel-steps li { flex: 1 1 130px; }
.funnel-step {
    display: block; padding: .7rem .9rem; border-radius: var(--aks-radius);
    border: 1px solid var(--aks-line); background: #fff; font-size: .84rem; color: var(--aks-ink-soft);
    border-top: 3px solid var(--aks-line);
}
.funnel-step .num {
    display: inline-grid; place-items: center; width: 22px; height: 22px; border-radius: 50%;
    background: var(--aks-paper-warm); font-size: .72rem; font-weight: 600; margin-right: .4rem;
}
.funnel-step.is-current { border-top-color: var(--aks-sakura); color: var(--aks-ink); font-weight: 600; }
.funnel-step.is-current .num { background: var(--aks-sakura); color: #fff; }
.funnel-step.is-done { border-top-color: var(--aks-indigo); }
.funnel-step.is-done .num { background: var(--aks-indigo); color: #fff; }

.funnel-panel {
    background: #fff; border: 1px solid var(--aks-line); border-radius: var(--aks-radius);
    padding: clamp(1.5rem, 4vw, 2.5rem); box-shadow: var(--aks-shadow);
}

/* Bandeau de prise en main. Collé en haut, non masquable, contrasté :
   il doit rester lisible même quand on a fait défiler la page, sans quoi
   on oublie qu'on agit dans l'espace de quelqu'un d'autre. */
.prise-en-main {
    position: sticky; top: 0; z-index: 1080;
    background: #7a1f2b; color: #fff; font-size: .9rem;
    box-shadow: 0 2px 10px rgba(0, 0, 0, .18);
}
.prise-en-main-inner {
    display: flex; flex-wrap: wrap; gap: .5rem 1rem;
    align-items: center; justify-content: space-between;
    padding-top: .5rem; padding-bottom: .5rem;
}
.prise-en-main-texte { min-width: 0; }
.prise-en-main strong { font-weight: 600; }
.prise-en-main-reste {
    display: inline-block; margin-left: .35rem; padding: .05rem .45rem;
    border: 1px solid rgba(255, 255, 255, .45); border-radius: 999px;
    font-size: .8rem; white-space: nowrap;
}
.prise-en-main-form { margin: 0; flex: 0 0 auto; }

.nav-espace { display: inline-flex; align-items: center; gap: .35rem; }
.nav-espace-icon { flex: 0 0 auto; opacity: .75; }

/* Reprise d'un dossier existant, au-dessus de l'étape 1 du tunnel.
   Repliée par défaut : un primo-adhérent ne doit pas se demander s'il a
   quelque chose à y faire, il descend directement au formulaire. */
.funnel-reprise {
    background: #fff; border: 1px solid var(--aks-line);
    border-radius: var(--aks-radius); padding: 1rem 1.25rem; margin-bottom: 1.25rem;
}
.funnel-reprise > summary {
    cursor: pointer; list-style: none; font-size: .95rem;
}
.funnel-reprise > summary::-webkit-details-marker { display: none; }
.funnel-reprise > summary::before {
    content: '+'; display: inline-block; width: 1.25rem; height: 1.25rem;
    margin-right: .5rem; text-align: center; line-height: 1.15rem;
    border: 1px solid var(--aks-line); border-radius: 50%;
    color: var(--aks-sakura-dk); font-weight: 600;
}
.funnel-reprise[open] > summary::before { content: '−'; }
.funnel-reprise > summary:focus-visible {
    outline: 2px solid var(--aks-sakura); outline-offset: 3px; border-radius: 4px;
}
.funnel-reprise--connu {
    border-left: 3px solid var(--aks-sakura);
}

.form-label { font-weight: 500; font-size: .9rem; color: var(--aks-ink-soft); }
.form-control, .form-select {
    border-color: var(--aks-line); border-radius: var(--aks-radius); padding: .6rem .8rem;
}
.form-control:focus, .form-select:focus {
    border-color: var(--aks-sakura); box-shadow: 0 0 0 3px rgba(212, 134, 154, .18);
}
.required::after { content: ' *'; color: var(--aks-sakura-dk); }

/* Zone de dépôt de fichier */
.dropzone {
    border: 2px dashed var(--aks-line); border-radius: var(--aks-radius);
    padding: 1.5rem; text-align: center; background: var(--aks-paper); cursor: pointer;
    transition: border-color .18s ease, background .18s ease;
}
.dropzone:hover, .dropzone.is-dragover { border-color: var(--aks-sakura); background: var(--aks-sakura-lt); }
.dropzone.is-done { border-style: solid; border-color: #2f7d5c; background: #eff7f2; }
.doc-item { display: flex; align-items: center; justify-content: space-between; gap: 1rem; }

/* Choix du mode de paiement */
.pay-option { position: relative; }
.pay-option input { position: absolute; opacity: 0; pointer-events: none; }
.pay-option label {
    display: block; height: 100%; padding: 1.25rem; cursor: pointer;
    border: 1px solid var(--aks-line); border-radius: var(--aks-radius); background: #fff;
    transition: border-color .18s ease, box-shadow .18s ease;
}
.pay-option input:checked + label {
    border-color: var(--aks-sakura); box-shadow: 0 0 0 3px rgba(212, 134, 154, .16);
}
.pay-option input:focus-visible + label { outline: 2px solid var(--aks-indigo); outline-offset: 2px; }

/* ---------- Statuts ---------- */
.status-badge {
    display: inline-block; font-size: .72rem; font-weight: 600; letter-spacing: .04em;
    padding: .22rem .55rem; border-radius: 2px; text-transform: uppercase; white-space: nowrap;
}
.status-active             { background: #e4f2ea; color: #1f6647; }
.status-awaiting_payment   { background: #fdf0dd; color: #8a5a11; }
.status-awaiting_documents { background: #e8eefb; color: #274a91; }
.status-rejected,
.status-cancelled          { background: #fbe6e6; color: #8f2b2b; }
.status-draft              { background: #eeece9; color: #5b5750; }
.status-pending            { background: #fdf0dd; color: #8a5a11; }
.status-succeeded,
.status-approved           { background: #e4f2ea; color: #1f6647; }
.status-failed             { background: #fbe6e6; color: #8f2b2b; }

/* ---------- Pied de page ---------- */
.site-footer { background: var(--aks-ink); color: #cfd2d8; }
.site-footer a { color: #e8dfe2; text-decoration: none; }
.site-footer a:hover { color: var(--aks-sakura); text-decoration: underline; }
.footer-title { font-size: 1.05rem; color: #fff; margin-bottom: .9rem; }
.footer-rule { border-color: rgba(255,255,255,.12); margin: 2.5rem 0 1.25rem; }

/* ---------- Back-office ---------- */
.admin-body { background: #f5f6f8; }
.admin-sidebar {
    background: var(--aks-ink); color: #b9bec9; min-height: 100vh; width: 248px; flex: 0 0 248px;
    position: sticky; top: 0; height: 100vh; overflow-y: auto;
}
.admin-sidebar .nav-link { color: #b9bec9; border-radius: var(--aks-radius); padding: .5rem .75rem; font-size: .9rem; }
.admin-sidebar .nav-link:hover { background: rgba(255,255,255,.06); color: #fff; }
.admin-sidebar .nav-link.active { background: var(--aks-sakura); color: #fff; }
.admin-sidebar .nav-section {
    font-size: .68rem; letter-spacing: .18em; text-transform: uppercase;
    color: #6c7280; padding: 1.25rem .75rem .35rem;
}
.admin-main { min-width: 0; }
.admin-topbar { background: #fff; border-bottom: 1px solid #e6e8ec; }

.stat-card { background: #fff; border: 1px solid #e6e8ec; border-radius: var(--aks-radius); padding: 1.25rem; }
.stat-card .stat-value { font-size: 1.9rem; font-weight: 600; line-height: 1.1; font-variant-numeric: tabular-nums; }
.stat-card .stat-label { font-size: .78rem; text-transform: uppercase; letter-spacing: .1em; color: #6c7280; }

.table-aks { background: #fff; }
.table-aks thead th {
    font-size: .74rem; text-transform: uppercase; letter-spacing: .08em;
    color: #6c7280; font-weight: 600; border-bottom: 2px solid #e6e8ec; white-space: nowrap;
}
.table-aks td { vertical-align: middle; font-size: .9rem; }
.tabular { font-variant-numeric: tabular-nums; }

@media (max-width: 991.98px) {
    .admin-sidebar { position: static; height: auto; min-height: 0; width: 100%; flex-basis: auto; }
}

/* ---------- Accessibilité & impression ---------- */
:focus-visible { outline: 2px solid var(--aks-indigo); outline-offset: 2px; }

@media (prefers-reduced-motion: reduce) {
    *, *::before, *::after { animation-duration: .01ms !important; transition-duration: .01ms !important; }
}

@media print {
    .site-header, .site-footer, .btn, .admin-sidebar, .admin-topbar { display: none !important; }
    body { background: #fff; }
}

/* =====================================================================
   Médias : logo, portraits, galerie
   ===================================================================== */

/* ---------- Logo ---------- */
.site-logo { display: inline-flex; align-items: center; flex: 0 0 auto; }
.site-logo .logo-img {
    height: var(--logo-h, 46px);
    width: auto;
    display: block;
}

/*
 * Médaillon de marque : logo et nom du club encapsulés dans un demi-disque
 * qui déborde sous la bande de l'en-tête.
 *
 * Le débordement n'est lisible comme une intention que s'il est ADOSSÉ à
 * quelque chose ; ici c'est le médaillon lui-même, qui prolonge l'en-tête vers
 * le bas et porte l'ombre. Il reprend le fond de la bande, flou compris, pour
 * qu'on ne voie pas la jointure.
 *
 * L'arrondi est une ELLIPSE (`60% / 46%`) et non un cercle : le médaillon est
 * bien plus large que haut, un rayon unique produirait deux angles mous plutôt
 * que l'arc continu voulu.
 */
/* L'en-tête occupe toute la largeur : pas de padding à gauche, pour que le
   médaillon touche le bord ; de l'air à droite, pour que le menu ne colle pas
   au bord de l'écran. */
.header-fluid { padding-inline: 0 clamp(1rem, 3vw, 3rem); }

@media (min-width: 1400px) {
    .site-header .navbar-brand {
        position: relative;
        margin-block: -.5rem -4.6rem;
        padding: .9rem 3.6rem 4.6rem clamp(1rem, 3vw, 3rem);
        background: rgba(250, 248, 245, .97);
        backdrop-filter: blur(8px);
        /* Bas-droite seul, et très creusé : c'est un arc, pas un coin adouci.
           Le rayon vertical à 100 % fait descendre la courbe jusqu'au bas du
           bloc, ce qui donne le demi-disque. */
        border-radius: 0 0 62% 0 / 0 0 100% 0;
        border-inline-end: 1px solid var(--aks-line);
        border-block-end: 1px solid var(--aks-line);
        box-shadow: 0 18px 36px rgba(22, 26, 36, .12);
        z-index: 2;
        /* Le contenu reste calé en haut : l'arc se creuse SOUS lui. Centré, le
           logo tomberait dans le vide de la courbe. */
        align-items: flex-start;
    }
    /* Masque le filet de l'en-tête là où le médaillon le croise. */
    .site-header .navbar-brand::before {
        content: ''; position: absolute; inset-block-start: -1px;
        inset-inline: 0; height: 1px; background: rgba(250, 248, 245, .97);
    }
}

/* En dessous, l'en-tête est trop serré pour un logo débordant : il
   bousculerait le menu ou le bouton hamburger. */
@media (max-width: 1399.98px) {
    .site-header .site-logo .logo-img { height: 46px; }
}
/* Le logo mêle encre sombre et rose : l'inverser vire la fleur au vert.
   On le pose donc sur une pastille claire, comme les logos fédéraux. */
.footer-logo {
    display: inline-block; background: var(--aks-paper);
    padding: .5rem .9rem; border-radius: var(--aks-radius);
}

/* ---------- Marque décorative du hero ---------- */
.hero-mark {
    position: absolute; right: 3%; top: 6%;
    width: clamp(180px, 30vw, 380px);
    opacity: .08; pointer-events: none; user-select: none;
}
.hero-mark img { width: 100%; height: auto; display: block; }

@media (max-width: 767.98px) {
    .hero-mark { right: -8%; top: auto; bottom: 2%; width: 55vw; opacity: .06; }
}

/* ---------- Portraits ---------- */
/* Les portraits sont détourés : le fond du cercle traverse la photo. C'est
   donc lui qui porte la couleur du groupe — d'où la variable plutôt qu'une
   valeur fixe, qui écrasait la distinction adultes/enfants. */
.teacher-avatar.has-photo,
.board-avatar.has-photo {
    padding: 0; overflow: hidden; background: var(--audience-lt, var(--aks-sakura-lt));
}
.teacher-avatar.has-photo picture,
.teacher-avatar.has-photo img,
.board-avatar.has-photo picture,
.board-avatar.has-photo img {
    width: 100%; height: 100%; object-fit: cover; object-position: center top; display: block;
}
.board-avatar {
    width: 84px; height: 84px; border-radius: 50%; flex: 0 0 84px;
    background: var(--aks-sakura-lt); color: var(--aks-sakura-dk);
    display: grid; place-items: center;
    font-family: 'Cormorant Garamond', serif; font-size: 1.6rem;
}

/* ---------- Maîtres fondateurs ---------- */
.master-photo {
    width: 100%; aspect-ratio: 1; border-radius: var(--aks-radius);
    overflow: hidden; background: var(--aks-paper-warm);
}
.master-photo img { width: 100%; height: 100%; object-fit: cover; display: block; filter: grayscale(1); }

/* Sur la page Aïkido, le bloc suit un long texte : on l'en détache et on
   borne la taille des portraits — en pleine largeur de colonne, deux carrés
   de 380 px écraseraient tout ce qui précède. */
.masters { margin-block-start: 1.75rem; }
.masters:not(.masters-compact) { max-width: 460px; }
.masters:not(.masters-compact) .master-photo { border-radius: 3px; }
.content-body + .masters { margin-block-start: 1rem; }

/* ---------- Galerie ---------- */
/* Quatre colonnes sur deux rangées : la sélection de l'accueil est cadrée à
   huit photos, un compte fixe donne donc une grille pleine plutôt qu'une
   dernière rangée dépareillée. `auto-fill` faisait varier le nombre de
   colonnes avec la largeur et laissait trois photos orphelines. */
.gallery-grid {
    display: grid; gap: .75rem;
    grid-template-columns: repeat(2, 1fr);
}
@media (min-width: 576px) { .gallery-grid { grid-template-columns: repeat(3, 1fr); } }
@media (min-width: 992px) { .gallery-grid { grid-template-columns: repeat(4, 1fr); } }
/* La page Galerie, elle, affiche tout le fonds : le nombre de colonnes doit
   suivre la largeur disponible, pas un compte fixe. */
.gallery-grid-lg { grid-template-columns: repeat(auto-fill, minmax(260px, 1fr)); }
@media (min-width: 992px) { .gallery-grid-lg { grid-template-columns: repeat(auto-fill, minmax(260px, 1fr)); } }

.gallery-item {
    display: block; position: relative; overflow: hidden;
    border-radius: var(--aks-radius); background: var(--aks-paper-warm);
    aspect-ratio: 4 / 3; cursor: zoom-in;
}
.gallery-item img {
    width: 100%; height: 100%; object-fit: cover; display: block;
    transition: transform .35s ease, filter .35s ease;
}
.gallery-item:hover img,
.gallery-item:focus-visible img { transform: scale(1.04); filter: brightness(1.04); }
.gallery-item::after {
    content: ''; position: absolute; inset: 0;
    box-shadow: inset 0 0 0 1px rgba(22, 24, 29, .08);
    border-radius: var(--aks-radius); pointer-events: none;
}

/* ---------- Visionneuse ---------- */
.lightbox {
    border: 0; padding: 0; background: transparent; max-width: 100vw; max-height: 100vh;
    width: 100%; height: 100%;
}
.lightbox::backdrop { background: rgba(12, 13, 16, .93); }
.lightbox-figure {
    margin: 0; height: 100%; display: flex; flex-direction: column;
    align-items: center; justify-content: center; gap: 1rem; padding: 3rem 1rem;
}
.lightbox-figure img {
    max-width: min(1200px, 92vw); max-height: 82vh;
    object-fit: contain; border-radius: var(--aks-radius);
    box-shadow: 0 24px 60px rgba(0, 0, 0, .5);
}
.lightbox-figure figcaption { color: #e6e2dd; font-size: .9rem; text-align: center; max-width: 60ch; }
.lightbox-close, .lightbox-nav {
    position: absolute; background: rgba(255, 255, 255, .1); color: #fff;
    border: 0; border-radius: 50%; cursor: pointer; line-height: 1;
    display: grid; place-items: center; transition: background .2s ease;
}
.lightbox-close { top: 1rem; right: 1rem; width: 44px; height: 44px; font-size: 1.6rem; }
.lightbox-nav { top: 50%; transform: translateY(-50%); width: 52px; height: 52px; font-size: 2.2rem; }
.lightbox-prev { left: 1rem; }
.lightbox-next { right: 1rem; }
.lightbox-close:hover, .lightbox-nav:hover { background: rgba(255, 255, 255, .22); }

@media (max-width: 575.98px) {
    .lightbox-nav { width: 42px; height: 42px; font-size: 1.7rem; }
    .lightbox-prev { left: .35rem; }
    .lightbox-next { right: .35rem; }
}

/* ---------- Partenaires ---------- */
.footer-partners {
    display: flex; flex-wrap: wrap; gap: 1.75rem;
    align-items: center; justify-content: center; margin-bottom: 1.5rem;
}
/* Logos fédéraux sur pastille blanche : la plupart sont dessinés pour un fond
   clair, les désaturer sur fond noir les transformait en rectangles gris. */
.partner-logo {
    display: inline-flex; align-items: center; justify-content: center;
    background: #fff; padding: .7rem 1.15rem; border-radius: var(--aks-radius);
    opacity: .88; transition: opacity .2s ease, transform .2s ease;
}
.partner-logo:hover,
.partner-logo:focus-visible { opacity: 1; transform: translateY(-2px); }
.partner-logo img { height: 52px; width: auto; display: block; }

/* Le gris de .text-muted de Bootstrap est calculé pour un fond clair :
   sur le pied de page en encre, il tombe sous le seuil de contraste AA. */
.site-footer .text-muted { color: #9aa0ab !important; }

/* =====================================================================
   ENCRE VIVANTE — mouvement
   -----------------------------------------------------------------
   Règle unique et non négociable : tout ce qui bouge ici est décoratif.
   Sous prefers-reduced-motion, chaque animation s'arrête sur son état
   final et la page reste complète — aucune information n'est portée par
   le mouvement seul.
   ===================================================================== */

/* ---------- Apparition au défilement ----------
   L'état initial n'est posé QUE si le JS a pris la main (.js sur <html>).
   Sans JavaScript, rien n'est masqué : le contenu reste lisible. */
.js [data-reveal] {
    opacity: 0;
    transform: translateY(18px);
    transition: opacity .7s cubic-bezier(.22, .61, .36, 1),
                transform .7s cubic-bezier(.22, .61, .36, 1);
}
.js [data-reveal].is-revealed { opacity: 1; transform: none; }

/* Cascade légère entre éléments d'une même rangée. */
.js [data-reveal][data-reveal-delay="1"] { transition-delay: .08s; }
.js [data-reveal][data-reveal-delay="2"] { transition-delay: .16s; }
.js [data-reveal][data-reveal-delay="3"] { transition-delay: .24s; }
.js [data-reveal][data-reveal-delay="4"] { transition-delay: .32s; }
.js [data-reveal][data-reveal-delay="5"] { transition-delay: .40s; }

/* ---------- Trait de pinceau ---------- */
.brush-rule { display: block; margin: .85rem 0 0; overflow: visible; }
.brush-rule-path {
    fill: var(--aks-sakura);
    /* Le trait se révèle par un masque horizontal : un clip-path anime
       mieux qu'un scaleX, qui déformerait la pointe du pinceau. */
    clip-path: inset(0 100% 0 0);
    transition: clip-path 1s cubic-bezier(.16, .84, .44, 1) .1s;
}
.is-revealed .brush-rule-path,
.brush-rule.is-revealed .brush-rule-path { clip-path: inset(0 0 0 0); }
.section-ink .brush-rule-path { fill: var(--aks-sakura-lt); }

/* ---------- Pétales de sakura ----------
   Le canvas est purement décoratif et ne capte jamais le pointeur. */
/* Le canvas couvre la fenêtre et reste fixe : les pétales traversent le site
   entier au lieu d'être enfermés dans une section. En `fixed`, il ne participe
   pas au défilement et ne provoque donc aucun recalcul de mise en page.
   z-index 0 et `pointer-events: none` : toujours derrière le contenu, jamais
   dans le chemin du pointeur ni du clavier. */
/* Le canvas est AU-DESSUS du contenu, jamais derrière : les sections ont des
   fonds opaques — le papier, l'aplat d'encre — et un canvas placé dessous
   serait purement et simplement invisible. Devant, avec une opacité de pétale
   comprise entre 0,16 et 0,42, les fleurs passent sans gêner la lecture.
   `pointer-events: none` garantit qu'il n'intercepte ni clic ni focus. */
.petals-canvas {
    position: fixed;
    inset: 0;
    width: 100vw;
    height: 100vh;
    pointer-events: none;
    z-index: 5;
}
/* L'en-tête collant reste au-dessus des pétales : les voir passer devant le
   menu donnerait l'impression d'un calque mal réglé. */
.site-header { position: sticky; z-index: 1030; }

/* ---------- Séquence aïkido (sprites) ----------
   La planche fait 8 cases côte à côte. On affiche une case et on décale le
   fond de 100 % par pas : `steps(8, end)` fige chaque image au lieu
   d'interpoler, ce qui donne le rendu image par image d'une animation
   dessinée — une interpolation ferait glisser les personnages. */
/* ---------- Séquence aïkido (canvas) ----------
   Le canvas est dimensionné par le JS d'après la largeur du bloc, densité
   d'écran comprise. On réserve la place avec aspect-ratio pour qu'aucun saut
   de mise en page ne se produise avant qu'il soit peint. */
/* ---------- Visuel du hero : une photo du club, encadrée ---------- */
.hero-visual {
    position: relative;
    margin: 0;
    width: 100%;
    max-width: 520px;
    margin-inline: auto;
}

/* Sur grand écran, le visuel déborde jusqu'au bord droit de la fenêtre.
   La marge négative vaut exactement la gouttière du conteneur Bootstrap à
   chaque palier : le bord du bloc atterrit pile sur le bord de l'écran sans
   jamais le dépasser. C'est ce qui l'agrandit sans rogner la colonne de
   texte — la seule autre façon d'y arriver aurait été de rétrécir le titre.
   `.hero` porte déjà `overflow: hidden`, ce qui verrouille le cas limite. */
/* Sur grand écran, le visuel déborde de sa colonne jusqu'au bord droit de la
   fenêtre. C'est le VISUEL qu'on élargit, pas la colonne : élargir la colonne
   ferait dépasser la somme des douze douzièmes de la grille et la ligne se
   casserait, le visuel passant sous le texte. Le débordement vaut la
   demi-gouttière du conteneur à chaque palier, si bien que le bord droit
   atterrit pile sur celui de l'écran ; `.hero` porte déjà `overflow: hidden`,
   ce qui verrouille le cas limite. */
@media (min-width: 992px) {
    .hero-visual {
        max-width: 910px;
        width: calc(100% + (100vw - 960px) / 2);
        margin-inline: 0;
    }
}
@media (min-width: 1200px) { .hero-visual { width: calc(100% + (100vw - 1140px) / 2); } }
@media (min-width: 1400px) { .hero-visual { width: calc(100% + (100vw - 1320px) / 2); } }

@media (min-width: 992px) {
    /* Le bloc touchant le bord de l'écran, un sceau posé en débord à droite
       serait rogné : il passe à gauche, du côté du texte, où il reste entier.
       L'ombre décalée perd aussi son sens à droite — elle ne descend plus
       que vers le bas. */
    .hero-visual-seal { inset-inline-end: auto; inset-inline-start: -18px; }
    .hero-visual-img,
    .hero-visual-media {
        box-shadow: 0 22px 48px rgba(22, 26, 36, .22);
    }
}
.hero-visual-img,
.hero-visual-media {
    display: block;
    width: 100%;
    height: auto;
    border-radius: 2px;
    /* Le cadre décalé rappelle un tirage posé sur une planche, plutôt qu'une
       image collée dans la page. */
    box-shadow: 14px 14px 0 var(--aks-sakura-lt),
                0 18px 42px rgba(22, 26, 36, .18);
}
.section-ink .hero-visual-img,
.section-ink .hero-visual-media { box-shadow: 14px 14px 0 rgba(221, 97, 109, .28); }
/* La vidéo est décorative : elle ne doit pas capter le focus clavier ni
   afficher de contrôles. */
.hero-visual-media { pointer-events: none; background: var(--aks-ink); }
.hero-visual-media::-webkit-media-controls { display: none !important; }

/* Sceau : le kanji « sakura », posé en coin comme un cachet d'artiste. */
.hero-visual-seal {
    position: absolute;
    inset-inline-end: -14px;
    inset-block-start: -14px;
    width: 46px;
    height: 46px;
    display: grid;
    place-items: center;
    background: var(--aks-sakura);
    color: #fff;
    font-size: 1.35rem;
    line-height: 1;
    border-radius: 3px;
    box-shadow: 0 6px 16px rgba(176, 77, 84, .35);
}

/* ---------- Cercles tai sabaki en fond de section ---------- */
.tai-sabaki {
    position: absolute;
    inset-inline-end: -12%;
    inset-block-start: -18%;
    width: min(46vw, 560px);
    aspect-ratio: 1;
    pointer-events: none;
    opacity: .5;
    z-index: 0;
}
.tai-sabaki svg { width: 100%; height: 100%; }
.tai-sabaki circle {
    fill: none;
    stroke: var(--aks-line);
    stroke-width: 1;
    transform-origin: 50% 50%;
}
.section-ink .tai-sabaki circle { stroke: rgba(246, 230, 234, .18); }
.js .tai-sabaki circle:nth-child(1) { animation: am-spin 90s linear infinite; stroke-dasharray: 3 12; }
.js .tai-sabaki circle:nth-child(2) { animation: am-spin 70s linear infinite reverse; stroke-dasharray: 1 9; }
.js .tai-sabaki circle:nth-child(3) { animation: am-spin 120s linear infinite; }

/* ---------- Kanji en filigrane ---------- */
.kanji-mark {
    position: absolute;
    font-family: 'Cormorant Garamond', Georgia, serif;
    font-size: clamp(9rem, 26vw, 22rem);
    line-height: .82;
    letter-spacing: .04em;
    color: var(--aks-ink);
    opacity: .045;
    pointer-events: none;
    user-select: none;
    z-index: 0;
    writing-mode: vertical-rl;
}
.section-ink .kanji-mark { color: var(--aks-paper); opacity: .06; }

/* ---------- Boutons : l'encre se remplit ---------- */
.btn-sakura, .btn-ink, .btn-outline-ink {
    position: relative;
    overflow: hidden;
    isolation: isolate;
    transition: color .35s ease, border-color .35s ease, transform .18s ease;
}
.btn-sakura::after, .btn-ink::after, .btn-outline-ink::after {
    content: '';
    position: absolute; inset: 0;
    background: currentColor;
    opacity: .12;
    transform: scaleX(0);
    transform-origin: left center;
    transition: transform .4s cubic-bezier(.22, .61, .36, 1);
    z-index: -1;
}
.btn-sakura:hover::after, .btn-ink:hover::after, .btn-outline-ink:hover::after { transform: scaleX(1); }
.btn-sakura:active, .btn-ink:active, .btn-outline-ink:active { transform: translateY(1px); }

/* ---------- Cartes : soulèvement discret ---------- */
.card-aks, .plan-card, .teacher-card {
    transition: transform .35s cubic-bezier(.22, .61, .36, 1), box-shadow .35s ease;
}
.card-aks:hover, .plan-card:hover, .teacher-card:hover {
    transform: translateY(-4px);
    box-shadow: 0 2px 4px rgba(22, 24, 29, .07), 0 18px 40px rgba(22, 24, 29, .10);
}

/* ---------- Galerie : recadrage lent au survol ---------- */
.gallery-item img { transition: transform .8s cubic-bezier(.22, .61, .36, 1); }
.gallery-item:hover img, .gallery-item:focus-visible img { transform: scale(1.06); }

/* =====================================================================
   RESPECT DE prefers-reduced-motion
   Tout s'arrête. Les postures ne clignotent plus, le canvas de pétales
   n'est pas démarré (côté JS), et les éléments à révéler sont visibles
   d'emblée — sinon la page resterait vide pour qui a désactivé le
   mouvement, ce qui serait pire que trop d'animation.
   ===================================================================== */
@media (prefers-reduced-motion: reduce) {
    .js [data-reveal] { opacity: 1; transform: none; transition: none; }
    .brush-rule-path  { clip-path: inset(0 0 0 0); transition: none; }

    .js .tai-sabaki circle { animation: none !important; }
    /* Le canvas d'aïkido est géré côté JS : sous reduced-motion il est peint
       une seule fois, sur la garde, et la boucle n'est jamais lancée. */

    .card-aks, .plan-card, .teacher-card, .gallery-item img,
    .btn-sakura, .btn-ink, .btn-outline-ink { transition: none; }
    .card-aks:hover, .plan-card:hover, .teacher-card:hover { transform: none; }
    .gallery-item:hover img { transform: none; }
    .btn-sakura::after, .btn-ink::after, .btn-outline-ink::after { transition: none; }
}

/* Variante centrée du trait de pinceau (pages d'erreur, écrans de fin de
   parcours) : même signature graphique que sur les titres alignés à gauche. */
.brush-rule.brush-center { margin-inline: auto; }

/* =====================================================================
   MÉDIATHÈQUE (back-office)
   ===================================================================== */

.media-albums .nav-link {
    color: var(--aks-ink); background: #fff; border: 1px solid #e3e5ea;
    padding: .35rem .7rem; font-size: .875rem; display: flex; align-items: center; gap: .4rem;
}
.media-albums .nav-link.active { background: var(--aks-ink); color: #fff; border-color: var(--aks-ink); }
.media-albums .nav-link.active .badge { background: rgba(255,255,255,.18) !important; color: #fff; }

.media-grid {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(190px, 1fr));
    gap: 1rem;
}

.media-tile {
    position: relative; margin: 0; background: #fff; border: 1px solid #e3e5ea;
    border-radius: var(--aks-radius); overflow: hidden; cursor: grab;
    transition: box-shadow .15s ease, transform .15s ease;
}
.media-tile:hover { box-shadow: 0 6px 18px rgba(22,26,36,.12); }
/* Pendant le déplacement : la tuile prise s'efface, celle survolée s'ouvre.
   Sans ce retour, on lâche à l'aveugle et l'ordre obtenu n'est jamais celui
   qu'on visait. */
.media-tile.is-dragging { opacity: .35; cursor: grabbing; }
.media-tile.is-over { outline: 2px dashed var(--aks-sakura); outline-offset: -4px; }
.media-tile.is-hidden .media-thumb { filter: grayscale(1); opacity: .55; }

/* `height: auto` n'est pas décoratif : le helper écrit width= et height= sur
   la balise, et cet attribut de hauteur l'emporte sur `aspect-ratio`, qui ne
   calcule une dimension que si l'autre est `auto`. Sans lui, la vignette
   s'affiche à sa hauteur intrinsèque et la grille part en colonnes de 450 px. */
.media-thumb {
    width: 100%; height: auto; aspect-ratio: 4 / 3;
    object-fit: cover; display: block;
}
.media-tile picture { display: block; }
.media-tile figcaption {
    padding: .5rem .6rem; font-size: .78rem; display: flex; flex-wrap: wrap;
    align-items: center; gap: .3rem;
}
.media-name { flex: 1 1 auto; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.media-tile figcaption .badge { font-size: .62rem; }

.media-pick { position: absolute; inset-block-start: .4rem; inset-inline-start: .4rem; z-index: 2; }
.media-pick input { width: 1.15rem; height: 1.15rem; cursor: pointer; }
.media-edit { position: absolute; inset-block-start: .4rem; inset-inline-end: .4rem; z-index: 2; font-size: .72rem; }

/* Barre d'actions groupées : collée en bas de l'écran, elle reste atteignable
   quelle que soit la position de défilement dans une grille de 200 photos. */
.media-bulkbar {
    position: sticky; inset-block-end: 1rem; z-index: 20;
    display: flex; align-items: center; gap: .5rem; flex-wrap: wrap;
    background: var(--aks-ink); color: #fff;
    padding: .6rem .9rem; border-radius: var(--aks-radius);
    box-shadow: 0 10px 30px rgba(22,26,36,.35); margin-bottom: 1rem;
}

/* ---------- Sélecteur de recadrage ---------- */
.media-crop {
    position: relative; user-select: none; background: #101319;
    border-radius: var(--aks-radius); overflow: hidden; touch-action: none;
}
.media-crop img { width: 100%; height: auto; display: block; }
/* L'extérieur du cadre est assombri par une ombre portée immense plutôt que
   par quatre masques positionnés : une seule boîte à déplacer, et le cadre
   reste net quel que soit le rapport d'aspect. */
.media-crop-box {
    position: absolute; border: 1px solid #fff; box-shadow: 0 0 0 9999px rgba(0,0,0,.55);
    pointer-events: none;
}

/* =====================================================================
   ORGANIGRAMME
   ===================================================================== */

.orga { margin-block-start: 2.5rem; }
.orga-legend {
    text-transform: uppercase; letter-spacing: .22em; font-size: .7rem;
    color: var(--aks-sakura-dk); margin-block: 1.5rem .25rem; text-align: center;
}
.orga-legend-second { margin-block-start: 2.75rem; }

.orga-top { display: flex; justify-content: center; }

/* Les liens sont tracés en CSS et non en SVG : le nombre de membres du bureau
   change d'une assemblée à l'autre, et un tracé figé aurait fini décalé. */
.orga-top .orga-card::after {
    content: ''; position: absolute; inset-block-start: 100%; inset-inline-start: 50%;
    width: 2px; height: 1.4rem; background: var(--aks-line, #d9d5cd);
}

.orga-branch {
    /* `width: fit-content` + marges auto plutôt que `justify-content: center` :
       la boîte épouse alors les cartes, ce qui permet d'ancrer la barre de
       liaison sur elles. Centrée dans une boîte pleine largeur, la barre était
       calculée sur la colonne et débordait des cartes. */
    display: flex; flex-wrap: wrap;
    width: fit-content; max-width: 100%; margin-inline: auto;
    gap: 1.25rem; margin-block-start: 1.4rem; position: relative;
}
/* Barre horizontale reliant les nœuds d'un même niveau. Bornée aux extrêmes
   pour qu'elle ne dépasse pas des cartes de bout de ligne. */
.orga-branch::before {
    content: ''; position: absolute; inset-block-start: -1.4rem;
    /* La barre s'arrête au CENTRE des cartes de bout de ligne, pas au bord du
       conteneur : une demi-carte de retrait de chaque côté. En pourcentage,
       elle dépassait dès que le nombre de nœuds changeait. */
    inset-inline: 100px;
    height: 2px; background: var(--aks-line, #d9d5cd);
}
.orga-branch-flat::before { display: none; }
.orga-branch-flat { margin-block-start: .6rem; }

.orga-node { position: relative; }
.orga-branch:not(.orga-branch-flat) .orga-node::before {
    content: ''; position: absolute; inset-block-start: -1.4rem; inset-inline-start: 50%;
    width: 2px; height: 1.4rem; background: var(--aks-line, #d9d5cd);
}

.orga-card {
    position: relative; width: 200px; text-align: center;
    background: #fff; border: 1px solid #e7e3db;
    border-radius: var(--aks-radius); padding: 1rem .75rem .85rem;
}
.orga-top .orga-card { border-color: var(--aks-sakura); }
.orga-avatar { width: 112px; margin-inline: auto; margin-block-end: .7rem; }
.orga-avatar-inner {
    width: 112px; height: 112px; border-radius: 50%; overflow: hidden;
    background: var(--aks-sakura-lt); color: var(--aks-sakura-dk);
    display: grid; place-items: center;
    font-family: 'Cormorant Garamond', serif; font-size: 2.1rem;
}
.orga-avatar-inner picture, .orga-avatar-inner img {
    width: 100%; height: 100%; object-fit: cover; object-position: center top; display: block;
}
.orga-name { font-weight: 600; font-size: .98rem; margin: 0; }
.orga-role { font-size: .8rem; color: #6b6a66; margin: .15rem 0 0; }
.orga-contact { font-size: .74rem; margin: .25rem 0 0; }

@media (max-width: 575.98px) {
    /* En colonne, les traits horizontaux n'ont plus de sens : on empile. */
    .orga-branch { flex-direction: column; align-items: center; }
    .orga-branch::before,
    .orga-branch .orga-node::before,
    .orga-top .orga-card::after { display: none; }
}

/* =====================================================================
   MATÉRIEL (page « La pratique »)
   ===================================================================== */

.materiel { margin-block-start: 2.5rem; }
/* Seuil à 280 px pour obtenir 2×2 dans la colonne de texte plutôt que 3 + 1 :
   quatre planches sur une rangée les réduiraient à 170 px, où les annotations
   ne se lisent plus. Deux par rangée, elles sont deux fois plus grandes. */
.materiel-grid {
    display: grid; gap: 1.5rem;
    grid-template-columns: repeat(auto-fit, minmax(min(100%, 280px), 1fr));
}
.materiel-item { margin: 0; height: 100%; }
.materiel-visuel {
    position: relative; cursor: zoom-in; text-decoration: none;
    transition: box-shadow .25s ease, transform .25s ease;
    background: #fff; border: 1px solid #e7e3db; border-radius: var(--aks-radius);
    padding: 1rem; display: grid; place-items: center;
    /* Hauteur commune : les trois planches n'ont pas le même format, et sans
       cadre partagé la rangée se lit comme trois blocs dépareillés. */
    aspect-ratio: 4 / 3; overflow: hidden;
}
.materiel-visuel svg { width: 100%; height: 100%; display: block; }
.materiel-photo { width: 100%; height: 100%; object-fit: cover; border-radius: 2px; }
.materiel-visuel picture { display: block; width: 100%; height: 100%; }
.materiel-visuel:hover, .materiel-visuel:focus-visible {
    box-shadow: 0 10px 26px rgba(22, 26, 36, .14); transform: translateY(-2px);
}
/* Les annotations des planches sont fines : sans repère, rien n'indique
   qu'elles s'agrandissent. La loupe le dit. */
.materiel-loupe {
    position: absolute; inset-block-end: .5rem; inset-inline-end: .6rem;
    width: 28px; height: 28px; display: grid; place-items: center;
    border-radius: 50%; background: var(--aks-ink); color: #fff;
    font-size: .85rem; line-height: 1; opacity: .55; transition: opacity .25s ease;
}
.materiel-visuel:hover .materiel-loupe,
.materiel-visuel:focus-visible .materiel-loupe { opacity: 1; }

/* Un SVG agrandi doit occuper la place offerte, et sur un fond opaque : il est
   transparent, et la page se voyait au travers du voile de la visionneuse.
   `*=` et non `$=` : l'URL porte un paramètre de cache (`?v=…`), elle ne se
   termine donc jamais par « .svg ». */
.lightbox-figure img[src*=".svg"] {
    width: min(1100px, 92vw); height: auto; max-height: 84vh;
    background: #fff; padding: 1.75rem; border-radius: var(--aks-radius);
}

.materiel-item figcaption { margin-block-start: .7rem; font-size: .88rem; }
.materiel-item figcaption strong { display: block; }
.materiel-item figcaption span { color: #6b6a66; }

/* ---------- Grille des formules d'adhésion ----------
   `auto-fit` et non `auto-fill` : les pistes vides sont supprimées, si bien
   que deux formules occupent chacune la moitié de la largeur au lieu de se
   serrer à gauche en laissant un tiers de rangée vide. Le nombre de formules
   varie avec les saisons, la grille s'y adapte seule. */
.plan-grid {
    display: grid;
    gap: 1.5rem;
    grid-template-columns: repeat(auto-fit, minmax(min(100%, 280px), 1fr));
    align-items: stretch;
}
.plan-grid > * { display: flex; }
.plan-grid .plan-card { width: 100%; }

/* =====================================================================
   GRADES (page « La pratique »)
   ===================================================================== */

.grades { margin-block-start: 2.75rem; }

/* Les Kyu forment une progression : le trait vertical qui relie les étapes le
   dit mieux qu'une liste à puces, où six lignes se lisent comme six éléments
   interchangeables. */
.grade-list {
    list-style: none; padding: 0; margin: 1.25rem 0 0;
    position: relative;
}
.grade-step {
    position: relative; display: flex; align-items: flex-start; gap: 1rem;
    padding-block: .7rem;
}
.grade-step::before {
    content: ''; position: absolute; inset-block: 0; inset-inline-start: 19px;
    width: 2px; background: var(--aks-line);
}
.grade-step:first-child::before { inset-block-start: 50%; }
.grade-step:last-child::before  { inset-block-end: 50%; }

.grade-kanji {
    position: relative; z-index: 1; flex: 0 0 40px;
    width: 40px; height: 40px; display: grid; place-items: center;
    border-radius: 50%; background: var(--aks-sakura-lt);
    color: var(--aks-sakura-dk); font-size: .82rem; line-height: 1;
}
.grade-step.is-start .grade-kanji { background: var(--aks-ink); color: #fff; }

.grade-body { display: flex; flex-direction: column; gap: .1rem; padding-block-start: .15rem; }
.grade-rank { font-size: .85rem; color: var(--aks-sakura-dk); }
.grade-delay { font-size: .85rem; color: #6b6a66; }

.grade-dan {
    margin-block-start: 1.5rem; padding: 1.1rem 1.25rem;
    background: var(--aks-paper-warm); border-inline-start: 3px solid var(--aks-sakura);
    border-radius: 0 var(--aks-radius) var(--aks-radius) 0;
}

.grade-forms {
    display: grid; gap: .6rem 1.5rem; margin: .75rem 0 0;
    grid-template-columns: repeat(auto-fit, minmax(min(100%, 260px), 1fr));
}
.grade-forms > div { padding-block-end: .55rem; border-block-end: 1px solid var(--aks-line); }
.grade-forms dt { font-weight: 600; font-size: .92rem; }
.grade-forms dd { margin: .1rem 0 0; font-size: .88rem; color: #6b6a66; }

/* ---------- Parcours d'un enseignant ---------- */
.teacher-bio { margin-block-start: .9rem; text-align: start; }
.teacher-bio summary {
    cursor: pointer; font-size: .82rem; color: var(--aks-sakura-dk);
    text-align: center; list-style: none; padding-block: .3rem;
}
.teacher-bio summary::-webkit-details-marker { display: none; }
.teacher-bio summary::after { content: ' ▾'; font-size: .7em; }
.teacher-bio[open] summary::after { content: ' ▴'; }
.teacher-bio p {
    font-size: .84rem; line-height: 1.65; color: #55534f;
    margin-block: .5rem 0; padding-block-start: .6rem;
    border-block-start: 1px solid var(--aks-line);
}

/* ---------- Carte de document téléchargeable ---------- */
.doc-card {
    display: flex; align-items: center; gap: 1rem;
    margin-block-start: 1.75rem; padding: 1rem 1.25rem;
    background: #fff; border: 1px solid #e7e3db; border-radius: var(--aks-radius);
    text-decoration: none; color: inherit;
    transition: box-shadow .2s ease, transform .2s ease;
}
.doc-card:hover, .doc-card:focus-visible {
    box-shadow: 0 10px 26px rgba(22, 26, 36, .12); transform: translateY(-2px);
}
.doc-card-icon {
    flex: 0 0 auto; width: 48px; height: 48px; display: grid; place-items: center;
    border-radius: var(--aks-radius); background: var(--aks-sakura); color: #fff;
    font-size: .72rem; font-weight: 700; letter-spacing: .06em;
}
.doc-card-body { display: flex; flex-direction: column; gap: .12rem; }
.doc-card-body span { font-size: .88rem; color: #6b6a66; }
.doc-card-meta { font-size: .78rem !important; color: #8a8781 !important; }

/* =====================================================================
   CARTE DU DOJO (chargement sur clic)
   ===================================================================== */

.carte {
    margin-block-start: 2.5rem;
    border-radius: var(--aks-radius); overflow: hidden;
    border: 1px solid var(--aks-line);
    /* Hauteur réservée dès l'aperçu : quand l'iframe arrive, rien ne saute. */
    min-height: 420px; position: relative; background: var(--aks-paper-warm);
}
.carte-apercu {
    position: absolute; inset: 0; display: flex; flex-direction: column;
    align-items: center; justify-content: center; gap: .85rem; padding: 2rem 1.5rem;
    text-align: center;
    /* Trame discrète : un aplat nu se lirait comme un bloc en panne de
       chargement. Dessinée en CSS, donc aucune requête. */
    background-image:
        linear-gradient(0deg, rgba(22,26,36,.05) 1px, transparent 1px),
        linear-gradient(90deg, rgba(22,26,36,.05) 1px, transparent 1px);
    background-size: 32px 32px;
}
.carte-pin {
    width: 22px; height: 22px; border-radius: 50% 50% 50% 0;
    transform: rotate(-45deg); background: var(--aks-sakura);
    box-shadow: 0 6px 14px rgba(176, 77, 84, .35);
}
.carte-adresse { margin: .4rem 0 0; font-weight: 600; }
.carte-note { margin: 0; font-size: .78rem; color: #6b6a66; max-width: 42ch; }
.carte-lien { font-size: .82rem; }
.carte iframe { width: 100%; height: 420px; border: 0; display: block; }

@media (min-width: 992px) { .carte, .carte iframe { min-height: 480px; height: 480px; } }

/* =====================================================================
   PROGRAMME TECHNIQUE
   ===================================================================== */

.programme { margin-block-start: 2.75rem; }

/* Une couleur par grade, reprise du tableau d'origine. Elles ne portent
   jamais l'information seule : le chiffre est toujours écrit dans la case,
   pour qui ne distingue pas ces teintes. */
.prog-k1 { --pk: #7a5a1c; }
.prog-k2 { --pk: #2f6fbf; }
.prog-k3 { --pk: #3f7d43; }
.prog-k4 { --pk: #d99a20; }
.prog-k5 { --pk: #b8a51f; }

.prog-filtres { display: flex; flex-wrap: wrap; gap: .4rem; margin-block: 1rem .5rem; }
.prog-chip {
    border: 1px solid var(--aks-line); background: #fff; color: var(--aks-ink);
    border-radius: 999px; padding: .3rem .85rem; font-size: .82rem; cursor: pointer;
    transition: background .15s ease, color .15s ease, border-color .15s ease;
}
.prog-chip:hover { border-color: var(--aks-ink); }
.prog-chip.is-on { background: var(--pk, var(--aks-ink)); border-color: transparent; color: #fff; }
.prog-compte { font-size: .82rem; color: #6b6a66; min-height: 1.2em; margin-block-end: .75rem; }

.prog-bloc { margin-block-start: 1.5rem; }
.prog-bloc[hidden] { display: none; }
.prog-titre { margin-block-end: .5rem; }
.prog-titre span { font-weight: 400; color: #6b6a66; font-size: .82rem; margin-inline-start: .4rem; }

/* Dix-neuf colonnes ne tiennent pas dans une colonne de texte : le tableau
   défile horizontalement, et la première colonne reste visible — sans elle on
   ne sait plus de quelle attaque on lit la ligne. */
.prog-scroll {
    overflow-x: auto; border: 1px solid var(--aks-line);
    border-radius: var(--aks-radius); background: #fff;
}
.prog-table { border-collapse: separate; border-spacing: 0; font-size: .8rem; margin: 0; }
.prog-table th, .prog-table td {
    border-block-end: 1px solid #eeebe4; border-inline-end: 1px solid #f3f1ea;
    padding: .45rem .5rem; text-align: center; white-space: nowrap;
}
/* Pas de `position: sticky` vertical sur l'en-tête : `.prog-scroll` ne défile
   qu'horizontalement, le collage se ferait donc par rapport à la PAGE et la
   ligne de titres viendrait glisser par-dessus le reste du contenu. Les
   tableaux tiennent en une douzaine de lignes, on s'en passe. */
.prog-table thead th {
    background: var(--aks-ink); color: #fff; font-weight: 600;
    font-size: .72rem; letter-spacing: .02em;
}
.prog-table tbody th[scope="row"] {
    position: sticky; inset-inline-start: 0; z-index: 1;
    background: var(--aks-paper-warm); text-align: start; font-weight: 600;
    box-shadow: 1px 0 0 var(--aks-line);
}
.prog-table thead th:first-child {
    position: sticky; inset-inline-start: 0; z-index: 3;
    box-shadow: 1px 0 0 rgba(255, 255, 255, .15);
}
.prog-groupe th {
    background: #f6f4ee; text-align: start; text-transform: uppercase;
    letter-spacing: .14em; font-size: .68rem; color: var(--aks-sakura-dk);
    position: sticky; inset-inline-start: 0;
}

.prog-case {
    display: inline-grid; place-items: center; width: 24px; height: 24px;
    border-radius: 5px; background: var(--pk); color: #fff;
    font-weight: 600; font-size: .78rem;
}
/* Filtrage : les cases hors grade s'effacent au lieu de disparaître — la
   forme du tableau reste lisible, et on voit ce qui vient avant et après. */
.programme.is-filtre td:not(.is-match) .prog-case { opacity: .12; }
.programme.is-filtre tbody tr.is-vide { opacity: .35; }

@media print {
    .prog-filtres, .prog-compte { display: none; }
    .prog-scroll { overflow: visible; border: 0; }
    .prog-table { font-size: .62rem; }
    .prog-bloc { break-inside: avoid; }
}

/* ---------- Reçu imprimable ---------- */
@media print {
    .recu-actions { display: none; }
    .recu { border: 0 !important; box-shadow: none !important; }
}
.carte-echec {
    margin: 0; max-width: 46ch; font-size: .82rem;
    color: var(--aks-sakura-dk); background: var(--aks-sakura-lt);
    padding: .6rem .9rem; border-radius: var(--aks-radius);
}

/* ------------------------------------------------------------------
   Vidéos
   Une façade remplace le lecteur tiers tant que le visiteur n'a pas
   cliqué : rien n'est chargé chez YouTube ou Vimeo avant ce clic.
   ------------------------------------------------------------------ */
/* Le cadre épouse le format du fichier : plus de bandes noires autour d'une
   vidéo verticale, donc plus besoin d'un fond noir pour les masquer. Le fond
   ne sert que le temps du chargement des métadonnées. */
.video-cadre {
    background: var(--aks-indigo, #1d2433);
    border-radius: var(--aks-radius, .5rem);
    overflow: hidden;
}

.video-cadre video,
.video-cadre img {
    width: 100%;
    height: 100%;
    object-fit: cover;
}

/* Une verticale se recadre mal : on la montre entière, quitte à laisser
   respirer les côtés — c'est le sujet qui compte, pas le remplissage. */
.video-cadre--vertical video {
    object-fit: contain;
}

/* Bootstrap ne fournit pas le 9/16 : le portrait n'existe pas dans sa liste. */
.ratio-9x16 {
    --bs-aspect-ratio: 177.78%;
}

/* Les cartes d'une même rangée s'alignent en haut : une verticale et une
   horizontale n'ont pas la même hauteur, et les centrer ferait onduler la
   ligne de légendes. */
.video-grille {
    align-items: start;
}

.video-facade {
    background: var(--aks-indigo, #1d2433);
    border-radius: var(--aks-radius, .5rem);
    overflow: hidden;
}

/* `position: absolute` et non `relative` : dans un conteneur `.ratio`, la
   hauteur vient du calage en padding, donc un enfant resté dans le flux
   mesure zéro et le bouton devient incliquable. */
.video-facade-btn {
    position: absolute;
    inset: 0;
    display: block;
    width: 100%;
    height: 100%;
    padding: 0;
    border: 0;
    background: none;
    cursor: pointer;
}

.video-facade-btn img {
    width: 100%;
    height: 100%;
    object-fit: cover;
}

/* Le bouton de lecture est dessiné, pas écrit : le caractère ▶ n'a pas la
   même allure d'une police à l'autre, et disparaît sur certaines. */
.video-facade-play {
    position: absolute;
    inset: 0;
    background: rgba(0, 0, 0, .2);
    transition: background .15s ease;
}

.video-facade-play::before {
    content: '';
    position: absolute;
    top: 50%;
    left: 50%;
    width: 4.25rem;
    height: 4.25rem;
    transform: translate(-50%, -50%);
    border-radius: 50%;
    background: rgba(255, 255, 255, .92);
    box-shadow: 0 4px 18px rgba(0, 0, 0, .35);
}

.video-facade-play::after {
    content: '';
    position: absolute;
    top: 50%;
    left: 50%;
    transform: translate(-38%, -50%);
    border-style: solid;
    border-width: .85rem 0 .85rem 1.4rem;
    border-color: transparent transparent transparent var(--aks-indigo, #1d2433);
}

.video-facade-btn:hover .video-facade-play,
.video-facade-btn:focus-visible .video-facade-play {
    background: rgba(0, 0, 0, .34);
}

.video-facade iframe {
    width: 100%;
    height: 100%;
    border: 0;
}

/* ------------------------------------------------------------------
   Certificat médical dans la liste des adhérents.
   La couleur alerte, le libellé informe : sur un écran mal réglé ou
   pour un daltonien, seul le texte reste lisible.
   ------------------------------------------------------------------ */
.table-aks tbody td.certif-perime,
.certif-perime {
    background: #fdeaea;
    color: #8a1f1f;
    box-shadow: inset 3px 0 0 #c0392b;
}

.table-aks tbody td.certif-bientot,
.certif-bientot {
    background: #fdf4e3;
    color: #7a5200;
    box-shadow: inset 3px 0 0 #d99a1e;
}

.table-aks tbody td.certif-absent,
.certif-absent {
    background: #f4f4f5;
}

/* ------------------------------------------------------------------
   Pages éditoriales (L'Aïkido, Le club, La pratique, une actualité).
   Elles partageaient une colonne étroite quand l'accueil occupe toute
   la largeur du conteneur : côte à côte, la page de contenu avait l'air
   d'un encart. Elles suivent maintenant la même respiration.

   Le texte occupe toute la colonne : un plafond en `ch` laisserait une
   bande vide à droite, c'est-à-dire exactement ce qu'on cherchait à
   supprimer. La longueur de ligne reste tenable parce que le corps du
   texte est déjà généreux.
   ------------------------------------------------------------------ */
.page-lisible .content-body,
.page-lisible > .lead {
    max-width: 100%;
}

/* ------------------------------------------------------------------
   Signature saisie au clavier.
   Le champ prend l'allure d'une signature à mesure qu'on écrit : le
   représentant légal voit ce que le club éditera, au lieu de taper son
   nom dans un champ comme un autre et de découvrir le rendu plus tard.
   ------------------------------------------------------------------ */
.signature-manuscrite {
    font-family: 'Caveat', 'Segoe Script', cursive;
    font-size: 1.75rem;
    line-height: 1.4;
    padding-block: .35rem;
}

.signature-manuscrite::placeholder {
    font-family: var(--aks-font-body, system-ui, sans-serif);
    font-size: 1rem;
}

.funnel-autorisation {
    background: var(--aks-sakura-lt, #fdf1f3);
    border-radius: var(--aks-radius, .5rem);
    padding: 1.25rem;
    margin-inline: -1.25rem;
}

/* Certificat présent mais sans date connue : ni rassurant comme un
   certificat valide, ni alarmant comme un certificat absent. Il appelle
   un geste — ouvrir la pièce et saisir la date — et non une relance. */
.table-aks tbody td.certif-inconnu,
.certif-inconnu {
    background: #eef2f7;
    box-shadow: inset 3px 0 0 #7d8ea6;
}
