templates/application/whileresume/website/components/footer.html.twig line 7

Open in your IDE?
  1. {% set _locale = app.request.locale %}
  2. {% set _isFr = _locale == 'fr' %}
  3. {# Données dynamiques #}
  4. {% set footerArticles = getFooterArticles(_locale, 5) %}
  5. {% set footerLandingJobs = getFooterFeaturedLandingJobs(_locale, 5) %}
  6. {% set footerJobsCities = getFooterJobsCities(_locale, 6) %}
  7. {% set footerEnterprisesCities = getFooterEnterprisesCities(_locale, 6) %}
  8. {# Liens stores : nouvelle source de vérité (table cvs_app_store_links) #}
  9. {% set _storeData = getAppStoreCountries() %}
  10. {% set _storePrimary = _storeData.primary|default({}) %}
  11. {% set _storeOthers = _storeData.others|default({}) %}
  12. <style>
  13.     /* ---------- Footer WhileResume ---------- */
  14.     .whr-footer {
  15.         margin-top: 32px;
  16.         padding: 36px 24px 24px;
  17.         background: #F9FAFD;
  18.         border-radius: 16px;
  19.         color: #2c2c46;
  20.         width: auto;
  21.         max-width: none;
  22.         margin-left: 16px;
  23.         margin-right: 16px;
  24.     }
  25.     .theme-dark .whr-footer {
  26.         background: #2a2a3c;
  27.         color: #e9e9ef;
  28.     }
  29.     .middle-sidebar-left .whr-footer {
  30.         width: 100%;
  31.         margin-left: 0;
  32.         margin-right: 0;
  33.     }
  34.     /* Stores en haut de la col 1 */
  35.     .whr-footer .whr-stores {
  36.         display: flex;
  37.         flex-direction: column;
  38.         gap: 8px;
  39.         margin-bottom: 18px;
  40.         position: relative; /* pour le dropdown */
  41.     }
  42.     .whr-footer .whr-store-link {
  43.         display: inline-flex;
  44.         align-items: center;
  45.         gap: 10px;
  46.         padding: 8px 14px;
  47.         background: #111;
  48.         color: #fff !important;
  49.         border-radius: 10px;
  50.         font-size: 12px;
  51.         font-weight: 600;
  52.         text-decoration: none !important;
  53.         line-height: 1.2;
  54.         transition: transform .15s ease, background .2s ease;
  55.         max-width: 200px;
  56.         cursor: pointer;
  57.         border: none;
  58.         font-family: inherit;
  59.         text-align: left;
  60.     }
  61.     .whr-footer .whr-store-link:hover {
  62.         background: #2c2c46;
  63.         transform: translateY(-1px);
  64.     }
  65.     .whr-footer .whr-store-link small {
  66.         display: block;
  67.         font-weight: 400;
  68.         font-size: 10px;
  69.         opacity: .7;
  70.     }
  71.     .whr-footer .whr-store-link strong { font-size: 13px; display: block; }
  72.     /* Wrapper du bouton + dropdown (version EN) */
  73.     .whr-store-wrap {
  74.         position: relative;
  75.         display: inline-block;
  76.     }
  77.     .whr-store-wrap .whr-store-link {
  78.         width: 100%;
  79.         max-width: 200px;
  80.     }
  81.     /* === Dropdown élargi (2 colonnes + search + featured pinné) === */
  82.     .whr-store-dropdown {
  83.         position: absolute;
  84.         bottom: calc(100% + 6px);
  85.         left: 0;
  86.         width: 380px;
  87.         max-width: calc(100vw - 32px);
  88.         background: #fff;
  89.         border-radius: 12px;
  90.         box-shadow: 0 -8px 24px rgba(0,0,0,.15), 0 -2px 6px rgba(0,0,0,.08);
  91.         z-index: 1000;
  92.         display: none;
  93.         overflow: hidden;
  94.     }
  95.     .theme-dark .whr-store-dropdown {
  96.         background: #34344a;
  97.         box-shadow: 0 -8px 24px rgba(0,0,0,.4), 0 -2px 6px rgba(0,0,0,.2);
  98.     }
  99.     .whr-store-wrap.is-open .whr-store-dropdown {
  100.         display: flex;
  101.         flex-direction: column;
  102.         animation: whrFadeInUp .15s ease;
  103.     }
  104.     @keyframes whrFadeInUp {
  105.         from { opacity: 0; transform: translateY(4px); }
  106.         to { opacity: 1; transform: translateY(0); }
  107.     }
  108.     /* Chevron */
  109.     .whr-store-link .whr-store-chevron {
  110.         margin-left: auto;
  111.         font-size: 10px;
  112.         opacity: .7;
  113.         transition: transform .2s ease;
  114.     }
  115.     .whr-store-wrap.is-open .whr-store-link .whr-store-chevron {
  116.         transform: rotate(180deg);
  117.     }
  118.     /* Zone search en haut */
  119.     .whr-store-search-wrap {
  120.         padding: 10px 10px 6px;
  121.         border-bottom: 1px solid rgba(0,0,0,.06);
  122.         flex-shrink: 0;
  123.     }
  124.     .theme-dark .whr-store-search-wrap { border-bottom-color: rgba(255,255,255,.08); }
  125.     .whr-store-search {
  126.         width: 100%;
  127.         height: 34px;
  128.         padding: 0 12px 0 32px;
  129.         border: 1px solid rgba(0,0,0,.1);
  130.         border-radius: 8px;
  131.         background: #f5f5f8 url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='14' height='14' viewBox='0 0 24 24' fill='none' stroke='%23888' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'><circle cx='11' cy='11' r='8'/><line x1='21' y1='21' x2='16.65' y2='16.65'/></svg>") no-repeat 10px center;
  132.         font-size: 13px;
  133.         color: #2c2c46;
  134.         outline: none;
  135.         transition: border-color .15s ease, background-color .15s ease;
  136.         font-family: inherit;
  137.     }
  138.     .whr-store-search:focus {
  139.         border-color: var(--theme-color, #6C3AED);
  140.         background-color: #fff;
  141.     }
  142.     .theme-dark .whr-store-search {
  143.         background-color: #2a2a3c;
  144.         border-color: rgba(255,255,255,.1);
  145.         color: #e9e9ef;
  146.     }
  147.     .theme-dark .whr-store-search:focus { background-color: #3c3c52; }
  148.     .whr-store-search::placeholder { color: #999; }
  149.     /* Featured pinné (toujours visible, hors scroll) */
  150.     .whr-store-featured {
  151.         padding: 8px 8px 4px;
  152.         flex-shrink: 0;
  153.         border-bottom: 1px solid rgba(0,0,0,.06);
  154.     }
  155.     .theme-dark .whr-store-featured { border-bottom-color: rgba(255,255,255,.08); }
  156.     /* Zone scrollable des "other regions" */
  157.     .whr-store-others {
  158.         padding: 8px;
  159.         max-height: 280px;
  160.         overflow-y: auto;
  161.         flex: 1;
  162.     }
  163.     .whr-store-others::-webkit-scrollbar { width: 6px; }
  164.     .whr-store-others::-webkit-scrollbar-thumb { background: rgba(0,0,0,.15); border-radius: 3px; }
  165.     .theme-dark .whr-store-others::-webkit-scrollbar-thumb { background: rgba(255,255,255,.15); }
  166.     /* Header de section */
  167.     .whr-store-dropdown-header {
  168.         font-size: 10px;
  169.         font-weight: 700;
  170.         text-transform: uppercase;
  171.         letter-spacing: .5px;
  172.         opacity: .55;
  173.         padding: 4px 8px 6px;
  174.         color: #2c2c46;
  175.     }
  176.     .theme-dark .whr-store-dropdown-header { color: #e9e9ef; }
  177.     /* Grille 2 colonnes pour les pays */
  178.     .whr-store-grid {
  179.         display: grid;
  180.         grid-template-columns: 1fr 1fr;
  181.         gap: 2px;
  182.     }
  183.     /* Item pays */
  184.     .whr-store-country {
  185.         display: flex;
  186.         align-items: center;
  187.         gap: 8px;
  188.         padding: 7px 9px;
  189.         border-radius: 6px;
  190.         text-decoration: none !important;
  191.         color: #2c2c46 !important;
  192.         font-size: 12.5px;
  193.         transition: background .15s ease;
  194.         min-width: 0;
  195.     }
  196.     .theme-dark .whr-store-country { color: #e9e9ef !important; }
  197.     .whr-store-country:hover {
  198.         background: rgba(108, 58, 237, .08);
  199.         color: var(--theme-color, #6C3AED) !important;
  200.     }
  201.     .theme-dark .whr-store-country:hover { background: rgba(108, 58, 237, .2); }
  202.     .whr-store-country .whr-flag {
  203.         font-size: 16px;
  204.         line-height: 1;
  205.         width: 18px;
  206.         text-align: center;
  207.         flex-shrink: 0;
  208.     }
  209.     .whr-store-country .whr-country-name {
  210.         flex: 1;
  211.         font-weight: 500;
  212.         white-space: nowrap;
  213.         overflow: hidden;
  214.         text-overflow: ellipsis;
  215.         min-width: 0;
  216.     }
  217.     /* Featured = pleine largeur, plus mis en avant */
  218.     .whr-store-featured .whr-store-country {
  219.         background: linear-gradient(135deg, rgba(108, 58, 237, .08), rgba(108, 58, 237, .03));
  220.         font-weight: 600;
  221.         padding: 9px 10px;
  222.     }
  223.     .theme-dark .whr-store-featured .whr-store-country {
  224.         background: linear-gradient(135deg, rgba(108, 58, 237, .25), rgba(108, 58, 237, .1));
  225.     }
  226.     /* Message "aucun résultat" */
  227.     .whr-store-empty {
  228.         text-align: center;
  229.         padding: 20px 12px;
  230.         font-size: 12px;
  231.         color: #999;
  232.         font-style: italic;
  233.     }
  234.     .theme-dark .whr-store-empty { color: #aaa; }
  235.     /* Item caché par la recherche */
  236.     .whr-store-country.is-hidden { display: none; }
  237.     /* Responsive : sur mobile, 1 colonne et largeur ajustée */
  238.     @media (max-width: 575.98px) {
  239.         .whr-store-dropdown {
  240.             width: calc(100vw - 32px);
  241.             max-width: 360px;
  242.         }
  243.         .whr-store-grid {
  244.             grid-template-columns: 1fr;
  245.         }
  246.     }
  247.     /* Colonnes */
  248.     .whr-footer .whr-foot-col h4 {
  249.         font-size: 13px;
  250.         font-weight: 700;
  251.         margin: 0 0 14px 0;
  252.         color: inherit;
  253.         text-transform: uppercase;
  254.         letter-spacing: .3px;
  255.     }
  256.     .whr-footer .whr-foot-col ul {
  257.         list-style: none;
  258.         padding: 0;
  259.         margin: 0;
  260.         font-size: 13px;
  261.     }
  262.     .whr-footer .whr-foot-col ul li { margin-bottom: 10px; }
  263.     .whr-footer .whr-foot-col a {
  264.         color: inherit;
  265.         opacity: .75;
  266.         text-decoration: none;
  267.         transition: opacity .2s ease, color .2s ease;
  268.     }
  269.     .whr-footer .whr-foot-col a:hover { opacity: 1; color: var(--theme-color, #6C3AED); }
  270.     .whr-footer .whr-foot-empty {
  271.         font-size: 12px;
  272.         opacity: .5;
  273.         font-style: italic;
  274.     }
  275.     .whr-footer .whr-foot-action-links a {
  276.         display: inline-flex;
  277.         align-items: center;
  278.         gap: 8px;
  279.     }
  280.     .whr-footer .whr-foot-action-links a i {
  281.         font-size: 14px;
  282.         opacity: .7;
  283.         width: 16px;
  284.         text-align: center;
  285.     }
  286.     .whr-footer .whr-foot-col .whr-city-link {
  287.         display: inline-flex;
  288.         align-items: center;
  289.         gap: 6px;
  290.     }
  291.     .whr-footer .whr-foot-col .whr-city-link .whr-city-icon {
  292.         font-size: 14px;
  293.         line-height: 1;
  294.         display: inline-block;
  295.         width: 18px;
  296.         text-align: center;
  297.         opacity: .85;
  298.     }
  299.     .whr-footer .whr-foot-grid {
  300.         display: grid;
  301.         gap: 28px;
  302.         grid-template-columns: 1fr;
  303.     }
  304.     @media (min-width: 576px) {
  305.         .whr-footer .whr-foot-grid { grid-template-columns: 1fr 1fr; }
  306.     }
  307.     @media (min-width: 992px) {
  308.         .whr-footer .whr-foot-grid {
  309.             grid-template-columns: repeat(5, 1fr);
  310.             gap: 32px;
  311.         }
  312.     }
  313.     .whr-footer .whr-foot-bottom {
  314.         margin-top: 32px;
  315.         padding-top: 20px;
  316.         border-top: 1px solid rgba(0,0,0,.08);
  317.         display: flex;
  318.         flex-direction: column;
  319.         gap: 14px;
  320.         align-items: center;
  321.         text-align: center;
  322.     }
  323.     .theme-dark .whr-footer .whr-foot-bottom { border-top-color: rgba(255,255,255,.1); }
  324.     @media (min-width: 768px) {
  325.         .whr-footer .whr-foot-bottom {
  326.             flex-direction: row;
  327.             justify-content: space-between;
  328.             text-align: left;
  329.         }
  330.     }
  331.     .whr-footer .whr-foot-copy {
  332.         display: inline-flex;
  333.         align-items: center;
  334.         gap: 8px;
  335.         font-size: 12px;
  336.         opacity: .7;
  337.         margin: 0;
  338.     }
  339.     .whr-footer .whr-foot-copy img.whr-favicon {
  340.         width: 18px;
  341.         height: 18px;
  342.         border-radius: 4px;
  343.         flex-shrink: 0;
  344.     }
  345.     .whr-footer .whr-foot-legal {
  346.         display: flex;
  347.         flex-wrap: wrap;
  348.         gap: 6px 16px;
  349.         justify-content: center;
  350.         font-size: 12px;
  351.     }
  352.     .whr-footer .whr-foot-legal a {
  353.         color: inherit;
  354.         opacity: .75;
  355.         text-decoration: none;
  356.     }
  357.     .whr-footer .whr-foot-legal a:hover { opacity: 1; }
  358.     .whr-footer .whr-foot-legal .whr-admin-link { color: #e74c3c !important; opacity: 1; }
  359.     .whr-footer .whr-foot-social {
  360.         display: flex;
  361.         flex-wrap: wrap;
  362.         gap: 6px;
  363.         list-style: none;
  364.         padding: 0;
  365.         margin: 0;
  366.     }
  367.     .whr-footer .whr-foot-social a {
  368.         width: 32px; height: 32px;
  369.         border-radius: 8px;
  370.         background: #fff;
  371.         display: inline-flex;
  372.         align-items: center;
  373.         justify-content: center;
  374.         color: #2c2c46;
  375.         text-decoration: none !important;
  376.         transition: background .2s ease, color .2s ease, transform .15s ease;
  377.         box-shadow: 0 1px 2px rgba(0,0,0,.04);
  378.     }
  379.     .whr-footer .whr-foot-social a:hover {
  380.         background: var(--theme-color, #6C3AED);
  381.         color: #fff;
  382.         transform: translateY(-1px);
  383.     }
  384.     .theme-dark .whr-footer .whr-foot-social a {
  385.         background: #34344a;
  386.         color: #fff;
  387.         box-shadow: none;
  388.     }
  389.     .whr-footer .whr-foot-social i { font-size: 14px; }
  390.     @media (max-width: 575.98px) {
  391.         .whr-footer {
  392.             padding: 24px 18px 20px;
  393.             margin-left: 8px;
  394.             margin-right: 8px;
  395.         }
  396.         .whr-store-dropdown {
  397.             min-width: 220px;
  398.             max-width: 90vw;
  399.         }
  400.     }
  401. </style>
  402. <footer class="whr-footer" role="contentinfo">
  403.     {# === Grille principale 5 colonnes === #}
  404.     <div class="whr-foot-grid">
  405.         {# ===== Col 1 : Mon compte / Commencer ici ===== #}
  406.         <div class="whr-foot-col whr-foot-col-action">
  407.             {% if connectUser %}
  408.                 <h4>{{ 'layout.footer.my_account'|trans({}, 'whr-public')|default('Mon compte') }}</h4>
  409.             {% else %}
  410.                 <h4>{{ 'layout.footer.start_here'|trans({}, 'whr-public')|default('Commencer ici') }}</h4>
  411.             {% endif %}
  412.             <div class="whr-stores">
  413.                 {# === Dropdown unifié (FR & EN) — la version FR aura FR en featured, la EN aura US === #}
  414.                 {# -- Bouton App Store + dropdown -- #}
  415.                 {% set _hasIos = false %}
  416.                 {% for c in _storePrimary %}{% if c.ios %}{% set _hasIos = true %}{% endif %}{% endfor %}
  417.                 {% for c in _storeOthers %}{% if c.ios %}{% set _hasIos = true %}{% endif %}{% endfor %}
  418.                 {% if _hasIos %}
  419.                     <div class="whr-store-wrap" data-whr-store="ios">
  420.                         <button type="button" class="whr-store-link" aria-haspopup="true" aria-expanded="false" aria-label="App Store - Choose your country">
  421.                             <svg width="18" height="18" viewBox="0 0 24 24" fill="#fff" aria-hidden="true">
  422.                                 <path d="M18.71 19.5C17.88 20.74 17 21.95 15.66 21.97C14.32 22 13.89 21.18 12.37 21.18C10.84 21.18 10.37 21.95 9.09997 22C7.78997 22.05 6.79997 20.68 5.95997 19.47C4.24997 17 2.93997 12.45 4.69997 9.39C5.56997 7.87 7.12997 6.91 8.81997 6.88C10.1 6.86 11.32 7.75 12.11 7.75C12.89 7.75 14.37 6.68 15.92 6.84C16.57 6.87 18.39 7.1 19.56 8.82C19.47 8.88 17.39 10.1 17.41 12.63C17.44 15.65 20.06 16.66 20.09 16.67C20.06 16.74 19.67 18.11 18.71 19.5ZM13 3.5C13.73 2.67 14.94 2.04 15.94 2C16.07 3.17 15.6 4.35 14.9 5.19C14.21 6.04 13.07 6.7 11.95 6.61C11.8 5.46 12.36 4.26 13 3.5Z"/>
  423.                             </svg>
  424.                             <span>
  425.                                     <small>{{ 'layout.download_on'|trans({}, 'whr-public')|default('Download on') }}</small>
  426.                                     <strong>App Store</strong>
  427.                                 </span>
  428.                             <span class="whr-store-chevron" aria-hidden="true">▲</span>
  429.                         </button>
  430.                         <div class="whr-store-dropdown" role="menu">
  431.                             {# Search bar (n'apparaît que si > 20 pays "others") #}
  432.                             {% set _iosOthersCount = 0 %}
  433.                             {% for c in _storeOthers %}{% if c.ios %}{% set _iosOthersCount = _iosOthersCount + 1 %}{% endif %}{% endfor %}
  434.                             {% if _iosOthersCount > 20 %}
  435.                                 <div class="whr-store-search-wrap">
  436.                                     <input type="text"
  437.                                            class="whr-store-search"
  438.                                            placeholder="{{ 'layout.search_country'|trans({}, 'whr-public')|default('Search country...') }}"
  439.                                            aria-label="Search country"
  440.                                            autocomplete="off">
  441.                                 </div>
  442.                             {% endif %}
  443.                             {# Featured (pinné, pas dans le scroll) #}
  444.                             {% set _iosPrimaryCount = 0 %}
  445.                             {% for c in _storePrimary %}{% if c.ios %}{% set _iosPrimaryCount = _iosPrimaryCount + 1 %}{% endif %}{% endfor %}
  446.                             {% if _iosPrimaryCount > 0 %}
  447.                                 <div class="whr-store-featured">
  448.                                     <div class="whr-store-dropdown-header">
  449.                                         {{ 'layout.featured'|trans({}, 'whr-public')|default('Featured') }}
  450.                                     </div>
  451.                                     {% for code, country in _storePrimary %}
  452.                                         {% if country.ios %}
  453.                                             <a href="{{ country.ios }}"
  454.                                                class="whr-store-country"
  455.                                                data-search="{{ country.label|lower }} {{ code|lower }}"
  456.                                                target="_blank" rel="noopener" role="menuitem">
  457.                                                 {% if country.flag %}<span class="whr-flag">{{ country.flag }}</span>{% endif %}
  458.                                                 <span class="whr-country-name">{{ country.label }}</span>
  459.                                             </a>
  460.                                         {% endif %}
  461.                                     {% endfor %}
  462.                                 </div>
  463.                             {% endif %}
  464.                             {# Other regions (grille 2 colonnes, scrollable) #}
  465.                             {% if _storeOthers is not empty %}
  466.                                 <div class="whr-store-others">
  467.                                     <div class="whr-store-dropdown-header">
  468.                                         {{ 'layout.other_regions'|trans({}, 'whr-public')|default('Other regions') }}
  469.                                     </div>
  470.                                     <div class="whr-store-grid">
  471.                                         {% for code, country in _storeOthers %}
  472.                                             {% if country.ios %}
  473.                                                 <a href="{{ country.ios }}"
  474.                                                    class="whr-store-country"
  475.                                                    data-search="{{ country.label|lower }} {{ code|lower }}"
  476.                                                    target="_blank" rel="noopener" role="menuitem">
  477.                                                     {% if country.flag %}<span class="whr-flag">{{ country.flag }}</span>{% endif %}
  478.                                                     <span class="whr-country-name">{{ country.label }}</span>
  479.                                                 </a>
  480.                                             {% endif %}
  481.                                         {% endfor %}
  482.                                     </div>
  483.                                     <div class="whr-store-empty" style="display: none;">
  484.                                         {{ 'layout.no_country_found'|trans({}, 'whr-public')|default('No country found') }}
  485.                                     </div>
  486.                                 </div>
  487.                             {% endif %}
  488.                         </div>
  489.                     </div>
  490.                 {% endif %}
  491.                 {# -- Bouton Google Play + dropdown -- #}
  492.                 {% set _hasAndroid = false %}
  493.                 {% for c in _storePrimary %}{% if c.android %}{% set _hasAndroid = true %}{% endif %}{% endfor %}
  494.                 {% for c in _storeOthers %}{% if c.android %}{% set _hasAndroid = true %}{% endif %}{% endfor %}
  495.                 {% if _hasAndroid %}
  496.                     <div class="whr-store-wrap" data-whr-store="android">
  497.                         <button type="button" class="whr-store-link" aria-haspopup="true" aria-expanded="false" aria-label="Google Play - Choose your country">
  498.                             <svg width="18" height="18" viewBox="0 0 512 512" aria-hidden="true">
  499.                                 <path style="fill:#3A9BC8;" d="M225.656,256.052L14.016,485.451l-6.442,7.052c-4.005-5.919-6.704-12.972-7.313-20.806C0.087,470.305,0,468.91,0,467.518V44.499c0-9.488,2.873-18.02,7.574-24.987L225.656,256.052z"/>
  500.                                 <path style="fill:#9BCD83;" d="M320.811,152.8l-95.155,103.253L7.574,19.512C19.936,1.405,45.183-6.342,66.6,6.02L320.811,152.8z"/>
  501.                                 <path style="fill:#EEB84C;" d="M455.056,257.27c-0.348,14.453-7.748,28.904-22.113,37.174l-112.132,64.771l-95.155-103.163L320.811,152.8l70.518,40.745l41.614,24.026C448.178,226.366,455.579,241.861,455.056,257.27z"/>
  502.                                 <path style="fill:#B43F70;" d="M7.591,492.492c12.368,18.116,37.599,25.838,58.976,13.496L320.775,359.22l-95.156-103.209L7.591,492.492z"/>
  503.                             </svg>
  504.                             <span>
  505.                                     <small>{{ 'layout.available_on'|trans({}, 'whr-public')|default('Available on') }}</small>
  506.                                     <strong>Google Play</strong>
  507.                                 </span>
  508.                             <span class="whr-store-chevron" aria-hidden="true">▲</span>
  509.                         </button>
  510.                         <div class="whr-store-dropdown" role="menu">
  511.                             {# Search bar (n'apparaît que si > 20 pays "others") #}
  512.                             {% set _androidOthersCount = 0 %}
  513.                             {% for c in _storeOthers %}{% if c.android %}{% set _androidOthersCount = _androidOthersCount + 1 %}{% endif %}{% endfor %}
  514.                             {% if _androidOthersCount > 20 %}
  515.                                 <div class="whr-store-search-wrap">
  516.                                     <input type="text"
  517.                                            class="whr-store-search"
  518.                                            placeholder="{{ 'layout.search_country'|trans({}, 'whr-public')|default('Search country...') }}"
  519.                                            aria-label="Search country"
  520.                                            autocomplete="off">
  521.                                 </div>
  522.                             {% endif %}
  523.                             {# Featured (pinné) #}
  524.                             {% set _androidPrimaryCount = 0 %}
  525.                             {% for c in _storePrimary %}{% if c.android %}{% set _androidPrimaryCount = _androidPrimaryCount + 1 %}{% endif %}{% endfor %}
  526.                             {% if _androidPrimaryCount > 0 %}
  527.                                 <div class="whr-store-featured">
  528.                                     <div class="whr-store-dropdown-header">
  529.                                         {{ 'layout.featured'|trans({}, 'whr-public')|default('Featured') }}
  530.                                     </div>
  531.                                     {% for code, country in _storePrimary %}
  532.                                         {% if country.android %}
  533.                                             <a href="{{ country.android }}"
  534.                                                class="whr-store-country"
  535.                                                data-search="{{ country.label|lower }} {{ code|lower }}"
  536.                                                target="_blank" rel="noopener" role="menuitem">
  537.                                                 {% if country.flag %}<span class="whr-flag">{{ country.flag }}</span>{% endif %}
  538.                                                 <span class="whr-country-name">{{ country.label }}</span>
  539.                                             </a>
  540.                                         {% endif %}
  541.                                     {% endfor %}
  542.                                 </div>
  543.                             {% endif %}
  544.                             {# Other regions (grille 2 colonnes) #}
  545.                             {% if _storeOthers is not empty %}
  546.                                 <div class="whr-store-others">
  547.                                     <div class="whr-store-dropdown-header">
  548.                                         {{ 'layout.other_regions'|trans({}, 'whr-public')|default('Other regions') }}
  549.                                     </div>
  550.                                     <div class="whr-store-grid">
  551.                                         {% for code, country in _storeOthers %}
  552.                                             {% if country.android %}
  553.                                                 <a href="{{ country.android }}"
  554.                                                    class="whr-store-country"
  555.                                                    data-search="{{ country.label|lower }} {{ code|lower }}"
  556.                                                    target="_blank" rel="noopener" role="menuitem">
  557.                                                     {% if country.flag %}<span class="whr-flag">{{ country.flag }}</span>{% endif %}
  558.                                                     <span class="whr-country-name">{{ country.label }}</span>
  559.                                                 </a>
  560.                                             {% endif %}
  561.                                         {% endfor %}
  562.                                     </div>
  563.                                     <div class="whr-store-empty" style="display: none;">
  564.                                         {{ 'layout.no_country_found'|trans({}, 'whr-public')|default('No country found') }}
  565.                                     </div>
  566.                                 </div>
  567.                             {% endif %}
  568.                         </div>
  569.                     </div>
  570.                 {% endif %}
  571.             </div>
  572.             <ul class="whr-foot-action-links">
  573.                 <li>
  574.                     <a href="{{ path('whileresume_homepage') }}">
  575.                         <i class="feather-flag"></i>
  576.                         English
  577.                     </a>
  578.                 </li>
  579.                 <li>
  580.                     <a href="{{ path('locale_whileresume_homepage',{'_locale':'fr'}) }}">
  581.                         <i class="feather-flag"></i>
  582.                         Français
  583.                     </a>
  584.                 </li>
  585.             </ul>
  586.         </div>
  587.         {# ===== Col 2 : Articles récents (featured) ===== #}
  588.         <div class="whr-foot-col">
  589.             <h4>{{ 'layout.footer.latest_articles'|trans({}, 'whr-public')|default('Articles récents') }}</h4>
  590.             {% if footerArticles is not empty %}
  591.                 <ul>
  592.                     {% for article in footerArticles %}
  593.                         <li>
  594.                             <a href="{% if _isFr %}{{ path('locale_cvs_website_article', {'_locale': _locale, 'slug': article.slug}) }}{% else %}{{ path('cvs_website_article', {'slug': article.slug}) }}{% endif %}"
  595.                                title="{{ article.title }}">
  596.                                 {{ article.shortTitle ?: cleanSubstr(article.title, 45) }}
  597.                             </a>
  598.                         </li>
  599.                     {% endfor %}
  600.                 </ul>
  601.             {% else %}
  602.                 <p class="whr-foot-empty">{{ 'layout.footer.coming_soon'|trans({}, 'whr-public')|default('Bientôt disponible') }}</p>
  603.             {% endif %}
  604.         </div>
  605.         {# ===== Col 3 : Emplois par ville ===== #}
  606.         <div class="whr-foot-col">
  607.             <h4>{{ 'layout.footer.jobs_by_city'|trans({}, 'whr-public')|default('Emplois par ville') }}</h4>
  608.             {% if footerJobsCities is not empty %}
  609.                 <ul>
  610.                     {% for city in footerJobsCities %}
  611.                         <li>
  612.                             <a class="whr-city-link"
  613.                                href="{% if _isFr %}{{ path('locale_cvs_application_jobs_filter', {'_locale': _locale, 'slug': city.slug}) }}{% else %}{{ path('cvs_application_jobs_filter', {'slug': city.slug}) }}{% endif %}"
  614.                                title="{{ city.shortTitle ?: city.label }}">
  615.                                 {% if city.icon %}
  616.                                     <span class="whr-city-icon">{{ city.icon }}</span>
  617.                                 {% else %}
  618.                                     <i class="feather-map-pin whr-city-icon"></i>
  619.                                 {% endif %}
  620.                                 <span>{{ city.label }}</span>
  621.                             </a>
  622.                         </li>
  623.                     {% endfor %}
  624.                 </ul>
  625.             {% else %}
  626.                 <p class="whr-foot-empty">{{ 'layout.footer.coming_soon'|trans({}, 'whr-public')|default('Bientôt disponible') }}</p>
  627.             {% endif %}
  628.         </div>
  629.         {# ===== Col 4 : Entreprises par ville ===== #}
  630.         <div class="whr-foot-col">
  631.             <h4>{{ 'layout.footer.companies_by_city'|trans({}, 'whr-public')|default('Entreprises par ville') }}</h4>
  632.             {% if footerEnterprisesCities is not empty %}
  633.                 <ul>
  634.                     {% for city in footerEnterprisesCities %}
  635.                         <li>
  636.                             <a class="whr-city-link"
  637.                                href="{% if _isFr %}{{ path('locale_cvs_application_companies_filter', {'_locale': _locale, 'slug': city.slug}) }}{% else %}{{ path('cvs_application_companies_filter', {'slug': city.slug}) }}{% endif %}"
  638.                                title="{{ city.shortTitle ?: city.label }}">
  639.                                 {% if city.icon %}
  640.                                     <span class="whr-city-icon">{{ city.icon }}</span>
  641.                                 {% else %}
  642.                                     <i class="feather-map-pin whr-city-icon"></i>
  643.                                 {% endif %}
  644.                                 <span>{{ city.label }}</span>
  645.                             </a>
  646.                         </li>
  647.                     {% endfor %}
  648.                 </ul>
  649.             {% else %}
  650.                 <p class="whr-foot-empty">{{ 'layout.footer.coming_soon'|trans({}, 'whr-public')|default('Bientôt disponible') }}</p>
  651.             {% endif %}
  652.         </div>
  653.         {# ===== Col 5 : Pages SEO (LandingJobs featured) ===== #}
  654.         <div class="whr-foot-col">
  655.             <h4>{{ 'layout.footer.featured_pages'|trans({}, 'whr-public')|default('À découvrir') }}</h4>
  656.             {% if footerLandingJobs is not empty %}
  657.                 <ul>
  658.                     {% for landing in footerLandingJobs %}
  659.                         <li>
  660.                             <a href="{% if _isFr %}{{ path('locale_whileresume_homepage_landing', {'_locale': _locale, 'slug': landing.slug}) }}{% else %}{{ path('whileresume_homepage_landing', {'slug': landing.slug}) }}{% endif %}">
  661.                                 {{ landing.title }}
  662.                             </a>
  663.                         </li>
  664.                     {% endfor %}
  665.                 </ul>
  666.             {% endif %}
  667.         </div>
  668.     </div>
  669.     {# === Bas du footer === #}
  670.     <div class="whr-foot-bottom">
  671.         <p class="whr-foot-copy">
  672.             {% if favicon %}
  673.                 <img src="{{ favicon }}" alt="" class="whr-favicon" />
  674.             {% endif %}
  675.             <span>&copy; {{ "now"|date('Y') }} {{ websitename }}. {{ 'layout.rights_reserved'|trans({}, 'whr-public')|default('Tous droits réservés.') }}</span>
  676.         </p>
  677.         <div class="whr-foot-legal">
  678.             {% set menuFooter = getMenuWebsiteLocaleArray(_locale, "footer", connectUser) %}
  679.             {% if menuFooter is not empty %}
  680.                 {% for m in menuFooter %}
  681.                     <a href="{{ m.link }}"
  682.                        aria-label="{{ m.title }}"
  683.                        title="{{ m.title }}"
  684.                        {% if m.targetBlank == 1 %}target="_blank" rel="noreferrer"{% endif %}>
  685.                         {{ m.title }}
  686.                     </a>
  687.                 {% endfor %}
  688.             {% endif %}
  689.             {% if app.user is not null and is_granted("ROLE_SUPER_ADMIN") %}
  690.                 <a href="{{ path('backoffice_dashboard') }}" class="whr-admin-link" title="Administration">
  691.                     <i class="feather-settings"></i> Administration
  692.                 </a>
  693.             {% endif %}
  694.         </div>
  695.         <ul class="whr-foot-social">
  696.             {% if facebook %}
  697.                 <li><a href="{{ facebook }}" target="_blank" rel="noopener" aria-label="Facebook"><i class="feather-facebook"></i></a></li>
  698.             {% endif %}
  699.             {% if twitter %}
  700.                 <li><a href="{{ twitter }}" target="_blank" rel="noopener" aria-label="X / Twitter"><i class="feather-twitter"></i></a></li>
  701.             {% endif %}
  702.             {% if instagram %}
  703.                 <li><a href="{{ instagram }}" target="_blank" rel="noopener" aria-label="Instagram"><i class="feather-instagram"></i></a></li>
  704.             {% endif %}
  705.             {% if linkedin %}
  706.                 <li><a href="{{ linkedin }}" target="_blank" rel="noopener" aria-label="LinkedIn"><i class="feather-linkedin"></i></a></li>
  707.             {% endif %}
  708.             {% if youtube %}
  709.                 <li><a href="{{ youtube }}" target="_blank" rel="noopener" aria-label="YouTube"><i class="feather-youtube"></i></a></li>
  710.             {% endif %}
  711.         </ul>
  712.     </div>
  713. </footer>
  714. {# ====== JS dropdown stores (vanilla, autonome, pas de dépendance) ====== #}
  715. <script>
  716.     (function() {
  717.         'use strict';
  718.         function closeAllDropdowns() {
  719.             document.querySelectorAll('.whr-store-wrap.is-open').forEach(function(w) {
  720.                 w.classList.remove('is-open');
  721.                 var b = w.querySelector('.whr-store-link');
  722.                 if (b) b.setAttribute('aria-expanded', 'false');
  723.                 // Reset search à la fermeture
  724.                 var input = w.querySelector('.whr-store-search');
  725.                 if (input) {
  726.                     input.value = '';
  727.                     applyFilter(w, '');
  728.                 }
  729.             });
  730.         }
  731.         function applyFilter(wrap, query) {
  732.             query = (query || '').trim().toLowerCase();
  733.             var items = wrap.querySelectorAll('.whr-store-country');
  734.             var othersWrap = wrap.querySelector('.whr-store-others');
  735.             var emptyMsg = wrap.querySelector('.whr-store-empty');
  736.             var grid = wrap.querySelector('.whr-store-grid');
  737.             var visibleInOthers = 0;
  738.             items.forEach(function(item) {
  739.                 var searchData = item.dataset.search || '';
  740.                 var matches = query === '' || searchData.indexOf(query) !== -1;
  741.                 if (matches) {
  742.                     item.classList.remove('is-hidden');
  743.                     // Compter uniquement les items dans la grille "others" (pas le featured)
  744.                     if (grid && grid.contains(item)) {
  745.                         visibleInOthers++;
  746.                     }
  747.                 } else {
  748.                     item.classList.add('is-hidden');
  749.                 }
  750.             });
  751.             // Afficher le message "aucun résultat" si rien ne matche dans others
  752.             if (emptyMsg && grid) {
  753.                 if (query !== '' && visibleInOthers === 0) {
  754.                     grid.style.display = 'none';
  755.                     emptyMsg.style.display = 'block';
  756.                 } else {
  757.                     grid.style.display = '';
  758.                     emptyMsg.style.display = 'none';
  759.                 }
  760.             }
  761.         }
  762.         function initWhrStoreDropdowns() {
  763.             var wraps = document.querySelectorAll('.whr-store-wrap');
  764.             if (!wraps.length) return;
  765.             wraps.forEach(function(wrap) {
  766.                 var btn = wrap.querySelector('.whr-store-link');
  767.                 if (!btn || btn.dataset.whrInit === '1') return;
  768.                 btn.dataset.whrInit = '1';
  769.                 // === Toggle au clic sur le bouton ===
  770.                 btn.addEventListener('click', function(e) {
  771.                     e.preventDefault();
  772.                     e.stopPropagation();
  773.                     var isOpen = wrap.classList.contains('is-open');
  774.                     closeAllDropdowns();
  775.                     if (!isOpen) {
  776.                         wrap.classList.add('is-open');
  777.                         btn.setAttribute('aria-expanded', 'true');
  778.                         // Auto-focus sur la search à l'ouverture (desktop seulement,
  779.                         // pour éviter le clavier qui pop sur mobile)
  780.                         var input = wrap.querySelector('.whr-store-search');
  781.                         if (input && window.innerWidth >= 768) {
  782.                             setTimeout(function() { input.focus(); }, 50);
  783.                         }
  784.                     }
  785.                 });
  786.                 // === Filtrage live sur la search ===
  787.                 var input = wrap.querySelector('.whr-store-search');
  788.                 if (input) {
  789.                     input.addEventListener('input', function() {
  790.                         applyFilter(wrap, this.value);
  791.                     });
  792.                     // Empêcher la fermeture du dropdown quand on clique dans le champ
  793.                     input.addEventListener('click', function(e) {
  794.                         e.stopPropagation();
  795.                     });
  796.                     // Échap dans le champ → vider la recherche d'abord, puis fermer
  797.                     input.addEventListener('keydown', function(e) {
  798.                         if (e.key === 'Escape') {
  799.                             if (this.value !== '') {
  800.                                 this.value = '';
  801.                                 applyFilter(wrap, '');
  802.                                 e.stopPropagation();
  803.                             }
  804.                         }
  805.                     });
  806.                 }
  807.             });
  808.             // === Listeners globaux (un seul fois) ===
  809.             if (!document.body.dataset.whrStoreOutsideInit) {
  810.                 document.body.dataset.whrStoreOutsideInit = '1';
  811.                 // Click outside → close
  812.                 document.addEventListener('click', function(e) {
  813.                     if (!e.target.closest('.whr-store-wrap')) {
  814.                         closeAllDropdowns();
  815.                     }
  816.                 });
  817.                 // ESC → close
  818.                 document.addEventListener('keydown', function(e) {
  819.                     if (e.key === 'Escape') {
  820.                         closeAllDropdowns();
  821.                     }
  822.                 });
  823.             }
  824.         }
  825.         if (document.readyState === 'loading') {
  826.             document.addEventListener('DOMContentLoaded', initWhrStoreDropdowns);
  827.         } else {
  828.             initWhrStoreDropdowns();
  829.         }
  830.     })();
  831. </script>