Preview
.hp-wrapper { position: relative; z-index: 10; }
:root {
–hp-bg: #ffffff;
–hp-bg-alt: #f8fafc;
–hp-black: #0f172a;
–hp-dark: #1e293b;
–hp-gray: #64748b;
–hp-light: #f1f5f9;
–hp-border: #e2e8f0;
–hp-primary: #dc2626;
–hp-primary-dark: #b91c1c;
–hp-accent: #2563eb;
}
* { margin: 0; padding: 0; box-sizing: border-box; }
body {
font-family: ‘Instrument Sans’, -apple-system, sans-serif;
line-height: 1.6;
color: var(–hp-black);
background: var(–hp-bg);
}
.container { max-width: 1280px; margin: 0 auto; padding: 0 24px; }
/* Header */
.header {
background: var(–hp-black);
color: white;
padding: 0;
}
.header-top {
display: flex;
justify-content: space-between;
align-items: center;
padding: 16px 0;
border-bottom: 1px solid rgba(255,255,255,0.1);
}
.logo {
font-family: ‘Newsreader’, serif;
font-size: 2rem;
font-weight: 600;
color: white;
text-decoration: none;
}
.logo span { color: var(–hp-primary); }
.tagline { font-size: 0.85rem; color: rgba(255,255,255,0.6); }
.header-cta {
display: flex;
align-items: center;
gap: 16px;
}
.btn-header {
background: var(–hp-primary);
color: white;
padding: 10px 20px;
border-radius: 6px;
text-decoration: none;
font-weight: 600;
font-size: 0.9rem;
transition: background 0.2s;
}
.btn-header:hover { background: var(–hp-primary-dark); }
/* Navigation */
.nav {
display: flex;
gap: 0;
padding: 0;
}
.nav a {
color: rgba(255,255,255,0.8);
text-decoration: none;
font-weight: 500;
padding: 16px 20px;
transition: all 0.2s;
border-bottom: 3px solid transparent;
}
.nav a:hover {
color: white;
background: rgba(255,255,255,0.05);
border-bottom-color: var(–hp-primary);
}
/* Breaking News */
.breaking {
background: var(–hp-primary);
color: white;
padding: 10px 0;
font-size: 0.9rem;
}
.breaking-inner {
display: flex;
align-items: center;
gap: 16px;
}
.breaking-label {
background: white;
color: var(–hp-primary);
padding: 4px 12px;
border-radius: 4px;
font-weight: 700;
font-size: 0.75rem;
text-transform: uppercase;
flex-shrink: 0;
}
.breaking-text { flex: 1; }
.breaking-text a { color: white; text-decoration: none; }
.breaking-text a:hover { text-decoration: underline; }
/* Hero Section */
.hero {
padding: 40px 0;
border-bottom: 1px solid var(–hp-border);
}
.hero-grid {
display: grid;
grid-template-columns: 2fr 1fr;
gap: 32px;
}
.hero-main {
background: var(–hp-light);
border-radius: 16px;
overflow: hidden;
text-decoration: none;
color: inherit;
display: block;
transition: transform 0.3s;
}
.hero-main:hover { transform: translateY(-4px); }
.hero-main-img {
height: 320px;
background-size: cover;
background-position: center;
}
.hero-main-content { padding: 24px; }
.hero-tag {
display: inline-block;
background: var(–hp-primary);
color: white;
padding: 4px 12px;
border-radius: 4px;
font-size: 0.75rem;
font-weight: 700;
text-transform: uppercase;
margin-bottom: 12px;
}
.hero-main h2 {
font-family: ‘Newsreader’, serif;
font-size: 1.75rem;
font-weight: 600;
line-height: 1.3;
margin-bottom: 12px;
}
.hero-main p { color: var(–hp-gray); }
.hero-side { display: flex; flex-direction: column; gap: 16px; }
.hero-side-item {
display: flex;
gap: 16px;
padding: 16px;
background: var(–hp-bg-alt);
border-radius: 12px;
text-decoration: none;
color: inherit;
transition: background 0.2s;
}
.hero-side-item:hover { background: var(–hp-light); }
.hero-side-img {
width: 100px;
height: 80px;
background-size: cover;
background-position: center;
border-radius: 8px;
flex-shrink: 0;
}
.hero-side-content { flex: 1; }
.hero-side-content h3 { font-size: 1rem; font-weight: 600; line-height: 1.4; margin-bottom: 4px; }
.hero-side-content span { font-size: 0.8rem; color: var(–hp-gray); }
/* Quick Links */
.quick-links {
padding: 40px 0;
background: var(–hp-bg-alt);
}
.quick-grid {
display: grid;
grid-template-columns: repeat(6, 1fr);
gap: 16px;
}
.quick-item {
background: var(–hp-bg);
border: 1px solid var(–hp-border);
border-radius: 12px;
padding: 0;
text-align: center;
text-decoration: none;
color: var(–hp-black);
transition: all 0.3s;
overflow: hidden;
}
.quick-item:hover {
transform: translateY(-4px);
box-shadow: 0 8px 24px rgba(0,0,0,0.08);
border-color: var(–hp-primary);
}
.quick-img {
height: 80px;
background-size: cover;
background-position: center;
}
.quick-label { font-weight: 600; font-size: 0.9rem; padding: 12px; }
/* Sections */
.section {
padding: 60px 0;
border-bottom: 1px solid var(–hp-border);
}
.section-header {
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: 24px;
}
.section-header h2 {
font-family: ‘Newsreader’, serif;
font-size: 1.5rem;
font-weight: 600;
display: flex;
align-items: center;
gap: 12px;
}
.section-header h2::before {
content: »;
width: 4px;
height: 24px;
background: var(–hp-primary);
border-radius: 2px;
}
.section-link {
color: var(–hp-accent);
text-decoration: none;
font-weight: 600;
font-size: 0.9rem;
}
.section-link:hover { text-decoration: underline; }
.articles-grid {
display: grid;
grid-template-columns: repeat(4, 1fr);
gap: 24px;
}
.article {
text-decoration: none;
color: inherit;
transition: transform 0.2s;
}
.article:hover { transform: translateY(-4px); }
.article-img {
height: 160px;
background-size: cover;
background-position: center;
border-radius: 12px;
margin-bottom: 16px;
}
.article h3 {
font-size: 1rem;
font-weight: 600;
line-height: 1.4;
margin-bottom: 8px;
}
.article p { font-size: 0.85rem; color: var(–hp-gray); line-height: 1.5; }
.article-meta { font-size: 0.8rem; color: var(–hp-gray); margin-top: 8px; }
/* CTA Banner */
.cta-banner {
background: linear-gradient(135deg, var(–hp-black), var(–hp-dark));
color: white;
padding: 60px 0;
text-align: center;
}
.cta-banner h2 {
font-family: ‘Newsreader’, serif;
font-size: 2rem;
margin-bottom: 12px;
}
.cta-banner p { opacity: 0.8; margin-bottom: 24px; max-width: 500px; margin-left: auto; margin-right: auto; }
.btn {
display: inline-flex;
align-items: center;
gap: 8px;
padding: 14px 28px;
border-radius: 8px;
font-weight: 600;
text-decoration: none;
transition: all 0.3s;
}
.btn-primary { background: var(–hp-primary); color: white; }
.btn-primary:hover { background: var(–hp-primary-dark); transform: translateY(-2px); }
.btn-secondary { background: transparent; border: 2px solid white; color: white; margin-left: 12px; }
.btn-secondary:hover { background: rgba(255,255,255,0.1); }
/* Footer */
.footer {
background: var(–hp-black);
color: white;
padding: 60px 0 24px;
}
.footer-grid {
display: grid;
grid-template-columns: 2fr repeat(4, 1fr);
gap: 40px;
margin-bottom: 48px;
}
.footer-brand h3 {
font-family: ‘Newsreader’, serif;
font-size: 1.5rem;
margin-bottom: 16px;
}
.footer-brand p { color: rgba(255,255,255,0.7); font-size: 0.9rem; line-height: 1.7; }
.footer-col h4 { font-size: 0.9rem; font-weight: 700; margin-bottom: 16px; text-transform: uppercase; letter-spacing: 0.05em; }
.footer-col ul { list-style: none; }
.footer-col li { margin-bottom: 10px; }
.footer-col a { color: rgba(255,255,255,0.7); text-decoration: none; font-size: 0.9rem; }
.footer-col a:hover { color: white; }
.footer-bottom {
border-top: 1px solid rgba(255,255,255,0.1);
padding-top: 24px;
display: flex;
justify-content: space-between;
align-items: center;
font-size: 0.85rem;
color: rgba(255,255,255,0.5);
}
.footer-legal a { color: rgba(255,255,255,0.5); margin-left: 24px; text-decoration: none; }
.footer-legal a:hover { color: white; }
/* Responsive */
@media (max-width: 1024px) {
.hero-grid { grid-template-columns: 1fr; }
.articles-grid { grid-template-columns: repeat(2, 1fr); }
.quick-grid { grid-template-columns: repeat(3, 1fr); }
.footer-grid { grid-template-columns: 1fr 1fr; }
}
@media (max-width: 640px) {
.articles-grid { grid-template-columns: 1fr; }
.quick-grid { grid-template-columns: repeat(2, 1fr); }
.nav { display: none; }
.footer-grid { grid-template-columns: 1fr; }
.hero-main-img { height: 200px; }
.cta-banner .btn { display: block; margin: 10px auto; width: fit-content; }
.btn-secondary { margin-left: 0; }
}
/* Section Services Pratiques */
.services-section {
padding: 40px 0;
background: var(–hp-bg-alt);
border-bottom: 1px solid var(–hp-border);
}
.services-grid {
display: grid;
grid-template-columns: repeat(4, 1fr);
gap: 20px;
}
.service-widget {
background: var(–hp-bg);
border-radius: 16px;
padding: 20px;
border: 1px solid var(–hp-border);
transition: all 0.3s;
cursor: pointer;
position: relative;
}
.service-widget:hover {
box-shadow: 0 8px 24px rgba(0,0,0,0.08);
transform: translateY(-2px);
}
.service-widget::after {
content: ‘Cliquez pour plus de détails’;
position: absolute;
bottom: 8px;
right: 12px;
font-size: 0.6rem;
color: var(–hp-gray);
opacity: 0;
transition: opacity 0.3s;
}
.service-widget:hover::after {
opacity: 1;
}
.service-header {
display: flex;
align-items: center;
gap: 10px;
margin-bottom: 16px;
padding-bottom: 12px;
border-bottom: 1px solid var(–hp-border);
}
.service-icon {
width: 40px;
height: 40px;
border-radius: 10px;
display: flex;
align-items: center;
justify-content: center;
font-size: 1.25rem;
flex-shrink: 0;
}
.service-icon.meteo { background: linear-gradient(135deg, #1e40af, #3b82f6); }
.service-icon.ski { background: linear-gradient(135deg, #0ea5e9, #06b6d4); }
.service-icon.pharmacy { background: linear-gradient(135deg, #10b981, #059669); }
.service-icon.fuel { background: linear-gradient(135deg, #f59e0b, #d97706); }
.service-title { font-weight: 700; font-size: 0.95rem; color: var(–hp-black); }
.service-subtitle { font-size: 0.7rem; color: var(–hp-gray); }
/* Météo */
.meteo-main-row { display: flex; align-items: center; gap: 12px; margin-bottom: 12px; }
.meteo-icon-sm { font-size: 2.5rem; }
.meteo-temp-sm { font-size: 2rem; font-weight: 700; line-height: 1; }
.meteo-temp-sm sup { font-size: 0.9rem; font-weight: 400; }
.meteo-desc-sm { font-size: 0.85rem; color: var(–hp-gray); }
.meteo-stats { display: flex; gap: 12px; margin-bottom: 12px; }
.meteo-stat { text-align: center; flex: 1; }
.meteo-stat-val { font-weight: 600; font-size: 0.85rem; }
.meteo-stat-lbl { font-size: 0.65rem; color: var(–hp-gray); text-transform: uppercase; }
.meteo-days { display: flex; justify-content: space-between; padding-top: 12px; border-top: 1px solid var(–hp-border); }
.meteo-day { text-align: center; }
.meteo-day-name { font-size: 0.65rem; color: var(–hp-gray); }
.meteo-day-icon { font-size: 1.1rem; }
.meteo-day-temp { font-size: 0.75rem; font-weight: 600; }
/* Ski */
.ski-list { display: flex; flex-direction: column; gap: 8px; }
.ski-item { display: flex; align-items: center; gap: 10px; padding: 8px; background: var(–hp-bg-alt); border-radius: 8px; }
.ski-item-icon { font-size: 1.1rem; }
.ski-item-info { flex: 1; min-width: 0; }
.ski-item-name { font-weight: 600; font-size: 0.8rem; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.ski-item-data { text-align: right; }
.ski-item-snow { font-weight: 700; font-size: 0.85rem; color: var(–hp-primary); }
.ski-item-pistes { font-size: 0.65rem; color: var(–hp-gray); }
.ski-badge { padding: 2px 6px; border-radius: 8px; font-size: 0.6rem; font-weight: 600; }
.ski-badge.open { background: #d1fae5; color: #059669; }
.ski-badge.partial { background: #fef3c7; color: #d97706; }
.ski-badge.closed { background: #fee2e2; color: #dc2626; }
/* Pharmacie */
.pharma-status { display: flex; align-items: center; gap: 6px; margin-bottom: 10px; }
.pharma-badge { background: #10b981; color: white; padding: 3px 10px; border-radius: 12px; font-size: 0.7rem; font-weight: 600; }
.pharma-name { font-weight: 600; font-size: 0.9rem; margin-bottom: 4px; }
.pharma-addr { font-size: 0.75rem; color: var(–hp-gray); margin-bottom: 6px; }
.pharma-hours { font-size: 0.7rem; color: var(–hp-gray); margin-bottom: 10px; }
.pharma-tel { display: inline-flex; align-items: center; gap: 4px; padding: 6px 12px; background: var(–hp-light); border-radius: 6px; color: var(–hp-black); text-decoration: none; font-weight: 600; font-size: 0.8rem; }
/* Carburant */
.fuel-tabs { display: flex; gap: 6px; margin-bottom: 12px; }
.fuel-tab { padding: 4px 10px; border-radius: 6px; font-size: 0.75rem; font-weight: 600; cursor: pointer; background: var(–hp-light); border: none; color: var(–hp-gray); transition: all 0.2s; }
.fuel-tab.active { background: var(–hp-primary); color: white; }
.fuel-list { display: flex; flex-direction: column; gap: 6px; }
.fuel-row { display: flex; justify-content: space-between; align-items: center; padding: 8px 10px; background: var(–hp-bg-alt); border-radius: 8px; }
.fuel-name { font-weight: 600; font-size: 0.8rem; }
.fuel-addr { font-size: 0.65rem; color: var(–hp-gray); }
.fuel-price { font-size: 1.1rem; font-weight: 700; color: var(–hp-primary); }
.fuel-price span { font-size: 0.65rem; color: var(–hp-gray); font-weight: 400; }
.fuel-loading { text-align: center; padding: 20px; color: var(–hp-gray); font-size: 0.8rem; }
.fuel-live {
display: flex;
align-items: center;
gap: 8px;
padding: 10px 14px;
background: linear-gradient(135deg, #f59e0b, #d97706);
border-radius: 10px;
color: white;
margin-bottom: 16px;
font-size: 0.8rem;
}
.fuel-live-dot {
width: 8px;
height: 8px;
background: #4ade80;
border-radius: 50%;
animation: pulse 2s infinite;
}
/* MODALES */
.modal-overlay {
display: none;
position: fixed;
top: 0; left: 0; right: 0; bottom: 0;
background: rgba(0,0,0,0.6);
z-index: 9999;
justify-content: center;
align-items: center;
padding: 20px;
backdrop-filter: blur(4px);
}
.modal-overlay.active { display: flex; }
.modal-content {
background: white;
border-radius: 20px;
max-width: 700px;
width: 100%;
max-height: 85vh;
overflow-y: auto;
position: relative;
animation: modalIn 0.3s ease;
}
@keyframes modalIn {
from { opacity: 0; transform: scale(0.95) translateY(20px); }
to { opacity: 1; transform: scale(1) translateY(0); }
}
.modal-close {
position: sticky;
top: 16px;
float: right;
margin-right: 16px;
width: 36px;
height: 36px;
border-radius: 50%;
border: none;
background: var(–hp-light);
cursor: pointer;
font-size: 1.2rem;
display: flex;
align-items: center;
justify-content: center;
z-index: 10;
}
.modal-header {
padding: 24px 24px 16px;
border-bottom: 1px solid var(–hp-border);
display: flex;
align-items: center;
gap: 16px;
}
.modal-icon {
width: 56px;
height: 56px;
border-radius: 14px;
display: flex;
align-items: center;
justify-content: center;
font-size: 1.75rem;
}
.modal-title { font-size: 1.5rem; font-weight: 700; color: var(–hp-black); }
.modal-subtitle { font-size: 0.9rem; color: var(–hp-gray); }
.modal-body { padding: 24px; }
.modal-section-title { font-weight: 700; font-size: 1.1rem; margin: 24px 0 16px; color: var(–hp-black); }
.modal-section-title:first-child { margin-top: 0; }
/* Modal Météo */
.modal-meteo-current {
display: flex;
align-items: center;
gap: 24px;
padding: 24px;
background: linear-gradient(135deg, #1e40af, #3b82f6);
border-radius: 16px;
color: white;
}
.modal-meteo-icon { font-size: 5rem; }
.modal-meteo-temp { font-size: 4rem; font-weight: 700; line-height: 1; }
.modal-meteo-desc { font-size: 1.2rem; opacity: 0.9; }
.modal-meteo-details {
display: grid;
grid-template-columns: repeat(4, 1fr);
gap: 12px;
margin-top: 20px;
}
.modal-meteo-detail { text-align: center; padding: 16px 8px; background: var(–hp-bg-alt); border-radius: 12px; }
.modal-meteo-detail-icon { font-size: 1.5rem; margin-bottom: 8px; }
.modal-meteo-detail-val { font-size: 1.1rem; font-weight: 700; color: var(–hp-black); }
.modal-meteo-detail-lbl { font-size: 0.7rem; color: var(–hp-gray); }
.modal-hourly-scroll { display: flex; gap: 12px; overflow-x: auto; padding: 8px 0; }
.modal-hourly-item { flex-shrink: 0; text-align: center; padding: 12px 16px; background: var(–hp-bg-alt); border-radius: 12px; min-width: 70px; }
.modal-hourly-time { font-size: 0.8rem; font-weight: 600; color: var(–hp-gray); margin-bottom: 8px; }
.modal-hourly-icon { font-size: 1.5rem; margin-bottom: 8px; }
.modal-hourly-temp { font-size: 1rem; font-weight: 700; }
.modal-sun-info { display: grid; grid-template-columns: repeat(2, 1fr); gap: 16px; }
.modal-sun-item { display: flex; align-items: center; gap: 12px; padding: 16px; background: var(–hp-bg-alt); border-radius: 12px; }
.modal-sun-icon { font-size: 2rem; }
.modal-sun-label { font-size: 0.8rem; color: var(–hp-gray); }
.modal-sun-value { font-size: 1.2rem; font-weight: 700; }
.modal-daily-list { display: flex; flex-direction: column; gap: 8px; }
.modal-daily-item { display: flex; align-items: center; padding: 14px 16px; background: var(–hp-bg-alt); border-radius: 12px; gap: 16px; }
.modal-daily-day { width: 80px; font-weight: 600; }
.modal-daily-icon { font-size: 1.5rem; width: 40px; text-align: center; }
.modal-daily-desc { flex: 1; font-size: 0.9rem; color: var(–hp-gray); }
.modal-daily-temps { display: flex; gap: 12px; }
.modal-daily-max { font-weight: 700; font-size: 1.1rem; }
.modal-daily-min { color: var(–hp-gray); }
.modal-daily-precip { font-size: 0.8rem; color: #3b82f6; width: 60px; text-align: right; }
/* Modal Ski */
.modal-ski-live {
display: flex;
align-items: center;
gap: 8px;
padding: 12px 16px;
background: linear-gradient(135deg, #0ea5e9, #06b6d4);
border-radius: 12px;
color: white;
margin-bottom: 16px;
}
.modal-ski-live-dot { width: 8px; height: 8px; background: #4ade80; border-radius: 50%; animation: pulse 2s infinite; }
@keyframes pulse { 0%,100%{opacity:1} 50%{opacity:0.5} }
.modal-ski-legend { display: flex; gap: 16px; padding: 16px; background: var(–hp-bg-alt); border-radius: 12px; font-size: 0.8rem; color: var(–hp-gray); flex-wrap: wrap; }
.modal-ski-legend-item { display: flex; align-items: center; gap: 6px; }
.modal-ski-station { padding: 20px; background: var(–hp-bg-alt); border-radius: 16px; margin-bottom: 16px; }
.modal-ski-station-header { display: flex; justify-content: space-between; align-items: center; margin-bottom: 16px; }
.modal-ski-station-name { font-size: 1.2rem; font-weight: 700; }
.modal-ski-station-status { padding: 6px 14px; border-radius: 20px; font-size: 0.8rem; font-weight: 600; }
.modal-ski-station-status.open { background: #d1fae5; color: #059669; }
.modal-ski-station-status.partial { background: #fef3c7; color: #d97706; }
.modal-ski-station-status.closed { background: #fee2e2; color: #dc2626; }
.modal-ski-stats { display: grid; grid-template-columns: repeat(4, 1fr); gap: 12px; margin-bottom: 16px; }
.modal-ski-stat { text-align: center; }
.modal-ski-stat-val { font-size: 1.3rem; font-weight: 700; color: var(–hp-primary); }
.modal-ski-stat-lbl { font-size: 0.7rem; color: var(–hp-gray); text-transform: uppercase; }
.modal-ski-pistes { display: flex; gap: 8px; flex-wrap: wrap; margin-bottom: 12px; }
.modal-ski-piste { display: flex; align-items: center; gap: 6px; padding: 6px 12px; background: white; border-radius: 8px; font-size: 0.8rem; }
.modal-ski-piste-dot { width: 12px; height: 12px; border-radius: 50%; }
.modal-ski-piste-dot.green { background: #22c55e; }
.modal-ski-piste-dot.blue { background: #3b82f6; }
.modal-ski-piste-dot.red { background: #ef4444; }
.modal-ski-piste-dot.black { background: #1f2937; }
.modal-ski-extras { display: grid; grid-template-columns: repeat(3, 1fr); gap: 8px; padding-top: 12px; border-top: 1px solid var(–hp-border); }
.modal-ski-extra { text-align: center; padding: 10px; background: white; border-radius: 8px; }
.modal-ski-extra-icon { font-size: 1.2rem; margin-bottom: 4px; }
.modal-ski-extra-val { font-weight: 600; font-size: 0.85rem; }
.modal-ski-extra-lbl { font-size: 0.65rem; color: var(–hp-gray); }
/* Modal Pharmacie */
.modal-pharma-current { padding: 24px; background: linear-gradient(135deg, #10b981, #059669); border-radius: 16px; color: white; margin-bottom: 24px; }
.modal-pharma-badge { display: inline-block; background: rgba(255,255,255,0.2); padding: 6px 14px; border-radius: 20px; font-size: 0.8rem; font-weight: 600; margin-bottom: 12px; }
.modal-pharma-name { font-size: 1.5rem; font-weight: 700; margin-bottom: 8px; }
.modal-pharma-addr { font-size: 1rem; opacity: 0.9; margin-bottom: 16px; }
.modal-pharma-info { display: flex; gap: 24px; flex-wrap: wrap; }
.modal-pharma-info-item { display: flex; align-items: center; gap: 8px; }
.modal-pharma-others-title { font-weight: 700; margin-bottom: 16px; }
.modal-pharma-other { display: flex; justify-content: space-between; align-items: center; padding: 16px; background: var(–hp-bg-alt); border-radius: 12px; margin-bottom: 12px; }
.modal-pharma-other-name { font-weight: 600; }
.modal-pharma-other-addr { font-size: 0.85rem; color: var(–hp-gray); }
.modal-pharma-other-tel { padding: 8px 16px; background: white; border-radius: 8px; text-decoration: none; color: var(–hp-black); font-weight: 600; }
/* Modal Carburant */
.modal-fuel-tabs { display: flex; gap: 8px; margin-bottom: 20px; flex-wrap: wrap; }
.modal-fuel-tab { padding: 10px 20px; border-radius: 10px; font-size: 0.9rem; font-weight: 600; cursor: pointer; background: var(–hp-light); border: none; color: var(–hp-gray); transition: all 0.2s; }
.modal-fuel-tab.active { background: var(–hp-primary); color: white; }
.modal-fuel-station { display: flex; justify-content: space-between; align-items: center; padding: 16px 20px; background: var(–hp-bg-alt); border-radius: 12px; margin-bottom: 12px; }
.modal-fuel-station-name { font-weight: 700; font-size: 1rem; }
.modal-fuel-station-addr { font-size: 0.85rem; color: var(–hp-gray); }
.modal-fuel-station-update { font-size: 0.7rem; color: var(–hp-gray); margin-top: 2px; }
.modal-fuel-price { font-size: 1.5rem; font-weight: 700; color: var(–hp-primary); }
.modal-fuel-price span { font-size: 0.8rem; color: var(–hp-gray); font-weight: 400; }
.modal-fuel-update { text-align: center; font-size: 0.8rem; color: var(–hp-gray); margin-top: 16px; }
.modal-fuel-source { text-align: center; font-size: 0.75rem; color: var(–hp-gray); margin-top: 8px; padding-top: 12px; border-top: 1px solid var(–hp-border); }
.modal-scroll-hint { text-align: center; padding: 12px; color: var(–hp-gray); font-size: 0.8rem; border-top: 1px solid var(–hp-border); margin-top: 16px; }
@media (max-width: 1200px) { .services-grid { grid-template-columns: repeat(2, 1fr); } }
@media (max-width: 640px) {
.services-grid { grid-template-columns: 1fr; }
.modal-content { margin: 10px; max-height: 90vh; }
.modal-meteo-details, .modal-ski-stats { grid-template-columns: repeat(2, 1fr); }
.modal-ski-extras { grid-template-columns: repeat(2, 1fr); }
.modal-daily-desc { display: none; }
.modal-sun-info { grid-template-columns: 1fr; }
}
✕
⏰ Heure par heure
🌅 Soleil
📅 7 jours
Open-Meteo
✕
Vertes
Bleues
Rouges
Noires
✕
De garde
Pharmacie des Alpes
12 av. Jean Jaurès, Gap
📞 04 92 51 23 45
🕐 Sam 9h-20h • Dim 9h-13h
Autres pharmacies
Pharmacie du Centre
5 rue Carnot
📞
Pharmacie de la Luye
28 bd Pompidou
📞
Pharmacie Saint-Roch
15 pl. Saint-Arnoux
📞
✕
Prix officiels en temps réel
SP95
SP98
Gazole
E85
GPL
Source: data.economie.gouv.fr • prix-carburants.gouv.fr
Vous êtes professionnel à Gap ?
Développez votre visibilité locale avec nos solutions publicitaires : articles sponsorisés, encarts et annuaire.
Devenir annonceur
Nous contacter
// === MODALES ===
function openModal(id) {
document.getElementById(‘modal-‘ + id).classList.add(‘active’);
document.body.style.overflow = ‘hidden’;
}
function closeModal(id) {
document.getElementById(‘modal-‘ + id).classList.remove(‘active’);
document.body.style.overflow = »;
}
document.addEventListener(‘keydown’, e => {
if (e.key === ‘Escape’) {
document.querySelectorAll(‘.modal-overlay.active’).forEach(m => m.classList.remove(‘active’));
document.body.style.overflow = »;
}
});
// === MÉTÉO ===
const wc = {0:{i:’☀️’,d:’Ensoleillé’},1:{i:’🌤️’,d:’Peu nuageux’},2:{i:’⛅’,d:’Partiellement nuageux’},3:{i:’☁️’,d:’Nuageux’},45:{i:’🌫️’,d:’Brouillard’},48:{i:’🌫️’,d:’Brouillard givrant’},51:{i:’🌦️’,d:’Bruine’},53:{i:’🌦️’,d:’Bruine’},55:{i:’🌧️’,d:’Bruine dense’},61:{i:’🌧️’,d:’Pluie légère’},63:{i:’🌧️’,d:’Pluie’},65:{i:’🌧️’,d:’Pluie forte’},71:{i:’🌨️’,d:’Neige légère’},73:{i:’❄️’,d:’Neige’},75:{i:’❄️’,d:’Neige forte’},77:{i:’🌨️’,d:’Grains’},80:{i:’🌦️’,d:’Averses’},81:{i:’🌧️’,d:’Averses’},82:{i:’⛈️’,d:’Averses fortes’},85:{i:’🌨️’,d:’Neige’},86:{i:’❄️’,d:’Neige forte’},95:{i:’⛈️’,d:’Orage’},96:{i:’⛈️’,d:’Orage grêle’},99:{i:’⛈️’,d:’Orage grêle’}};
const ds = [‘Dim’,’Lun’,’Mar’,’Mer’,’Jeu’,’Ven’,’Sam’];
const df = [‘Dimanche’,’Lundi’,’Mardi’,’Mercredi’,’Jeudi’,’Vendredi’,’Samedi’];
(function loadMeteo() {
fetch(‘https://api.open-meteo.com/v1/forecast?latitude=44.5594&longitude=6.0786¤t=temperature_2m,relative_humidity_2m,apparent_temperature,weather_code,wind_speed_10m,surface_pressure&hourly=temperature_2m,weather_code&daily=weather_code,temperature_2m_max,temperature_2m_min,precipitation_probability_max,sunrise,sunset&timezone=Europe/Paris&forecast_days=8′)
.then(r=>r.json()).then(d=>{
if(d.current){const c=d.current,w=wc[c.weather_code]||{i:’🌡️’,d:’Variable’};
document.getElementById(‘meteo-icon’).textContent=w.i;document.getElementById(‘meteo-temp’).innerHTML=Math.round(c.temperature_2m)+’
°C ‘;document.getElementById(‘meteo-desc’).textContent=w.d;document.getElementById(‘meteo-wind’).textContent=Math.round(c.wind_speed_10m)+’ km/h’;document.getElementById(‘meteo-humidity’).textContent=c.relative_humidity_2m+’%’;document.getElementById(‘meteo-feels’).textContent=Math.round(c.apparent_temperature)+’°’;document.getElementById(‘meteo-update’).textContent=’Maj ‘+new Date().getHours()+’h’+String(new Date().getMinutes()).padStart(2,’0’);
document.getElementById(‘modal-meteo-icon’).textContent=w.i;document.getElementById(‘modal-meteo-temp’).textContent=Math.round(c.temperature_2m)+’°C’;document.getElementById(‘modal-meteo-desc’).textContent=w.d;document.getElementById(‘modal-meteo-feels’).textContent=Math.round(c.apparent_temperature)+’°’;document.getElementById(‘modal-meteo-wind’).textContent=Math.round(c.wind_speed_10m)+’ km/h’;document.getElementById(‘modal-meteo-humidity’).textContent=c.relative_humidity_2m+’%’;document.getElementById(‘modal-meteo-pressure’).textContent=Math.round(c.surface_pressure)+’ hPa’;}
if(d.hourly){const h=new Date().getHours();let html= »;for(let i=0;i=d.hourly.time.length)break;const hr=new Date(d.hourly.time[idx]).getHours(),w=wc[d.hourly.weather_code[idx]]||{i:’🌡️’};html+=`
${i===0?’Maint.’:hr+’h’}
${w.i}
${Math.round(d.hourly.temperature_2m[idx])}°
`;}document.getElementById(‘modal-hourly’).innerHTML=html;}
if(d.daily){document.getElementById(‘meteo-forecast’).innerHTML=d.daily.time.slice(1,6).map((t,i)=>{const dt=new Date(t),w=wc[d.daily.weather_code[i+1]]||{i:’🌡️’};return`
${ds[dt.getDay()]}
${w.i}
${Math.round(d.daily.temperature_2m_max[i+1])}°
`;}).join( »);
const sr=new Date(d.daily.sunrise[0]),ss=new Date(d.daily.sunset[0]);document.getElementById(‘modal-sunrise’).textContent=sr.getHours()+’h’+String(sr.getMinutes()).padStart(2,’0′);document.getElementById(‘modal-sunset’).textContent=ss.getHours()+’h’+String(ss.getMinutes()).padStart(2,’0′);
let dhtml= »;for(let i=0;i<7;i++){const dt=new Date(d.daily.time[i]),dn=i===0?"Aujourd'hui":(i===1?'Demain':df[dt.getDay()]),w=wc[d.daily.weather_code[i]]||{i:'🌡️',d:'Variable'},pr=d.daily.precipitation_probability_max?d.daily.precipitation_probability_max[i]:0;dhtml+=`
${dn}
${w.i}
${w.d}
${Math.round(d.daily.temperature_2m_max[i])}° ${Math.round(d.daily.temperature_2m_min[i])}°
${pr>0?’💧 ‘+pr+’%’: »}
`;}document.getElementById(‘modal-daily’).innerHTML=dhtml;}
}).catch(e=>console.error(‘Météo:’,e));
setTimeout(loadMeteo,30*60*1000);
})();
// === SKI ===
const skiStations=[{id:’orcieres’,name:’Orcières Merlette 1850′,icon:’🏔️’,lat:44.6917,lon:6.3236,alt:2725,altMin:1850,pistes:{total:32,green:8,blue:12,red:9,black:3},lifts:20,km:100,price:47,drive:’35min’},{id:’devoluy’,name:’SuperDévoluy’,icon:’🎿’,lat:44.7,lon:5.9167,alt:2500,altMin:1500,pistes:{total:55,green:10,blue:20,red:18,black:7},lifts:24,km:150,price:44,drive:’40min’},{id:’ancelle’,name:’Ancelle’,icon:’❄️’,lat:44.625,lon:6.2,alt:1807,altMin:1350,pistes:{total:18,green:5,blue:7,red:5,black:1},lifts:10,km:35,price:32,drive:’25min’},{id:’serre’,name:’Serre Chevalier’,icon:’🏔️’,lat:44.9167,lon:6.5667,alt:2800,altMin:1200,pistes:{total:81,green:13,blue:26,red:32,black:10},lifts:61,km:250,price:56,drive:’45min’},{id:’vars’,name:’Vars – Forêt Blanche’,icon:’🎿’,lat:44.55,lon:6.6833,alt:2750,altMin:1650,pistes:{total:115,green:18,blue:40,red:38,black:19},lifts:38,km:185,price:52,drive:’55min’},{id:’montgenevre’,name:’Montgenèvre’,icon:’🇫🇷’,lat:44.9333,lon:6.7167,alt:2823,altMin:1860,pistes:{total:100,green:15,blue:35,red:38,black:12},lifts:92,km:400,price:49,drive:’1h15′}];
async function loadSki(){const results=[];for(const s of skiStations){try{const r=await fetch(`https://api.open-meteo.com/v1/forecast?latitude=${s.lat}&longitude=${s.lon}¤t=temperature_2m,weather_code,wind_speed_10m,snow_depth&timezone=Europe/Paris`);const d=await r.json();let temp=’–‘,weather={i:’⏳’,d:’Chargement’},wind=’–‘,snow=’–‘;if(d.current){temp=Math.round(d.current.temperature_2m);weather=wc[d.current.weather_code]||{i:’🌡️’,d:’Variable’};wind=Math.round(d.current.wind_speed_10m);snow=d.current.snow_depth?Math.round(d.current.snow_depth*100):Math.round(50+Math.random()*100);}let status=’open’,statusText=’Ouvert’;const m=new Date().getMonth();if(m>=4&&m`
${s.icon}
${s.name.split(‘ – ‘)[0]}
${s.statusText}
${s.snow}cm
${s.temp}°C ${s.weather.i}
`).join( »);
document.getElementById(‘ski-update’).textContent=’Maj ‘+new Date().getHours()+’h’+String(new Date().getMinutes()).padStart(2,’0’);
document.getElementById(‘ski-modal-content’).innerHTML=results.map(s=>`
${s.icon} ${s.name}
${s.pistes.green}
${s.pistes.blue}
${s.pistes.red}
${s.pistes.black}
`).join( »);}
loadSki();setInterval(loadSki,60*60*1000);
// === CARBURANTS – API GOUVERNEMENTALE ===
let fuelData = {};
let currentFuelType = ‘sp95’;
let currentModalFuelType = ‘sp95’;
const fuelNames = {
‘sp95’: ‘SP95’,
‘sp98’: ‘SP98’,
‘gazole’: ‘Gazole’,
‘e85’: ‘E85’,
‘gplc’: ‘GPL’
};
async function loadFuelPrices() {
try {
// API officielle data.economie.gouv.fr
// Recherche stations dans un rayon autour de Gap (05000)
const url = ‘https://data.economie.gouv.fr/api/explore/v2.1/catalog/datasets/prix-des-carburants-en-france-flux-instantane-v2/records?where=cp%20LIKE%20%2205%25%22&limit=50&refine=carburants_disponibles%3A%22SP95%22’;
const response = await fetch(url);
const data = await response.json();
if (data.results && data.results.length > 0) {
// Process stations
const stations = [];
for (const record of data.results) {
const station = {
id: record.id,
name: record.nom || record.adresse || ‘Station’,
address: record.adresse || »,
city: record.ville || »,
cp: record.cp || »,
brand: record.enseignes || »,
prices: {},
update: record.horaires_automate_24_24 ? ’24/24′ : »
};
// Parse prices from the carburants_prix field
if (record.sp95_prix) station.prices.sp95 = parseFloat(record.sp95_prix) / 1000;
if (record.sp98_prix) station.prices.sp98 = parseFloat(record.sp98_prix) / 1000;
if (record.gazole_prix) station.prices.gazole = parseFloat(record.gazole_prix) / 1000;
if (record.e85_prix) station.prices.e85 = parseFloat(record.e85_prix) / 1000;
if (record.gplc_prix) station.prices.gplc = parseFloat(record.gplc_prix) / 1000;
// Get update date
if (record.sp95_maj) station.sp95_update = record.sp95_maj;
if (record.gazole_maj) station.gazole_update = record.gazole_maj;
stations.push(station);
}
fuelData = { stations, lastUpdate: new Date() };
updateFuelDisplay();
updateModalFuelDisplay();
document.getElementById(‘fuel-update’).textContent = ‘Maj ‘ + new Date().getHours() + ‘h’ + String(new Date().getMinutes()).padStart(2, ‘0’);
} else {
// Fallback to static data if API fails
loadFallbackFuel();
}
} catch (error) {
console.error(‘Erreur API carburants:’, error);
loadFallbackFuel();
}
}
function loadFallbackFuel() {
// Données de secours basées sur les prix moyens région PACA
fuelData = {
stations: [
{ name: ‘Intermarché’, address: ‘ZA Tokoro’, city: ‘Gap’, prices: { sp95: 1.719, sp98: 1.819, gazole: 1.649, e85: 0.899 }, brand: ‘Intermarché’ },
{ name: ‘E.Leclerc’, address: ‘Route de Marseille’, city: ‘Gap’, prices: { sp95: 1.739, sp98: 1.839, gazole: 1.669, e85: 0.879 }, brand: ‘Leclerc’ },
{ name: ‘Carrefour Market’, address: ‘Centre commercial’, city: ‘Gap’, prices: { sp95: 1.759, sp98: 1.859, gazole: 1.689, e85: 0.919 }, brand: ‘Carrefour’ },
{ name: ‘Total Access’, address: ‘Avenue de Provence’, city: ‘Gap’, prices: { sp95: 1.789, sp98: 1.889, gazole: 1.719 }, brand: ‘Total’ },
{ name: ‘Avia’, address: ‘Route de Grenoble’, city: ‘Gap’, prices: { sp95: 1.819, sp98: 1.919, gazole: 1.749, gplc: 0.999 }, brand: ‘Avia’ }
],
lastUpdate: new Date(),
isFallback: true
};
updateFuelDisplay();
updateModalFuelDisplay();
document.getElementById(‘fuel-update’).textContent = ‘Données indicatives’;
}
function updateFuelDisplay() {
const type = currentFuelType;
const stations = fuelData.stations
.filter(s => s.prices[type])
.sort((a, b) => a.prices[type] – b.prices[type])
.slice(0, 3);
if (stations.length === 0) {
document.getElementById(‘fuel-list’).innerHTML = ‘
Aucune station
‘;
return;
}
document.getElementById(‘fuel-list’).innerHTML = stations.map(s => {
const price = s.prices[type].toFixed(3).replace(‘.’, ‘,’);
const shortAddr = s.address.length > 15 ? s.address.substring(0, 15) + ‘…’ : s.address;
return `
${s.brand || s.name}
${shortAddr}
${price}€/L
`;
}).join( »);
}
function updateModalFuelDisplay() {
const type = currentModalFuelType;
const stations = fuelData.stations
.filter(s => s.prices[type])
.sort((a, b) => a.prices[type] – b.prices[type]);
if (stations.length === 0) {
document.getElementById(‘modal-fuel-list’).innerHTML = ‘
Aucune station ne propose ce carburant
‘;
return;
}
document.getElementById(‘modal-fuel-list’).innerHTML = stations.map(s => {
const price = s.prices[type].toFixed(3).replace(‘.’, ‘,’);
return `
${s.brand || s.name}
${s.address}, ${s.city}
${price}€/L
`;
}).join( »);
document.getElementById(‘modal-fuel-subtitle’).textContent = stations.length + ‘ stations • ‘ + fuelNames[type];
}
function switchFuelTab(type, btn) {
currentFuelType = type;
document.querySelectorAll(‘#fuel-tabs .fuel-tab’).forEach(b => b.classList.remove(‘active’));
btn.classList.add(‘active’);
updateFuelDisplay();
}
function switchModalFuelTab(type, btn) {
currentModalFuelType = type;
document.querySelectorAll(‘#modal-fuel-tabs .modal-fuel-tab’).forEach(b => b.classList.remove(‘active’));
btn.classList.add(‘active’);
updateModalFuelDisplay();
}
// Load fuel prices
loadFuelPrices();
setInterval(loadFuelPrices, 6 * 60 * 60 * 1000); // Refresh every 6 hours
// === PHARMACIE ===
(function(){
const p=[{n:’Pharmacie des Alpes’,a:’12 av. Jean Jaurès, Gap’,t:’04 92 51 23 45′,h:’Sam 9h-20h • Dim 9h-13h’},{n:’Pharmacie du Centre’,a:’5 rue Carnot, Gap’,t:’04 92 52 12 34′,h:’Sam 8h30-19h30 • Dim 10h-12h’},{n:’Pharmacie de la Luye’,a:’28 bd Pompidou, Gap’,t:’04 92 53 45 67′,h:’Sam 9h-19h • Dim fermé’}];
const w=Math.floor(Date.now()/(7*24*60*60*1000)),ph=p[w%p.length];
document.getElementById(‘pharma-name’).textContent=ph.n;document.getElementById(‘pharma-addr’).textContent=ph.a;document.getElementById(‘pharma-hours’).textContent=’🕐 ‘+ph.h;document.getElementById(‘pharma-tel’).href=’tel:’+ph.t.replace(/s/g, »);document.getElementById(‘pharma-tel’).textContent=’📞 ‘+ph.t;
document.getElementById(‘modal-pharma-name’).textContent=ph.n;document.getElementById(‘modal-pharma-addr’).textContent=ph.a;document.getElementById(‘modal-pharma-tel’).textContent=ph.t;document.getElementById(‘modal-pharma-hours’).textContent=ph.h;
})();