| 758 |
758 |
.ka-tabbar svg{transition:none} |
| 759 |
759 |
.ka-tabbar .active svg,.ka-tabbar .active::after{animation:none} |
| 760 |
760 |
} |
|
761 |
+ |
|
762 |
+ |
|
763 |
+/* ===================================================================== |
|
764 |
+ Fiche événement premium (refonte 2026-09-07, même socle que les fiches |
|
765 |
+ Lou-Ka v3 / Immo-Ka v3) — tokens --sk-*, styles SCOPÉS sous .sk-*. |
|
766 |
+ Fond papier, cartes blanches bord 1 px, FRAMBOISE réservée aux CTA / prix / |
|
767 |
+ états actifs. Aucun `order` : ordre DOM = ordre visuel. |
|
768 |
+ ===================================================================== */ |
|
769 |
+:root{ |
|
770 |
+ --sk-bg:#f5f3ee; --sk-surface:#ffffff; --sk-surface-2:#faf9f5; |
|
771 |
+ --sk-border:#e6e3dc; --sk-border-2:#d3cfc6; |
|
772 |
+ --sk-text:#141814; --sk-text-2:#4d5551; --sk-muted:#7c837e; |
|
773 |
+ --sk-accent:#d6336c; --sk-accent-deep:#a12551; --sk-accent-soft:#fbe0eb; |
|
774 |
+ --sk-success:#1e7b4a; --sk-success-soft:#e7f4ec; --sk-warning:#a8690a; --sk-warning-soft:#fcf3e1; |
|
775 |
+ --sk-danger:#b3423a; --sk-danger-soft:#fbe9e7; --sk-info:#3b5bdb; --sk-info-soft:#e9edfb; |
|
776 |
+ --sk-r-sm:10px; --sk-r-md:14px; --sk-r-lg:18px; --sk-r-xl:22px; |
|
777 |
+ --sk-shadow-sm:0 2px 12px rgba(0,0,0,.04); --sk-shadow-md:0 8px 28px rgba(0,0,0,.07); |
|
778 |
+ --sk-header-h:56px; --sk-nav-h:52px; |
|
779 |
+} |
|
780 |
+body.sk-fiche-page{background:var(--sk-bg)} |
|
781 |
+body.sk-fiche-page .ticker{display:none} |
|
782 |
+body.sk-fiche-page .ka-tabbar{display:none!important} |
|
783 |
+body.sk-fiche-page .kaa-btn,body.sk-fiche-page .kaa-hello{display:none!important} |
|
784 |
+body.sk-fiche-page .header{background:rgba(245,243,238,.92);backdrop-filter:blur(12px);-webkit-backdrop-filter:blur(12px);border-bottom:1px solid var(--sk-border)} |
|
785 |
+body.sk-fiche-page .header-inner{min-height:var(--sk-header-h);gap:10px} |
|
786 |
+body.sk-fiche-page .header .brand{font-size:21px} |
|
787 |
+body.sk-fiche-page .header .brand-tag,body.sk-fiche-page .header .gk-badge{display:none} |
|
788 |
+body.sk-fiche-page .header .nav{margin-left:0} |
|
789 |
+.hdr-actions{display:flex;align-items:center;gap:6px;margin-left:auto} |
|
790 |
+.hdr-btn{display:inline-grid;place-items:center;width:40px;height:40px;border-radius:999px;border:1px solid var(--sk-border); |
|
791 |
+ background:var(--sk-surface);color:var(--sk-text);cursor:pointer;padding:0;transition:background .15s,transform .15s} |
|
792 |
+.hdr-btn:active{transform:scale(.95)} |
|
793 |
+.hdr-btn.on{color:var(--sk-accent);border-color:var(--sk-accent);background:var(--sk-accent-soft)} |
|
794 |
+@media(hover:hover){.hdr-btn:hover{background:var(--sk-surface-2)}} |
|
795 |
+/* le cœur ♥ existant, posé dans la rangée d'actions de la fiche */ |
|
796 |
+.sk-fiche .fav-btn{position:static;width:46px;height:46px;border-radius:12px;border:1px solid var(--sk-border);background:var(--sk-surface);color:var(--sk-text);box-shadow:none} |
|
797 |
+.sk-fiche .fav-btn.on{color:var(--sk-accent);border-color:var(--sk-accent);background:var(--sk-accent-soft)} |
|
798 |
+.sk-fiche .fav-btn svg{width:19px;height:19px;stroke:currentColor;fill:none;stroke-width:2} |
|
799 |
+.sk-fiche .fav-btn.on svg{fill:currentColor} |
|
800 |
+/* ---- gabarit ---- */ |
|
801 |
+.sk-fiche { padding: 10px 0 110px; color: var(--sk-text); } |
|
802 |
+.sk-wrap { max-width: 1200px; margin: 0 auto; padding: 0 16px; } |
|
803 |
+.sk-grid { display: block; } |
|
804 |
+.sk-main { min-width: 0; display: flex; flex-direction: column; gap: 14px; } |
|
805 |
+.sk-aside { display: none; } |
|
806 |
+@media (min-width: 768px) { |
|
807 |
+ .sk-wrap { padding: 0 24px; } |
|
808 |
+ .sk-fiche { padding-top: 18px; } |
|
809 |
+ .sk-main { gap: 16px; } |
|
810 |
+} |
|
811 |
+@media (min-width: 1024px) { |
|
812 |
+ .sk-grid { display: grid; grid-template-columns: minmax(0, 1fr) 356px; gap: 32px; align-items: start; } |
|
813 |
+ .sk-aside { display: block; position: sticky; top: calc(var(--sk-header-h) + 16px); } |
|
814 |
+ .sk-fiche { padding-bottom: 80px; } |
|
815 |
+} |
|
816 |
+.sk-crumbs { display: flex; align-items: center; gap: 6px; flex-wrap: wrap; font-size: 12px; color: var(--sk-muted); margin: 0 0 10px; } |
|
817 |
+.sk-crumbs a { color: var(--sk-text-2); } |
|
818 |
+.sk-crumbs span:last-child { color: var(--sk-text); font-weight: 600; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; max-width: 60vw; } |
|
819 |
+.sk-fiche section[id] { scroll-margin-top: calc(var(--sk-header-h) + var(--sk-nav-h) + 10px); } |
|
820 |
+ |
|
821 |
+/* ---- carte de section ---- */ |
|
822 |
+.sk-card { |
|
823 |
+ background: var(--sk-surface); border: 1px solid var(--sk-border); |
|
824 |
+ border-radius: var(--sk-r-lg); box-shadow: var(--sk-shadow-sm); |
|
825 |
+ padding: 16px; min-width: 0; |
|
826 |
+} |
|
827 |
+@media (min-width: 768px) { .sk-card { padding: 20px 22px; } } |
|
828 |
+.sk-card-head { display: flex; align-items: flex-start; justify-content: space-between; gap: 12px; margin-bottom: 12px; } |
|
829 |
+.sk-card-title { display: flex; align-items: center; gap: 9px; margin: 0; font-family: var(--font-display); font-weight: 700; font-size: 17px; line-height: 1.2; letter-spacing: -0.02em; color: var(--sk-text); } |
|
830 |
+.sk-card-title svg { color: var(--sk-accent-deep); flex: none; } |
|
831 |
+.sk-card-sub { font-size: 12.5px; color: var(--sk-muted); margin: 3px 0 0; } |
|
832 |
+.sk-card-aside { flex: none; display: flex; align-items: center; gap: 8px; } |
|
833 |
+.sk-link { background: none; border: 0; padding: 0; color: var(--sk-text-2); font: 600 13px var(--font-body); cursor: pointer; text-decoration: underline; text-underline-offset: 3px; text-decoration-color: var(--sk-border-2); } |
|
834 |
+.sk-link:hover { color: var(--sk-accent-deep); } |
|
835 |
+.sk-more { |
|
836 |
+ display: inline-flex; align-items: center; justify-content: center; gap: 8px; |
|
837 |
+ width: 100%; min-height: 44px; margin-top: 12px; padding: 8px 14px; |
|
838 |
+ border: 1px solid var(--sk-border); border-radius: var(--sk-r-sm); background: var(--sk-surface); |
|
839 |
+ color: var(--sk-text); font: 600 13.5px var(--font-body); cursor: pointer; |
|
840 |
+ transition: background 0.15s, border-color 0.15s; |
|
841 |
+} |
|
842 |
+.sk-more:hover { background: var(--sk-surface-2); border-color: var(--sk-border-2); } |
|
843 |
+.sk-more svg { color: var(--sk-muted); } |
|
844 |
+ |
|
845 |
+/* ---- boutons ---- */ |
|
846 |
+.sk-btn { |
|
847 |
+ display: inline-flex; align-items: center; justify-content: center; gap: 8px; |
|
848 |
+ min-height: 46px; padding: 10px 16px; border-radius: 12px; border: 1px solid transparent; |
|
849 |
+ font: 600 14.5px var(--font-body); cursor: pointer; text-decoration: none; |
|
850 |
+ transition: transform 0.12s, background 0.15s, box-shadow 0.15s; white-space: nowrap; |
|
851 |
+} |
|
852 |
+.sk-btn:active { transform: translateY(1px); } |
|
853 |
+.sk-btn-primary { background: var(--sk-accent); color: #fff; box-shadow: 0 6px 18px rgba(226, 55, 68, 0.22); } |
|
854 |
+.sk-btn-primary:hover { background: var(--sk-accent-deep); } |
|
855 |
+.sk-btn-ghost { background: var(--sk-surface); border-color: var(--sk-border); color: var(--sk-text); } |
|
856 |
+.sk-btn-ghost:hover { background: var(--sk-surface-2); border-color: var(--sk-border-2); } |
|
857 |
+.sk-btn-icon { width: 46px; padding: 0; flex: none; } |
|
858 |
+.sk-btn-icon.on { color: var(--sk-accent); border-color: var(--sk-accent); background: var(--sk-accent-soft); } |
|
859 |
+ |
|
860 |
+/* ---- héro ---- */ |
|
861 |
+.sk-hero { display: flex; flex-direction: column; gap: 10px; padding: 4px 0 0; } |
|
862 |
+.sk-hero-top { display: flex; align-items: flex-start; justify-content: space-between; gap: 12px; } |
|
863 |
+.sk-price { font-family: var(--font-display); font-weight: 700; font-size: clamp(32px, 8.4vw, 38px); line-height: 1; letter-spacing: -0.035em; color: var(--sk-text); display: flex; align-items: baseline; flex-wrap: wrap; gap: 4px 8px; } |
|
864 |
+.sk-price small { font: 500 14px var(--font-body); color: var(--sk-muted); letter-spacing: 0; } |
|
865 |
+.sk-price-row { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; } |
|
866 |
+.sk-capsule { |
|
867 |
+ display: inline-flex; align-items: center; gap: 6px; padding: 5px 10px; |
|
868 |
+ border-radius: 999px; font: 600 12.5px var(--font-body); border: 1px solid transparent; white-space: nowrap; |
|
869 |
+} |
|
870 |
+.sk-capsule b { font-weight: 700; } |
|
871 |
+.sk-capsule.good { background: var(--sk-success-soft); color: var(--sk-success); } |
|
872 |
+.sk-capsule.ok { background: var(--sk-surface); color: var(--sk-text-2); border-color: var(--sk-border); } |
|
873 |
+.sk-capsule.high { background: var(--sk-warning-soft); color: var(--sk-warning); } |
|
874 |
+.sk-capsule.neutral { background: var(--sk-surface-2); color: var(--sk-muted); border-color: var(--sk-border); } |
|
875 |
+.sk-capsule.brand { background: var(--sk-accent-soft); color: var(--sk-accent-deep); } |
|
876 |
+.sk-h1 { margin: 0; font-family: var(--font-body); font-weight: 600; font-size: 16px; line-height: 1.35; letter-spacing: 0; color: var(--sk-text); } |
|
877 |
+.sk-h1 .sk-city { display: block; font-weight: 500; font-size: 14px; color: var(--sk-text-2); } |
|
878 |
+.sk-summary { margin: 0; font-size: 14px; color: var(--sk-text-2); display: flex; flex-wrap: wrap; gap: 4px 8px; align-items: center; } |
|
879 |
+.sk-summary .sep { color: var(--sk-border-2); } |
|
880 |
+.sk-actions { display: flex; gap: 8px; align-items: center; } |
|
881 |
+.sk-actions .sk-btn-primary { flex: 1; } |
|
882 |
+.sk-hero .sk-actions { margin-top: 2px; } |
|
883 |
+@media (min-width: 1024px) { |
|
884 |
+ .sk-hero .sk-actions { display: none; } /* actions dans l'aside sticky */ |
|
885 |
+} |
|
886 |
+ |
|
887 |
+/* ---- galerie ---- */ |
|
888 |
+.sk-gallery { position: relative; border-radius: var(--sk-r-lg); overflow: hidden; background: #ecece8; } |
|
889 |
+.sk-gallery-track { display: flex; overflow-x: auto; scroll-snap-type: x mandatory; aspect-ratio: 4 / 3; scrollbar-width: none; -webkit-overflow-scrolling: touch; } |
|
890 |
+.sk-gallery-track::-webkit-scrollbar { display: none; } |
|
891 |
+.sk-gallery-track img, .sk-gallery > img { flex: 0 0 100%; width: 100%; height: 100%; object-fit: cover; scroll-snap-align: center; cursor: zoom-in; display: block; } |
|
892 |
+.sk-gallery > img { aspect-ratio: 4 / 3; } |
|
893 |
+@media (min-width: 768px) { .sk-gallery-track, .sk-gallery > img { aspect-ratio: 16 / 9; } } |
|
894 |
+.sk-gallery-count { |
|
895 |
+ position: absolute; left: 12px; bottom: 12px; z-index: 2; |
|
896 |
+ background: rgba(20, 24, 20, 0.66); color: #fff; font: 600 12px var(--font-body); |
|
897 |
+ padding: 4px 10px; border-radius: 999px; backdrop-filter: blur(6px); -webkit-backdrop-filter: blur(6px); |
|
898 |
+ font-variant-numeric: tabular-nums; |
|
899 |
+} |
|
900 |
+.sk-gallery-full, .sk-gallery-nav { |
|
901 |
+ position: absolute; z-index: 2; display: grid; place-items: center; |
|
902 |
+ width: 40px; height: 40px; border-radius: 999px; border: 0; cursor: pointer; |
|
903 |
+ background: rgba(255, 255, 255, 0.92); color: var(--sk-text); box-shadow: 0 2px 10px rgba(0, 0, 0, 0.12); |
|
904 |
+} |
|
905 |
+.sk-gallery-full { right: 12px; bottom: 12px; } |
|
906 |
+.sk-gallery-nav { top: 50%; transform: translateY(-50%); display: none; } |
|
907 |
+.sk-gallery-nav.prev { left: 12px; } .sk-gallery-nav.next { right: 12px; } |
|
908 |
+@media (hover: hover) and (min-width: 768px) { .sk-gallery-nav { display: grid; } } |
|
909 |
+.sk-thumbs { display: none; } |
|
910 |
+@media (min-width: 768px) { |
|
911 |
+ .sk-thumbs { display: grid; grid-template-columns: repeat(auto-fill, minmax(76px, 1fr)); gap: 6px; margin-top: 8px; } |
|
912 |
+ .sk-thumbs button { border: 0; padding: 0; border-radius: 8px; overflow: hidden; aspect-ratio: 4 / 3; background: #ecece8; cursor: pointer; outline-offset: 2px; opacity: 0.75; transition: opacity 0.15s; } |
|
913 |
+ .sk-thumbs button.on, .sk-thumbs button:hover { opacity: 1; } |
|
914 |
+ .sk-thumbs button.on { outline: 2px solid var(--sk-accent); } |
|
915 |
+ .sk-thumbs img { width: 100%; height: 100%; object-fit: cover; } |
|
916 |
+} |
|
917 |
+/* lightbox (plein écran) */ |
|
918 |
+.sk-lightbox { position: fixed; inset: 0; z-index: var(--z-modal, 900); background: rgba(12, 14, 12, 0.96); } |
|
919 |
+.sk-lightbox-track { display: flex; overflow-x: auto; scroll-snap-type: x mandatory; height: 100%; scrollbar-width: none; touch-action: pan-x pinch-zoom; } |
|
920 |
+.sk-lightbox-track::-webkit-scrollbar { display: none; } |
|
921 |
+.sk-lightbox-cell { flex: 0 0 100%; height: 100%; scroll-snap-align: center; display: flex; align-items: center; justify-content: center; padding: max(56px, env(safe-area-inset-top)) 10px max(28px, env(safe-area-inset-bottom)); overflow: hidden; } |
|
922 |
+.sk-lightbox-cell img { max-width: 100%; max-height: 100%; border-radius: 10px; user-select: none; -webkit-user-drag: none; will-change: transform; } |
|
923 |
+.sk-lightbox-close { position: fixed; top: max(12px, env(safe-area-inset-top)); right: 12px; z-index: 3; width: 44px; height: 44px; border-radius: 50%; border: 1px solid rgba(255, 255, 255, 0.3); background: rgba(0, 0, 0, 0.5); color: #fff; display: grid; place-items: center; cursor: pointer; } |
|
924 |
+.sk-lightbox-count { position: fixed; top: max(22px, env(safe-area-inset-top)); left: 50%; transform: translateX(-50%); z-index: 3; color: #fff; font: 600 13px var(--font-body); background: rgba(0, 0, 0, 0.45); padding: 4px 12px; border-radius: 999px; } |
|
925 |
+.sk-lightbox .sk-gallery-nav { display: none; } |
|
926 |
+@media (hover: hover) { .sk-lightbox .sk-gallery-nav { display: grid; position: fixed; } } |
|
927 |
+ |
|
928 |
+/* ---- Score ---- */ |
|
929 |
+.sk-score { display: grid; grid-template-columns: auto 1fr; gap: 16px; align-items: center; } |
|
930 |
+.sk-score-ring { position: relative; width: 88px; height: 88px; flex: none; } |
|
931 |
+.sk-score-ring svg { width: 88px; height: 88px; transform: rotate(-90deg); } |
|
932 |
+.sk-score-ring .bg { fill: none; stroke: var(--sk-surface-2); stroke-width: 7; } |
|
933 |
+.sk-score-ring .arc { fill: none; stroke: var(--sk-accent); stroke-width: 7; stroke-linecap: round; transition: stroke-dasharray 0.9s cubic-bezier(0.2, 0.8, 0.2, 1); } |
|
934 |
+.sk-score-ring .arc.partial { stroke: var(--sk-text-2); } |
|
935 |
+.sk-score-val { position: absolute; inset: 0; display: grid; place-items: center; font-family: var(--font-display); font-weight: 700; font-size: 27px; letter-spacing: -0.03em; line-height: 1; } |
|
936 |
+.sk-score-val small { display: block; text-align: center; font: 600 10px var(--font-body); color: var(--sk-muted); margin-top: 2px; letter-spacing: 0.04em; } |
|
937 |
+.sk-score-lbl { font-family: var(--font-display); font-weight: 700; font-size: 17px; letter-spacing: -0.02em; } |
|
938 |
+.sk-score-sub { font-size: 13px; color: var(--sk-text-2); margin-top: 2px; line-height: 1.4; } |
|
939 |
+.sk-score-parts { display: flex; flex-wrap: wrap; gap: 6px; margin-top: 10px; } |
|
940 |
+.sk-score-part { display: inline-flex; align-items: center; gap: 6px; font-size: 12.5px; padding: 4px 9px; border-radius: 8px; background: var(--sk-surface-2); border: 1px solid var(--sk-border); color: var(--sk-text-2); } |
|
941 |
+.sk-score-part b { color: var(--sk-text); font-variant-numeric: tabular-nums; } |
|
942 |
+.sk-score-part.na { color: var(--sk-muted); border-style: dashed; } |
|
943 |
+ |
|
944 |
+/* ---- En bref ---- */ |
|
945 |
+.sk-brief { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 10px; } |
|
946 |
+.sk-brief li { display: grid; grid-template-columns: 24px 1fr; gap: 10px; align-items: start; } |
|
947 |
+.sk-brief-ico { width: 24px; height: 24px; border-radius: 8px; display: grid; place-items: center; font-size: 12px; font-weight: 700; margin-top: 1px; } |
|
948 |
+.sk-brief-ico.good { background: var(--sk-success-soft); color: var(--sk-success); } |
|
949 |
+.sk-brief-ico.warn { background: var(--sk-warning-soft); color: var(--sk-warning); } |
|
950 |
+.sk-brief-ico.bad { background: var(--sk-danger-soft); color: var(--sk-danger); } |
|
951 |
+.sk-brief-ico.neutral { background: var(--sk-surface-2); color: var(--sk-muted); border: 1px solid var(--sk-border); } |
|
952 |
+.sk-brief-t { font-weight: 600; font-size: 14px; line-height: 1.35; } |
|
953 |
+.sk-brief-d { font-size: 13px; color: var(--sk-text-2); line-height: 1.4; margin-top: 1px; } |
|
954 |
+ |
|
955 |
+/* ---- navigation par sections (sticky) ---- */ |
|
956 |
+.sk-nav { |
|
957 |
+ position: sticky; top: var(--sk-header-h); z-index: var(--z-sticky, 300); |
|
958 |
+ margin: 0 -16px; padding: 6px 16px; |
|
959 |
+ background: rgba(245, 243, 238, 0.97); backdrop-filter: blur(12px); -webkit-backdrop-filter: blur(12px); |
|
960 |
+ border-bottom: 1px solid var(--sk-border); |
|
961 |
+} |
|
962 |
+@media (min-width: 768px) { .sk-nav { margin: 0 -24px; padding: 6px 24px; } } |
|
963 |
+@media (min-width: 1024px) { .sk-nav { margin: 0; padding: 6px 0; border-radius: 0; } } |
|
964 |
+.sk-nav-track { display: flex; gap: 6px; overflow-x: auto; scrollbar-width: none; -webkit-overflow-scrolling: touch; } |
|
965 |
+.sk-nav-track::-webkit-scrollbar { display: none; } |
|
966 |
+.sk-nav a { |
|
967 |
+ flex: 0 0 auto; display: inline-flex; align-items: center; min-height: 40px; padding: 8px 13px; |
|
968 |
+ border-radius: 999px; font: 600 13px var(--font-body); color: var(--sk-text-2); |
|
969 |
+ border: 1px solid transparent; transition: background 0.15s, color 0.15s; scroll-snap-align: start; |
|
970 |
+} |
|
971 |
+.sk-nav a:hover { background: var(--sk-surface); border-color: var(--sk-border); } |
|
972 |
+.sk-nav a.on { background: var(--sk-text); color: #fff; border-color: var(--sk-text); } |
|
973 |
+ |
|
974 |
+/* ---- caractéristiques ---- */ |
|
975 |
+.sk-facts { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 8px; } |
|
976 |
+@media (min-width: 560px) { .sk-facts { grid-template-columns: repeat(3, minmax(0, 1fr)); } } |
|
977 |
+@media (min-width: 900px) { .sk-facts { grid-template-columns: repeat(4, minmax(0, 1fr)); } } |
|
978 |
+.sk-fact { display: flex; align-items: center; gap: 10px; padding: 10px 12px; border: 1px solid var(--sk-border); border-radius: 12px; background: var(--sk-surface-2); min-width: 0; } |
|
979 |
+.sk-fact-ico { width: 32px; height: 32px; border-radius: 9px; background: var(--sk-surface); border: 1px solid var(--sk-border); display: grid; place-items: center; color: var(--sk-accent-deep); flex: none; } |
|
980 |
+.sk-fact-v { font-weight: 700; font-size: 14px; line-height: 1.2; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; } |
|
981 |
+.sk-fact-l { font-size: 11.5px; color: var(--sk-muted); margin-top: 1px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; } |
|
982 |
+.sk-fact-txt { min-width: 0; } |
|
983 |
+.sk-facts-rows { margin-top: 12px; } |
|
984 |
+.sk-kv { display: flex; justify-content: space-between; gap: 12px; padding: 8px 0; border-top: 1px solid var(--sk-border); font-size: 13.5px; } |
|
985 |
+.sk-kv .k { color: var(--sk-muted); } .sk-kv .v { font-weight: 600; text-align: right; } |
|
986 |
+.sk-note { margin: 10px 0 0; padding: 9px 12px; border-radius: 10px; font-size: 13px; line-height: 1.4; } |
|
987 |
+.sk-note.good { background: var(--sk-success-soft); color: var(--sk-success); } |
|
988 |
+.sk-note.info { background: var(--sk-info-soft); color: var(--sk-info); } |
|
989 |
+.sk-note.warn { background: var(--sk-warning-soft); color: var(--sk-warning); } |
|
990 |
+ |
|
991 |
+/* ---- description ---- */ |
|
992 |
+.sk-desc { position: relative; } |
|
993 |
+.sk-desc-body p { font-size: 15px; line-height: 1.6; color: var(--sk-text-2); margin: 0 0 10px; white-space: pre-line; } |
|
994 |
+.sk-desc-body h4 { margin: 12px 0 3px; font: 700 14px var(--font-body); color: var(--sk-text); } |
|
995 |
+.sk-desc-lead { font-size: 15.5px !important; color: var(--sk-text) !important; font-weight: 500; } |
|
996 |
+.sk-desc.clamped .sk-desc-body { max-height: 200px; overflow: hidden; -webkit-mask-image: linear-gradient(#000 62%, transparent); mask-image: linear-gradient(#000 62%, transparent); } |
|
997 |
+.sk-desc-orig { margin-top: 8px; } |
|
998 |
+.sk-desc-orig p { font-size: 13.5px; color: var(--sk-muted); } |
|
999 |
+ |
|
1000 |
+/* ---- inclusions ---- */ |
|
1001 |
+.sk-amen { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 0 16px; } |
|
1002 |
+@media (min-width: 640px) { .sk-amen { grid-template-columns: repeat(3, minmax(0, 1fr)); } } |
|
1003 |
+.sk-amen-it { display: flex; align-items: center; gap: 9px; min-height: 42px; padding: 5px 0; border-bottom: 1px solid var(--sk-border); font-size: 13.5px; min-width: 0; } |
|
1004 |
+.sk-amen-ico { width: 28px; height: 28px; border-radius: 8px; background: var(--sk-accent-soft); color: var(--sk-accent-deep); display: grid; place-items: center; flex: none; } |
|
1005 |
+.sk-amen-it.unconfirmed { color: var(--sk-text-2); } |
|
1006 |
+.sk-amen-it.unconfirmed .sk-amen-ico { background: var(--sk-surface-2); color: var(--sk-muted); border: 1px dashed var(--sk-border-2); } |
|
1007 |
+.sk-amen-txt { min-width: 0; line-height: 1.25; } |
|
1008 |
+.sk-amen-conf { margin-left: auto; color: var(--sk-success); flex: none; } |
|
1009 |
+ |
|
1010 |
+/* ---- KPI / tuiles ---- */ |
|
1011 |
+.sk-kpis { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 8px; } |
|
1012 |
+@media (min-width: 600px) { .sk-kpis { grid-template-columns: repeat(3, minmax(0, 1fr)); } .sk-kpi-v { font-size: 20px; } } |
|
1013 |
+.sk-kpis.cols-3 { grid-template-columns: repeat(3, minmax(0, 1fr)); } |
|
1014 |
+.sk-kpi { padding: 10px 12px; border: 1px solid var(--sk-border); border-radius: 12px; background: var(--sk-surface); min-width: 0; } |
|
1015 |
+.sk-kpi.accent { background: var(--sk-accent-soft); border-color: #f5c2c6; } |
|
1016 |
+.sk-kpi-v { font-family: var(--font-display); font-weight: 700; font-size: clamp(16px, 4.8vw, 20px); letter-spacing: -0.025em; line-height: 1.1; font-variant-numeric: tabular-nums; color: var(--sk-text); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; } |
|
1017 |
+.sk-kpi-v.wrap { white-space: normal; font-size: 16px; line-height: 1.2; } |
|
1018 |
+.sk-kpi-v small { font: 600 11px var(--font-body); color: var(--sk-muted); margin-left: 3px; } |
|
1019 |
+.sk-kpi-l { font-size: 11.5px; color: var(--sk-muted); margin-top: 3px; line-height: 1.3; } |
|
1020 |
+.sk-kpi.anim .sk-kpi-v { animation: sk-rise 0.5s ease both; } |
|
1021 |
+@keyframes sk-rise { from { opacity: 0; transform: translateY(4px); } to { opacity: 1; transform: none; } } |
|
1022 |
+ |
|
1023 |
+/* ---- rangées compactes (accessibilité, mesures) ---- */ |
|
1024 |
+.sk-rows { display: flex; flex-direction: column; gap: 4px; } |
|
1025 |
+.sk-row { display: grid; grid-template-columns: minmax(0, 1fr) auto auto; align-items: center; gap: 10px; min-height: 30px; font-size: 13.5px; } |
|
1026 |
+.sk-row-name { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; color: var(--sk-text); } |
|
1027 |
+.sk-row-name small { color: var(--sk-muted); font-size: 12px; margin-left: 4px; } |
|
1028 |
+.sk-row-bar { width: 78px; height: 6px; border-radius: 3px; background: var(--sk-surface-2); border: 1px solid var(--sk-border); overflow: hidden; } |
|
1029 |
+.sk-row-bar i { display: block; height: 100%; background: var(--sk-text); border-radius: 3px; } |
|
1030 |
+.sk-row-bar i.good { background: var(--sk-success); } |
|
1031 |
+.sk-row-bar i.warn { background: var(--sk-warning); } |
|
1032 |
+.sk-row-bar i.bad { background: var(--sk-danger); } |
|
1033 |
+.sk-row-val { font-weight: 700; font-size: 13px; font-variant-numeric: tabular-nums; min-width: 28px; text-align: right; } |
|
1034 |
+.sk-row-lbl { font-size: 12px; color: var(--sk-muted); min-width: 68px; text-align: right; } |
|
1035 |
+.sk-row-lbl.good { color: var(--sk-success); } .sk-row-lbl.warn { color: var(--sk-warning); } .sk-row-lbl.bad { color: var(--sk-danger); } |
|
1036 |
+ |
|
1037 |
+/* ---- pastilles d'état ---- */ |
|
1038 |
+.sk-badge { display: inline-flex; align-items: center; gap: 6px; padding: 4px 10px; border-radius: 999px; font: 600 12px var(--font-body); border: 1px solid transparent; white-space: nowrap; } |
|
1039 |
+.sk-badge::before { content: ""; width: 6px; height: 6px; border-radius: 50%; background: currentColor; flex: none; } |
|
1040 |
+.sk-badge.good { background: var(--sk-success-soft); color: var(--sk-success); } |
|
1041 |
+.sk-badge.warn { background: var(--sk-warning-soft); color: var(--sk-warning); } |
|
1042 |
+.sk-badge.bad { background: var(--sk-danger-soft); color: var(--sk-danger); } |
|
1043 |
+.sk-badge.neutral { background: var(--sk-surface-2); color: var(--sk-text-2); border-color: var(--sk-border); } |
|
1044 |
+.sk-badge.info { background: var(--sk-info-soft); color: var(--sk-info); } |
|
1045 |
+.sk-badge.lg { font-size: 13.5px; padding: 6px 12px; } |
|
1046 |
+.sk-pill { display: inline-block; font: 600 10.5px var(--font-body); text-transform: uppercase; letter-spacing: 0.05em; padding: 2px 7px; border-radius: 6px; margin-left: 6px; vertical-align: 1px; } |
|
1047 |
+.sk-pill.included { background: var(--sk-success-soft); color: var(--sk-success); } |
|
1048 |
+.sk-pill.observed { background: var(--sk-surface-2); color: var(--sk-text-2); border: 1px solid var(--sk-border); } |
|
1049 |
+.sk-pill.estimated { background: var(--sk-accent-soft); color: var(--sk-accent-deep); } |
|
1050 |
+.sk-pill.unknown { background: var(--sk-surface-2); color: var(--sk-muted); border: 1px dashed var(--sk-border-2); } |
|
1051 |
+ |
|
1052 |
+/* ---- listes d'items (lieux, comparables, stations) ---- */ |
|
1053 |
+.sk-list { list-style: none; margin: 0; padding: 0; } |
|
1054 |
+.sk-item { display: flex; align-items: center; gap: 12px; padding: 10px 0; border-top: 1px solid var(--sk-border); min-width: 0; } |
|
1055 |
+.sk-list > .sk-item:first-child { border-top: 0; padding-top: 2px; } |
|
1056 |
+.sk-item-ico { width: 34px; height: 34px; border-radius: 10px; display: grid; place-items: center; flex: none; background: var(--sk-surface-2); border: 1px solid var(--sk-border); color: var(--sk-text-2); } |
|
1057 |
+.sk-item-ico svg.cm-ico { width: 26px; height: 26px; } |
|
1058 |
+.sk-item-main { flex: 1; min-width: 0; } |
|
1059 |
+.sk-item-t { font-weight: 600; font-size: 14px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; } |
|
1060 |
+.sk-item-s { font-size: 12.5px; color: var(--sk-muted); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; } |
|
1061 |
+.sk-item-r { text-align: right; flex: none; } |
|
1062 |
+.sk-item-v { font-weight: 700; font-size: 14px; font-variant-numeric: tabular-nums; } |
|
1063 |
+.sk-item-m { font-size: 12px; color: var(--sk-muted); } |
|
1064 |
+.sk-item-best { color: var(--sk-success); font-weight: 700; font-size: 11.5px; margin-left: 6px; } |
|
1065 |
+ |
|
1066 |
+/* ---- carrousel horizontal ---- */ |
|
1067 |
+.sk-carousel { display: flex; gap: 10px; overflow-x: auto; scroll-snap-type: x mandatory; scrollbar-width: none; -webkit-overflow-scrolling: touch; margin: 0 -16px; padding: 2px 16px 6px; } |
|
1068 |
+.sk-carousel::-webkit-scrollbar { display: none; } |
|
1069 |
+@media (min-width: 768px) { .sk-carousel { margin: 0; padding: 2px 0 6px; } } |
|
1070 |
+.sk-ccard { flex: 0 0 44%; min-width: 148px; max-width: 210px; scroll-snap-align: start; border: 1px solid var(--sk-border); border-radius: var(--sk-r-md); padding: 12px; background: var(--sk-surface); display: flex; flex-direction: column; gap: 6px; min-height: 104px; } |
|
1071 |
+@media (min-width: 768px) { .sk-ccard { flex-basis: 176px; } } |
|
1072 |
+.sk-ccard-top { display: flex; align-items: center; justify-content: space-between; gap: 8px; } |
|
1073 |
+.sk-ccard-c { font: 600 10.5px var(--font-body); text-transform: uppercase; letter-spacing: 0.06em; color: var(--sk-muted); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; } |
|
1074 |
+.sk-ccard-d { font-family: var(--font-display); font-weight: 700; font-size: 18px; letter-spacing: -0.02em; font-variant-numeric: tabular-nums; } |
|
1075 |
+.sk-ccard-n { font-size: 12.5px; color: var(--sk-text-2); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; } |
|
1076 |
+.sk-ccard-m { font-size: 11.5px; color: var(--sk-muted); } |
|
1077 |
+ |
|
1078 |
+/* ---- filtres (chips) ---- */ |
|
1079 |
+.sk-chips { display: flex; gap: 6px; overflow-x: auto; scrollbar-width: none; -webkit-overflow-scrolling: touch; padding-bottom: 10px; } |
|
1080 |
+.sk-chips::-webkit-scrollbar { display: none; } |
|
1081 |
+.sk-chip { flex: 0 0 auto; display: inline-flex; align-items: center; gap: 7px; min-height: 38px; padding: 6px 12px; border-radius: 999px; border: 1px solid var(--sk-border); background: var(--sk-surface); color: var(--sk-text-2); font: 600 12.5px var(--font-body); cursor: pointer; transition: background 0.15s, color 0.15s, border-color 0.15s; } |
|
1082 |
+.sk-chip .dot { width: 8px; height: 8px; border-radius: 50%; background: var(--c, var(--sk-text)); flex: none; } |
|
1083 |
+.sk-chip small { font-weight: 600; opacity: 0.65; } |
|
1084 |
+.sk-chip.on { background: var(--sk-text); color: #fff; border-color: var(--sk-text); } |
|
1085 |
+.sk-chip:disabled { opacity: 0.45; cursor: default; } |
|
1086 |
+ |
|
1087 |
+/* ---- carte ---- */ |
|
1088 |
+.sk-map { position: relative; height: 340px; border-radius: var(--sk-r-lg); overflow: hidden; border: 1px solid var(--sk-border); background: #ecece8; } |
|
1089 |
+@media (min-width: 768px) { .sk-map { height: 440px; } } |
|
1090 |
+@media (min-width: 1024px) { .sk-map { height: 520px; } } |
|
1091 |
+.sk-map .ka-map { |
|
1092 |
+ position: absolute; inset: 0; |
|
1093 |
+ --ka-accent: var(--sk-accent); --ka-on-accent: #fff; --ka-surface: var(--sk-surface); |
|
1094 |
+ --ka-ink: var(--sk-text); --ka-line: var(--sk-border-2); --ka-radius: 10px; |
|
1095 |
+ --ka-shadow: 0 8px 24px rgba(20, 24, 20, 0.14); --ka-font: var(--font-body); |
|
1096 |
+} |
|
1097 |
+.sk-map-legend { position: absolute; left: 10px; bottom: 10px; z-index: 5; display: inline-flex; align-items: center; gap: 6px; padding: 4px 10px; border-radius: 999px; background: rgba(255, 255, 255, 0.92); border: 1px solid var(--sk-border); font: 500 11px var(--font-body); color: var(--sk-text-2); pointer-events: none; } |
|
1098 |
+.sk-map-legend i { width: 10px; height: 10px; border-radius: 3px; background: var(--sk-accent); } |
|
1099 |
+.sk-map-skel { position: absolute; inset: 0; } |
|
1100 |
+.sk-map-hint { font-size: 12px; color: var(--sk-muted); margin: 8px 0 0; } |
|
1101 |
+ |
|
1102 |
+/* ---- accordéon ---- */ |
|
1103 |
+.sk-acc { border-top: 1px solid var(--sk-border); } |
|
1104 |
+.sk-acc:first-child { border-top: 0; } |
|
1105 |
+.sk-acc-btn { width: 100%; display: flex; align-items: center; justify-content: space-between; gap: 10px; min-height: 48px; padding: 10px 0; background: none; border: 0; font: 600 14px var(--font-body); color: var(--sk-text); cursor: pointer; text-align: left; } |
|
1106 |
+.sk-acc-btn .sk-acc-meta { font-weight: 500; font-size: 12.5px; color: var(--sk-muted); margin-left: auto; white-space: nowrap; } |
|
1107 |
+.sk-acc-btn .chev { color: var(--sk-muted); flex: none; transition: transform 0.2s ease; } |
|
1108 |
+.sk-acc-btn[aria-expanded="true"] .chev { transform: rotate(180deg); } |
|
1109 |
+.sk-acc-body { display: grid; grid-template-rows: 0fr; transition: grid-template-rows 0.22s ease; } |
|
1110 |
+.sk-acc-body.open { grid-template-rows: 1fr; } |
|
1111 |
+.sk-acc-body > div { min-height: 0; overflow: hidden; } |
|
1112 |
+.sk-acc-inner { padding: 0 0 14px; font-size: 13.5px; color: var(--sk-text-2); line-height: 1.5; } |
|
1113 |
+.sk-acc-inner p { margin: 0 0 8px; } |
|
1114 |
+.sk-acc-inner a { color: var(--sk-text-2); text-decoration: underline; text-underline-offset: 2px; } |
|
1115 |
+.sk-acc.sm .sk-acc-btn { min-height: 40px; font-size: 13px; color: var(--sk-text-2); } |
|
1116 |
+ |
|
1117 |
+/* ---- bottom sheet (mobile) / modale (desktop) ---- */ |
|
1118 |
+.sk-sheet-backdrop { position: fixed; inset: 0; z-index: var(--z-overlay, 800); background: rgba(20, 24, 20, 0.42); animation: sk-fade 0.18s ease; } |
|
1119 |
+.sk-sheet { |
|
1120 |
+ position: fixed; left: 0; right: 0; bottom: 0; z-index: var(--z-modal, 900); |
|
1121 |
+ height: var(--sk-sheet-h, 68dvh); max-height: 94dvh; |
|
1122 |
+ background: var(--sk-surface); border-radius: 20px 20px 0 0; |
|
1123 |
+ display: flex; flex-direction: column; box-shadow: 0 -10px 40px rgba(0, 0, 0, 0.18); |
|
1124 |
+ animation: sk-up 0.28s cubic-bezier(0.2, 0.8, 0.2, 1); |
|
1125 |
+ padding-bottom: env(safe-area-inset-bottom); |
|
1126 |
+ touch-action: pan-y; |
|
1127 |
+} |
|
1128 |
+.sk-sheet.full { height: 94dvh; } |
|
1129 |
+.sk-sheet-handle { width: 40px; height: 4px; border-radius: 2px; background: var(--sk-border-2); margin: 8px auto 0; flex: none; } |
|
1130 |
+.sk-sheet-head { display: flex; align-items: center; justify-content: space-between; gap: 10px; padding: 10px 16px 10px; border-bottom: 1px solid var(--sk-border); flex: none; } |
|
1131 |
+.sk-sheet-title { font-family: var(--font-display); font-weight: 700; font-size: 16px; letter-spacing: -0.02em; margin: 0; } |
|
1132 |
+.sk-sheet-sub { font-size: 12.5px; color: var(--sk-muted); margin: 2px 0 0; } |
|
1133 |
+.sk-sheet-x { width: 36px; height: 36px; border-radius: 50%; border: 1px solid var(--sk-border); background: var(--sk-surface-2); display: grid; place-items: center; cursor: pointer; color: var(--sk-text); flex: none; } |
|
1134 |
+.sk-sheet-body { flex: 1; overflow-y: auto; -webkit-overflow-scrolling: touch; overscroll-behavior: contain; padding: 12px 16px 18px; } |
|
1135 |
+.sk-sheet-foot { flex: none; padding: 10px 16px; border-top: 1px solid var(--sk-border); background: var(--sk-surface); } |
|
1136 |
+@keyframes sk-up { from { transform: translateY(40px); opacity: 0.6; } to { transform: none; opacity: 1; } } |
|
1137 |
+@keyframes sk-fade { from { opacity: 0; } to { opacity: 1; } } |
|
1138 |
+@keyframes sk-pop { from { transform: translate(-50%, -50%) scale(0.97); opacity: 0; } to { transform: translate(-50%, -50%) scale(1); opacity: 1; } } |
|
1139 |
+@media (min-width: 900px) { |
|
1140 |
+ .sk-sheet, .sk-sheet.full { |
|
1141 |
+ left: 50%; right: auto; top: 50%; bottom: auto; transform: translate(-50%, -50%); |
|
1142 |
+ width: min(680px, calc(100vw - 48px)); height: auto; max-height: min(82vh, 780px); |
|
1143 |
+ border-radius: var(--sk-r-lg); animation: sk-pop 0.18s ease; padding-bottom: 0; |
|
1144 |
+ } |
|
1145 |
+ .sk-sheet-handle { display: none; } |
|
1146 |
+ .sk-sheet-head { padding: 16px 20px 12px; } |
|
1147 |
+ .sk-sheet-body { padding: 14px 20px 20px; } |
|
1148 |
+} |
|
1149 |
+.sk-sheet-filters { display: flex; gap: 6px; flex-wrap: wrap; margin-bottom: 10px; } |
|
1150 |
+.sk-seg { display: inline-flex; border: 1px solid var(--sk-border); border-radius: 999px; overflow: hidden; background: var(--sk-surface); } |
|
1151 |
+.sk-seg button { border: 0; background: transparent; padding: 7px 12px; min-height: 36px; font: 600 12.5px var(--font-body); color: var(--sk-text-2); cursor: pointer; } |
|
1152 |
+.sk-seg button.on { background: var(--sk-text); color: #fff; } |
|
1153 |
+.sk-seg button + button { border-left: 1px solid var(--sk-border); } |
|
1154 |
+ |
|
1155 |
+/* ---- CTA sticky ---- */ |
|
1156 |
+.sk-cta-bar { |
|
1157 |
+ position: fixed; left: 0; right: 0; bottom: var(--consent-h, 0px); z-index: var(--z-bottombar, 600); |
|
1158 |
+ display: flex; align-items: center; gap: 12px; |
|
1159 |
+ padding: 10px 16px calc(10px + env(safe-area-inset-bottom)); |
|
1160 |
+ background: rgba(255, 255, 255, 0.94); backdrop-filter: blur(14px); -webkit-backdrop-filter: blur(14px); |
|
1161 |
+ border-top: 1px solid var(--sk-border); |
|
1162 |
+ transform: translateY(110%); transition: transform 0.25s ease; will-change: transform; |
|
1163 |
+} |
|
1164 |
+.sk-cta-bar.show { transform: none; } |
|
1165 |
+.sk-cta-txt { min-width: 0; flex: 0 1 auto; } |
|
1166 |
+.sk-cta-price { font-family: var(--font-display); font-weight: 700; font-size: 18px; letter-spacing: -0.02em; line-height: 1.1; white-space: nowrap; } |
|
1167 |
+.sk-cta-price small { font: 500 11px var(--font-body); color: var(--sk-muted); letter-spacing: 0; } |
|
1168 |
+.sk-cta-sub { font-size: 12px; color: var(--sk-text-2); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; } |
|
1169 |
+.sk-cta-sub.good { color: var(--sk-success); font-weight: 600; } |
|
1170 |
+.sk-cta-bar .sk-btn-primary { flex: 1; min-height: 44px; margin-left: auto; max-width: 260px; } |
|
1171 |
+@media (min-width: 1024px) { .sk-cta-bar { display: none; } } |
|
1172 |
+ |
|
1173 |
+/* ---- Demander à Ka ---- */ |
|
1174 |
+.sk-ka-btn { |
|
1175 |
+ position: fixed; right: 14px; bottom: calc(78px + env(safe-area-inset-bottom) + var(--consent-h, 0px)); z-index: var(--z-dropdown, 700); |
|
1176 |
+ display: inline-flex; align-items: center; gap: 7px; min-height: 42px; padding: 8px 14px 8px 12px; |
|
1177 |
+ border-radius: 999px; border: 0; background: var(--sk-text); color: #fff; |
|
1178 |
+ font: 600 13px var(--font-body); cursor: pointer; box-shadow: 0 6px 20px rgba(0, 0, 0, 0.2); |
|
1179 |
+ transition: transform 0.15s, opacity 0.2s; |
|
1180 |
+} |
|
1181 |
+.sk-ka-btn svg { color: var(--sk-accent); } |
|
1182 |
+.sk-ka-btn:active { transform: scale(0.97); } |
|
1183 |
+.sk-ka-btn.hide { opacity: 0; pointer-events: none; transform: translateY(8px); } |
|
1184 |
+@media (min-width: 1024px) { .sk-ka-btn { display: none; } } /* desktop : bouton dans l'aside */ |
|
1185 |
+.sk-ka-intro { display: flex; gap: 12px; align-items: flex-start; padding: 4px 0 12px; } |
|
1186 |
+.sk-ka-avatar { width: 38px; height: 38px; border-radius: 12px; background: var(--sk-text); color: var(--sk-accent); display: grid; place-items: center; flex: none; } |
|
1187 |
+.sk-ka-intro p { margin: 0; font-size: 13.5px; color: var(--sk-text-2); line-height: 1.45; } |
|
1188 |
+.sk-ka-ctx { display: flex; align-items: center; gap: 10px; padding: 10px 12px; border-radius: 12px; background: var(--sk-surface-2); border: 1px solid var(--sk-border); font-size: 12.5px; color: var(--sk-text-2); margin-bottom: 12px; } |
|
1189 |
+.sk-ka-ctx img { width: 44px; height: 34px; object-fit: cover; border-radius: 6px; flex: none; } |
|
1190 |
+.sk-ka-ctx b { color: var(--sk-text); display: block; font-size: 13px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; } |
|
1191 |
+.sk-ka-sugs { display: flex; flex-direction: column; gap: 6px; } |
|
1192 |
+.sk-ka-sug { display: flex; align-items: center; justify-content: space-between; gap: 10px; width: 100%; min-height: 46px; padding: 10px 14px; border-radius: 12px; border: 1px solid var(--sk-border); background: var(--sk-surface); font: 500 14px var(--font-body); color: var(--sk-text); cursor: pointer; text-align: left; transition: background 0.15s, border-color 0.15s; } |
|
1193 |
+.sk-ka-sug:hover { background: var(--sk-accent-soft); border-color: #f5c2c6; } |
|
1194 |
+.sk-ka-sug svg { color: var(--sk-muted); flex: none; } |
|
1195 |
+.sk-ka-in { display: flex; gap: 8px; align-items: center; } |
|
1196 |
+.sk-ka-in input { flex: 1; min-height: 46px; padding: 10px 14px; border-radius: 12px; border: 1px solid var(--sk-border); background: var(--sk-surface); font: 400 16px var(--font-body); color: var(--sk-text); } |
|
1197 |
+.sk-ka-in input:focus { outline: 2px solid var(--sk-accent); outline-offset: 1px; } |
|
1198 |
+.sk-ka-in button { width: 46px; height: 46px; border-radius: 12px; border: 0; background: var(--sk-accent); color: #fff; display: grid; place-items: center; cursor: pointer; flex: none; } |
|
1199 |
+.sk-ka-in button:disabled { opacity: 0.4; cursor: default; } |
|
1200 |
+ |
|
1201 |
+/* ---- aside desktop ---- */ |
|
1202 |
+.sk-aside-card { display: flex; flex-direction: column; gap: 12px; } |
|
1203 |
+.sk-aside .sk-btn-primary { white-space: normal; text-align: center; line-height: 1.25; } |
|
1204 |
+.sk-aside .sk-ka-inline { justify-content: flex-start; } |
|
1205 |
+.sk-aside .sk-ka-inline svg { color: var(--sk-accent); } |
|
1206 |
+.sk-aside .sk-price { font-size: 32px; } |
|
1207 |
+.sk-aside-addr { font-size: 14px; color: var(--sk-text-2); line-height: 1.4; } |
|
1208 |
+.sk-aside-sep { border: 0; border-top: 1px solid var(--sk-border); margin: 4px 0; } |
|
1209 |
+.sk-aside-score { display: flex; align-items: center; gap: 12px; } |
|
1210 |
+.sk-aside-score .sk-score-ring { width: 56px; height: 56px; } |
|
1211 |
+.sk-aside-score .sk-score-ring svg { width: 56px; height: 56px; } |
|
1212 |
+.sk-aside-score .sk-score-val { font-size: 18px; } |
|
1213 |
+.sk-aside-score .sk-score-val small { display: none; } |
|
1214 |
+.sk-aside-score-txt { font-size: 13px; color: var(--sk-text-2); line-height: 1.4; } |
|
1215 |
+.sk-aside-score-txt b { display: block; color: var(--sk-text); font-size: 14px; } |
|
1216 |
+.sk-aside .sk-brief { gap: 8px; } |
|
1217 |
+.sk-aside .sk-brief-t { font-size: 13.5px; } |
|
1218 |
+.sk-aside .sk-brief-d { display: none; } |
|
1219 |
+.sk-aside-meta { font-size: 12px; color: var(--sk-muted); text-align: center; } |
|
1220 |
+ |
|
1221 |
+/* ---- source & méthodologie (pied de section) ---- */ |
|
1222 |
+.sk-source { display: flex; align-items: center; justify-content: space-between; gap: 10px; flex-wrap: wrap; margin-top: 12px; padding-top: 10px; border-top: 1px solid var(--sk-border); font-size: 12px; color: var(--sk-muted); } |
|
1223 |
+.sk-source b { font-weight: 600; color: var(--sk-text-2); } |
|
1224 |
+.sk-source a, .sk-source button { color: var(--sk-text-2); background: none; border: 0; padding: 0; font: inherit; text-decoration: underline; text-underline-offset: 2px; text-decoration-color: var(--sk-border-2); cursor: pointer; } |
|
1225 |
+.sk-source a:hover, .sk-source button:hover { color: var(--sk-accent-deep); } |
|
1226 |
+.sk-fine { font-size: 12.5px; color: var(--sk-muted); line-height: 1.5; margin: 8px 0 0; } |
|
1227 |
+.sk-fine a { color: var(--sk-text-2); text-decoration: underline; text-underline-offset: 2px; } |
|
1228 |
+.sk-fine.meth { margin-top: 0; } |
|
1229 |
+ |
|
1230 |
+/* ---- états : squelettes, vides, erreurs ---- */ |
|
1231 |
+.sk-skel { border-radius: 10px; background: linear-gradient(90deg, #ecece8 25%, #f4f4f1 50%, #ecece8 75%); background-size: 400% 100%; animation: sk-shimmer 1.3s infinite linear; } |
|
1232 |
+@keyframes sk-shimmer { from { background-position: 100% 0; } to { background-position: 0 0; } } |
|
1233 |
+.sk-skel-lines { display: flex; flex-direction: column; gap: 8px; } |
|
1234 |
+.sk-skel-lines .sk-skel { height: 12px; } |
|
1235 |
+.sk-skel-lines .sk-skel.short { width: 55%; } |
|
1236 |
+.sk-empty { padding: 14px; border-radius: 12px; background: var(--sk-surface-2); border: 1px dashed var(--sk-border-2); color: var(--sk-muted); font-size: 13.5px; text-align: center; line-height: 1.45; } |
|
1237 |
+.sk-error { display: flex; align-items: center; justify-content: space-between; gap: 10px; padding: 12px 14px; border-radius: 12px; background: var(--sk-warning-soft); color: var(--sk-warning); font-size: 13.5px; } |
|
1238 |
+.sk-error button { border: 1px solid currentColor; background: transparent; color: inherit; border-radius: 999px; padding: 6px 12px; font: 600 12.5px var(--font-body); cursor: pointer; min-height: 36px; } |
|
1239 |
+.sk-page-error { max-width: 520px; margin: 60px auto; text-align: center; padding: 0 16px; } |
|
1240 |
+.sk-page-error h2 { font-family: var(--font-display); letter-spacing: -0.02em; } |
|
1241 |
+.sk-page-error p { color: var(--sk-text-2); } |
|
1242 |
+.sk-toast { position: fixed; left: 50%; bottom: calc(96px + env(safe-area-inset-bottom) + var(--consent-h, 0px)); transform: translateX(-50%); z-index: var(--z-toast, 950); background: var(--sk-text); color: #fff; font: 600 13px var(--font-body); padding: 10px 16px; border-radius: 999px; box-shadow: 0 8px 24px rgba(0, 0, 0, 0.2); animation: sk-up 0.25s ease; max-width: calc(100vw - 32px); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; } |
|
1243 |
+ |
|
1244 |
+/* ---- prix / marché ---- */ |
|
1245 |
+.sk-market-head { display: grid; grid-template-columns: 1fr auto; gap: 12px; align-items: start; } |
|
1246 |
+.sk-market-big { font-family: var(--font-display); font-weight: 700; font-size: 28px; letter-spacing: -0.03em; line-height: 1; } |
|
1247 |
+.sk-market-big small { font: 500 13px var(--font-body); color: var(--sk-muted); margin-left: 4px; letter-spacing: 0; } |
|
1248 |
+.sk-market-sub { font-size: 13px; color: var(--sk-text-2); margin-top: 4px; } |
|
1249 |
+.sk-histo { display: block; width: 100%; max-width: 520px; height: auto; margin: 12px 0 4px; } |
|
1250 |
+.sk-histo-bar { fill: #dedfd9; } |
|
1251 |
+.sk-histo-bar.on { fill: var(--sk-accent); } |
|
1252 |
+.sk-histo-lbl { font: 700 10px var(--font-body); fill: var(--sk-text); } |
|
1253 |
+.sk-histo-lbl.fv { fill: var(--sk-text-2); } |
|
1254 |
+.sk-histo-axis { font: 500 9.5px var(--font-body); fill: var(--sk-muted); } |
|
1255 |
+.sk-meta { display: flex; flex-wrap: wrap; gap: 4px 14px; font-size: 12.5px; color: var(--sk-text-2); margin: 6px 0 0; } |
|
1256 |
+.sk-meta b { color: var(--sk-text); } |
|
1257 |
+ |
|
1258 |
+/* jauge du registre des loyers */ |
|
1259 |
+.sk-gauge { margin: 14px 0 6px; } |
|
1260 |
+.sk-gauge-lbls { display: flex; justify-content: space-between; font: 600 11px var(--font-body); color: var(--sk-muted); margin-bottom: 6px; } |
|
1261 |
+.sk-gauge-lbls .good { color: var(--sk-success); } .sk-gauge-lbls .bad { color: var(--sk-danger); } |
|
1262 |
+.sk-gauge svg { display: block; width: 100%; max-width: 520px; height: auto; overflow: visible; } |
|
1263 |
+.sk-gauge, .sk-gauge-lbls { max-width: 520px; } |
|
1264 |
+.sk-gauge-track { fill: var(--sk-surface-2); stroke: var(--sk-border); } |
|
1265 |
+.sk-gauge-box { fill: #ecece8; } |
|
1266 |
+.sk-gauge-med { stroke: var(--sk-text-2); stroke-width: 1.5; } |
|
1267 |
+.sk-gauge-me { fill: var(--sk-accent); stroke: #fff; stroke-width: 2.5; } |
|
1268 |
+.sk-gauge-txt { font: 600 10.5px var(--font-body); fill: var(--sk-muted); } |
|
1269 |
+.sk-gauge-txt.me { fill: var(--sk-text); font-weight: 700; } |
|
1270 |
+.sk-bars { display: block; width: 100%; max-width: 520px; height: auto; margin: 6px 0 0; } |
|
1271 |
+.sk-bar { fill: #dedfd9; } |
|
1272 |
+.sk-bar.on { fill: var(--sk-accent); } |
|
1273 |
+.sk-bar-val { font: 600 10px var(--font-body); fill: var(--sk-text-2); } |
|
1274 |
+.sk-bar-cat { font: 600 11px var(--font-body); fill: var(--sk-text-2); } |
|
1275 |
+.sk-bar-cat.on { fill: var(--sk-text); font-weight: 700; } |
|
1276 |
+.sk-bar-n { font: 500 9.5px var(--font-body); fill: var(--sk-muted); } |
|
1277 |
+.sk-bars-axe { stroke: var(--sk-border); } |
|
1278 |
+ |
|
1279 |
+/* ---- risques / environnement ---- */ |
|
1280 |
+.sk-status { display: flex; align-items: center; gap: 12px; flex-wrap: wrap; } |
|
1281 |
+.sk-status-t { font-family: var(--font-display); font-weight: 700; font-size: 18px; letter-spacing: -0.02em; } |
|
1282 |
+.sk-status-d { font-size: 13.5px; color: var(--sk-text-2); margin: 8px 0 0; line-height: 1.5; } |
|
1283 |
+.sk-air { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 8px; margin-top: 12px; } |
|
1284 |
+@media (max-width: 400px) { .sk-air { grid-template-columns: repeat(2, minmax(0, 1fr)); } } |
|
1285 |
+.sk-air-c { padding: 10px 12px; border-radius: 12px; border: 1px solid var(--sk-border); background: var(--sk-surface-2); min-width: 0; } |
|
1286 |
+.sk-air-p { font: 600 11.5px var(--font-body); color: var(--sk-muted); text-transform: uppercase; letter-spacing: 0.05em; } |
|
1287 |
+.sk-air-v { font-family: var(--font-display); font-weight: 700; font-size: 18px; letter-spacing: -0.02em; margin-top: 2px; font-variant-numeric: tabular-nums; white-space: nowrap; } |
|
1288 |
+.sk-air-v small { font: 500 11px var(--font-body); color: var(--sk-muted); margin-left: 3px; } |
|
1289 |
+.sk-air-s { font-size: 11.5px; margin-top: 3px; line-height: 1.3; } |
|
1290 |
+.sk-air-s.good { color: var(--sk-success); } .sk-air-s.warn { color: var(--sk-warning); } .sk-air-s.bad { color: var(--sk-danger); } .sk-air-s.neutral { color: var(--sk-muted); } |
|
1291 |
+ |
|
1292 |
+/* ---- coût réel ---- */ |
|
1293 |
+.sk-cost { list-style: none; margin: 0; padding: 0; } |
|
1294 |
+.sk-cost li { display: flex; justify-content: space-between; align-items: baseline; gap: 12px; padding: 8px 0; border-top: 1px solid var(--sk-border); font-size: 13.5px; } |
|
1295 |
+.sk-cost li:first-child { border-top: 0; } |
|
1296 |
+.sk-cost .n { color: var(--sk-text-2); min-width: 0; } |
|
1297 |
+.sk-cost .v { font-weight: 600; font-variant-numeric: tabular-nums; white-space: nowrap; } |
|
1298 |
+.sk-cost .v.na { color: var(--sk-muted); font-weight: 500; } |
|
1299 |
+.sk-cost li.total { border-top: 1px solid var(--sk-border-2); margin-top: 4px; padding-top: 10px; font-size: 15px; } |
|
1300 |
+.sk-cost li.total .n, .sk-cost li.total .v { color: var(--sk-text); font-weight: 700; } |
|
1301 |
+.sk-cost li.annuel { font-size: 12.5px; color: var(--sk-muted); border-top: 0; padding-top: 0; } |
|
1302 |
+.sk-cost-note { font-size: 12.5px; color: var(--sk-text-2); margin: 8px 0 0; } |
|
1303 |
+ |
|
1304 |
+/* ---- dossier de l'immeuble (accordéons) ---- */ |
|
1305 |
+.sk-tl { list-style: none; margin: 4px 0 0; padding: 0 0 0 12px; border-left: 2px solid var(--sk-border); display: flex; flex-direction: column; gap: 8px; } |
|
1306 |
+.sk-tl li { position: relative; font-size: 13px; color: var(--sk-text-2); } |
|
1307 |
+.sk-tl li::before { content: ""; position: absolute; left: -17.5px; top: 5px; width: 8px; height: 8px; border-radius: 50%; background: var(--sk-surface); border: 2px solid var(--sk-border-2); } |
|
1308 |
+.sk-tl li.prix::before { border-color: var(--sk-accent); } |
|
1309 |
+.sk-tl li.disparition::before { border-color: var(--sk-danger); } |
|
1310 |
+.sk-tl li.reapparition::before { border-color: var(--sk-success); } |
|
1311 |
+.sk-tl-date { display: inline-block; min-width: 84px; font: 600 11.5px var(--font-body); color: var(--sk-muted); } |
|
1312 |
+.sk-star { font-family: var(--font-display); font-weight: 700; font-size: 20px; color: var(--sk-text); display: inline-flex; align-items: center; gap: 5px; } |
|
1313 |
+.sk-star svg { color: #e0a800; } |
|
1314 |
+.sk-quote { margin: 10px 0 0; padding: 8px 12px; font-size: 13px; color: var(--sk-text-2); border-left: 3px solid var(--sk-border-2); background: var(--sk-surface-2); border-radius: 8px; } |
|
1315 |
+.sk-quote footer { margin-top: 4px; font-size: 11.5px; color: var(--sk-muted); } |
|
1316 |
+.sk-tags { display: flex; flex-wrap: wrap; gap: 5px; margin-top: 4px; } |
|
1317 |
+.sk-tag { font: 600 11.5px var(--font-body); padding: 2px 8px; border-radius: 999px; background: var(--sk-danger-soft); color: var(--sk-danger); } |
|
1318 |
+.sk-tag.n { background: var(--sk-surface-2); color: var(--sk-text-2); border: 1px solid var(--sk-border); } |
|
1319 |
+ |
|
1320 |
+/* ---- KA Scores (cercles compacts) ---- */ |
|
1321 |
+.sk-ks { display: grid; grid-template-columns: repeat(5, minmax(0, 1fr)); gap: 6px; } |
|
1322 |
+@media (max-width: 400px) { .sk-ks { grid-template-columns: repeat(3, minmax(0, 1fr)); } } |
|
1323 |
+.sk-ks-c { text-align: center; padding: 8px 4px; border-radius: 12px; border: 1px solid var(--sk-border); background: var(--sk-surface-2); min-width: 0; } |
|
1324 |
+.sk-ks-c svg { width: 52px; height: 52px; transform: rotate(-90deg); } |
|
1325 |
+.sk-ks-c .bg { fill: none; stroke: #e6e6e1; stroke-width: 5; } |
|
1326 |
+.sk-ks-c .arc { fill: none; stroke: var(--sk-text); stroke-width: 5; stroke-linecap: round; } |
|
1327 |
+.sk-ks-c.haut .arc { stroke: var(--sk-success); } .sk-ks-c.bon .arc { stroke: var(--sk-text); } .sk-ks-c.moyen .arc { stroke: var(--sk-warning); } .sk-ks-c.bas .arc { stroke: var(--sk-danger); } |
|
1328 |
+.sk-ks-wrap { position: relative; width: 52px; height: 52px; margin: 0 auto; } |
|
1329 |
+.sk-ks-v { position: absolute; inset: 0; display: grid; place-items: center; font: 700 15px var(--font-display); letter-spacing: -0.02em; } |
|
1330 |
+.sk-ks-n { font: 600 11.5px var(--font-body); margin-top: 6px; color: var(--sk-text); } |
|
1331 |
+.sk-ks-l { font-size: 10.5px; color: var(--sk-muted); margin-top: 1px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; } |
|
1332 |
+.sk-ks-detail { display: grid; grid-template-columns: repeat(auto-fit, minmax(180px, 1fr)); gap: 8px 18px; } |
|
1333 |
+.sk-ks-detail h4 { margin: 8px 0 4px; font: 700 12.5px var(--font-body); color: var(--sk-text); } |
|
1334 |
+.sk-ks-detail ul { margin: 0; padding-left: 16px; font-size: 13px; color: var(--sk-text-2); } |
|
1335 |
+.sk-ks-detail li { margin: 2px 0; } |
|
1336 |
+ |
|
1337 |
+/* ---- fin de fiche ---- */ |
|
1338 |
+.sk-end { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 8px; } |
|
1339 |
+@media (min-width: 640px) { .sk-end { grid-template-columns: repeat(4, minmax(0, 1fr)); } } |
|
1340 |
+.sk-end a, .sk-end button { display: flex; flex-direction: column; align-items: flex-start; gap: 6px; padding: 12px; border-radius: 12px; border: 1px solid var(--sk-border); background: var(--sk-surface); color: var(--sk-text); font: 600 13px var(--font-body); cursor: pointer; text-align: left; min-height: 64px; } |
|
1341 |
+.sk-end a:hover, .sk-end button:hover { background: var(--sk-surface-2); } |
|
1342 |
+.sk-end svg { color: var(--sk-accent-deep); } |
|
1343 |
+.sk-end small { font-weight: 500; color: var(--sk-muted); font-size: 12px; } |
|
1344 |
+.sk-sources { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; } |
|
1345 |
+.sk-sources li { display: grid; grid-template-columns: minmax(0, 1fr) auto; gap: 4px 12px; padding: 9px 0; border-top: 1px solid var(--sk-border); font-size: 13px; align-items: center; } |
|
1346 |
+.sk-sources li:first-child { border-top: 0; } |
|
1347 |
+.sk-sources .n { font-weight: 600; grid-column: 1; grid-row: 1; } |
|
1348 |
+.sk-sources .r { font-size: 12.5px; color: var(--sk-text-2); grid-column: 1; grid-row: 2; } |
|
1349 |
+.sk-sources .d { font-size: 12px; color: var(--sk-muted); grid-column: 2; grid-row: 1 / span 2; text-align: right; white-space: nowrap; align-self: start; } |
|
1350 |
+.sk-sources a { color: var(--sk-text-2); text-decoration: underline; text-underline-offset: 2px; } |
|
1351 |
+ |
|
1352 |
+ |
|
1353 |
+/* ---- ajouts Immo-Ka : héro, galerie, formulaire, tableaux, rôle ---- */ |
|
1354 |
+.sk-kicker { font-family: var(--font-mono); font-size: 11px; font-weight: 500; text-transform: uppercase; letter-spacing: 0.12em; color: var(--sk-muted); margin-bottom: 4px; } |
|
1355 |
+.sk-gallery-empty { display: grid; place-items: center; aspect-ratio: 4 / 3; } |
|
1356 |
+@media (min-width: 768px) { .sk-gallery-empty { aspect-ratio: 16 / 9; } } |
|
1357 |
+.sk-gallery-empty .type-fallback { position: static; width: 100%; height: 100%; } |
|
1358 |
+.sk-gallery-caption { |
|
1359 |
+ position: absolute; left: 12px; top: 12px; z-index: 2; max-width: calc(100% - 24px); |
|
1360 |
+ background: rgba(20, 24, 20, 0.62); color: #fff; font: 500 12px var(--font-body); |
|
1361 |
+ padding: 4px 10px; border-radius: 999px; backdrop-filter: blur(6px); -webkit-backdrop-filter: blur(6px); |
|
1362 |
+ overflow: hidden; text-overflow: ellipsis; white-space: nowrap; |
|
1363 |
+} |
|
1364 |
+.sk-subtitle { margin: 14px 0 8px !important; font-weight: 600 !important; color: var(--sk-text-2) !important; font-size: 13px !important; } |
|
1365 |
+.sk-subtitle small { font-weight: 500; color: var(--sk-muted); } |
|
1366 |
+.sk-more .flip { transform: rotate(180deg); } |
|
1367 |
+.sk-acc-ico { vertical-align: -2px; margin-right: 8px; color: var(--sk-muted); } |
|
1368 |
+.sk-role { margin-top: 14px; } |
|
1369 |
+.sk-tl li.baisse::before { border-color: var(--sk-success); } |
|
1370 |
+.sk-tl li.hausse::before { border-color: var(--sk-warning); } |
|
1371 |
+/* formulaire du calculateur */ |
|
1372 |
+.sk-form { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 8px; } |
|
1373 |
+@media (min-width: 640px) { .sk-form { grid-template-columns: repeat(4, minmax(0, 1fr)); } } |
|
1374 |
+.sk-form label { display: flex; flex-direction: column; gap: 4px; min-width: 0; } |
|
1375 |
+.sk-form label span { font-size: 11.5px; color: var(--sk-muted); font-weight: 600; } |
|
1376 |
+.sk-form input, .sk-form select { |
|
1377 |
+ min-height: 42px; padding: 8px 10px; border-radius: 10px; border: 1px solid var(--sk-border); background: var(--sk-surface); |
|
1378 |
+ font: 500 15px var(--font-body); color: var(--sk-text); width: 100%; min-width: 0; appearance: none; -webkit-appearance: none; |
|
1379 |
+} |
|
1380 |
+.sk-form select { background-image: linear-gradient(45deg, transparent 50%, var(--sk-muted) 50%), linear-gradient(135deg, var(--sk-muted) 50%, transparent 50%); background-position: calc(100% - 16px) 50%, calc(100% - 11px) 50%; background-size: 5px 5px; background-repeat: no-repeat; padding-right: 28px; } |
|
1381 |
+.sk-form input:focus, .sk-form select:focus { outline: 2px solid var(--sk-accent); outline-offset: 1px; } |
|
1382 |
+/* tableaux (pièces, banques, amortissement) */ |
|
1383 |
+.sk-table-wrap { overflow-x: auto; -webkit-overflow-scrolling: touch; margin: 0 -4px; padding: 0 4px; } |
|
1384 |
+.sk-table { width: 100%; border-collapse: collapse; font-size: 13px; } |
|
1385 |
+.sk-table th { text-align: left; font: 600 11.5px var(--font-body); color: var(--sk-muted); text-transform: uppercase; letter-spacing: 0.04em; padding: 6px 8px; border-bottom: 1px solid var(--sk-border); white-space: nowrap; } |
|
1386 |
+.sk-table td { padding: 8px 8px; border-bottom: 1px solid var(--sk-border); vertical-align: top; color: var(--sk-text-2); } |
|
1387 |
+.sk-table td:first-child { color: var(--sk-text); font-weight: 500; } |
|
1388 |
+.sk-table tr:last-child td { border-bottom: 0; } |
|
1389 |
+.sk-table a { color: var(--sk-text-2); text-decoration: underline; text-underline-offset: 2px; } |
|
1390 |
+/* aside : courtier */ |
|
1391 |
+.sk-aside-broker { display: flex; flex-direction: column; gap: 2px; font-size: 13.5px; color: var(--sk-text-2); } |
|
1392 |
+.sk-aside-broker-k { font: 600 11px var(--font-body); text-transform: uppercase; letter-spacing: 0.06em; color: var(--sk-muted); } |
|
1393 |
+.sk-aside-broker b { color: var(--sk-text); } |
|
1394 |
+.sk-aside-broker a { display: inline-flex; align-items: center; gap: 6px; color: var(--sk-text-2); } |
|
1395 |
+/* jauge Vrai-Prix : libellés */ |
|
1396 |
+.sk-gauge-lbls { margin-top: 4px; margin-bottom: 0; } |
|
1397 |
+.sk-kv .v a { color: var(--sk-text-2); text-decoration: underline; text-underline-offset: 2px; } |
|
1398 |
+.sk-kv .v { min-width: 0; overflow-wrap: anywhere; } |
|
1399 |
+ |
|
1400 |
+ |
|
1401 |
+ |
|
1402 |
+body.sk-fiche-page .header-inner{padding-left:16px;padding-right:16px} |
|
1403 |
+@media(min-width:641px){body.sk-fiche-page .header-inner{padding-left:24px;padding-right:24px}} |
|
1404 |
+.hdr-actions .fav-btn{position:static;width:40px;height:40px;border-radius:999px;border:1px solid var(--sk-border);background:var(--sk-surface);color:var(--sk-text);box-shadow:none;display:inline-grid;place-items:center} |
|
1405 |
+.hdr-actions .fav-btn.on{color:var(--sk-accent);border-color:var(--sk-accent);background:var(--sk-accent-soft)} |
|
1406 |
+.hdr-actions .fav-btn svg{width:18px;height:18px;stroke:currentColor;fill:none;stroke-width:2} |
|
1407 |
+.hdr-actions .fav-btn.on svg{fill:currentColor} |
|
1408 |
+@media(max-width:980px){body.sk-fiche-page .header .nav{display:none}} |
|
1409 |
+ |
|
1410 |
+/* ---- ajouts Sorti·Ka : image, accordéons natifs, carte, statut ---- */ |
|
1411 |
+.sk-image{position:relative;border-radius:var(--sk-r-lg);overflow:hidden;background:linear-gradient(135deg,var(--sk-accent-soft),var(--sk-surface-2));aspect-ratio:16/9} |
|
1412 |
+@media(max-width:640px){.sk-image{aspect-ratio:4/3}} |
|
1413 |
+.sk-image img{width:100%;height:100%;object-fit:cover;display:block} |
|
1414 |
+.sk-image.noimg{aspect-ratio:16/6;display:grid;place-items:center;color:var(--sk-accent-deep);font-family:var(--font-display);font-weight:700;font-size:20px} |
|
1415 |
+.sk-capsule.date{background:var(--sk-text);color:#fff} |
|
1416 |
+.sk-details{border-top:1px solid var(--sk-border)} |
|
1417 |
+.sk-details:first-child{border-top:0} |
|
1418 |
+.sk-details summary{list-style:none;display:flex;align-items:center;justify-content:space-between;gap:10px;min-height:44px;padding:8px 0;font:600 13.5px var(--font-body);color:var(--sk-text-2);cursor:pointer} |
|
1419 |
+.sk-details summary::-webkit-details-marker{display:none} |
|
1420 |
+.sk-details summary::after{content:"";width:8px;height:8px;border-right:2px solid var(--sk-muted);border-bottom:2px solid var(--sk-muted);transform:rotate(45deg);transition:transform .2s;flex:none;margin-right:6px} |
|
1421 |
+.sk-details[open] summary::after{transform:rotate(-135deg)} |
|
1422 |
+.sk-details .sk-acc-inner{padding:0 0 14px;font-size:13.5px;color:var(--sk-text-2);line-height:1.5} |
|
1423 |
+.sk-details .sk-acc-inner p{margin:0 0 8px} |
|
1424 |
+.sk-map{height:300px} |
|
1425 |
+@media(min-width:768px){.sk-map{height:380px}} |
|
1426 |
+.sk-map .leaflet-container{position:absolute;inset:0;font:inherit} |
|
1427 |
+.sk-fiche .grid{margin-top:0} |
|
1428 |
+.sk-sheet .sk-ka-sugs{margin-top:0} |
|
1429 |
+.sk-sheet-x{font-size:18px;line-height:1} |
|
1430 |
+.sk-fiche h3[id]{scroll-margin-top:calc(var(--sk-header-h) + var(--sk-nav-h) + 10px)} |
|
1431 |
+.sk-status{margin-top:6px} |
|
1432 |
+ |
|
1433 |
+/* ---- accessibilité mouvement réduit ---- */ |
|
1434 |
+@media (prefers-reduced-motion: reduce) { |
|
1435 |
+ .sk-sheet, .sk-sheet-backdrop, .sk-toast, .sk-kpi.anim .sk-kpi-v { animation: none; } |
|
1436 |
+ .sk-score-ring .arc, .sk-acc-body, .sk-cta-bar { transition: none; } |
|
1437 |
+} |
|
1438 |
+ |
|
1439 |
+/* ---- utilitaire a11y ---- */ |
|
1440 |
+.visually-hidden { position: absolute !important; width: 1px; height: 1px; overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; } |
|
1441 |
+ |
| 761 |
1442 |
</style> |
| 762 |
1443 |
</head> |
| 763 |
1444 |
<body> |
| 929 |
1610 |
<div class="toast" id="toast" role="status" aria-live="polite"></div> |
| 930 |
1611 |
|
| 931 |
1612 |
<!-- ======== VUE FICHE ÉVÉNEMENT ======== --> |
| 932 |
|
−<main id="view-detail" class="hidden"> |
| 933 |
|
− <div class="container detail"> |
| 934 |
|
− <span class="back" id="back">← Toutes les sorties</span> |
| 935 |
|
− <div class="detail-grid"> |
| 936 |
|
− <article class="detail-main"> |
| 937 |
|
− <div class="d-imgwrap" id="d-img"></div> |
| 938 |
|
− <div class="d-body"> |
| 939 |
|
− <span class="klabel" id="d-cats-label"></span> |
| 940 |
|
− <div id="d-status"></div> |
| 941 |
|
− <div class="d-title-row"><h1 id="d-title"></h1><span id="d-fav"></span></div> |
| 942 |
|
− <div class="desc" id="d-desc"></div> |
| 943 |
|
− <div class="detail-cats" id="d-cats"></div> |
| 944 |
|
− </div> |
| 945 |
|
− </article> |
| 946 |
|
− <aside class="side"> |
| 947 |
|
− <div class="box" id="d-facts"></div> |
| 948 |
|
− <a class="btn btn-cta" id="d-cta" target="_blank" rel="noopener">Billets · fiche originale ↗</a> |
| 949 |
|
− <div class="box" id="d-src"></div> |
| 950 |
|
− </aside> |
| 951 |
|
− </div> |
| 952 |
|
− <section class="similar"> |
| 953 |
|
− <span class="kicker">À voir aussi</span> |
| 954 |
|
− <h2 id="d-similar-title">Événements similaires</h2> |
| 955 |
|
− <div class="grid" id="d-similar"></div> |
| 956 |
|
− </section> |
| 957 |
|
− </div> |
| 958 |
|
− <!-- CTA sticky mobile : le billet toujours à portée de pouce --> |
| 959 |
|
− <div class="d-ctabar" id="d-ctabar"></div> |
| 960 |
|
−</main> |
|
1613 |
+<main id="view-detail" class="hidden sk-fiche"><div id="sk-root"></div></main> |
| 961 |
1614 |
|
| 962 |
1615 |
<!-- ======== VUE FAVORIS (/favoris) — ♥ « Mon univers Ka » (hub groupe-ka.com) ======== --> |
| 963 |
1616 |
<main id="view-favoris" class="hidden"> |
| 1691 |
2344 |
} |
| 1692 |
2345 |
|
| 1693 |
2346 |
/* ---------- fiche événement ---------- */ |
|
2347 |
+/* ==================== fiche événement — refonte premium 2026-09-07 ========== |
|
2348 |
+ Même socle que les fiches Lou-Ka v3 / Immo-Ka v3, en JS natif : héro |
|
2349 |
+ (catégorie · source, prix, capsules date/statut, titre, résumé, image, |
|
2350 |
+ actions) → En bref (constats déterministes) → navigation sticky (scroll-spy) |
|
2351 |
+ → Quand et où (faits + carte Leaflet) → Programme (description, artistes, |
|
2352 |
+ étiquettes) → Billets (prix, billetterie) → À voir aussi → Dossier → |
|
2353 |
+ Sources. CTA sticky mobile, aside desktop, « Demander à Ka » (widget KA |
|
2354 |
+ Agent). Ordre DOM = ordre visuel, aucun scrollIntoView à l'ouverture. */ |
|
2355 |
+const SK_ICO = { |
|
2356 |
+ share: '<svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.7" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><circle cx="18" cy="5" r="2.5"/><circle cx="6" cy="12" r="2.5"/><circle cx="18" cy="19" r="2.5"/><path d="M8.2 10.8 15.8 6.3M8.2 13.2l7.6 4.5"/></svg>', |
|
2357 |
+ ext: '<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.7" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M14.4 4h5.6v5.6"/><path d="M20 4 11.4 12.6"/><path d="M18.6 13.6V18a2 2 0 0 1-2 2H6a2 2 0 0 1-2-2V7.4a2 2 0 0 1 2-2h4.4"/></svg>', |
|
2358 |
+ spark: '<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.7" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M12 3l1.9 5.6 5.6 1.9-5.6 1.9L12 18l-1.9-5.6-5.6-1.9 5.6-1.9L12 3z"/><path d="M19 16l.8 2.2 2.2.8-2.2.8L19 22l-.8-2.2-2.2-.8 2.2-.8L19 16z"/></svg>', |
|
2359 |
+ pin: '<svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.7" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M12 21.2S5.4 15.7 5.4 10.8a6.6 6.6 0 0 1 13.2 0c0 4.9-6.6 10.4-6.6 10.4z"/><circle cx="12" cy="10.6" r="2.3"/></svg>', |
|
2360 |
+ cal: '<svg width="17" height="17" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.7" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><rect x="4" y="5.6" width="16" height="14.8" rx="2"/><path d="M4 10.2h16M8.2 3.4v4M15.8 3.4v4"/></svg>', |
|
2361 |
+ tag: '<svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.7" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="m12.9 3.6 7.5 7.5a1.8 1.8 0 0 1 0 2.5l-6.8 6.8a1.8 1.8 0 0 1-2.5 0L3.6 12.9V3.6z"/><circle cx="8" cy="8" r="1.5"/></svg>', |
|
2362 |
+ folder: '<svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.7" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M3 6h6l2 2.5h10V19H3z"/></svg>', |
|
2363 |
+ music: '<svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.7" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M9 18V5l12-2v13"/><circle cx="6" cy="18" r="3"/><circle cx="18" cy="16" r="3"/></svg>', |
|
2364 |
+ ticket: '<svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.7" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M3 9a2 2 0 0 0 0 6v3a1 1 0 0 0 1 1h16a1 1 0 0 0 1-1v-3a2 2 0 0 0 0-6V6a1 1 0 0 0-1-1H4a1 1 0 0 0-1 1z"/><path d="M13 5v14"/></svg>', |
|
2365 |
+ alert: '<svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.7" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M12 4.2 2.9 19.4h18.2z"/><path d="M12 10.2v4.4"/><path d="M12 17.4v.05"/></svg>', |
|
2366 |
+ chev: '<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.7" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="m9.5 5 7 7-7 7"/></svg>', |
|
2367 |
+ people: '<svg width="17" height="17" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.7" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><circle cx="9" cy="8" r="3.2"/><path d="M3.6 20a5.4 5.4 0 0 1 10.8 0"/><path d="M15.4 5.4a3.2 3.2 0 0 1 0 5.9M17 14.8a5.4 5.4 0 0 1 3.4 5.2"/></svg>', |
|
2368 |
+}; |
|
2369 |
+const SK_STATE = { uid: null, cleanup: [] }; |
|
2370 |
+ |
|
2371 |
+function skDays(ev){ |
|
2372 |
+ if(!ev.start_date) return null; |
|
2373 |
+ const d = new Date(`${ev.start_date}T12:00:00`), t = new Date(); t.setHours(12,0,0,0); |
|
2374 |
+ return Math.round((d - t) / 86400000); |
|
2375 |
+} |
|
2376 |
+function skQuand(ev){ |
|
2377 |
+ const n = skDays(ev); |
|
2378 |
+ if(n == null) return { tone:"neutral", titre:"Date à confirmer", detail:"La source ne publie pas de date précise" }; |
|
2379 |
+ const fin = ev.end_date && ev.end_date !== ev.start_date; |
|
2380 |
+ const finN = fin ? Math.round((new Date(`${ev.end_date}T12:00:00`) - new Date(new Date().setHours(12,0,0,0))) / 86400000) : n; |
|
2381 |
+ if(finN < 0) return { tone:"bad", titre:"Événement terminé", detail:`${fmtDate(ev.start_date, true)}${fin ? ` au ${fmtDate(ev.end_date, true)}` : ""}` }; |
|
2382 |
+ if(n <= 0 && finN >= 0 && fin) return { tone:"good", titre:"En cours", detail:`Jusqu'au ${fmtDate(ev.end_date, true)}${ev.end_time ? ` · ${fmtTime(ev.end_time)}` : ""}` }; |
|
2383 |
+ if(n === 0) return { tone:"good", titre:"C'est aujourd'hui", detail:`${fmtDate(ev.start_date, true)}${ev.start_time ? ` · ${fmtTime(ev.start_time)}` : ""}` }; |
|
2384 |
+ if(n === 1) return { tone:"good", titre:"C'est demain", detail:`${fmtDate(ev.start_date, true)}${ev.start_time ? ` · ${fmtTime(ev.start_time)}` : ""}` }; |
|
2385 |
+ const dow = new Date(`${ev.start_date}T12:00:00`).getDay(); |
|
2386 |
+ if(n <= 7) return { tone:"good", titre:(dow === 0 || dow === 6) ? "Ce week-end" : `Dans ${n} jours`, detail:`${fmtDate(ev.start_date, true)}${ev.start_time ? ` · ${fmtTime(ev.start_time)}` : ""}` }; |
|
2387 |
+ return { tone:"neutral", titre:`Dans ${n} jours`, detail:`${fmtDate(ev.start_date, true)}${fin ? ` au ${fmtDate(ev.end_date, true)}` : ""}${ev.start_time ? ` · ${fmtTime(ev.start_time)}` : ""}` }; |
|
2388 |
+} |
|
2389 |
+function skPrix(ev){ |
|
2390 |
+ if(ev.is_free === true) return "Gratuit"; |
|
2391 |
+ if(ev.price_min != null) return `Dès ${money(ev.price_min)}`; |
|
2392 |
+ if(ev.is_free === false) return "Billetterie"; |
|
2393 |
+ return "Voir la source"; |
|
2394 |
+} |
|
2395 |
+function skEnBref(ev){ |
|
2396 |
+ const out = []; |
|
2397 |
+ const q = skQuand(ev); out.push({ cle:"quand", ...q }); |
|
2398 |
+ if(ev.status && STATUS_LABELS[ev.status]) |
|
2399 |
+ out.push({ cle:"statut", tone: ev.status === "soldout" ? "warn" : "bad", titre: ev.status === "cancelled" ? "Événement annulé" : ev.status === "postponed" ? "Événement reporté" : "Complet — plus de billets", |
|
2400 |
+ detail:"Statut publié par la source — vérifiez la fiche originale" }); |
|
2401 |
+ if(ev.is_free === true) out.push({ cle:"prix", tone:"good", titre:"Entrée gratuite", detail:"Selon la source — inscription parfois requise" }); |
|
2402 |
+ else if(ev.price_min != null) out.push({ cle:"prix", tone:"neutral", titre:`Billets dès ${money(ev.price_min)}`, detail: ev.price_label || "Prix publié par la billetterie, frais en sus possibles" }); |
|
2403 |
+ else if(ev.is_free === false) out.push({ cle:"prix", tone:"neutral", titre:"Événement payant", detail:"Prix non publié — voir la billetterie" }); |
|
2404 |
+ if(ev.venue || ev.city) out.push({ cle:"lieu", tone:"info", titre:[ev.venue, ev.city].filter(Boolean).join(" · "), detail:[ev.address, ev.region && ev.region !== ev.city ? ev.region : null].filter(Boolean).join(" · ") || "Lieu publié par la source" }); |
|
2405 |
+ if(ev.artists && ev.artists.length) out.push({ cle:"artistes", tone:"info", titre:`À l'affiche : ${ev.artists.slice(0,3).join(", ")}${ev.artists.length > 3 ? ` +${ev.artists.length - 3}` : ""}`, detail:`${ev.artists.length} artiste${ev.artists.length > 1 ? "s" : ""} annoncé${ev.artists.length > 1 ? "s" : ""}` }); |
|
2406 |
+ if(ev.audience) out.push({ cle:"public", tone:"neutral", titre:`Public : ${ev.audience}`, detail:"Indication de la source" }); |
|
2407 |
+ return out.slice(0, 6); |
|
2408 |
+} |
|
2409 |
+function skBrief(items, compact){ |
|
2410 |
+ const g = t => t === "good" ? "✓" : t === "bad" ? "✕" : t === "warn" ? "!" : "○"; |
|
2411 |
+ return `<ul class="sk-brief">${items.map(c => `<li><span class="sk-brief-ico ${c.tone === "info" ? "neutral" : c.tone}" aria-hidden="true">${g(c.tone)}</span> |
|
2412 |
+ <div><div class="sk-brief-t">${esc(c.titre)}</div>${!compact && c.detail ? `<div class="sk-brief-d">${esc(c.detail)}</div>` : ""}</div></li>`).join("")}</ul>`; |
|
2413 |
+} |
|
2414 |
+function skCard(id, title, ico, body, sub, aside){ |
|
2415 |
+ return `<section id="sk-${id}" class="sk-card">${title ? `<div class="sk-card-head"><div><h2 class="sk-card-title">${ico || ""}${esc(title)}</h2>${sub ? `<p class="sk-card-sub">${sub}</p>` : ""}</div>${aside ? `<div class="sk-card-aside">${aside}</div>` : ""}</div>` : ""}${body}</section>`; |
|
2416 |
+} |
|
2417 |
+function skFact(ico, v, l){ return `<div class="sk-fact" role="listitem"><span class="sk-fact-ico" aria-hidden="true">${ico}</span><span class="sk-fact-txt"><div class="sk-fact-v" title="${esc(v)}">${esc(v)}</div><div class="sk-fact-l">${esc(l)}</div></span></div>`; } |
|
2418 |
+function skKv(k, v){ return `<div class="sk-kv"><span class="k">${esc(k)}</span><span class="v">${v}</span></div>`; } |
|
2419 |
+function skDetails(title, body, meta){ return `<details class="sk-details"><summary><span>${title}</span>${meta ? `<span class="sk-acc-meta">${esc(meta)}</span>` : ""}</summary><div class="sk-acc-inner">${body}</div></details>`; } |
|
2420 |
+ |
| 1694 |
2421 |
async function showDetail(uid){ |
| 1695 |
2422 |
let ev; |
| 1696 |
2423 |
try{ ev = await (await fetch(`/api/events/${encodeURIComponent(uid)}`)).json(); } |
| 1697 |
2424 |
catch(e){ go("/"); return; } |
| 1698 |
2425 |
if(ev.detail){ go("/"); return; } |
|
2426 |
+ SK_STATE.cleanup.forEach(f => { try{ f(); }catch(_){} }); SK_STATE.cleanup = []; SK_STATE.uid = ev.uid; |
|
2427 |
+ FAV.meta[ev.uid] = favItem(ev); |
| 1699 |
2428 |
|
| 1700 |
2429 |
document.title = `${ev.title} — ${ev.city || "Québec"} | Sorti·Ka`; |
| 1701 |
|
− $("d-img").innerHTML = ev.image |
| 1702 |
|
− ? `<img src="${esc(ev.image)}" alt="" onerror="this.remove()">` : ""; |
| 1703 |
|
− $("d-img").classList.toggle("noimg", !ev.image); |
| 1704 |
|
− $("d-cats-label").textContent = (ev.categories||[]).filter(c=>c!=="autre") |
| 1705 |
|
− .map(c=>CAT_LABELS[c]||c).join(" · ") || "Événement"; |
| 1706 |
|
− $("d-status").innerHTML = ev.status && STATUS_LABELS[ev.status] |
| 1707 |
|
− ? `<div class="status-banner status-banner--${esc(ev.status)}">${ |
| 1708 |
|
− ev.status==="cancelled" ? "Cet événement est annulé" |
| 1709 |
|
− : ev.status==="postponed" ? "Cet événement est reporté — vérifiez la nouvelle date chez la source" |
| 1710 |
|
− : "Complet — plus de billets disponibles"}</div>` : ""; |
| 1711 |
|
− $("d-title").textContent = ev.title; |
| 1712 |
|
− $("d-fav").innerHTML = favBtn(ev, true); |
| 1713 |
|
− $("d-desc").textContent = ev.description || ""; |
| 1714 |
|
− $("d-cats").innerHTML = (ev.raw_categories||[]).slice(0,5).filter(c=>c.length<40) |
| 1715 |
|
− .map(c=>`<span class="cat">${esc(c)}</span>`).join(""); |
| 1716 |
|
− |
|
2430 |
+ const cats = (ev.categories||[]).filter(c=>c!=="autre").map(c=>CAT_LABELS[c]||c); |
|
2431 |
+ const catTxt = cats.join(" · ") || "Événement"; |
|
2432 |
+ const src = SRC_LABELS[ev.source] || ev.source; |
|
2433 |
+ const brief = skEnBref(ev); |
|
2434 |
+ const quand = skQuand(ev); |
|
2435 |
+ const prix = skPrix(ev); |
|
2436 |
+ const resume = [ev.venue, ev.city, evDate(ev)].filter(Boolean); |
|
2437 |
+ const geo = ev.lat && ev.lng; |
|
2438 |
+ const statusCap = ev.status && STATUS_LABELS[ev.status] ? `<span class="sk-capsule high"><b>${esc(STATUS_LABELS[ev.status])}</b></span>` : ""; |
|
2439 |
+ const dateCap = quand ? `<span class="sk-capsule ${quand.tone === "good" ? "good" : quand.tone === "bad" ? "high" : "date"}"><b>${esc(quand.titre)}</b></span>` : ""; |
|
2440 |
+ const shareBtn = (cls) => `<button type="button" class="${cls}" data-sk-share aria-label="Partager">${SK_ICO.share}</button>`; |
|
2441 |
+ const cta = (cls, txt) => `<a class="${cls}" href="${esc(ev.url)}" target="_blank" rel="noopener noreferrer">${txt} ${SK_ICO.ext}</a>`; |
|
2442 |
+ const nav = [["resume","Résumé"],["quand","Quand et où"],["programme","Programme"],["billets","Billets"],["similaires","À voir aussi"],["dossier","Dossier"],["sources","Sources"]]; |
|
2443 |
+ |
|
2444 |
+ // --- faits « Quand et où » |
| 1717 |
2445 |
const facts = []; |
| 1718 |
|
− facts.push(["Quand", dateBadge(ev, true)]); |
| 1719 |
|
− if(ev.artists && ev.artists.length) |
| 1720 |
|
− facts.push(["À l'affiche", ev.artists.map(esc).join(", ")]); |
| 1721 |
|
− if(ev.venue) facts.push(["Lieu", esc(ev.venue)]); |
| 1722 |
|
− if(ev.address) facts.push(["Adresse", esc(ev.address)]); |
| 1723 |
|
− if(ev.city) facts.push(["Ville", esc(ev.city)]); |
| 1724 |
|
− if(ev.region) facts.push(["Région", esc(ev.region)]); |
| 1725 |
|
− if(ev.is_free === true) facts.push(["Prix", `<span class="badge-free">Gratuit</span>`]); |
| 1726 |
|
− else if(ev.price_min != null) facts.push(["Prix", `Dès ${ev.price_min.toFixed(2).replace(".",",")} $ CAD`]); |
| 1727 |
|
− else if(ev.is_free === false) facts.push(["Prix", "Payant — voir la billetterie"]); |
| 1728 |
|
− if(ev.price_label) facts.push(["Détail prix", esc(ev.price_label)]); |
| 1729 |
|
− if(ev.audience) facts.push(["Public", esc(ev.audience)]); |
| 1730 |
|
− if(ev.organizer) facts.push(["Organisé par", esc(ev.organizer)]); |
| 1731 |
|
− if(ev.lat && ev.lng) facts.push(["Carte", |
| 1732 |
|
− `<a class="maplink" target="_blank" rel="noopener" href="https://www.google.com/maps?q=${ev.lat},${ev.lng}">Voir sur la carte ↗</a>`]); |
| 1733 |
|
− $("d-facts").innerHTML = facts.map(([k,v]) => |
| 1734 |
|
− `<div class="fact"><span class="k">${k}</span><span class="v">${v}</span></div>`).join(""); |
| 1735 |
|
− |
| 1736 |
|
− $("d-cta").href = ev.url; |
| 1737 |
|
− $("d-ctabar").innerHTML = `<div class="p"> |
| 1738 |
|
− <b>${priceTxt(ev) || (ev.is_free === false ? "Payant — voir la billetterie" : "Voir la billetterie")}</b> |
| 1739 |
|
− <span>${evDate(ev)}</span></div> |
| 1740 |
|
− <a class="btn btn-cta" href="${esc(ev.url)}" target="_blank" rel="noopener">Billets ↗</a>`; |
| 1741 |
|
− $("d-src").innerHTML = `<span class="klabel">Source & attribution</span> |
| 1742 |
|
− <div style="margin-top:6px;font-size:13px">${SRC_LABELS[ev.source]||ev.source}</div> |
| 1743 |
|
− <div style="font-family:var(--font-mono);font-size:10px;color:var(--ink-3);margin-top:4px"> |
| 1744 |
|
− Capté le ${new Date((ev.updated_at||0)*1000).toLocaleDateString("fr-CA")} · |
| 1745 |
|
− identifiant ${esc(ev.uid)}</div>`; |
|
2446 |
+ if(ev.start_date) facts.push(skFact(SK_ICO.cal, fmtDate(ev.start_date, true), ev.end_date && ev.end_date !== ev.start_date ? `Du … au ${fmtDate(ev.end_date, true)}` : "Date")); |
|
2447 |
+ if(ev.start_time) facts.push(skFact(SK_ICO.cal, `${fmtTime(ev.start_time)}${ev.end_time ? ` – ${fmtTime(ev.end_time)}` : ""}`, "Heure")); |
|
2448 |
+ if(ev.venue) facts.push(skFact(SK_ICO.pin, ev.venue, "Lieu")); |
|
2449 |
+ if(ev.city) facts.push(skFact(SK_ICO.pin, ev.city, ev.region && ev.region !== ev.city ? `Ville · ${ev.region}` : "Ville")); |
|
2450 |
+ if(ev.audience) facts.push(skFact(SK_ICO.people, ev.audience, "Public")); |
|
2451 |
+ if(ev.organizer) facts.push(skFact(SK_ICO.people, ev.organizer, "Organisé par")); |
|
2452 |
+ const rows = []; |
|
2453 |
+ if(ev.address) rows.push(skKv("Adresse", esc([ev.address, ev.city, ev.postal_code].filter(Boolean).join(", ")))); |
|
2454 |
+ if(ev.tourist_region) rows.push(skKv("Région touristique", esc(ev.tourist_region))); |
|
2455 |
+ if(geo) rows.push(skKv("Itinéraire", `<a href="https://www.google.com/maps?q=${ev.lat},${ev.lng}" target="_blank" rel="noopener">Google Maps ↗</a> · <a href="https://maps.apple.com/?q=${ev.lat},${ev.lng}" target="_blank" rel="noopener">Plans ↗</a>`)); |
|
2456 |
+ |
|
2457 |
+ // --- programme |
|
2458 |
+ const desc = (ev.description || "").trim(); |
|
2459 |
+ const long = desc.length > 420; |
|
2460 |
+ const raw = (ev.raw_categories||[]).filter(c => c && c.length < 40).slice(0, 8); |
|
2461 |
+ |
|
2462 |
+ const html = ` |
|
2463 |
+ <div class="sk-wrap"> |
|
2464 |
+ <nav class="sk-crumbs" aria-label="Fil d'Ariane"><a data-nav href="/">Sorties</a><span aria-hidden="true">›</span>${ev.region ? `<a data-nav href="/region/${esc(kaSlug(ev.region))}">${esc(ev.region)}</a><span aria-hidden="true">›</span>` : ""}<span>${esc(ev.title)}</span></nav> |
|
2465 |
+ <div class="sk-grid"> |
|
2466 |
+ <div class="sk-main"> |
|
2467 |
+ <header class="sk-hero" aria-label="Résumé de l'événement"> |
|
2468 |
+ <div class="sk-kicker">${esc(catTxt)} · ${esc(src)}</div> |
|
2469 |
+ <div class="sk-price">${esc(prix)}${ev.price_label && ev.price_min != null ? `<small>${esc(ev.price_label)}</small>` : ""}</div> |
|
2470 |
+ <div class="sk-price-row" style="margin-top:8px">${dateCap}${statusCap}${ev.is_free === true ? `<span class="sk-capsule good"><b>Gratuit</b></span>` : ""}</div> |
|
2471 |
+ <h1 class="sk-h1">${esc(ev.title)}${resume.length ? `<span class="sk-city">${resume.map(esc).join(" · ")}</span>` : ""}</h1> |
|
2472 |
+ <div class="sk-image ${ev.image ? "" : "noimg"}">${ev.image ? `<img src="${esc(ev.image)}" alt="" onerror="this.parentNode.classList.add('noimg');this.remove()">` : esc(catTxt)}</div> |
|
2473 |
+ <div class="sk-actions" id="sk-actions">${favBtn(ev, true)}${shareBtn("sk-btn sk-btn-ghost sk-btn-icon")}${cta("sk-btn sk-btn-primary", ev.is_free === true ? "Voir la fiche originale" : "Billets")}</div> |
|
2474 |
+ </header> |
|
2475 |
+ ${skCard("resume", "En bref", "", skBrief(brief))} |
|
2476 |
+ <nav class="sk-nav" aria-label="Sections de la fiche"><div class="sk-nav-track" id="sk-nav">${nav.map(([id,l], i) => `<a href="#sk-${id}" data-sk-nav="sk-${id}" class="${i === 0 ? "on" : ""}">${l}</a>`).join("")}</div></nav> |
|
2477 |
+ ${skCard("quand", "Quand et où", SK_ICO.pin, `${facts.length ? `<div class="sk-facts" role="list">${facts.join("")}</div>` : ""}${rows.length ? `<div class="sk-facts-rows">${rows.join("")}</div>` : ""}${geo ? `<div class="sk-map" style="position:relative;border-radius:var(--sk-r-lg);overflow:hidden;border:1px solid var(--sk-border);margin-top:12px"><div id="sk-map" style="position:absolute;inset:0"></div></div><div class="sk-source"><span>Source : <b>OpenStreetMap</b> · position géocodée de l'adresse publiée</span></div>` : ""}`, ev.venue ? `${esc(ev.venue)}${ev.city ? ` — ${esc(ev.city)}` : ""}` : "")} |
|
2478 |
+ ${skCard("programme", "Programme", SK_ICO.music, `${desc ? `<div class="sk-desc ${long ? "clamped" : ""}" id="sk-desc"><div class="sk-desc-body"><p>${esc(desc)}</p></div></div>${long ? `<button type="button" class="sk-more" data-sk-more aria-expanded="false">Lire la suite</button>` : ""}` : `<p class="sk-fine" style="margin-top:0">La source ne fournit pas de description pour cet événement.</p>`}${ev.artists && ev.artists.length ? `<h3 class="sk-card-sub sk-subtitle" id="artistes">À l'affiche <small>· ${ev.artists.length}</small></h3><div class="sk-amen" role="list">${ev.artists.map(a => `<div class="sk-amen-it" role="listitem"><span class="sk-amen-ico" aria-hidden="true">${SK_ICO.music}</span><span class="sk-amen-txt">${esc(a)}</span></div>`).join("")}</div>` : ""}${raw.length ? `<div class="sk-tags" style="margin-top:12px">${raw.map(c => `<span class="sk-tag n">${esc(c)}</span>`).join("")}</div>` : ""}`)} |
|
2479 |
+ ${skCard("billets", "Billets et prix", SK_ICO.ticket, `<div class="sk-kpis cols-3"><div class="sk-kpi accent"><div class="sk-kpi-v">${esc(prix)}</div><div class="sk-kpi-l">${ev.is_free === true ? "Entrée" : ev.price_min != null ? "Prix d'entrée minimum" : "Tarification"}</div></div>${ev.price_label ? `<div class="sk-kpi"><div class="sk-kpi-v wrap">${esc(ev.price_label)}</div><div class="sk-kpi-l">Détail publié</div></div>` : ""}<div class="sk-kpi"><div class="sk-kpi-v wrap">${esc(src)}</div><div class="sk-kpi-l">Billetterie / source</div></div></div>${cta("sk-btn sk-btn-primary", ev.is_free === true ? "Fiche originale" : "Acheter des billets chez " + src).replace('class="sk-btn sk-btn-primary"', 'class="sk-btn sk-btn-primary" style="margin-top:12px;width:100%"')}<p class="sk-fine">Prix affichés par la source lors de la dernière synchronisation — frais de service et taxes en sus possibles. Sorti·Ka ne vend pas de billets.</p>`)} |
|
2480 |
+ ${skCard("similaires", "À voir aussi", SK_ICO.tag, `<div class="grid" id="d-similar"><div class="sk-skel-lines" aria-busy="true"><div class="sk-skel"></div><div class="sk-skel"></div><div class="sk-skel short"></div></div></div>`, cats[0] ? `Autres sorties « ${esc(cats[0])} »${ev.region ? ` en ${esc(ev.region)}` : ""}` : "Autres sorties à proximité")} |
|
2481 |
+ ${skCard("dossier", "Dossier de la fiche", SK_ICO.folder, `${skDetails(`${SK_ICO.people} Organisateur et source`, `<p style="margin:0 0 6px"><b style="font-size:15px">${esc(ev.organizer || src)}</b></p><p style="margin:0">Fiche publiée par <b>${esc(src)}</b>${ev.website ? ` · <a href="${esc(ev.website)}" target="_blank" rel="noopener noreferrer">site de l'événement ↗</a>` : ""}. Sorti·Ka est un agrégateur indépendant : billets, horaires et annulations relèvent de l'organisateur.</p>`, esc(ev.organizer || src))}${skDetails(`${SK_ICO.cal} Suivi Sorti·Ka`, `<div class="sk-facts-rows" style="margin-top:0">${skKv("Première observation", ev.first_seen ? new Date(ev.first_seen*1000).toLocaleDateString("fr-CA", {day:"numeric", month:"long", year:"numeric"}) : "—")}${skKv("Dernière synchronisation", ev.updated_at ? new Date(ev.updated_at*1000).toLocaleDateString("fr-CA", {day:"numeric", month:"long", year:"numeric"}) : "—")}${skKv("Statut", ev.active ? "Publié par la source" : "Retiré")}</div>`, ev.updated_at ? `synchro ${new Date(ev.updated_at*1000).toLocaleDateString("fr-CA")}` : "")}${skDetails(`${SK_ICO.tag} Identifiants`, `<div class="sk-facts-rows" style="margin-top:0">${skKv("Identifiant source", esc(ev.external_id || ""))}${skKv("Identifiant Sorti·Ka", esc(ev.uid))}${skKv("Fiche originale", `<a href="${esc(ev.url)}" target="_blank" rel="noopener noreferrer">${esc(src)} ↗</a>`)}</div>`, esc(ev.external_id || ""))}`, "Ce que Sorti·Ka observe réellement : organisateur, suivi, identifiants")} |
|
2482 |
+ ${skCard("sources", "Sources et méthodologie", SK_ICO.folder, `<ul class="sk-sources"><li><span class="n"><a href="${esc(ev.url)}" target="_blank" rel="noopener noreferrer">${esc(src)}</a></span><span class="r">Titre, dates, lieu, prix, image et description (source originale)</span></li><li><span class="n">Sorti·Ka</span><span class="r">Catégorisation, géocodage, dédoublonnage entre sources, suivi des statuts — calculs maison, indicatifs</span></li>${geo ? `<li><span class="n">OpenStreetMap</span><span class="r">Fond de carte et position du lieu</span></li>` : ""}</ul><div class="sk-end" style="margin-top:14px"><a href="/#sources">${SK_ICO.folder}Sources<small>Toutes les sources Sorti·Ka</small></a><a data-nav href="/contact">${SK_ICO.alert}Signaler une erreur<small>Date, lieu, prix…</small></a><button type="button" data-sk-share>${SK_ICO.share}Partager<small>Lien de la fiche</small></button><a data-nav href="/stats">${SK_ICO.tag}Statistiques<small>Sorties par région</small></a></div><p class="sk-fine" style="margin-top:12px">Les dates, prix et disponibilités sont ceux affichés par la source — chaque fiche renvoie à la page originale. Sorti·Ka est un agrégateur indépendant.</p>`, "Chaque donnée de cette fiche renvoie à sa source ; les calculs Sorti·Ka sont indicatifs et documentés")} |
|
2483 |
+ </div> |
|
2484 |
+ <aside class="sk-aside" aria-label="Résumé et actions"><div class="sk-card sk-aside-card"> |
|
2485 |
+ <div><div class="sk-price">${esc(prix)}</div><div class="sk-price-row" style="margin-top:8px">${dateCap}${statusCap}</div></div> |
|
2486 |
+ <div class="sk-aside-addr"><b style="color:var(--sk-text)">${esc(ev.title)}</b><br>${resume.map(esc).join(" · ")}</div> |
|
2487 |
+ ${cta("sk-btn sk-btn-primary", ev.is_free === true ? "Voir la fiche originale" : "Billets chez " + esc(src))} |
|
2488 |
+ <div class="sk-actions" id="sk-aside-actions">${favBtn(ev, true)}${shareBtn("sk-btn sk-btn-ghost")}</div> |
|
2489 |
+ <button type="button" class="sk-btn sk-btn-ghost sk-ka-inline" data-sk-ka>${SK_ICO.spark} Demander à Ka</button> |
|
2490 |
+ ${brief.length ? `<hr class="sk-aside-sep">${skBrief(brief.slice(0, 4), true)}` : ""} |
|
2491 |
+ <div class="sk-aside-meta">${ev.updated_at ? `Synchronisé le ${new Date(ev.updated_at*1000).toLocaleDateString("fr-CA")} · ` : ""}${esc(src)}</div> |
|
2492 |
+ </div></aside> |
|
2493 |
+ </div> |
|
2494 |
+ </div> |
|
2495 |
+ <div class="sk-cta-bar" id="sk-ctabar" aria-hidden="true"><div class="sk-cta-txt"><div class="sk-cta-price">${esc(prix)}</div><div class="sk-cta-sub ${quand.tone === "good" ? "good" : ""}">${esc(quand.titre)} · ${esc(ev.venue || ev.city || "")}</div></div>${cta("sk-btn sk-btn-primary", ev.is_free === true ? "Fiche" : "Billets")}</div> |
|
2496 |
+ <button type="button" class="sk-ka-btn hide" id="sk-ka-btn" data-sk-ka aria-label="Demander à Ka, l'assistant Groupe KA">${SK_ICO.spark} Demander à Ka</button>`; |
|
2497 |
+ |
|
2498 |
+ const root = $("sk-root"); |
|
2499 |
+ root.innerHTML = html; |
|
2500 |
+ bindNav(root); |
|
2501 |
+ // header compact : favoris + partage à côté de la marque (retirés en quittant la fiche) |
|
2502 |
+ let hdr = $("sk-hdr"); |
|
2503 |
+ if(!hdr){ hdr = document.createElement("div"); hdr.id = "sk-hdr"; hdr.className = "hdr-actions"; const b = document.querySelector(".header .brand"); b.parentNode.insertBefore(hdr, b.nextSibling); } |
|
2504 |
+ hdr.innerHTML = `${favBtn(ev)}<button type="button" class="hdr-btn" data-sk-share aria-label="Partager">${SK_ICO.share}</button>`; |
|
2505 |
+ favPaint(); |
|
2506 |
+ |
|
2507 |
+ // partage |
|
2508 |
+ document.querySelectorAll("[data-sk-share]").forEach(b => b.onclick = async () => { |
|
2509 |
+ const url = `https://www.sorti-ka.com/evenement/${encodeURIComponent(ev.uid)}`; |
|
2510 |
+ try{ |
|
2511 |
+ if(navigator.share){ await navigator.share({ title: `${ev.title} — Sorti·Ka`, url }); return; } |
|
2512 |
+ await navigator.clipboard.writeText(url); toast("Lien copié"); |
|
2513 |
+ }catch(_){} |
|
2514 |
+ }); |
|
2515 |
+ // description « Lire la suite » |
|
2516 |
+ const more = root.querySelector("[data-sk-more]"); |
|
2517 |
+ if(more) more.onclick = () => { const open = $("sk-desc").classList.toggle("clamped") === false; more.textContent = open ? "Réduire" : "Lire la suite"; more.setAttribute("aria-expanded", open); }; |
|
2518 |
+ // navigation par sections : scroll-spy + défilement doux (jamais à l'ouverture) |
|
2519 |
+ const navEl = $("sk-nav"); |
|
2520 |
+ const links = [...navEl.querySelectorAll("a[data-sk-nav]")]; |
|
2521 |
+ links.forEach(a => a.onclick = e => { e.preventDefault(); const t = $(a.dataset.skNav); if(t) t.scrollIntoView({ behavior:"smooth", block:"start" }); }); |
|
2522 |
+ const visible = new Map(); |
|
2523 |
+ const io = new IntersectionObserver(entries => { |
|
2524 |
+ entries.forEach(en => visible.set(en.target.id, en.isIntersecting ? en.intersectionRatio : 0)); |
|
2525 |
+ const first = nav.map(([id]) => "sk-" + id).find(id => (visible.get(id) || 0) > 0); |
|
2526 |
+ if(first){ links.forEach(a => a.classList.toggle("on", a.dataset.skNav === first)); const on = navEl.querySelector(".on"); if(on){ const l = on.offsetLeft, r = l + on.offsetWidth; if(l < navEl.scrollLeft) navEl.scrollTo({ left: Math.max(0, l - 12), behavior:"smooth" }); else if(r > navEl.scrollLeft + navEl.clientWidth) navEl.scrollTo({ left: r - navEl.clientWidth + 12, behavior:"smooth" }); } } |
|
2527 |
+ }, { rootMargin:"-120px 0px -55% 0px", threshold:[0, .1, .5] }); |
|
2528 |
+ nav.forEach(([id]) => { const el = $("sk-" + id); if(el) io.observe(el); }); |
|
2529 |
+ SK_STATE.cleanup.push(() => io.disconnect()); |
|
2530 |
+ // CTA sticky + bouton Ka : après le héro |
|
2531 |
+ const actions = $("sk-actions"), bar = $("sk-ctabar"), kab = $("sk-ka-btn"); |
|
2532 |
+ const onScroll = () => { const past = actions.getBoundingClientRect().bottom < 0; bar.classList.toggle("show", past); bar.setAttribute("aria-hidden", !past); kab.classList.toggle("hide", !past); }; |
|
2533 |
+ window.addEventListener("scroll", onScroll, { passive:true }); onScroll(); |
|
2534 |
+ SK_STATE.cleanup.push(() => window.removeEventListener("scroll", onScroll)); |
|
2535 |
+ // Demander à Ka |
|
2536 |
+ root.querySelectorAll("[data-sk-ka]").forEach(b => b.onclick = () => skOpenKa(ev)); |
|
2537 |
+ |
|
2538 |
+ show("view-detail"); |
|
2539 |
+ window.scrollTo({ top:0 }); |
|
2540 |
+ |
|
2541 |
+ // carte Leaflet (après l'affichage : le conteneur doit être mesurable) |
|
2542 |
+ if(geo){ |
|
2543 |
+ ensureLeaflet().then(() => { |
|
2544 |
+ const m = L.map("sk-map", { zoomControl:true, scrollWheelZoom:false }).setView([ev.lat, ev.lng], 14); |
|
2545 |
+ L.tileLayer("https://tile.openstreetmap.org/{z}/{x}/{y}.png", { attribution:"© <a href='https://www.openstreetmap.org/copyright'>OpenStreetMap</a>", maxZoom:19 }).addTo(m); |
|
2546 |
+ L.marker([ev.lat, ev.lng]).addTo(m).bindPopup(`<b>${esc(ev.venue || ev.title)}</b><br>${esc([ev.address, ev.city].filter(Boolean).join(", "))}`); |
|
2547 |
+ setTimeout(() => m.invalidateSize(), 120); |
|
2548 |
+ SK_STATE.cleanup.push(() => { try{ m.remove(); }catch(_){} }); |
|
2549 |
+ }).catch(() => { const w = $("sk-map"); if(w) w.parentNode.innerHTML = `<div class="sk-empty">Carte indisponible — vérifiez la connexion.</div>`; }); |
|
2550 |
+ } |
| 1746 |
2551 |
|
| 1747 |
2552 |
// événements similaires : même catégorie prioritaire, sinon même ville |
| 1748 |
2553 |
const cat = (ev.categories||[]).filter(c=>c!=="autre")[0] || ""; |
| 1749 |
|
− const q = new URLSearchParams({limit: 7}); |
|
2554 |
+ const q = new URLSearchParams({ limit: 7 }); |
| 1750 |
2555 |
if(cat) q.set("category", cat); else if(ev.city) q.set("city", ev.city); |
| 1751 |
2556 |
if(ev.region && cat) q.set("region", ev.region); |
| 1752 |
2557 |
try{ |
| 1753 |
2558 |
const sim = await (await fetch(`/api/events?${q}`)).json(); |
| 1754 |
|
− const others = sim.events.filter(e=>e.uid!==ev.uid).slice(0,6); |
| 1755 |
|
− $("d-similar").innerHTML = others.map(card).join("") || |
| 1756 |
|
− `<div class="empty">Rien de similaire pour l'instant.</div>`; |
| 1757 |
|
− bindNav($("d-similar")); |
| 1758 |
|
− }catch(e){ $("d-similar").innerHTML = ""; } |
| 1759 |
|
− |
| 1760 |
|
− show("view-detail"); |
| 1761 |
|
− window.scrollTo({top:0}); |
|
2559 |
+ const others = sim.events.filter(e => e.uid !== ev.uid).slice(0, 6); |
|
2560 |
+ const host = $("d-similar"); |
|
2561 |
+ if(host && SK_STATE.uid === ev.uid){ host.innerHTML = others.map(card).join("") || `<div class="sk-empty">Rien de similaire pour l'instant.</div>`; bindNav(host); favPaint(); } |
|
2562 |
+ }catch(e){ const host = $("d-similar"); if(host) host.innerHTML = ""; } |
|
2563 |
+} |
|
2564 |
+ |
|
2565 |
+/* « ✦ Demander à Ka » : bottom sheet de démarrage → widget KA Agent (ka-agent.js) */ |
|
2566 |
+const SK_SUGS = ["Cet événement vaut-il le détour ?", "Que faire autour avant ou après ?", "Trouve des sorties semblables ce week-end", "Y a-t-il des billets moins chers ?", "Résume le programme"]; |
|
2567 |
+function skEnvoyerKa(question){ |
|
2568 |
+ const btn = document.querySelector(".kaa-btn"), ta = document.querySelector(".kaa-panel textarea"), send = document.querySelector(".kaa-in button"); |
|
2569 |
+ if(!btn || !ta || !send) return false; |
|
2570 |
+ btn.click(); ta.value = question; setTimeout(() => send.click(), 60); return true; |
|
2571 |
+} |
|
2572 |
+function skOpenKa(ev){ |
|
2573 |
+ const ctx = `(Événement consulté sur Sorti·Ka : ${ev.title}${ev.venue ? ` — ${ev.venue}` : ""}${ev.city ? `, ${ev.city}` : ""}${ev.start_date ? ` — ${fmtDate(ev.start_date, true)}` : ""} — https://www.sorti-ka.com/evenement/${encodeURIComponent(ev.uid)})`; |
|
2574 |
+ const old = $("sk-sheet"); if(old) old.remove(); |
|
2575 |
+ const el = document.createElement("div"); el.id = "sk-sheet"; |
|
2576 |
+ el.innerHTML = `<div class="sk-sheet-backdrop" data-close aria-hidden="true"></div> |
|
2577 |
+ <div class="sk-sheet" role="dialog" aria-modal="true" aria-label="Demander à Ka" tabindex="-1"> |
|
2578 |
+ <div class="sk-sheet-handle"></div> |
|
2579 |
+ <div class="sk-sheet-head"><div><h3 class="sk-sheet-title">Demander à Ka</h3><p class="sk-sheet-sub">Assistant Groupe KA · connaît cette fiche</p></div><button type="button" class="sk-sheet-x" data-close aria-label="Fermer">✕</button></div> |
|
2580 |
+ <div class="sk-sheet-body"> |
|
2581 |
+ <div class="sk-ka-intro"><span class="sk-ka-avatar" aria-hidden="true">${SK_ICO.spark}</span><p>Je peux situer cette sortie, proposer quoi faire autour, comparer les billets et chercher des événements semblables partout au Québec.</p></div> |
|
2582 |
+ <div class="sk-ka-ctx">${ev.image ? `<img src="${esc(ev.image)}" alt="">` : ""}<span style="min-width:0"><b>${esc(ev.title)}</b>${[ev.venue || ev.city, evDate(ev), skPrix(ev)].filter(Boolean).map(esc).join(" · ")}</span></div> |
|
2583 |
+ <div class="sk-ka-sugs">${SK_SUGS.map(s => `<button type="button" class="sk-ka-sug" data-q="${esc(s)}">${esc(s)} ${SK_ICO.chev}</button>`).join("")}</div> |
|
2584 |
+ <p class="sk-note warn hidden" id="sk-ka-err">L'assistant n'est pas encore chargé — réessayez dans un instant.</p> |
|
2585 |
+ </div> |
|
2586 |
+ <div class="sk-sheet-foot"><form class="sk-ka-in" id="sk-ka-form"><input placeholder="Posez votre question sur cette sortie…" aria-label="Votre question"><button type="submit" aria-label="Envoyer">${SK_ICO.chev}</button></form></div> |
|
2587 |
+ </div>`; |
|
2588 |
+ document.body.appendChild(el); |
|
2589 |
+ document.documentElement.classList.add("ka-scroll-lock"); |
|
2590 |
+ const close = () => { el.remove(); document.documentElement.classList.remove("ka-scroll-lock"); window.removeEventListener("keydown", onKey); }; |
|
2591 |
+ const onKey = e => { if(e.key === "Escape") close(); }; |
|
2592 |
+ window.addEventListener("keydown", onKey); |
|
2593 |
+ el.querySelectorAll("[data-close]").forEach(b => b.onclick = close); |
|
2594 |
+ const poser = q => { if(skEnvoyerKa(`${q}\n\n${ctx}`)) close(); else $("sk-ka-err").classList.remove("hidden"); }; |
|
2595 |
+ el.querySelectorAll(".sk-ka-sug").forEach(b => b.onclick = () => poser(b.dataset.q)); |
|
2596 |
+ $("sk-ka-form").onsubmit = e => { e.preventDefault(); const v = e.target.querySelector("input").value.trim(); if(v) poser(v); }; |
|
2597 |
+ setTimeout(() => el.querySelector(".sk-sheet").focus(), 30); |
| 1762 |
2598 |
} |
| 1763 |
2599 |
|
| 1764 |
2600 |
/* ==================== vue /stats — module ka-stats (vanilla + SVG) ========= |
| 2661 |
3497 |
const VIEWS = ["view-list","view-detail","view-contact","view-stats","view-favoris"]; |
| 2662 |
3498 |
function show(id){ |
| 2663 |
3499 |
VIEWS.forEach(v => $(v).classList.toggle("hidden", v !== id)); |
|
3500 |
+ // fiche événement : fond papier, header compact, ticker/tabbar/bulle KA masqués |
|
3501 |
+ document.body.classList.toggle("sk-fiche-page", id === "view-detail"); |
|
3502 |
+ if(id !== "view-detail"){ const hd = $("sk-hdr"); if(hd) hd.remove(); } |
|
3503 |
+ if(id !== "view-detail" && SK_STATE.cleanup.length){ SK_STATE.cleanup.forEach(f => { try{ f(); }catch(_){} }); SK_STATE.cleanup = []; } |
| 2664 |
3504 |
} |
| 2665 |
3505 |
|
| 2666 |
3506 |
function showList(){ |
| 2713 |
3553 |
}); |
| 2714 |
3554 |
} |
| 2715 |
3555 |
window.addEventListener("popstate", route); |
| 2716 |
|
−$("back").onclick = () => go("/"); |
|
3556 |
+/* (le lien « Toutes les sorties » de l'ancienne fiche est remplacé par le fil d'Ariane de la fiche v3) */ |
| 2717 |
3557 |
|
| 2718 |
3558 |
/* ---------- KA Nav v2 : menu mobile plein écran (2026-08-25) ---------- */ |
| 2719 |
3559 |
(function(){ |
| 2720 |
3560 |
|