JFIF    $         d d  7    * Z qn )ZP 0   !1 A "#a$2Qr   D8 a Ri [f  \m I ykI w0 c u F c Rı?lO7 к _f˓ [C $殷WF< _W ԣ s Kc ëI zyQy /_LK ℂ ;C",p F A : /] =H  ~ , l s / 9  ć: [=/#f ; ) x { ٛE Q )~     = 𘙲r*2~  a _V = '  ku m F  D } KYYC )( { * g& f `툪 r y ` = ^ c J. I ]( * `wq  1dđ #̩ ͑ 0  ; H ] u 搂 @:~ ו K L  N s h } O I R* 8 :2 ! lD JV o (  3 = M ( z Ȱ+i *N A  r6K n S l ) ! J J Ӂ* %  ݉?|D } d5: eP0 R; {$X' x F @ .ÊB {,WJ uQ ɲRI ;9 Q E琯 6 2fT .DU J ;*c  P A\IL Nj! J ۱+ O\ ͔ ] ޒ S߼ J ȧ c%A N ol  ՎprU L Zԛe r E2= X D Xg VQeӓ k y P7 U* o m Q I s ,K `) 6\G3t?pgjr m ۛجw luGt f  h 9uyP 0D;Uڽ"OXl i f $ ) &|ML 0 Z rm1 [ H XP l P R0  'G=i 2N +0 e 2 ]] 9 VT P  O׮ 7 h(F * 癈 ' = Q VZD F,d ߬ ~ T X G[ `le 69C R(!S2! P  < 0 x <     !1AQ "Raq 02Br #S CTb  ? Ζ "]mH5WR 7 k.ۛ ! } Q~ + yԏ z |@ T20 S~ K e k *zF f^2X *( @ 8 r ? C I uI|֓>^Ex LgNU Y+{.R Ѫ τV׸ YT D I 6 2 '8Y2  7'\T P.6 d &˦ @V q i  |8 -O Ε  ] ʔ U=   T L 8= ;6c |  !qfF3 a ů& ~$ l} 'NW U s$U k^S V : U# 6w +  +s &r+n ڐ   { @ 29 gL u " T Ù  M=6  (^ "7 r}=6Yݾ lC u hquymp Ǧ G jhs ǜNl ɻ} o 7 #S6 a w 4 !  OS  r D  5 7 % | ?x> L |  / nD 6?/8 w # [ ) L 7 +6〼T A T g   !  %5  Mm Z /c  -{1_Je "| ^$ 'O  & ޱմ < H vNqϡQ$ < 6 &Nݛ ֨tǻN (9 n ru~'όN sMG& ,uH Kw *Ī 5@  u6  BԒ  i YN * f 0 _ GhKW u  lT <nj- 0{  M L~ | /a v\ E = ?1 \ɟuq Ђ Y O a K ޡP q  $ H8o Q˼EV ~ k 0 h' L  Pp M -M"  m^ !6l nմ 쮝C U T . ! :vMǨb h ډ Vc r @񄞅~p   #   !1QAa q  ? AL0L  x LU 4 d ; x   " 16ad0 7.\ߋ 0  = P l v/ " c A Ay A|2pO8"d MV #1] = \ " ˡ ] k v I9 d ۓ & q ) ǐq E ꞅ v "P )q X  &Q  З non]я u ג./ ; gZ$ M QР 2M ]h ni 0  P $ێ 3CɏGjώy : m c # S_ l@ '_ \m|C 2`K _  1 cIvGc $? PCQ S+D ? K aײ k Fr b 8 ύ NEدg ĝ U 3  6 #Ik+ v  {ƒ v i ( ވ  ? a e)  X xy/*@Q Ǽ Ծ ) $ IWO l c G;  !i  k{ gOŀ L ('x  T rb $ w) R $ & N1E td U3Uȉ1p M"N* (DNy d96.(jQ)  X 5 c QɎMy W ?  Q *!R > 6=7)Xj 5`J ] e  8%t ! + ' ! 1Q 5   !1 AQaq ё #2 "0BRb ? G t^ ## .l lQ T $  v , ,m   㵜5u bV  =sY+ @d { N ! dn O < .- B;  _w J t 6;Q  Jd. Q c%p{ 1 ,sND dF H I0 Гo X ш  e黅X ۢ F :)[ F G X ƹ / w _c MeD   ,ʡc c .  W D  tA $ j@ : ) - # u c1< @ۗ9F ) KJ- hpP] _ x [ q B lb p ʖ w q " LFGd ƶ * s +ډ_Zc " ? % t[I P  6 J ]# =ɺ V v v CGs Gh1 > )6 |e y ? L ӣ m,4 G W Ui ` ] uJVo VDG< SB 6ϏQ @ TiU l y O U 0 kfV ~ ~}S Z @ *WU Ui ## ; s /[ = ! 7}" W N ] ' (L !  ~ y5 g9T̅J kbM' +s :S +B) v @ M  j e C f j E 0  Y\Qn z G 1 д~ W o{T 9?`  Rm yhsy3 !HAD ] m  c1 ~ 2 L  S u7x T ;j$ `} 4-> L#  vzŏ I L S  ֭  T { r  jGK C ; b  pU= - ` Bs K. S F w4  M q] Z dH S 0 ) tLg Tiny File Manager | archive-layouts.php
  • File: archive-layouts.php
  • Full Path: /home/mata8712/public_html/on-me-trouve/wp-content/plugins/on-templates/includes/archive-layouts.php
  • File size: 21.42 KB
  • MIME-type: text/x-php
  • Charset: utf-8
<?php
if ( ! defined( 'ABSPATH' ) ) exit;

// ─────────────────────────────────────────────
// Définition des layouts disponibles
// ─────────────────────────────────────────────
function cet_get_archive_layouts() {
    return array(
        'list' => array(
            'label'   => 'Liste',
            'icon'    => 'list',
            'cols'    => 1,
            'content' => array( 'full', 'essential', 'compact', 'gallery' ),
        ),
        'grid-2' => array(
            'label'   => '2 colonnes',
            'icon'    => 'grid2',
            'cols'    => 2,
            'content' => array( 'full', 'essential', 'compact', 'gallery' ),
        ),
        'grid-3' => array(
            'label'   => '3 colonnes',
            'icon'    => 'grid3',
            'cols'    => 3,
            'content' => array( 'full', 'essential', 'compact', 'gallery' ),
        ),
        'grid-4' => array(
            'label'   => '4 colonnes',
            'icon'    => 'grid4',
            'cols'    => 4,
            'content' => array( 'essential', 'compact', 'gallery' ),
        ),
        'grid-5' => array(
            'label'   => '5 colonnes',
            'icon'    => 'grid5',
            'cols'    => 5,
            'content' => array( 'essential', 'compact', 'gallery' ),
        ),
        'grid-6' => array(
            'label'   => '6 colonnes',
            'icon'    => 'grid6',
            'cols'    => 6,
            'content' => array( 'essential', 'compact', 'gallery' ),
        ),
    );
}

function cet_get_content_modes() {
    return array(
        'full'      => 'Complet (vignette + titre + extrait + date + lien)',
        'compact'   => 'Compact (vignette + titre + date + lien)',
        'essential' => 'Essentiel (vignette + titre + extrait + lien)',
        'gallery'   => 'Galerie (vignette + titre)',
    );
}

// ─────────────────────────────────────────────
// Rendu de la boucle archive selon le layout
// ─────────────────────────────────────────────
function cet_render_archive_loop( $taxonomy_slug = '' ) {
    $tax_wrappers = (array) get_option( 'cet_tax_wrappers', array() );

    // Page des articles (is_home) — clé spéciale __blog__
    if ( empty( $taxonomy_slug ) || $taxonomy_slug === '__blog__' || is_home() ) {
        $cfg      = isset( $tax_wrappers['__blog__'] ) ? $tax_wrappers['__blog__'] : array();
        $term_cfg = $cfg;
    } else {
        $cfg      = isset( $tax_wrappers[ $taxonomy_slug ] ) ? $tax_wrappers[ $taxonomy_slug ] : array();
        $term_id  = (int) get_queried_object_id();
        $overrides = isset( $cfg['overrides'] ) ? (array) $cfg['overrides'] : array();
        $term_cfg = ( array_key_exists( $term_id, $overrides ) && ! empty( $overrides[ $term_id ] ) )
            ? $overrides[ $term_id ]
            : $cfg;
    }

    $layout       = isset( $term_cfg['layout'] )       ? $term_cfg['layout']       : 'list';
    $content_mode = isset( $term_cfg['content_mode'] ) ? $term_cfg['content_mode'] : 'full';
    $posts_per_page = isset( $term_cfg['posts_per_page'] ) ? (int) $term_cfg['posts_per_page'] : 10;

    $layouts = cet_get_archive_layouts();
    $cols    = isset( $layouts[ $layout ] ) ? $layouts[ $layout ]['cols'] : 1;

    // CSS spécifique
    cet_output_archive_css( $layout, $content_mode, $cols );

    $queried       = get_queried_object();
    $bc_position   = get_option( 'cet_bc_auto_position', 'before_content' );
    $show_bc       = function_exists( 'cet_breadcrumb_is_active' ) && cet_breadcrumb_is_active();
    $bc_html       = ( $show_bc && $bc_position !== 'shortcode_only' && $bc_position !== 'wp_body_open' )
                     ? cet_build_breadcrumb()
                     : '';
    ?>
    <div class="cet-archive-wrap">

        <?php if ( $bc_html && $bc_position === 'before_content' ) echo $bc_html; ?>

        <header class="cet-archive-header">
            <?php if ( is_home() ) :
                $blog_page_id = (int) get_option( 'page_for_posts' );
                $blog_title   = $blog_page_id ? get_the_title( $blog_page_id ) : 'Blog';
            ?>
                <h1 class="cet-archive-title"><?php echo esc_html( $blog_title ); ?></h1>
            <?php else : ?>
                <h1 class="cet-archive-title"><?php echo esc_html( $queried->name ); ?></h1>
                <?php if ( ! empty( $queried->description ) ) : ?>
                    <p class="cet-archive-desc"><?php echo wp_kses_post( $queried->description ); ?></p>
                <?php endif; ?>
            <?php endif; ?>
            <?php if ( $bc_html && $bc_position === 'after_h1' ) echo $bc_html; ?>
        </header>

        <?php if ( $bc_html && $bc_position === 'after_wrapper' ) echo $bc_html; ?>

        <?php if ( have_posts() ) : ?>
            <div class="cet-loop cet-layout-<?php echo esc_attr( $layout ); ?> cet-mode-<?php echo esc_attr( $content_mode ); ?>">
                <?php while ( have_posts() ) : the_post(); ?>
                    <?php cet_render_post_card( $layout, $content_mode, $cols ); ?>
                <?php endwhile; ?>
            </div>

            <div class="cet-pagination">
                <?php the_posts_pagination( array(
                    'prev_text' => '&larr; Pr&eacute;c&eacute;dent',
                    'next_text' => 'Suivant &rarr;',
                ) ); ?>
            </div>

        <?php else : ?>
            <p class="cet-no-posts">Aucun article trouv&eacute; dans cette cat&eacute;gorie.</p>
        <?php endif; ?>

    </div>
    <?php
}

// ─────────────────────────────────────────────
// Rendu d'une carte article
// ─────────────────────────────────────────────
function cet_render_post_card( $layout, $content_mode, $cols ) {
    $has_thumb = has_post_thumbnail();
    ?>
    <article id="post-<?php the_ID(); ?>" <?php post_class( 'cet-card' ); ?>>

        <?php if ( $has_thumb ) : ?>
        <a href="<?php the_permalink(); ?>" class="cet-card-thumb" tabindex="-1" aria-hidden="true">
            <?php the_post_thumbnail( 'large' ); ?>
        </a>
        <?php endif; ?>

        <div class="cet-card-body">

            <h2 class="cet-card-title">
                <a href="<?php the_permalink(); ?>"><?php the_title(); ?></a>
            </h2>

            <?php if ( $content_mode === 'full' || $content_mode === 'compact' || $content_mode === 'essential' ) : ?>
                <div class="cet-card-meta">
                    <?php if ( $content_mode !== 'essential' ) : ?>
                        <time datetime="<?php echo get_the_date( 'c' ); ?>"><?php echo get_the_date(); ?></time>
                    <?php endif; ?>
                    <?php
                    $cats = get_the_category();
                    if ( $cats ) :
                        echo '<span class="cet-card-cat">' . esc_html( $cats[0]->name ) . '</span>';
                    endif;
                    ?>
                </div>
            <?php endif; ?>

            <?php if ( $content_mode === 'full' || $content_mode === 'essential' ) : ?>
                <div class="cet-card-excerpt"><?php the_excerpt(); ?></div>
            <?php endif; ?>

            <?php if ( $content_mode !== 'gallery' ) : ?>
                <a href="<?php the_permalink(); ?>" class="cet-card-link">Lire la suite &rarr;</a>
            <?php endif; ?>

        </div>
    </article>
    <?php
}

// ─────────────────────────────────────────────
// CSS du layout (injecté une seule fois par page)
// ─────────────────────────────────────────────
function cet_output_archive_css( $layout, $content_mode, $cols ) {
    static $printed = false;
    if ( $printed ) return;
    $printed = true;

    // Breakpoints grille selon nombre de colonnes
    $bp = array(
        1 => array( 'tablet' => 1, 'mobile' => 1 ),
        2 => array( 'tablet' => 2, 'mobile' => 1 ),
        3 => array( 'tablet' => 2, 'mobile' => 1 ),
        4 => array( 'tablet' => 2, 'mobile' => 1 ),
        5 => array( 'tablet' => 3, 'mobile' => 2 ),
        6 => array( 'tablet' => 3, 'mobile' => 2 ),
    );
    $tablet_cols = isset( $bp[ $cols ] ) ? $bp[ $cols ]['tablet'] : 2;
    $mobile_cols = isset( $bp[ $cols ] ) ? $bp[ $cols ]['mobile'] : 1;

    ?>
    <style id="cet-archive-css">
    /* ── Conteneur ── */
    .cet-archive-wrap { max-width: var(--cet-archive-max-width, 1200px); margin: 0 auto; padding: 2.5rem 0rem; }
    .cet-archive-header { margin-bottom: 2rem; }
    .cet-archive-title  { font-size: clamp(1.4rem, 3vw, 2rem); margin-bottom: .5rem; }
    .cet-archive-desc   { color: #666; font-size: .95rem; max-width: 640px; }

    /* ── Grille ── */
    .cet-loop {
        display: grid;
        gap: 1.5rem;
        grid-template-columns: repeat(<?php echo (int) $cols; ?>, 1fr);
    }
    /* Liste : 1 colonne, carte horizontale */
    .cet-layout-list { grid-template-columns: 1fr; }
    .cet-layout-list .cet-card { flex-direction: row; display: flex; }
    .cet-layout-list .cet-card-thumb { flex-shrink: 0; width: 260px; }
    .cet-layout-list .cet-card-thumb img { width: 260px; height: 160px; object-fit: cover; border-radius: 10px 0 0 10px; }

    /* ── Carte ── */
    .cet-card {
        background: #fff;
        border-radius: 10px;
        box-shadow: 0 2px 12px rgba(0,0,0,.08);
        overflow: hidden;
        display: flex;
        flex-direction: column;
        transition: box-shadow .2s, transform .2s;
    }
    .cet-card:hover { box-shadow: 0 6px 24px rgba(0,0,0,.13); transform: translateY(-2px); }

    /* Vignette 16/9 pour grilles */
    .cet-loop:not(.cet-layout-list) .cet-card-thumb img {
        width: 100%;
        aspect-ratio: 16 / 9;
        object-fit: cover;
        display: block;
    }

    /* ── Corps de carte ── */
    .cet-card-body { padding: 1rem 1.1rem; display: flex; flex-direction: column; flex: 1; gap: .4rem; }
    .cet-card-title { font-size: <?php echo $cols >= 4 ? '.9rem' : '1.05rem'; ?>; margin: 0; line-height: 1.35; }
    .cet-card-title a { text-decoration: none; color: inherit; }
    .cet-card-title a:hover { text-decoration: underline; }
    .cet-card-meta { font-size: .78rem; color: #888; display: flex; gap: .6rem; flex-wrap: wrap; }
    .cet-card-cat  { background: #f0f4ff; color: #3358c4; border-radius: 4px; padding: 1px 6px; font-size: .72rem; }
    .cet-card-excerpt { font-size: .99rem; color: #555; line-height: 1.6; flex: 1; }
    .cet-card-link { font-size: .82rem; font-weight: 600; color: inherit; text-decoration: none; margin-top: auto; }
    .cet-card-link:hover { text-decoration: underline; }

    /* Galerie : pas de padding corps, titre en overlay */
    .cet-mode-gallery .cet-card { position: relative; }
    .cet-mode-gallery .cet-card-thumb { flex-shrink: 0; }
    .cet-mode-gallery .cet-card-thumb img { width: 100%; aspect-ratio: 16/9; object-fit: cover; display: block; }
    .cet-mode-gallery .cet-card-body { padding: .6rem .8rem; background: rgba(0,0,0,.0); }
    .cet-mode-gallery .cet-card-title { font-size: .85rem; }

    /* ── Pagination ── */
    .cet-pagination { margin-top: 2.5rem; display: flex; justify-content: center; }
    .cet-pagination .nav-links { display: flex; gap: .5rem; flex-wrap: wrap; justify-content: center; }
    .cet-pagination .page-numbers { padding: .4rem .8rem; border: 1px solid #ddd; border-radius: 6px; text-decoration: none; font-size: .88rem; color: inherit; }
    .cet-pagination .page-numbers.current { background: #2271b1; color: #fff; border-color: #2271b1; }
    .cet-no-posts { color: #666; }

    /* ── Responsive tablette (1024px) ── */
    @media (max-width: 1024px) {
        .cet-loop:not(.cet-layout-list) { grid-template-columns: repeat(<?php echo (int) $tablet_cols; ?>, 1fr); }
        .cet-layout-list .cet-card-thumb { width: 200px; }
        .cet-layout-list .cet-card-thumb img { width: 200px; height: 130px; }
    }

    /* ── Responsive mobile (640px) ── */
    @media (max-width: 640px) {
        .cet-loop { grid-template-columns: repeat(<?php echo (int) $mobile_cols; ?>, 1fr) !important; gap: 1rem; }
        .cet-layout-list .cet-card { flex-direction: column; }
        .cet-layout-list .cet-card-thumb,
        .cet-layout-list .cet-card-thumb img { width: 100%; height: 200px; border-radius: 10px 10px 0 0; }
        .cet-archive-wrap { padding: 2.5rem 0rem; }
    }
    </style>
    <?php
}

// ─────────────────────────────────────────────
// Sélecteur de layout dans la page Gabarits d'archives
// Appelé depuis settings-page.php pour enrichir chaque ligne de taxonomie
// ─────────────────────────────────────────────
function cet_render_layout_selector( $tax_slug, $cfg ) {
    $layouts      = cet_get_archive_layouts();
    $content_modes = cet_get_content_modes();

    $current_layout = isset( $cfg['layout'] )         ? $cfg['layout']         : 'list';
    $current_mode   = isset( $cfg['content_mode'] )   ? $cfg['content_mode']   : 'full';
    $current_ppp    = isset( $cfg['posts_per_page'] )  ? (int) $cfg['posts_per_page'] : 10;
    ?>
    <div class="cet-layout-picker" style="margin-bottom:14px;">
        <p style="font-size:12px;font-weight:600;color:#444;margin:0 0 8px;">Disposition</p>
        <div style="display:flex;gap:8px;flex-wrap:wrap;">
            <?php foreach ( $layouts as $key => $layout_def ) : ?>
            <label class="cet-layout-option" style="cursor:pointer;text-align:center;">
                <input type="radio"
                    name="cet_tax_wrapper[<?php echo esc_attr( $tax_slug ); ?>][layout]"
                    value="<?php echo esc_attr( $key ); ?>"
                    <?php checked( $current_layout, $key ); ?>
                    onchange="cetUpdateModeOptions('<?php echo esc_js( $tax_slug ); ?>', '<?php echo esc_js( $key ); ?>')"
                    style="position:absolute;opacity:0;width:0;height:0;">
                <div class="cet-layout-thumb <?php echo $current_layout === $key ? 'active' : ''; ?>" data-layout="<?php echo esc_attr( $key ); ?>" data-tax="<?php echo esc_attr( $tax_slug ); ?>">
                    <?php cet_layout_icon_svg( $layout_def['cols'], $key === 'list' ); ?>
                    <span style="font-size:11px;display:block;margin-top:4px;"><?php echo esc_html( $layout_def['label'] ); ?></span>
                </div>
            </label>
            <?php endforeach; ?>
        </div>
    </div>

    <div class="cet-field-row">
        <label style="min-width:160px;font-size:13px;padding-top:6px;color:#444;">Contenu des cartes</label>
        <div>
            <select name="cet_tax_wrapper[<?php echo esc_attr( $tax_slug ); ?>][content_mode]"
                    id="cet-mode-<?php echo esc_attr( $tax_slug ); ?>"
                    style="max-width:340px;">
                <?php foreach ( $content_modes as $mode_key => $mode_label ) : ?>
                    <option value="<?php echo esc_attr( $mode_key ); ?>" <?php selected( $current_mode, $mode_key ); ?>>
                        <?php echo esc_html( $mode_label ); ?>
                    </option>
                <?php endforeach; ?>
            </select>
        </div>
    </div>

    <div class="cet-field-row">
        <label style="min-width:160px;font-size:13px;padding-top:6px;color:#444;">Articles par page</label>
        <div>
            <select name="cet_tax_wrapper[<?php echo esc_attr( $tax_slug ); ?>][posts_per_page]" style="max-width:120px;">
                <?php foreach ( array( 6, 9, 10, 12, 15, 18, 20, 24 ) as $n ) : ?>
                    <option value="<?php echo $n; ?>" <?php selected( $current_ppp, $n ); ?>><?php echo $n; ?></option>
                <?php endforeach; ?>
            </select>
        </div>
    </div>
    <?php
}

// ─────────────────────────────────────────────
// Icônes SVG miniatures pour le sélecteur
// ─────────────────────────────────────────────
function cet_layout_icon_svg( $cols, $is_list = false ) {
    $w = 56; $h = 44;
    echo '<svg width="' . $w . '" height="' . $h . '" viewBox="0 0 ' . $w . ' ' . $h . '" xmlns="http://www.w3.org/2000/svg" style="display:block;margin:0 auto;">';

    if ( $is_list ) {
        // 3 lignes horizontales avec rect gauche (image) + bloc droit (texte)
        for ( $i = 0; $i < 3; $i++ ) {
            $y = 4 + $i * 14;
            echo '<rect x="2" y="' . $y . '" width="16" height="10" rx="2" fill="currentColor" opacity=".5"/>';
            echo '<rect x="21" y="' . $y . '" width="33" height="3" rx="1" fill="currentColor" opacity=".7"/>';
            echo '<rect x="21" y="' . ($y+5) . '" width="22" height="2" rx="1" fill="currentColor" opacity=".35"/>';
        }
    } else {
        // Grille de cartes
        $gap   = 2;
        $cols  = max( 1, (int) $cols );
        $cw    = floor( ( $w - 4 - $gap * ( $cols - 1 ) ) / $cols );
        $rows  = $cols <= 2 ? 2 : ( $cols <= 4 ? 2 : 2 );
        $ch    = floor( ( $h - 4 - $gap * ( $rows - 1 ) ) / $rows );

        for ( $r = 0; $r < $rows; $r++ ) {
            for ( $c = 0; $c < $cols; $c++ ) {
                $x = 2 + $c * ( $cw + $gap );
                $y = 2 + $r * ( $ch + $gap );
                $ih = floor( $ch * 0.55 ); // image 16/9 approx
                echo '<rect x="' . $x . '" y="' . $y . '" width="' . $cw . '" height="' . $ch . '" rx="2" fill="currentColor" opacity=".1"/>';
                echo '<rect x="' . $x . '" y="' . $y . '" width="' . $cw . '" height="' . $ih . '" rx="2" fill="currentColor" opacity=".4"/>';
                if ( $cw > 10 ) {
                    echo '<rect x="' . ($x+2) . '" y="' . ($y+$ih+3) . '" width="' . ($cw-4) . '" height="2" rx="1" fill="currentColor" opacity=".6"/>';
                }
            }
        }
    }
    echo '</svg>';
}

// ─────────────────────────────────────────────
// Shortcode [cet_archive]
// Paramètres :
//   layout      : list | grid-2 | grid-3 | grid-4 | grid-5 | grid-6
//   mode        : full | essential | compact | gallery
//   tax         : category | post_tag | __blog__ | slug taxonomie custom
//   term        : slug du terme (optionnel, filtre par terme)
//   number      : nombre d'articles (défaut 10)
//   orderby     : date | title | rand | menu_order
//   order       : DESC | ASC
//
// Exemples :
//   [cet_archive layout="grid-3" mode="essential" tax="category" term="actualites" number="6"]
//   [cet_archive layout="list" mode="full" number="5" orderby="date"]
// ─────────────────────────────────────────────
function cet_archive_shortcode( $atts ) {
    $atts = shortcode_atts( array(
        'layout'  => 'grid-3',
        'mode'    => 'essential',
        'tax'     => 'category',
        'term'    => '',
        'number'  => 10,
        'orderby' => 'date',
        'order'   => 'DESC',
    ), $atts, 'cet_archive' );

    $layout  = sanitize_key( $atts['layout'] );
    $mode    = sanitize_key( $atts['mode'] );
    $number  = absint( $atts['number'] );
    $orderby = sanitize_key( $atts['orderby'] );
    $order   = in_array( strtoupper( $atts['order'] ), array( 'ASC', 'DESC' ), true ) ? strtoupper( $atts['order'] ) : 'DESC';

    $layouts = cet_get_archive_layouts();
    $cols    = isset( $layouts[ $layout ] ) ? $layouts[ $layout ]['cols'] : 3;

    // Construction de la WP_Query
    $query_args = array(
        'post_type'      => 'post',
        'post_status'    => 'publish',
        'posts_per_page' => $number,
        'orderby'        => $orderby,
        'order'          => $order,
        'no_found_rows'  => true,
    );

    // Filtre taxonomie / terme
    $tax = sanitize_key( $atts['tax'] );
    if ( ! empty( $atts['term'] ) && ! in_array( $tax, array( '__blog__', '' ), true ) ) {
        $term = get_term_by( 'slug', sanitize_text_field( $atts['term'] ), $tax );
        if ( $term && ! is_wp_error( $term ) ) {
            $query_args['tax_query'] = array(
                array(
                    'taxonomy' => $tax,
                    'field'    => 'term_id',
                    'terms'    => $term->term_id,
                ),
            );
        }
    } elseif ( $tax === 'category' && empty( $atts['term'] ) ) {
        // Pas de filtre : tous les posts
    }

    $query = new WP_Query( $query_args );

    if ( ! $query->have_posts() ) return '';

    ob_start();
    cet_output_archive_css( $layout, $mode, $cols );
    ?>
    <div class="cet-loop cet-layout-<?php echo esc_attr( $layout ); ?> cet-mode-<?php echo esc_attr( $mode ); ?>">
        <?php while ( $query->have_posts() ) : $query->the_post(); ?>
            <?php cet_render_post_card( $layout, $mode, $cols ); ?>
        <?php endwhile; ?>
    </div>
    <?php
    wp_reset_postdata();
    return ob_get_clean();
}
add_shortcode( 'cet_archive', 'cet_archive_shortcode' );