/* Les variables de ciel (--sky-*, --sea-*, --sun-*, etc.) sont réécrites par sky.js selon la
   position réelle du soleil en Nouvelle-Écosse. Les valeurs ci-dessous sont la nuit, par défaut. */
:root {
  --sky-top: #030814;
  --sky-mid: #07152a;
  --sky-low: #102c46;
  --sea-far: #0f3144;
  --sea-a: #091f30;
  --sea-b: #0d2a3f;
  --sea-c: #123b48;
  --stars: 1;
  --beam: 1;
  --muted: #8fa6b8;
  --sky-text: #8fa6b8;
  --lantern: #ffd98a;
  --sun: #ff7a3d;
  --sun-x: 50%; --sun-y: -20%; --sun-o: 0;
  --moon-x: 50%; --moon-y: -20%; --moon-o: 0;
  --sun-glint: 0; /* intensité du reflet du soleil sur l'eau : 0 sous l'horizon, 1 dès qu'il est un peu levé */
  /* Le même niveau de jour, sous deux formes : un nombre (1 = plein jour, 0 = nuit) et un pourcentage pour color-mix(). */
  --dayn: calc(1 - var(--beam));
  --day: calc(var(--dayn) * 100%);

  --glow: #ffd98a;
  --coral: #ff9f80;
  --cream: #fff6e6;
  --text: #e9eef3;
  --card: rgba(255, 255, 255, .07);
  --card-line: rgba(255, 255, 255, .13);
  --serif: "Fraunces", "Iowan Old Style", "Palatino Linotype", Georgia, serif;
  --sans: system-ui, -apple-system, "Segoe UI", Roboto, sans-serif;
}

* { box-sizing: border-box; margin: 0; }

html { color-scheme: dark; background: var(--sea-c); }

body {
  min-height: 100vh;
  min-height: 100dvh;
  display: flex; flex-direction: column;
  font-family: var(--sans);
  color: var(--text);
  background: var(--sea-c);
  overflow-x: hidden;
  -webkit-font-smoothing: antialiased;
  -webkit-tap-highlight-color: transparent;
}

.sr-only {
  position: absolute; width: 1px; height: 1px; overflow: hidden;
  clip-path: inset(50%); white-space: nowrap;
}

.column { width: 100%; max-width: 30rem; margin: 0 auto; padding-inline: 1.5rem; }

/* --- ciel ---------------------------------------------------------------- */

.sky {
  /* Largeur du phare, et « unité » du dessin du phare (le SVG fait 240 unités de large) : les bateaux et les
     poissons s'en servent pour se placer pile sur la ligne des vagues, quelle que soit la taille de l'écran. */
  --lh-w: min(78vw, 19rem);
  --u: calc(var(--lh-w) / 240);
  position: relative; overflow: hidden;
  background: linear-gradient(180deg, var(--sky-top) 0%, var(--sky-mid) 55%, var(--sky-low) 100%);
}
.sky-content {
  position: relative; z-index: 2;
  padding-top: max(1.5rem, env(safe-area-inset-top));
  text-align: center;
}

.stars { position: absolute; inset: 0; pointer-events: none; opacity: var(--stars); }
.stars::before, .stars::after {
  content: ""; position: absolute; top: 0; left: 0; width: 2px; height: 2px;
  border-radius: 50%; background: transparent;
  animation: twinkle 5s ease-in-out infinite;
}
.stars::before {
  box-shadow:
    8vw 6vh 0 0 #fff, 22vw 14vh 0 0 rgba(255,255,255,.7), 36vw 4vh 0 0 #fff,
    52vw 11vh 0 0 rgba(255,255,255,.6), 67vw 5vh 0 0 #fff, 81vw 15vh 0 0 rgba(255,255,255,.8),
    93vw 8vh 0 0 #fff, 14vw 24vh 0 0 rgba(255,255,255,.5), 44vw 21vh 0 0 rgba(255,255,255,.7),
    73vw 26vh 0 0 rgba(255,255,255,.6), 88vw 31vh 0 0 #fff, 4vw 37vh 0 0 rgba(255,255,255,.5);
}
.stars::after {
  animation-delay: -2.5s;
  box-shadow:
    15vw 9vh 0 0 rgba(255,255,255,.8), 29vw 19vh 0 0 #fff, 47vw 7vh 0 0 rgba(255,255,255,.6),
    60vw 18vh 0 0 #fff, 77vw 9vh 0 0 rgba(255,255,255,.7), 96vw 22vh 0 0 rgba(255,255,255,.5),
    3vw 16vh 0 0 #fff, 40vw 33vh 0 0 rgba(255,255,255,.5), 85vw 40vh 0 0 rgba(255,255,255,.6);
}
@keyframes twinkle { 0%, 100% { opacity: 1; } 50% { opacity: .35; } }

/* Soleil et lune : positionnés en % de la hauteur du ciel. Ils passent derrière le phare (z-index) et
   la mer du bas du ciel les cache en les faisant se coucher. */
.orb {
  position: absolute; z-index: 1; pointer-events: none;
  transform: translate(-50%, 50%);
}
.sun {
  left: var(--sun-x); bottom: var(--sun-y); opacity: var(--sun-o);
  width: 3.25rem; height: 3.25rem; border-radius: 50%;
  background: radial-gradient(circle, #fffdf0 0 38%, var(--sun) 100%);
  box-shadow: 0 0 60px 22px rgba(255, 200, 120, .45);
  box-shadow:
    0 0 0 .4rem color-mix(in srgb, var(--sun) 24%, transparent),
    0 0 64px 26px color-mix(in srgb, var(--sun) 45%, transparent);
}
.moon {
  left: var(--moon-x); bottom: var(--moon-y); opacity: var(--moon-o);
  width: 2.1rem; height: 2.1rem;
  filter: drop-shadow(0 0 10px rgba(255, 248, 225, .55));
}
.moon svg { display: block; width: 100%; height: 100%; }
.moon-dark { fill: rgba(205, 220, 240, .13); }
.moon-lit { fill: #f6f0de; }

.top { display: grid; gap: .65rem; justify-items: center; }

.eyebrow {
  font-size: .75rem; letter-spacing: .32em; text-transform: uppercase;
  color: var(--sky-text);
  padding-left: .32em; /* compense le letter-spacing pour centrer visuellement */
  text-shadow: 0 1px 8px rgba(0, 20, 45, .35);
}

.date-pill {
  font-size: .85rem; color: var(--cream);
  padding: .4rem .9rem; border-radius: 999px;
  background: rgba(6, 20, 36, .34); border: 1px solid rgba(255, 255, 255, .2);
  backdrop-filter: blur(6px); -webkit-backdrop-filter: blur(6px);
}

/* --- phare --------------------------------------------------------------- */

.lighthouse {
  width: var(--lh-w);
  margin: .5rem auto 0; /* aucun espace dessous : la mer du phare se raccorde à .sea */
}
.lighthouse svg { display: block; width: 100%; height: auto; overflow: visible; }

.lantern { fill: var(--lantern); }

.lamp { opacity: var(--lamp, var(--beam)); } /* --lamp : la nuit, ou le temps sombre (weather.js) qui allume un peu le phare de jour */
.beam { opacity: 0; }
.beam-r { animation: sweep 7s ease-in-out infinite; }
.beam-l { animation: sweep 7s ease-in-out infinite; animation-delay: -3.5s; }
@keyframes sweep {
  0%   { opacity: 0; }
  25%  { opacity: 1; }
  50%  { opacity: 0; }
  100% { opacity: 0; }
}
.halo { animation: pulse 3.5s ease-in-out infinite; transform-origin: 120px 62px; }
@keyframes pulse {
  0%, 100% { opacity: .75; transform: scale(1); }
  50%      { opacity: 1;   transform: scale(1.15); }
}

/* --- vagues -------------------------------------------------------------- */
/* Trois plans devant le phare (voir .waves-front dans index.html ; leurs formes viennent de waves-masks.css). Chaque plan
   est plus large que l'écran d'une vague entière de chaque côté et glisse d'exactement une vague en boucle : comme le
   motif se répète à chaque vague, on ne voit jamais la reprise. Les trois plans ont des longueurs d'onde différentes
   (96, 61 et 43 unités), des vitesses différentes et des sens opposés, d'où une houle qui ne se répète jamais vraiment,
   avec de la profondeur. Chacun tangue aussi doucement de haut en bas. */

.waves-front {
  position: absolute; left: 0; right: 0; bottom: 0; z-index: 3; pointer-events: none;
  height: calc(var(--u) * 26);
}
.wave {
  position: absolute; bottom: 0; left: calc(var(--p) * -1);
  width: calc(100% + var(--p) * 2); height: calc(var(--u) * var(--h));
  will-change: transform;
  animation: roll var(--t) linear infinite, bob var(--bob) ease-in-out infinite alternate;
  /* Mer agitée par mauvais temps : les vagues grandissent un peu avec la grisaille (le bas reste collé à la mer), et
     weather.js accélère la houle en réglant la vitesse de lecture de ces animations (sans à-coup, contrairement à un
     changement de durée). */
  transform-origin: 50% 100%;
  scale: 1 calc(1 + var(--gloom, 0) * .2);
}
.wave-far  { --p: calc(var(--u) * 96); --h: 26; --t: 46s; --bob: 7s;   --dir: 1;  }
.wave-mid  { --p: calc(var(--u) * 61); --h: 22; --t: 30s; --bob: 5.2s; --dir: -1; }
.wave-near { --p: calc(var(--u) * 43); --h: 17; --t: 19s; --bob: 4.1s; --dir: 1;  }
@keyframes roll { from { transform: translateX(0); } to { transform: translateX(calc(var(--p) * var(--dir))); } }
@keyframes bob { from { translate: 0 calc(var(--u) * .5); } to { translate: 0 calc(var(--u) * -.6); } }

.wave-body, .wave-foam {
  position: absolute; inset: 0;
  -webkit-mask-repeat: repeat-x; mask-repeat: repeat-x;
  -webkit-mask-size: var(--p) 100%; mask-size: var(--p) 100%;
}

/* Le corps de la vague : la couleur de la mer à cet éloignement (les variables du ciel, donc jour et nuit), un peu plus
   claire vers la crête. Le plan proche a EXACTEMENT la couleur du haut de .sea : sa partie basse est unie, donc la
   jonction entre le ciel et le contenu est invisible. */
.wave-far .wave-body {
  -webkit-mask-image: var(--mask-wave-far-body); mask-image: var(--mask-wave-far-body);
  background: linear-gradient(180deg, rgba(255, 255, 255, .12), rgba(255, 255, 255, 0) 55%), var(--sea-far);
}
.wave-mid .wave-body {
  -webkit-mask-image: var(--mask-wave-mid-body); mask-image: var(--mask-wave-mid-body);
  background: linear-gradient(180deg, rgba(255, 255, 255, .10), rgba(255, 255, 255, 0) 60%), var(--sea-far);
  background: linear-gradient(180deg, rgba(255, 255, 255, .10), rgba(255, 255, 255, 0) 60%), color-mix(in srgb, var(--sea-far) 45%, var(--sea-a));
}
.wave-near .wave-body {
  -webkit-mask-image: var(--mask-wave-near-body); mask-image: var(--mask-wave-near-body);
  background: linear-gradient(180deg, rgba(255, 255, 255, .08), rgba(255, 255, 255, 0) 70%), var(--sea-a);
}

/* Sous le plan proche, une bande de la même couleur : le bas d'un élément animé tombe rarement sur un pixel entier, et sa
   dernière ligne laisserait alors voir le ciel clair en dessous (une fine ligne claire à la jonction avec la mer). La bande
   déborde du ciel, qui la rogne : le bord devient invisible. */
.wave-near::after { content: ""; position: absolute; left: 0; right: 0; top: 100%; height: 4px; background: var(--sea-a); }

/* L'écume sur les crêtes : elle prend un peu la couleur de l'horizon (orangée au coucher du soleil, bleutée la nuit). */
.wave-foam { background: #fff; background: color-mix(in srgb, var(--sky-low) 50%, #fff); }
.wave-far  .wave-foam { -webkit-mask-image: var(--mask-wave-far-foam);  mask-image: var(--mask-wave-far-foam);  opacity: calc((.10 + .28 * var(--dayn)) * (1 + var(--gloom, 0) * .9)); }
.wave-mid  .wave-foam { -webkit-mask-image: var(--mask-wave-mid-foam);  mask-image: var(--mask-wave-mid-foam);  opacity: calc((.14 + .42 * var(--dayn)) * (1 + var(--gloom, 0) * .9)); }
.wave-near .wave-foam { -webkit-mask-image: var(--mask-wave-near-foam); mask-image: var(--mask-wave-near-foam); opacity: calc((.18 + .55 * var(--dayn)) * (1 + var(--gloom, 0) * .9)); } /* plus d'écume par mauvais temps */

/* Éclats de lumière qui scintillent sur l'eau : deux couches de petits traits qui s'allument et s'éteignent à des
   rythmes différents, donc jamais ensemble. Plus discrets la nuit (lumière de lune). */
.glints { position: absolute; inset: 0; opacity: calc(.16 + .72 * var(--dayn)); }
.glints i {
  position: absolute; inset: 0;
  background: #fff; background: color-mix(in srgb, #fff 85%, #9ec5ff);
  -webkit-mask-repeat: repeat-x; mask-repeat: repeat-x;
  -webkit-mask-size: calc(var(--u) * 200) calc(var(--u) * 24); mask-size: calc(var(--u) * 200) calc(var(--u) * 24);
}
.glints-a { -webkit-mask-image: var(--mask-glints-a); mask-image: var(--mask-glints-a); -webkit-mask-position: 0 100%; mask-position: 0 100%; animation: twinkle-a 3.7s ease-in-out infinite alternate; }
.glints-b { -webkit-mask-image: var(--mask-glints-b); mask-image: var(--mask-glints-b); -webkit-mask-position: calc(var(--u) * 77) 100%; mask-position: calc(var(--u) * 77) 100%; animation: twinkle-b 5.3s ease-in-out infinite alternate; }
@keyframes twinkle-a { from { opacity: .1; } to { opacity: .95; } }
@keyframes twinkle-b { from { opacity: .9; } to { opacity: .05; } }

/* Reflets du soleil, de la lune et de la lanterne du phare : ils se posent SUR la surface de l'eau, c'est-à-dire sur la
   bande de vagues devant l'horizon (jamais plus bas, dans la mer sous la surface, où ils auraient l'air d'être sous
   l'eau). Les petites barres sont créées par water.js, dans .waves-front, par-dessus les vagues. Tout est en unités
   --u, comme les vagues : chaque traînée est placée sous son astre, au même endroit que lui dans le ciel. */
.reflections { position: absolute; left: 0; right: 0; bottom: 0; height: calc(var(--u) * 22); }
.reflect { position: absolute; top: 0; bottom: 0; width: calc(var(--u) * 70); margin-left: calc(var(--u) * -35); }
.reflect-sun  { left: var(--sun-x);  opacity: var(--sun-glint); --c: color-mix(in srgb, var(--sun) 50%, #fff); }
.reflect-moon { left: var(--moon-x); opacity: calc(var(--moon-o) * .9); --c: #e9f1ff; }
.reflect-lamp { left: 50%; opacity: calc(var(--lamp, var(--beam)) * var(--lamp, var(--beam))); --c: #ffd98a; }
.reflect i {
  position: absolute; left: 50%; border-radius: 999px;
  background: linear-gradient(90deg, transparent, var(--c, #fff) 25%, var(--c, #fff) 75%, transparent);
  box-shadow: 0 0 5px var(--c, #fff); /* un léger halo : la lumière rayonne un peu autour de chaque éclat */
  animation: shimmer var(--d, 2.5s) ease-in-out infinite alternate;
}
@keyframes shimmer {
  from { transform: translateX(-50%) scaleX(.4); opacity: .3; }
  to   { transform: translateX(-50%) scaleX(1);  opacity: 1; }
}

/* --- météo : nuages, brume, précipitations, éclairs ----------------------------------------------------- */
/* weather.js lit la météo actuelle de Bridgewater et règle quelques variables (--cloud : couverture de nuages de 0 à 1 ;
   --gloom : grisaille, du ciel voilé à l'orage ; --whiteout : brume blanche de la tempête de neige). Il règle aussi la vitesse
   de lecture des animations des vagues et des nuages (le vent). sky.js grise le ciel et la mer, voile le soleil, la lune et
   les étoiles ; ce bloc dessine les nuages. Les précipitations et les éclairs sont dessinés sur un <canvas>. */

:root {
  --whiteout: 0;
  /* Couleur des nuages : éclairés (blancs de jour, teintés par l'horizon au crépuscule, bleu-gris la nuit), puis assombris
     par la grisaille. Le dessous est plus sombre que le dessus. */
  --cloud-top: #f1f4f8;
  --cloud-bot: #c9d2de;
  --cloud-lit: color-mix(in srgb, color-mix(in srgb, var(--sky-low) 28%, #fff) var(--day), color-mix(in srgb, var(--sky-low) 50%, #5b6a8c));
  --cloud-top: color-mix(in srgb, var(--cloud-lit) calc(100% - var(--gloom, 0) * 66%), #56606e);
  --cloud-bot: color-mix(in srgb, var(--cloud-top) 62%, color-mix(in srgb, var(--sky-mid) 60%, #2c3544));
}

.wx { position: absolute; inset: 0; z-index: 1; pointer-events: none; overflow: hidden; }

/* Trois plans de nuages à base plate, qui dérivent avec le vent (weather.js règle la vitesse et le sens de lecture de
   l'animation selon le vent de Bridgewater). Chaque plan apparaît à mesure
   que le ciel se couvre : les petits nuages hauts d'abord, les gros nuages bas quand il fait vraiment gris. Même principe que
   les vagues : un motif répété, plus large que l'écran d'un motif de chaque côté, qui glisse d'exactement un motif en boucle. */
.wx-cloud {
  position: absolute; left: calc(var(--cw) * -1); width: calc(100% + var(--cw) * 2);
  top: calc(var(--u) * var(--ctop)); height: calc(var(--u) * var(--ch));
  -webkit-mask-repeat: repeat-x; mask-repeat: repeat-x;
  -webkit-mask-size: var(--cw) 100%; mask-size: var(--cw) 100%;
  background: linear-gradient(180deg, var(--cloud-top), var(--cloud-bot));
  opacity: calc(clamp(0, calc((var(--cloud, 0) - var(--ca)) / var(--cb)), 1) * var(--cmax));
  will-change: transform;
  animation: cloud-drift var(--cdur) linear infinite;
}
.wx-cloud-a { --cw: calc(var(--u) * 420); --ch: 38; --ctop: 40; --ca: .04; --cb: .30; --cmax: .72; --cdur: 330s; -webkit-mask-image: var(--mask-cloud-a); mask-image: var(--mask-cloud-a); }
.wx-cloud-b { --cw: calc(var(--u) * 380); --ch: 54; --ctop: 74; --ca: .28; --cb: .32; --cmax: .88; --cdur: 250s; -webkit-mask-image: var(--mask-cloud-b); mask-image: var(--mask-cloud-b); }
.wx-cloud-c { --cw: calc(var(--u) * 560); --ch: 74; --ctop: 112; --ca: .50; --cb: .30; --cmax: .95; --cdur: 180s; -webkit-mask-image: var(--mask-cloud-c); mask-image: var(--mask-cloud-c);
  background: linear-gradient(180deg, var(--cloud-bot), color-mix(in srgb, var(--cloud-bot) 68%, #1e2530)); /* un dessous bien sombre */ }
@keyframes cloud-drift { from { transform: translateX(0); } to { transform: translateX(var(--cw)); } }

/* Quand le ciel est couvert : un plafond de nuages qui s'efface vers l'horizon. */
.wx-overcast {
  position: absolute; inset: 0;
  background: linear-gradient(180deg, var(--cloud-top), var(--cloud-bot));
  opacity: calc(clamp(0, calc((var(--cloud, 0) - .62) / .3), 1) * .8);
  /* il s'éclaircit vers l'horizon : un ciel couvert garde une bande claire au ras de l'eau */
  -webkit-mask-image: linear-gradient(180deg, #000 0%, #000 45%, rgba(0, 0, 0, .35) 80%, transparent 100%);
  mask-image: linear-gradient(180deg, #000 0%, #000 45%, rgba(0, 0, 0, .35) 80%, transparent 100%);
}

/* Tempête de neige : une brume blanche sur le ciel (derrière le texte, qui reste lisible) et le phare qui s'y estompe. */
.wx-whiteout {
  position: absolute; inset: 0; opacity: var(--whiteout, 0);
  /* blanc le jour, gris-bleu foncé la nuit (une tempête de neige de nuit n'est pas blanche) */
  background: linear-gradient(180deg, #2c3a4b, #34465a);
  background: linear-gradient(180deg,
    color-mix(in srgb, #e8eef5 var(--day), #2c3a4b),
    color-mix(in srgb, #d0dce9 var(--day), #34465a));
}
.lighthouse { opacity: calc(1 - var(--whiteout, 0) * .55); }
/* Sur la brume blanche, le texte clair du haut de page deviendrait illisible : le jour il fonce avec la brume (la nuit la
   brume est sombre, le texte reste clair). Le deuxième facteur, de 0 à 1, dit si le ciel est assez clair pour du texte foncé. */
.eyebrow {
  color: var(--sky-text);
  color: color-mix(in srgb, #1f3147 calc(clamp(0, calc(var(--whiteout, 0) * 1.3), 1) * clamp(0, calc((var(--dayn) - .3) * 3), 1) * 100%), var(--sky-text));
}
.date-pill { background: rgba(6, 20, 36, calc(.34 + var(--whiteout, 0) * .5)); }

/* Le canvas des précipitations (ajouté par weather.js, par-dessus les vagues) et l'éclair des orages. */
.wx-canvas { position: absolute; inset: 0; z-index: 4; width: 100%; height: 100%; pointer-events: none; }
.wx-flash {
  position: absolute; inset: 0; z-index: 6; pointer-events: none; opacity: 0;
  background: radial-gradient(ellipse at 50% 18%, #fff, rgba(204, 219, 255, .85));
}

/* La météo de Bridgewater, dans la carte « Chez toi » ; la source des données en dessous. */
.clock-weather { display: flex; align-items: center; justify-content: center; gap: .4rem; margin-top: .3rem; font-size: .78rem; line-height: 1.3; color: var(--cream); }
.clock-weather[hidden] { display: none; } /* `display: flex` l'emporterait sur l'attribut hidden */
.clock-weather:not([hidden]) { margin-bottom: auto; } /* absorbe l'espace libre : le badge de la carte voisine s'aligne en bas */
.clock-weather #weather-text { white-space: pre-line; text-align: left; }

/* --- mer : tout le contenu ----------------------------------------------- */

.sea {
  /* Pas d'overflow ici : il casserait le position: sticky de .underwater. Les couches qui doivent être rognées
     (.critters) le font elles-mêmes, et le débordement horizontal est coupé sur body. */
  position: relative;
  flex: 1;
  background: linear-gradient(180deg, var(--sea-a) 0%, var(--sea-b) 45%, var(--sea-c) 100%);
  text-align: center;
  padding: 1.1rem 0 0; /* le bas est géré par le fond marin (.deep) */
}

/* --- compteur ------------------------------------------------------------ */

.count { display: grid; justify-items: center; }

.count-lead {
  font-family: var(--serif); font-style: italic; font-weight: 300;
  font-size: 1.15rem; color: var(--muted);
}

.count-number {
  font-family: var(--serif);
  font-weight: 400;
  font-variation-settings: "opsz" 144;
  font-size: clamp(6.5rem, 34vw, 10.5rem);
  line-height: .95;
  font-variant-numeric: tabular-nums;
  background: linear-gradient(180deg, var(--cream) 10%, var(--glow) 55%, var(--coral) 100%);
  -webkit-background-clip: text; background-clip: text; color: transparent;
  filter: drop-shadow(0 0 28px rgba(255, 190, 110, .28));
  padding: .05em .1em;
}

.count-unit {
  font-family: var(--serif); font-weight: 400;
  font-size: 1.35rem; color: var(--cream);
  max-width: 18rem; text-wrap: balance;
}

/* --- tuiles : heures, minutes, secondes en direct ------------------------- */

.tiles {
  margin-top: 1.5rem;
  display: grid; grid-template-columns: repeat(3, 1fr); gap: .6rem;
}
.tile {
  padding: .9rem .4rem .8rem;
  border-radius: 1.1rem;
  background: var(--card); border: 1px solid var(--card-line);
  backdrop-filter: blur(6px); -webkit-backdrop-filter: blur(6px);
}
.tile-value {
  font-family: var(--serif); font-size: 1.9rem; font-weight: 400; line-height: 1.1;
  color: var(--cream);
  font-variant-numeric: tabular-nums;
}
.tile-label { margin-top: .25rem; font-size: .72rem; letter-spacing: .08em; color: var(--muted); }

/* --- progression --------------------------------------------------------- */

.progress { margin-top: 1.5rem; }

.progress-track {
  position: relative; height: .5rem; border-radius: 999px;
  background: rgba(255, 255, 255, .13);
}
.progress-fill {
  position: absolute; inset: 0 auto 0 0; width: 0;
  border-radius: inherit;
  background: linear-gradient(90deg, var(--coral), var(--glow));
  transition: width 1.4s cubic-bezier(.2, .8, .2, 1);
}
.progress-dot {
  position: absolute; top: 50%; left: 0;
  width: .95rem; height: .95rem; border-radius: 50%;
  background: var(--cream);
  box-shadow: 0 0 0 4px rgba(255, 217, 138, .22), 0 0 14px rgba(255, 217, 138, .6);
  transform: translate(-50%, -50%);
  transition: left 1.4s cubic-bezier(.2, .8, .2, 1);
}
.progress-label { margin-top: .85rem; font-size: .85rem; color: var(--muted); }

/* --- le petit mot -------------------------------------------------------- */
/* (views/petit-mot.html reprend le même style pour son aperçu : si tu modifies l'un, modifie l'autre.) */

.note-section { margin-top: 2rem; }

.mot {
  position: relative; margin: 0; padding: 1.35rem 1.3rem 1.2rem;
  border-radius: 1.1rem; text-align: center;
  background: var(--card); border: 1px solid var(--card-line);
  backdrop-filter: blur(6px); -webkit-backdrop-filter: blur(6px);
}
.mot::before { /* guillemet ouvrant décoratif */
  content: "“"; display: block; height: 1.6rem;
  font-family: var(--serif); font-size: 3.6rem; line-height: 1; color: var(--coral); opacity: .85;
}
.mot blockquote {
  margin: 0; font-family: var(--serif); font-style: italic; font-size: 1.2rem; line-height: 1.5; color: var(--cream);
  white-space: pre-line; /* garde les retours à la ligne écrits dans l'éditeur */
  overflow-wrap: anywhere; text-wrap: pretty;
}
.mot figcaption { margin-top: .9rem; font-size: .78rem; letter-spacing: .06em; color: var(--muted); }
.note-section:not([hidden]) { animation: fade-in .8s ease both; }
@keyframes fade-in { from { opacity: 0; transform: translateY(8px); } to { opacity: 1; transform: none; } }

/* --- horloges ------------------------------------------------------------ */

.clocks { margin-top: 2rem; }

.section-title {
  font-size: .75rem; font-weight: 400; letter-spacing: .32em; text-transform: uppercase;
  padding-left: .32em; margin-bottom: .8rem;
  color: var(--muted);
}

.clock-grid { display: grid; grid-template-columns: 1fr 1fr; gap: .6rem; }

.clock {
  /* Colonne : quand une carte a une ligne de météo plus longue que l'autre, le badge « Jour » reste aligné en bas. */
  display: flex; flex-direction: column; align-items: center;
  padding: .95rem .5rem .85rem;
  border-radius: 1.1rem;
  background: var(--card); border: 1px solid var(--card-line);
  backdrop-filter: blur(6px); -webkit-backdrop-filter: blur(6px);
}
.clock-place { font-size: .78rem; letter-spacing: .04em; color: var(--muted); }
.clock-time {
  margin: .35rem 0 .1rem;
  font-family: var(--serif); font-size: 1.6rem; font-weight: 400; line-height: 1.15;
  color: var(--cream); font-variant-numeric: tabular-nums;
}
.clock-date { font-size: .74rem; color: var(--muted); }
.clock-part {
  display: inline-flex; align-items: center; gap: .4rem;
  margin-top: .6rem; padding: .22rem .65rem; border-radius: 999px;
  font-size: .74rem; color: var(--cream);
  background: rgba(255, 255, 255, .08);
}

.clock-icon { width: .8rem; height: .8rem; border-radius: 50%; flex: none; }
.clock-icon[data-part="day"]  { background: #ffd98a; box-shadow: 0 0 8px 1px rgba(255, 217, 138, .75); }
.clock-icon[data-part="dawn"],
.clock-icon[data-part="dusk"] { background: #ff9f80; box-shadow: 0 0 8px 1px rgba(255, 159, 128, .7); }
.clock-icon[data-part="night"] { background: transparent; box-shadow: inset -.28rem -.04rem 0 0 #e8eef6; }

.clock-note { margin-top: .8rem; font-size: .82rem; color: var(--muted); }

.foot {
  padding-top: 2rem;
  font-size: .75rem; color: var(--muted); opacity: .85;
}
.foot span { color: var(--coral); }

/* --- le jour J ----------------------------------------------------------- */

body.is-home .tiles { display: none; }
body.is-home .count-number { animation: heartbeat 1.6s ease-in-out infinite; }
@keyframes heartbeat {
  0%, 100% { transform: scale(1); }
  14% { transform: scale(1.06); }
  28% { transform: scale(1); }
  42% { transform: scale(1.04); }
  56% { transform: scale(1); }
}

/* --- vie : oiseaux, avions, étoiles filantes, bateaux, poissons ------------- */
/* Les éléments sont créés et animés par ambient.js. Ici, seulement leur apparence : tout suit --beam (0 le jour,
   1 la nuit, déjà utilisé pour le phare), donc un bateau allume ses lumières tout seul à la tombée du jour. */

.critters {
  position: absolute; inset: 0; z-index: 1; pointer-events: none; overflow: hidden;
}
.critters-water { z-index: 0; }
.sea > .column { position: relative; z-index: 1; }

.critters > * { position: absolute; left: 0; top: 0; will-change: transform; }
.critters svg { display: block; width: 100%; height: auto; overflow: visible; }

/* oiseaux */
.bird .wings {
  fill: #2d3f55;
  fill: color-mix(in srgb, #2d3f55 var(--day), #0b121d);
  transform-box: fill-box; transform-origin: 50% 85%;
  animation: flap .55s ease-in-out infinite alternate;
}
@keyframes flap { from { transform: scaleY(1); } to { transform: scaleY(.3); } }

/* avion + traînée */
.plane-body { position: relative; }
.plane-body.flip { transform: scaleX(-1); } /* l'avion regarde à droite par défaut, la traînée est derrière lui */
.plane-fill {
  fill: #ffffff;
  fill: color-mix(in srgb, #ffffff var(--day), #7b8aa0);
}
.contrail {
  position: absolute; right: 86%; top: 47%; width: 150px; height: 2px; border-radius: 2px;
  background: linear-gradient(to left, rgba(255, 255, 255, .75), rgba(255, 255, 255, 0));
  opacity: var(--dayn);
}
.strobes { opacity: var(--beam); }
.strobe { fill: #ffffff; animation: blink 1.5s steps(1) infinite; }
.strobe.red { fill: #ff5a4d; animation-delay: -.75s; }
@keyframes blink { 0% { opacity: 1; } 12% { opacity: 0; } 100% { opacity: 0; } }

/* étoile filante : la tête est à droite, la queue s'efface vers la gauche (l'angle est donné par ambient.js) */
.meteor {
  height: 2.5px; transform-origin: 100% 50%; opacity: 0;
  background: linear-gradient(90deg, rgba(255, 255, 255, 0), rgba(255, 255, 255, .45) 65%, #fff);
  clip-path: polygon(0 50%, 100% 0, 100% 100%); /* effilée : fine à la queue, plus épaisse à la tête */
}

/* bateaux : posés sur la ligne des vagues, derrière elles (la coque est à moitié cachée) */
.boat { top: auto; bottom: calc(var(--u) * 20.5); }
.bob.flip svg { transform: scaleX(-1); }
.boat .sail    { fill: #f7f1e3; fill: color-mix(in srgb, #f7f1e3 var(--day), #3d4b5e); }
.boat .cabin   { fill: #ece6d8; fill: color-mix(in srgb, #ece6d8 var(--day), #364457); }
.boat .hull    { fill: #34495f; fill: color-mix(in srgb, #34495f var(--day), #0a121d); }
.boat .stripe  { fill: #b8453a; fill: color-mix(in srgb, #b8453a var(--day), #1b1218); }
.boat .funnel  { fill: #c4473a; fill: color-mix(in srgb, #c4473a var(--day), #1d1218); }
.boat .box     { fill: var(--c); fill: color-mix(in srgb, var(--c) var(--day), #101823); }
.boat .lights  { opacity: calc(var(--beam) * var(--beam)); }
.boat .halo    { fill: #ffe9a8; opacity: .22; }
.boat .lamp    { fill: #fff6d2; }
.boat .window  { fill: #ffd98a; }

/* poissons : nagent sous la surface (derrière le contenu), ou sautent hors de l'eau à l'horizon */
.fish svg { fill: #cfe6f5; opacity: calc(.26 + .2 * var(--dayn)); }
.fish.flip svg, .jumper.flip svg { transform: scaleX(-1); }
.fish .tail, .jumper .tail {
  transform-box: fill-box; transform-origin: 100% 50%;
  animation: tail .45s ease-in-out infinite alternate;
}
@keyframes tail { from { transform: rotate(-16deg); } to { transform: rotate(16deg); } }
.jumper svg { fill: #e9f4fa; fill: color-mix(in srgb, #e9f4fa var(--day), #a9bfd2); }
.splash {
  top: auto; bottom: calc(var(--u) * 21.2); width: 22px; height: 7px; margin-left: -11px;
  border: 1.5px solid rgba(255, 255, 255, .9); border-radius: 50%; opacity: 0;
}

/* --- fond marin : lumière, bulles, sable, coffre au trésor ----------------------- */

/* Couche collée à l'écran tant que la mer est visible : rayons de lumière venus de la surface, et bulles qui montent
   (créées par chest.js). Elle ne prend pas de place (marge négative) et reste derrière le contenu. */
.underwater {
  position: sticky; top: 0; z-index: 0; pointer-events: none; overflow: hidden;
  height: 100vh; height: 100dvh;
  margin-bottom: -100vh; margin-bottom: -100dvh;
}
.underwater::before {
  content: ""; position: absolute; inset: 0 -15% 25% -15%; /* part du haut de la couche : le fondu du masque commence là */
  background: repeating-linear-gradient(104deg, transparent 0, rgba(255, 255, 255, .5) 26px, transparent 70px);
  /* les rayons du soleil le jour, un halo discret la nuit ; ils s'éteignent à mesure qu'on descend (--depth, de 0 à 1) */
  opacity: calc((.07 + .26 * var(--dayn)) * (1 - .92 * var(--depth, 0)) * (1 - var(--cloud, 0) * .72)); /* les nuages voilent le soleil, donc ses rayons */
  /* les rayons apparaissent en douceur sous la surface (sans bord net à leur point de départ) puis s'éteignent en bas */
  -webkit-mask-image: linear-gradient(180deg, transparent 0%, #000 16%, transparent 78%);
  mask-image: linear-gradient(180deg, transparent 0%, #000 16%, transparent 78%);
  animation: rays 16s ease-in-out infinite alternate;
}
@keyframes rays { from { transform: translateX(-5%) skewX(-4deg); } to { transform: translateX(5%) skewX(4deg); } }

.bubble {
  position: absolute; bottom: -20px; border-radius: 50%; opacity: 0;
  border: 1px solid rgba(255, 255, 255, .5);
  background: radial-gradient(circle at 30% 30%, rgba(255, 255, 255, .5), rgba(255, 255, 255, .06));
  animation: bubble-rise linear infinite;
}
@keyframes bubble-rise {
  0%   { transform: translate(0, 0); opacity: 0; }
  10%  { opacity: .6; }
  100% { transform: translate(var(--sway, 0), -110vh); opacity: 0; }
}

.deep {
  --sand: #d9c493;
  --sand: color-mix(in srgb, #d9c493 var(--day), #213646);
  --sand-back: #b8a26b;
  --sand-back: color-mix(in srgb, #b8a26b var(--day), #182b3a);
  --sand-text: #4a3a1c;
  --sand-text: color-mix(in srgb, #4a3a1c var(--day), #cfe0ea);
  position: relative; z-index: 1;
  margin-top: 1rem;
  /* Beaucoup d'eau avant le fond : il faut descendre un bon moment pour trouver le coffre. */
  /* --floor : une bande de sable plat tout en bas, où Johny le lapin se promène (voir johny.css). Les dunes, le décor et
     les textes sont remontés d'autant : leur position les uns par rapport aux autres ne change pas. */
  --floor: 3.4rem;
  padding: clamp(22rem, 80vh, 38rem) 0 calc(var(--floor) + max(1.5rem, env(safe-area-inset-bottom)));
  background: linear-gradient(180deg, rgba(2, 11, 18, 0) 0%, rgba(2, 11, 18, .78) 100%); /* de plus en plus profond */
}
/* Pas de z-index ici : les éléments du coffre se superposent directement avec les couches de sable, dans l'ordre
   1 sable du fond · 2 plantes et coffre · 3 sable de devant (il recouvre leur pied) · 4 décor et trésor · 5 textes. */
.deep-inner { position: relative; }

/* pointer-events: none : la dune de devant recouvre le pied du coffre, mais les clics doivent passer au travers */
.sand, .sand-fore { position: absolute; left: 0; bottom: var(--floor); display: block; width: 100%; pointer-events: none; }
.deep::after { content: ""; position: absolute; left: 0; right: 0; bottom: 0; height: calc(var(--floor) + 1px); z-index: 3; background: var(--sand); pointer-events: none; }
.sand { z-index: 1; height: 12.5rem; }
.sand-fore { z-index: 3; height: 8rem; }
.sand-back  { fill: var(--sand-back); }
.sand-front { fill: var(--sand); }
/* rides du sable et arête éclairée des dunes : traits fins qui ne s'étirent pas avec l'écran */
.ripple, .crest { fill: none; stroke-linecap: round; vector-effect: non-scaling-stroke; }
.ripple { stroke: #a58b50; stroke: color-mix(in srgb, #a58b50 var(--day), #0e1c28); stroke-width: 1.6; opacity: .5; }
.crest  { stroke: rgba(255, 250, 225, .55); stroke-width: 1.6; opacity: calc(.15 + .4 * var(--dayn)); }

/* galets, étoile de mer, dollar des sables et coquillage posés sur le sable (jamais déformés par la largeur de l'écran) */
.sand-decor { position: absolute; left: 50%; bottom: var(--floor); z-index: 4; width: min(100%, 30rem); height: 8rem; transform: translateX(-50%); pointer-events: none; }
.pebble { fill: #b3a283; fill: color-mix(in srgb, #b3a283 var(--day), #3a4b58); }
.dollar circle { fill: #efe4cc; fill: color-mix(in srgb, #efe4cc var(--day), #4a5a66); }
.dollar path { fill: none; stroke: #bba67c; stroke-width: 1.3; stroke-linecap: round; }

.stage { position: relative; height: 17.5rem; margin-top: .5rem; }

/* algues, coraux, étoile de mer, coquillage */
.flora { position: absolute; bottom: -.15rem; z-index: 2; width: 5.6rem; height: auto; overflow: visible; }
.flora-l { left: -.6rem; }
.flora-r { right: -.6rem; }
.weed, .coral, .tube { fill: none; stroke-linecap: round; stroke-linejoin: round; }
.weed {
  stroke: #2f9b78;
  stroke: color-mix(in srgb, #2f9b78 var(--day), #123a3c);
  transform-box: fill-box; transform-origin: 50% 100%;
  animation: sway 4.6s ease-in-out infinite alternate;
}
.weed:nth-child(2) { animation-duration: 5.4s; animation-delay: -1.7s; }
.weed:nth-child(3) { animation-duration: 3.9s; animation-delay: -.8s; }
@keyframes sway { from { transform: rotate(-4.5deg); } to { transform: rotate(4.5deg); } }
.coral { stroke: #ee7f92; stroke: color-mix(in srgb, #ee7f92 var(--day), #3a2840); }
.coral-tip { fill: #ff9fae; fill: color-mix(in srgb, #ff9fae var(--day), #4a3350); }
.tube { stroke: #f0944d; stroke: color-mix(in srgb, #f0944d var(--day), #3d2a24); }
.tube-top { fill: #8a3f22; fill: color-mix(in srgb, #8a3f22 var(--day), #1f1416); }
.starfish { fill: #f08a4b; fill: color-mix(in srgb, #f08a4b var(--day), #3d2a24); }
.shell { fill: #f6e8cf; fill: color-mix(in srgb, #f6e8cf var(--day), #3a4a58); }
.shell-lines { fill: none; stroke: #cdb48a; stroke-width: 1.4; stroke-linecap: round; }
.deep:not(.in-view) .weed { animation-play-state: paused; }

/* le coffre : le couvercle s'aplatit puis se retourne derrière la caisse */
.chest {
  position: absolute; left: 50%; bottom: 0; z-index: 2; width: 9.5rem; margin-left: -4.75rem;
  padding: 0; border: 0; background: none; cursor: pointer; -webkit-tap-highlight-color: transparent;
  filter: drop-shadow(0 6px 10px rgba(0, 0, 0, .35));
  transform-origin: 50% 100%;
  transition: filter .3s;
}
.chest svg { display: block; width: 100%; height: auto; overflow: visible; }
.chest:focus-visible { outline: 2px solid var(--glow); outline-offset: 6px; border-radius: 12px; }
.chest.is-open { filter: drop-shadow(0 0 22px rgba(255, 214, 102, .7)) drop-shadow(0 6px 10px rgba(0, 0, 0, .35)); }
.deep.in-view .chest:not(.is-open) { animation: wiggle 5.5s ease-in-out infinite; } /* il frétille de temps en temps pour inviter à l'ouvrir */
@keyframes wiggle {
  0%, 84%, 100% { transform: rotate(0); }
  88% { transform: rotate(-3.5deg); }
  92% { transform: rotate(3.5deg); }
  96% { transform: rotate(-2deg); }
}

.lid-front { transform-origin: 60px 46px; transition: transform .2s ease-out .14s; }
.chest.is-open .lid-front { transform: scaleY(0); transition: transform .12s ease-in; }
.lid-back { transform-origin: 60px 42px; transform: scaleY(0); transition: transform .12s ease-in; }
.chest.is-open .lid-back { transform: scaleY(1); transition: transform .3s cubic-bezier(.3, 1.6, .5, 1) .12s; }
.interior { opacity: 0; transition: opacity .15s; }
.chest.is-open .interior { opacity: 1; transition: opacity .2s .1s; }

/* le trésor qui jaillit : un petit objet avec sa légende, ou un mot doux sur un parchemin */
.treasure {
  position: absolute; left: 50%; bottom: 8.8rem; z-index: 4; width: min(20rem, 100%);
  transform: translateX(-50%); display: flex; justify-content: center; pointer-events: none;
}
.item { display: flex; justify-content: center; }
.gem { position: relative; display: grid; justify-items: center; gap: .45rem; text-align: center; }
.gem::before {
  content: ""; position: absolute; top: -.6rem; width: 7rem; height: 7rem; border-radius: 50%;
  background: radial-gradient(circle, rgba(255, 226, 140, .55), rgba(255, 226, 140, 0) 70%);
}
.emoji {
  position: relative; font-size: 3.8rem; line-height: 1; filter: drop-shadow(0 4px 10px rgba(0, 0, 0, .35));
  font-family: "Apple Color Emoji", "Segoe UI Emoji", "Noto Color Emoji", sans-serif;
}
.caption {
  position: relative; max-width: 17rem;
  font-family: var(--serif); font-style: italic; font-size: 1.05rem; line-height: 1.3;
  color: var(--cream); text-shadow: 0 1px 8px rgba(0, 0, 0, .6); text-wrap: balance;
}
.note {
  position: relative; max-width: 17.5rem; padding: .9rem 1.15rem 1rem; border-radius: .45rem;
  transform: rotate(-1.5deg);
  background: linear-gradient(160deg, #f7ebcb, #ecd9a8); color: #5a3d1e;
  font-family: var(--serif); font-style: italic; font-size: 1.08rem; line-height: 1.35; text-wrap: balance;
  box-shadow: 0 8px 20px rgba(0, 0, 0, .4), inset 0 0 0 1px rgba(120, 80, 30, .25);
}
.note::after { /* le petit sceau de cire */
  content: "♥"; position: absolute; right: -.45rem; bottom: -.65rem; width: 1.5rem; height: 1.5rem;
  display: grid; place-items: center; border-radius: 50%;
  background: #c4473a; color: #ffe9e3; font-size: .8rem; font-style: normal;
  box-shadow: 0 2px 6px rgba(0, 0, 0, .35);
}
.spark {
  position: absolute; z-index: 5; pointer-events: none;
  color: #ffe9a8; font-size: 1rem; text-shadow: 0 0 8px rgba(255, 220, 120, .9);
}
.mini-bubble {
  position: absolute; z-index: 5; pointer-events: none; border-radius: 50%;
  border: 1px solid rgba(255, 255, 255, .6);
  background: radial-gradient(circle at 30% 30%, rgba(255, 255, 255, .6), rgba(255, 255, 255, .08));
}

/* indices pour la trouver : un filet de bulles qui monte du coffre, et des éclats dorés qui scintillent */
.trickle { position: absolute; left: 50%; bottom: 7.4rem; z-index: 1; width: 0; height: 0; pointer-events: none; }
.trickle i {
  position: absolute; left: 0; bottom: 0; border-radius: 50%; opacity: 0;
  border: 1px solid rgba(255, 255, 255, .45);
  background: radial-gradient(circle at 30% 30%, rgba(255, 255, 255, .5), rgba(255, 255, 255, .06));
  animation: trickle linear infinite;
}
@keyframes trickle {
  0%   { transform: translate(0, 0) scale(.6); opacity: 0; }
  12%  { opacity: .7; }
  100% { transform: translate(var(--sway, 0), -32rem) scale(1.15); opacity: 0; }
}
.glint {
  position: absolute; z-index: 4; width: .95rem; height: .95rem; margin-left: -.475rem; pointer-events: none;
  background: radial-gradient(circle, #fff 0 18%, #ffe48a 40%, #ffc94a 100%);
  clip-path: polygon(50% 0, 61% 39%, 100% 50%, 61% 61%, 50% 100%, 39% 61%, 0 50%, 39% 39%); /* étoile à quatre branches */
  opacity: 0; animation: glint 2.9s ease-in-out infinite;
}
@keyframes glint {
  0%, 100% { opacity: 0; transform: scale(.3) rotate(0); }
  45%      { opacity: 1; transform: scale(1) rotate(45deg); }
  70%      { opacity: 0; transform: scale(.4) rotate(90deg); }
}
.stage.is-open .glint { display: none; }
.deep:not(.in-view) .glint { animation-play-state: paused; }

.chest-hint, .chest-count { position: relative; z-index: 5; text-align: center; color: var(--sand-text); }
.chest-hint { margin-top: 1rem; min-height: 1.4em; font-family: var(--serif); font-style: italic; font-size: 1.05rem; }
.chest-count { margin-top: .35rem; font-size: .8rem; letter-spacing: .05em; opacity: .85; }
/* la source de la météo : le dernier élément de la page (après <main>), sur du sable de la même couleur que le fond marin au-dessus
   (mêmes formules que --sand et --sand-text de .deep) : on ne voit pas la jonction. margin-top: auto : si la page est plus courte
   que l'écran, il reste collé au bas de l'écran. Il est hors de .deep exprès : ce qu'on met dans .deep-inner décide de la
   hauteur du coffre par rapport aux dunes. */
.page-credit {
  margin-top: auto; padding: .45rem 1rem calc(.6rem + env(safe-area-inset-bottom, 0px)); text-align: center;
  font-size: .7rem; letter-spacing: .03em;
  background: #d9c493; color: rgba(74, 58, 28, .7);
  background: color-mix(in srgb, #d9c493 var(--day), #213646);
  color: color-mix(in srgb, color-mix(in srgb, #4a3a1c var(--day), #cfe0ea) 78%, transparent);
}
.page-credit a { color: inherit; text-decoration: underline; text-underline-offset: 2px; }

/* --- petits écrans bas (iPhone SE, paysage…) ----------------------------- */

@media (max-height: 640px) {
  .sky { --lh-w: min(56vw, 13rem); }
}

@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after { animation: none !important; transition: none !important; }
  .beam-r { opacity: .8; }
}
