refacto: Remake the interface so it is more 'vintage' looking + Adding a full calendar page
@@ -0,0 +1,50 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 527 713" role="img" aria-label="Jours complémentaires">
|
||||
<defs>
|
||||
<radialGradient id="sky" cx="50%" cy="40%" r="75%">
|
||||
<stop offset="0" stop-color="#efe3c5"/>
|
||||
<stop offset="1" stop-color="#d3bf93"/>
|
||||
</radialGradient>
|
||||
</defs>
|
||||
<rect width="527" height="713" fill="url(#sky)"/>
|
||||
<!-- laurel wreath -->
|
||||
<g fill="none" stroke="#5f6b3c" stroke-width="3" stroke-linecap="round">
|
||||
<path d="M263 640 C140 620 90 520 100 400 C108 300 150 220 210 180"/>
|
||||
<path d="M263 640 C386 620 436 520 426 400 C418 300 376 220 316 180"/>
|
||||
</g>
|
||||
<g fill="#7b8a4c" stroke="#4d5830" stroke-width="1.5">
|
||||
<g id="leaves-left">
|
||||
<ellipse cx="108" cy="560" rx="11" ry="25" transform="rotate(-35 108 560)"/>
|
||||
<ellipse cx="96" cy="500" rx="11" ry="25" transform="rotate(-18 96 500)"/>
|
||||
<ellipse cx="94" cy="440" rx="11" ry="25" transform="rotate(-6 94 440)"/>
|
||||
<ellipse cx="100" cy="380" rx="11" ry="25" transform="rotate(8 100 380)"/>
|
||||
<ellipse cx="116" cy="322" rx="11" ry="25" transform="rotate(22 116 322)"/>
|
||||
<ellipse cx="144" cy="270" rx="11" ry="25" transform="rotate(34 144 270)"/>
|
||||
<ellipse cx="184" cy="226" rx="11" ry="25" transform="rotate(46 184 226)"/>
|
||||
<ellipse cx="170" cy="580" rx="11" ry="25" transform="rotate(-60 170 580)"/>
|
||||
</g>
|
||||
<use href="#leaves-left" transform="translate(527 0) scale(-1 1)"/>
|
||||
</g>
|
||||
<!-- fasces -->
|
||||
<g transform="translate(213 130) scale(1.7 1.7)" fill="none" stroke="#3a2d1d" stroke-width="1.6" stroke-linejoin="round" stroke-linecap="round">
|
||||
<path d="M13 50 C11 26 22 10 38 9 C47 9 52 15 47 21 C44 25 48 31 47 50 Z" fill="#8e2b26"/>
|
||||
<rect x="11" y="46" width="38" height="8" rx="2" fill="#d9c9a3"/>
|
||||
<rect x="27" y="54" width="6" height="14" fill="#b9a67c"/>
|
||||
<g fill="#d9c9a3">
|
||||
<rect x="9" y="68" width="7" height="268" rx="3.5"/>
|
||||
<rect x="17" y="68" width="7" height="268" rx="3.5"/>
|
||||
<rect x="25" y="68" width="7" height="268" rx="3.5"/>
|
||||
<rect x="33" y="68" width="7" height="268" rx="3.5"/>
|
||||
<rect x="41" y="68" width="7" height="268" rx="3.5"/>
|
||||
</g>
|
||||
<g fill="#c9b684">
|
||||
<path d="M7 118 L51 98 L51 110 L7 130 Z"/>
|
||||
<path d="M7 168 L51 148 L51 160 L7 180 Z"/>
|
||||
<path d="M7 218 L51 198 L51 210 L7 230 Z"/>
|
||||
<path d="M7 268 L51 248 L51 260 L7 280 Z"/>
|
||||
</g>
|
||||
<g fill="#3a2d1d">
|
||||
<rect x="6" y="74" width="46" height="12" rx="2"/>
|
||||
<rect x="6" y="318" width="46" height="12" rx="2"/>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 2.5 KiB |
@@ -0,0 +1,29 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 60 360" fill="none" stroke="#3a2d1d" stroke-width="1.6" stroke-linejoin="round" stroke-linecap="round">
|
||||
<!-- Phrygian cap on its pike -->
|
||||
<path d="M13 50 C11 26 22 10 38 9 C47 9 52 15 47 21 C44 25 48 31 47 50 Z" fill="#8e2b26"/>
|
||||
<path d="M38 9 C41 6 45 7 46 10" stroke-width="1.2"/>
|
||||
<rect x="11" y="46" width="38" height="8" rx="2" fill="#d9c9a3"/>
|
||||
<rect x="27" y="54" width="6" height="14" fill="#b9a67c"/>
|
||||
<!-- rods -->
|
||||
<g fill="#d9c9a3">
|
||||
<rect x="9" y="68" width="7" height="268" rx="3.5"/>
|
||||
<rect x="17" y="68" width="7" height="268" rx="3.5"/>
|
||||
<rect x="25" y="68" width="7" height="268" rx="3.5"/>
|
||||
<rect x="33" y="68" width="7" height="268" rx="3.5"/>
|
||||
<rect x="41" y="68" width="7" height="268" rx="3.5"/>
|
||||
</g>
|
||||
<path d="M21 72V332M29 72V332M37 72V332M45 72V332" stroke-width="0.8" opacity=".55"/>
|
||||
<!-- spiral ribbon -->
|
||||
<g fill="#c9b684">
|
||||
<path d="M7 118 L51 98 L51 110 L7 130 Z"/>
|
||||
<path d="M7 168 L51 148 L51 160 L7 180 Z"/>
|
||||
<path d="M7 218 L51 198 L51 210 L7 230 Z"/>
|
||||
<path d="M7 268 L51 248 L51 260 L7 280 Z"/>
|
||||
</g>
|
||||
<!-- binding bands -->
|
||||
<g fill="#3a2d1d">
|
||||
<rect x="6" y="74" width="46" height="12" rx="2"/>
|
||||
<rect x="6" y="318" width="46" height="12" rx="2"/>
|
||||
</g>
|
||||
<rect x="6" y="342" width="46" height="8" rx="2" fill="#b9a67c"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 1.3 KiB |
@@ -0,0 +1,5 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 64 64">
|
||||
<circle cx="32" cy="32" r="29" fill="#8e2b26" stroke="#3a2d1d" stroke-width="3"/>
|
||||
<circle cx="32" cy="32" r="19" fill="#f3ead3"/>
|
||||
<circle cx="32" cy="32" r="9" fill="#2c4268"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 251 B |
@@ -0,0 +1,93 @@
|
||||
Google Inc.
|
||||
|
||||
This Font Software is licensed under the SIL Open Font License, Version 1.1.
|
||||
This license is copied below, and is also available with a FAQ at:
|
||||
http://scripts.sil.org/OFL
|
||||
|
||||
|
||||
-----------------------------------------------------------
|
||||
SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007
|
||||
-----------------------------------------------------------
|
||||
|
||||
PREAMBLE
|
||||
The goals of the Open Font License (OFL) are to stimulate worldwide
|
||||
development of collaborative font projects, to support the font creation
|
||||
efforts of academic and linguistic communities, and to provide a free and
|
||||
open framework in which fonts may be shared and improved in partnership
|
||||
with others.
|
||||
|
||||
The OFL allows the licensed fonts to be used, studied, modified and
|
||||
redistributed freely as long as they are not sold by themselves. The
|
||||
fonts, including any derivative works, can be bundled, embedded,
|
||||
redistributed and/or sold with any software provided that any reserved
|
||||
names are not used by derivative works. The fonts and derivatives,
|
||||
however, cannot be released under any other type of license. The
|
||||
requirement for fonts to remain under this license does not apply
|
||||
to any document created using the fonts or their derivatives.
|
||||
|
||||
DEFINITIONS
|
||||
"Font Software" refers to the set of files released by the Copyright
|
||||
Holder(s) under this license and clearly marked as such. This may
|
||||
include source files, build scripts and documentation.
|
||||
|
||||
"Reserved Font Name" refers to any names specified as such after the
|
||||
copyright statement(s).
|
||||
|
||||
"Original Version" refers to the collection of Font Software components as
|
||||
distributed by the Copyright Holder(s).
|
||||
|
||||
"Modified Version" refers to any derivative made by adding to, deleting,
|
||||
or substituting -- in part or in whole -- any of the components of the
|
||||
Original Version, by changing formats or by porting the Font Software to a
|
||||
new environment.
|
||||
|
||||
"Author" refers to any designer, engineer, programmer, technical
|
||||
writer or other person who contributed to the Font Software.
|
||||
|
||||
PERMISSION & CONDITIONS
|
||||
Permission is hereby granted, free of charge, to any person obtaining
|
||||
a copy of the Font Software, to use, study, copy, merge, embed, modify,
|
||||
redistribute, and sell modified and unmodified copies of the Font
|
||||
Software, subject to the following conditions:
|
||||
|
||||
1) Neither the Font Software nor any of its individual components,
|
||||
in Original or Modified Versions, may be sold by itself.
|
||||
|
||||
2) Original or Modified Versions of the Font Software may be bundled,
|
||||
redistributed and/or sold with any software, provided that each copy
|
||||
contains the above copyright notice and this license. These can be
|
||||
included either as stand-alone text files, human-readable headers or
|
||||
in the appropriate machine-readable metadata fields within text or
|
||||
binary files as long as those fields can be easily viewed by the user.
|
||||
|
||||
3) No Modified Version of the Font Software may use the Reserved Font
|
||||
Name(s) unless explicit written permission is granted by the corresponding
|
||||
Copyright Holder. This restriction only applies to the primary font name as
|
||||
presented to the users.
|
||||
|
||||
4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font
|
||||
Software shall not be used to promote, endorse or advertise any
|
||||
Modified Version, except to acknowledge the contribution(s) of the
|
||||
Copyright Holder(s) and the Author(s) or with their explicit written
|
||||
permission.
|
||||
|
||||
5) The Font Software, modified or unmodified, in part or in whole,
|
||||
must be distributed entirely under this license, and must not be
|
||||
distributed under any other license. The requirement for fonts to
|
||||
remain under this license does not apply to any document created
|
||||
using the Font Software.
|
||||
|
||||
TERMINATION
|
||||
This license becomes null and void if any of the above conditions are
|
||||
not met.
|
||||
|
||||
DISCLAIMER
|
||||
THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF
|
||||
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT
|
||||
OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE
|
||||
COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
||||
INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL
|
||||
DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM
|
||||
OTHER DEALINGS IN THE FONT SOFTWARE.
|
||||
@@ -0,0 +1,93 @@
|
||||
Copyright 2011 The Old Standard Project Authors (amkryukov@gmail.com) OldStandard-Italic.ttf: Copyright 2011 The Old Standard Project Authors (amkryukov@gmail.com) OldStandard-Bold.ttf: Copyright 2011 The Old Standard Project Authors (amkryukov@gmail.com)
|
||||
|
||||
This Font Software is licensed under the SIL Open Font License, Version 1.1.
|
||||
This license is copied below, and is also available with a FAQ at:
|
||||
http://scripts.sil.org/OFL
|
||||
|
||||
|
||||
-----------------------------------------------------------
|
||||
SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007
|
||||
-----------------------------------------------------------
|
||||
|
||||
PREAMBLE
|
||||
The goals of the Open Font License (OFL) are to stimulate worldwide
|
||||
development of collaborative font projects, to support the font creation
|
||||
efforts of academic and linguistic communities, and to provide a free and
|
||||
open framework in which fonts may be shared and improved in partnership
|
||||
with others.
|
||||
|
||||
The OFL allows the licensed fonts to be used, studied, modified and
|
||||
redistributed freely as long as they are not sold by themselves. The
|
||||
fonts, including any derivative works, can be bundled, embedded,
|
||||
redistributed and/or sold with any software provided that any reserved
|
||||
names are not used by derivative works. The fonts and derivatives,
|
||||
however, cannot be released under any other type of license. The
|
||||
requirement for fonts to remain under this license does not apply
|
||||
to any document created using the fonts or their derivatives.
|
||||
|
||||
DEFINITIONS
|
||||
"Font Software" refers to the set of files released by the Copyright
|
||||
Holder(s) under this license and clearly marked as such. This may
|
||||
include source files, build scripts and documentation.
|
||||
|
||||
"Reserved Font Name" refers to any names specified as such after the
|
||||
copyright statement(s).
|
||||
|
||||
"Original Version" refers to the collection of Font Software components as
|
||||
distributed by the Copyright Holder(s).
|
||||
|
||||
"Modified Version" refers to any derivative made by adding to, deleting,
|
||||
or substituting -- in part or in whole -- any of the components of the
|
||||
Original Version, by changing formats or by porting the Font Software to a
|
||||
new environment.
|
||||
|
||||
"Author" refers to any designer, engineer, programmer, technical
|
||||
writer or other person who contributed to the Font Software.
|
||||
|
||||
PERMISSION & CONDITIONS
|
||||
Permission is hereby granted, free of charge, to any person obtaining
|
||||
a copy of the Font Software, to use, study, copy, merge, embed, modify,
|
||||
redistribute, and sell modified and unmodified copies of the Font
|
||||
Software, subject to the following conditions:
|
||||
|
||||
1) Neither the Font Software nor any of its individual components,
|
||||
in Original or Modified Versions, may be sold by itself.
|
||||
|
||||
2) Original or Modified Versions of the Font Software may be bundled,
|
||||
redistributed and/or sold with any software, provided that each copy
|
||||
contains the above copyright notice and this license. These can be
|
||||
included either as stand-alone text files, human-readable headers or
|
||||
in the appropriate machine-readable metadata fields within text or
|
||||
binary files as long as those fields can be easily viewed by the user.
|
||||
|
||||
3) No Modified Version of the Font Software may use the Reserved Font
|
||||
Name(s) unless explicit written permission is granted by the corresponding
|
||||
Copyright Holder. This restriction only applies to the primary font name as
|
||||
presented to the users.
|
||||
|
||||
4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font
|
||||
Software shall not be used to promote, endorse or advertise any
|
||||
Modified Version, except to acknowledge the contribution(s) of the
|
||||
Copyright Holder(s) and the Author(s) or with their explicit written
|
||||
permission.
|
||||
|
||||
5) The Font Software, modified or unmodified, in part or in whole,
|
||||
must be distributed entirely under this license, and must not be
|
||||
distributed under any other license. The requirement for fonts to
|
||||
remain under this license does not apply to any document created
|
||||
using the Font Software.
|
||||
|
||||
TERMINATION
|
||||
This license becomes null and void if any of the above conditions are
|
||||
not met.
|
||||
|
||||
DISCLAIMER
|
||||
THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF
|
||||
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT
|
||||
OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE
|
||||
COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
||||
INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL
|
||||
DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM
|
||||
OTHER DEALINGS IN THE FONT SOFTWARE.
|
||||
|
After Width: | Height: | Size: 84 KiB |
@@ -1,9 +0,0 @@
|
||||
<svg viewBox="0 0 120 120" xmlns="http://www.w3.org/2000/svg" role="img" aria-label="Brumaire">
|
||||
<circle cx="60" cy="60" r="54" fill="#f6efe0" stroke="#8a6b45" stroke-width="2"/>
|
||||
<circle cx="62" cy="46" r="12" fill="#e9dcb8" opacity="0.8"/>
|
||||
<g fill="none" stroke="#8a9a94" stroke-width="3" stroke-linecap="round">
|
||||
<path d="M28 56 Q38 50 48 56 T68 56 T92 56"/>
|
||||
<path d="M24 68 Q34 62 44 68 T64 68 T96 68"/>
|
||||
<path d="M30 80 Q40 74 50 80 T70 80 T90 80"/>
|
||||
</g>
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 483 B |
@@ -1,9 +0,0 @@
|
||||
<svg viewBox="0 0 120 120" xmlns="http://www.w3.org/2000/svg" role="img" aria-label="Jours complémentaires">
|
||||
<circle cx="60" cy="60" r="54" fill="#f6efe0" stroke="#8a6b45" stroke-width="2"/>
|
||||
<g fill="none" stroke="#7a9a5a" stroke-width="3" stroke-linecap="round">
|
||||
<path d="M60 90 C40 84 32 66 38 46 C46 54 48 66 60 90 Z"/>
|
||||
<path d="M60 90 C80 84 88 66 82 46 C74 54 72 66 60 90 Z"/>
|
||||
</g>
|
||||
<path d="M60 26 L64 38 L76 38 L66 46 L70 58 L60 50 L50 58 L54 46 L44 38 L56 38 Z"
|
||||
fill="#e8b84b" stroke="#a97e1f" stroke-width="1.5"/>
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 554 B |
|
After Width: | Height: | Size: 80 KiB |
@@ -1,14 +0,0 @@
|
||||
<svg viewBox="0 0 120 120" xmlns="http://www.w3.org/2000/svg" role="img" aria-label="Floréal">
|
||||
<circle cx="60" cy="60" r="54" fill="#f6efe0" stroke="#8a6b45" stroke-width="2"/>
|
||||
<path d="M60 68 L60 92" stroke="#5c7a4a" stroke-width="3" stroke-linecap="round"/>
|
||||
<path d="M60 82 C52 80 48 74 50 70 C58 70 62 76 60 82 Z" fill="#7a9a5a" stroke="#4f6b3d" stroke-width="1.2"/>
|
||||
<g fill="#c76b8a" stroke="#8a3b58" stroke-width="1.2">
|
||||
<ellipse cx="60" cy="44" rx="8" ry="12"/>
|
||||
<ellipse cx="60" cy="44" rx="8" ry="12" transform="rotate(60 60 44)"/>
|
||||
<ellipse cx="60" cy="44" rx="8" ry="12" transform="rotate(120 60 44)"/>
|
||||
<ellipse cx="60" cy="44" rx="8" ry="12" transform="rotate(180 60 44)"/>
|
||||
<ellipse cx="60" cy="44" rx="8" ry="12" transform="rotate(240 60 44)"/>
|
||||
<ellipse cx="60" cy="44" rx="8" ry="12" transform="rotate(300 60 44)"/>
|
||||
</g>
|
||||
<circle cx="60" cy="44" r="6" fill="#e8b84b" stroke="#a97e1f" stroke-width="1"/>
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 956 B |
|
After Width: | Height: | Size: 78 KiB |
@@ -1,13 +0,0 @@
|
||||
<svg viewBox="0 0 120 120" xmlns="http://www.w3.org/2000/svg" role="img" aria-label="Frimaire">
|
||||
<circle cx="60" cy="60" r="54" fill="#f6efe0" stroke="#8a6b45" stroke-width="2"/>
|
||||
<g stroke="#6f8794" stroke-width="2.5" stroke-linecap="round">
|
||||
<line x1="60" y1="32" x2="60" y2="88"/>
|
||||
<line x1="32" y1="60" x2="88" y2="60"/>
|
||||
<line x1="40" y1="40" x2="80" y2="80"/>
|
||||
<line x1="40" y1="80" x2="80" y2="40"/>
|
||||
<path d="M60 32 L54 40 M60 32 L66 40"/>
|
||||
<path d="M60 88 L54 80 M60 88 L66 80"/>
|
||||
<path d="M32 60 L40 54 M32 60 L40 66"/>
|
||||
<path d="M88 60 L80 54 M88 60 L80 66"/>
|
||||
</g>
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 611 B |
|
After Width: | Height: | Size: 75 KiB |
@@ -1,8 +0,0 @@
|
||||
<svg viewBox="0 0 120 120" xmlns="http://www.w3.org/2000/svg" role="img" aria-label="Fructidor">
|
||||
<circle cx="60" cy="60" r="54" fill="#f6efe0" stroke="#8a6b45" stroke-width="2"/>
|
||||
<circle cx="50" cy="66" r="14" fill="#8a3b2b" stroke="#5c2318" stroke-width="1.5"/>
|
||||
<path d="M50 52 C48 46 52 44 54 46" fill="none" stroke="#5c7a4a" stroke-width="2" stroke-linecap="round"/>
|
||||
<path d="M52 46 C58 42 62 46 58 50 C54 50 52 48 52 46 Z" fill="#7a9a5a" stroke="#4f6b3d" stroke-width="1"/>
|
||||
<path d="M74 74 C66 74 62 66 66 58 C74 58 78 66 74 74 Z" fill="#c9973b" stroke="#8a6b28" stroke-width="1.5"/>
|
||||
<path d="M70 58 C68 52 72 50 74 52" fill="none" stroke="#5c7a4a" stroke-width="2" stroke-linecap="round"/>
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 714 B |
|
After Width: | Height: | Size: 67 KiB |
@@ -1,7 +0,0 @@
|
||||
<svg viewBox="0 0 120 120" xmlns="http://www.w3.org/2000/svg" role="img" aria-label="Germinal">
|
||||
<circle cx="60" cy="60" r="54" fill="#f6efe0" stroke="#8a6b45" stroke-width="2"/>
|
||||
<ellipse cx="60" cy="86" rx="7" ry="5" fill="#8a6b45" stroke="#5c4326" stroke-width="1.5"/>
|
||||
<path d="M60 82 C58 68 60 56 60 44" fill="none" stroke="#5c7a4a" stroke-width="3" stroke-linecap="round"/>
|
||||
<path d="M60 60 C50 56 46 48 48 40 C58 42 62 50 60 60 Z" fill="#7a9a5a" stroke="#4f6b3d" stroke-width="1.5"/>
|
||||
<path d="M60 68 C70 64 74 56 72 48 C62 50 58 58 60 68 Z" fill="#7a9a5a" stroke="#4f6b3d" stroke-width="1.5"/>
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 614 B |
|
After Width: | Height: | Size: 76 KiB |
@@ -1,16 +0,0 @@
|
||||
<svg viewBox="0 0 120 120" xmlns="http://www.w3.org/2000/svg" role="img" aria-label="Messidor">
|
||||
<circle cx="60" cy="60" r="54" fill="#f6efe0" stroke="#8a6b45" stroke-width="2"/>
|
||||
<g stroke="#c9973b" stroke-width="2.5" stroke-linecap="round" fill="none">
|
||||
<path d="M60 88 L48 42"/>
|
||||
<path d="M60 88 L54 40"/>
|
||||
<path d="M60 88 L60 38"/>
|
||||
<path d="M60 88 L66 40"/>
|
||||
<path d="M60 88 L72 42"/>
|
||||
<path d="M48 42 q-2 -6 4 -8"/>
|
||||
<path d="M72 42 q2 -6 -4 -8"/>
|
||||
<path d="M54 40 q-2 -6 4 -8"/>
|
||||
<path d="M66 40 q2 -6 -4 -8"/>
|
||||
<path d="M60 38 q0 -6 0 -8"/>
|
||||
</g>
|
||||
<path d="M46 82 Q60 74 74 82 L74 90 Q60 84 46 90 Z" fill="#8a6b45" stroke="#5c4326" stroke-width="1.2"/>
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 702 B |
|
After Width: | Height: | Size: 70 KiB |
@@ -1,14 +0,0 @@
|
||||
<svg viewBox="0 0 120 120" xmlns="http://www.w3.org/2000/svg" role="img" aria-label="Nivôse">
|
||||
<circle cx="60" cy="60" r="54" fill="#f6efe0" stroke="#8a6b45" stroke-width="2"/>
|
||||
<g stroke="#5b6b7a" stroke-width="2.5" stroke-linecap="round">
|
||||
<line x1="60" y1="28" x2="60" y2="92"/>
|
||||
<line x1="28" y1="60" x2="92" y2="60"/>
|
||||
<line x1="38" y1="38" x2="82" y2="82"/>
|
||||
<line x1="38" y1="82" x2="82" y2="38"/>
|
||||
<path d="M60 38 L54 44 M60 38 L66 44"/>
|
||||
<path d="M60 82 L54 76 M60 82 L66 76"/>
|
||||
<path d="M38 60 L44 54 M38 60 L44 66"/>
|
||||
<path d="M82 60 L76 54 M82 60 L76 66"/>
|
||||
</g>
|
||||
<circle cx="60" cy="60" r="4" fill="#5b6b7a"/>
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 659 B |
|
After Width: | Height: | Size: 72 KiB |
@@ -1,10 +0,0 @@
|
||||
<svg viewBox="0 0 120 120" xmlns="http://www.w3.org/2000/svg" role="img" aria-label="Pluviôse">
|
||||
<circle cx="60" cy="60" r="54" fill="#f6efe0" stroke="#8a6b45" stroke-width="2"/>
|
||||
<path d="M40 56 a12 12 0 0 1 4 -23.6 a15 15 0 0 1 29 -4 a13 13 0 0 1 8 26.6 Z"
|
||||
fill="#dfe6ea" stroke="#5b6b7a" stroke-width="2"/>
|
||||
<g fill="#5b7a94">
|
||||
<path d="M46 76 q3 8 0 12 q-3 -4 0 -12 Z"/>
|
||||
<path d="M60 80 q3 8 0 12 q-3 -4 0 -12 Z"/>
|
||||
<path d="M74 76 q3 8 0 12 q-3 -4 0 -12 Z"/>
|
||||
</g>
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 500 B |
|
After Width: | Height: | Size: 76 KiB |
@@ -1,15 +0,0 @@
|
||||
<svg viewBox="0 0 120 120" xmlns="http://www.w3.org/2000/svg" role="img" aria-label="Prairial">
|
||||
<circle cx="60" cy="60" r="54" fill="#f6efe0" stroke="#8a6b45" stroke-width="2"/>
|
||||
<g fill="none" stroke="#5c7a4a" stroke-width="3" stroke-linecap="round">
|
||||
<path d="M36 90 C34 74 40 64 38 50"/>
|
||||
<path d="M48 90 C48 72 54 64 50 48"/>
|
||||
<path d="M60 90 C60 70 56 60 60 44"/>
|
||||
<path d="M72 90 C72 72 66 64 70 48"/>
|
||||
<path d="M84 90 C86 74 80 64 82 50"/>
|
||||
</g>
|
||||
<g fill="#c76b8a" stroke="#8a3b58" stroke-width="1">
|
||||
<circle cx="60" cy="42" r="5"/>
|
||||
<circle cx="70" cy="46" r="4"/>
|
||||
<circle cx="50" cy="46" r="4"/>
|
||||
</g>
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 649 B |
|
After Width: | Height: | Size: 78 KiB |
@@ -1,14 +0,0 @@
|
||||
<svg viewBox="0 0 120 120" xmlns="http://www.w3.org/2000/svg" role="img" aria-label="Thermidor">
|
||||
<circle cx="60" cy="60" r="54" fill="#f6efe0" stroke="#8a6b45" stroke-width="2"/>
|
||||
<circle cx="60" cy="60" r="16" fill="#e8b84b" stroke="#b5652b" stroke-width="2"/>
|
||||
<g stroke="#b5652b" stroke-width="3" stroke-linecap="round">
|
||||
<line x1="60" y1="28" x2="60" y2="38"/>
|
||||
<line x1="60" y1="82" x2="60" y2="92"/>
|
||||
<line x1="28" y1="60" x2="38" y2="60"/>
|
||||
<line x1="82" y1="60" x2="92" y2="60"/>
|
||||
<line x1="39" y1="39" x2="46" y2="46"/>
|
||||
<line x1="74" y1="74" x2="81" y2="81"/>
|
||||
<line x1="81" y1="39" x2="74" y2="46"/>
|
||||
<line x1="46" y1="74" x2="39" y2="81"/>
|
||||
</g>
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 694 B |
|
After Width: | Height: | Size: 68 KiB |
@@ -1,16 +0,0 @@
|
||||
<svg viewBox="0 0 120 120" xmlns="http://www.w3.org/2000/svg" role="img" aria-label="Vendémiaire">
|
||||
<circle cx="60" cy="60" r="54" fill="#f6efe0" stroke="#8a6b45" stroke-width="2"/>
|
||||
<path d="M60 30 C64 36 64 42 60 46" fill="none" stroke="#5c7a4a" stroke-width="2.5" stroke-linecap="round"/>
|
||||
<path d="M60 34 C68 30 74 34 72 40 C66 42 61 39 60 34 Z" fill="#7a9a5a" stroke="#4f6b3d" stroke-width="1.5"/>
|
||||
<g fill="#7a4a6b" stroke="#452a3a" stroke-width="1.2">
|
||||
<circle cx="52" cy="56" r="6.5"/>
|
||||
<circle cx="68" cy="56" r="6.5"/>
|
||||
<circle cx="60" cy="52" r="6.5"/>
|
||||
<circle cx="46" cy="66" r="6.5"/>
|
||||
<circle cx="60" cy="64" r="6.5"/>
|
||||
<circle cx="74" cy="66" r="6.5"/>
|
||||
<circle cx="53" cy="76" r="6.5"/>
|
||||
<circle cx="67" cy="76" r="6.5"/>
|
||||
<circle cx="60" cy="86" r="6.5"/>
|
||||
</g>
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 820 B |
|
After Width: | Height: | Size: 69 KiB |
@@ -1,8 +0,0 @@
|
||||
<svg viewBox="0 0 120 120" xmlns="http://www.w3.org/2000/svg" role="img" aria-label="Ventôse">
|
||||
<circle cx="60" cy="60" r="54" fill="#f6efe0" stroke="#8a6b45" stroke-width="2"/>
|
||||
<g fill="none" stroke="#7d8a76" stroke-width="3" stroke-linecap="round">
|
||||
<path d="M26 46 C50 36 62 46 78 40"/>
|
||||
<path d="M22 62 C52 50 66 64 94 54"/>
|
||||
<path d="M30 78 C54 70 64 80 84 72"/>
|
||||
</g>
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 395 B |
@@ -0,0 +1,14 @@
|
||||
{
|
||||
"vendemiaire": ["Raisin", "Safran", "Châtaigne", "Colchique", "Cheval", "Balsamine", "Carotte", "Amaranthe", "Panais", "Cuve", "Pomme de terre", "Immortelle", "Potiron", "Réséda", "Âne", "Belle de nuit", "Citrouille", "Sarrasin", "Tournesol", "Pressoir", "Chanvre", "Pêche", "Navet", "Amaryllis", "Bœuf", "Aubergine", "Piment", "Tomate", "Orge", "Tonneau"],
|
||||
"brumaire": ["Pomme", "Céleri", "Poire", "Betterave", "Oie", "Héliotrope", "Figue", "Scorsonère", "Alisier", "Charrue", "Salsifis", "Mâcre", "Topinambour", "Endive", "Dindon", "Chervis", "Cresson", "Dentelaire", "Grenade", "Herse", "Bacchante", "Azerole", "Garance", "Orange", "Faisan", "Pistache", "Macjonc", "Coing", "Cormier", "Rouleau"],
|
||||
"frimaire": ["Raiponce", "Turneps", "Chicorée", "Nèfle", "Cochon", "Mâche", "Chou-fleur", "Miel", "Genièvre", "Pioche", "Cire", "Raifort", "Cèdre", "Sapin", "Chevreuil", "Ajonc", "Cyprès", "Lierre", "Sabine", "Hoyau", "Érable à sucre", "Bruyère", "Roseau", "Oseille", "Grillon", "Pignon", "Liège", "Truffe", "Olive", "Pelle"],
|
||||
"nivose": ["Tourbe", "Houille", "Bitume", "Soufre", "Chien", "Lave", "Terre végétale", "Fumier", "Salpêtre", "Fléau", "Granit", "Argile", "Ardoise", "Grès", "Lapin", "Silex", "Marne", "Pierre à chaux", "Marbre", "Van", "Pierre à plâtre", "Sel", "Fer", "Cuivre", "Chat", "Étain", "Plomb", "Zinc", "Mercure", "Crible"],
|
||||
"pluviose": ["Lauréole", "Mousse", "Fragon", "Perce-neige", "Taureau", "Laurier-thym", "Amadouvier", "Mézéréon", "Peuplier", "Coignée", "Ellébore", "Brocoli", "Laurier", "Avelinier", "Vache", "Buis", "Lichen", "If", "Pulmonaire", "Serpette", "Thlaspi", "Thimelé", "Chiendent", "Trainasse", "Lièvre", "Guède", "Noisetier", "Cyclamen", "Chélidoine", "Traîneau"],
|
||||
"ventose": ["Tussilage", "Cornouiller", "Violier", "Troène", "Bouc", "Asaret", "Alaterne", "Violette", "Marceau", "Bêche", "Narcisse", "Orme", "Fumeterre", "Vélar", "Chèvre", "Épinard", "Doronic", "Mouron", "Cerfeuil", "Cordeau", "Mandragore", "Persil", "Cochléaria", "Pâquerette", "Thon", "Pissenlit", "Sylve", "Capillaire", "Frêne", "Plantoir"],
|
||||
"germinal": ["Primevère", "Platane", "Asperge", "Tulipe", "Poule", "Bette", "Bouleau", "Jonquille", "Aulne", "Couvoir", "Pervenche", "Charme", "Morille", "Hêtre", "Abeille", "Laitue", "Mélèze", "Ciguë", "Radis", "Ruche", "Gainier", "Romaine", "Marronnier", "Roquette", "Pigeon", "Lilas", "Anémone", "Pensée", "Myrtille", "Greffoir"],
|
||||
"floreal": ["Rose", "Chêne", "Fougère", "Aubépine", "Rossignol", "Ancolie", "Muguet", "Champignon", "Hyacinthe", "Râteau", "Rhubarbe", "Sainfoin", "Bâton-d'or", "Chamérisier", "Ver à soie", "Consoude", "Pimprenelle", "Corbeille d'or", "Arroche", "Sarcloir", "Statice", "Fritillaire", "Bourrache", "Valériane", "Carpe", "Fusain", "Civette", "Buglosse", "Sénevé", "Houlette"],
|
||||
"prairial": ["Luzerne", "Hémérocalle", "Trèfle", "Angélique", "Canard", "Mélisse", "Fromental", "Martagon", "Serpolet", "Faux", "Fraise", "Bétoine", "Pois", "Acacia", "Caille", "Œillet", "Sureau", "Pavot", "Tilleul", "Fourche", "Barbeau", "Camomille", "Chèvrefeuille", "Caille-lait", "Tanche", "Jasmin", "Verveine", "Thym", "Pivoine", "Chariot"],
|
||||
"messidor": ["Seigle", "Avoine", "Oignon", "Véronique", "Mulet", "Romarin", "Concombre", "Échalote", "Absinthe", "Faucille", "Coriandre", "Artichaut", "Girofle", "Lavande", "Chamois", "Tabac", "Groseille", "Gesse", "Cerise", "Parc", "Menthe", "Cumin", "Haricot", "Orcanète", "Pintade", "Sauge", "Ail", "Vesce", "Blé", "Chalémie"],
|
||||
"thermidor": ["Épeautre", "Bouillon-blanc", "Melon", "Ivraie", "Bélier", "Prêle", "Armoise", "Carthame", "Mûre", "Arrosoir", "Panic", "Salicorne", "Abricot", "Basilic", "Brebis", "Guimauve", "Lin", "Amande", "Gentiane", "Écluse", "Carline", "Câprier", "Lentille", "Aunée", "Loutre", "Myrte", "Colza", "Lupin", "Coton", "Moulin"],
|
||||
"fructidor": ["Prune", "Millet", "Lycoperdon", "Escourgeon", "Saumon", "Tubéreuse", "Sucrion", "Apocyn", "Réglisse", "Échelle", "Pastèque", "Fenouil", "Épine-vinette", "Noix", "Truite", "Citron", "Cardère", "Nerprun", "Tagète", "Hotte", "Églantier", "Noisette", "Houblon", "Sorgho", "Écrevisse", "Bigarade", "Verge d'or", "Maïs", "Marron", "Panier"]
|
||||
}
|
||||
@@ -4,16 +4,15 @@
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<title data-i18n="site.title">Calendrier républicain</title>
|
||||
<link rel="icon" href="data:,">
|
||||
<link rel="preconnect" href="https://fonts.googleapis.com">
|
||||
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
|
||||
<link href="https://fonts.googleapis.com/css2?family=Fraunces:ital,opsz,wght@0,9..144,400;0,9..144,600;1,9..144,500&family=Inter:wght@400;500;600;700&display=swap" rel="stylesheet">
|
||||
<link rel="icon" type="image/svg+xml" href="assets/favicon.svg">
|
||||
<link rel="preload" href="assets/fonts/old-standard-tt-400.woff2" as="font" type="font/woff2" crossorigin>
|
||||
<link rel="preload" href="assets/fonts/im-fell-english-sc.woff2" as="font" type="font/woff2" crossorigin>
|
||||
<link rel="stylesheet" href="css/style.css">
|
||||
</head>
|
||||
<body>
|
||||
<header class="site-header">
|
||||
<a class="brand" href="#/">
|
||||
<span class="brand-mark">an</span>
|
||||
<span class="cockade" aria-hidden="true"></span>
|
||||
<span class="brand-title" data-i18n="site.title">Calendrier républicain</span>
|
||||
</a>
|
||||
<div class="header-actions">
|
||||
@@ -29,6 +28,7 @@
|
||||
|
||||
<nav id="main-nav" class="main-nav" aria-hidden="true">
|
||||
<a href="#/" class="nav-link" data-view="home" data-i18n="nav.home">Accueil</a>
|
||||
<a href="#/calendar" class="nav-link" data-view="calendar" data-i18n="nav.calendar">Le calendrier complet</a>
|
||||
<p class="nav-section-label" data-i18n="nav.about">À propos</p>
|
||||
<a href="#/about/history" class="nav-link" data-view="history" data-i18n="nav.aboutHistory">Histoire du calendrier</a>
|
||||
<a href="#/about/leap-years" class="nav-link" data-view="leap-years" data-i18n="nav.aboutLeapYears">Les années sextiles</a>
|
||||
@@ -38,32 +38,45 @@
|
||||
|
||||
<main id="app">
|
||||
<section id="view-home" class="view">
|
||||
<h1 class="today-heading">
|
||||
<span data-i18n="home.todayHeading">Nous sommes aujourd'hui le</span>
|
||||
</h1>
|
||||
<div class="tablet">
|
||||
<header class="tablet-head">
|
||||
<h1 class="today-heading" data-i18n="home.todayHeading">Nous sommes aujourd'hui le</h1>
|
||||
<div class="ornament" aria-hidden="true"></div>
|
||||
</header>
|
||||
|
||||
<div class="calendar-card">
|
||||
<div class="month-illustration">
|
||||
<img id="month-image" src="assets/months/vendemiaire.svg" alt="" width="140" height="140">
|
||||
<p id="month-period" class="month-period"></p>
|
||||
</div>
|
||||
<div class="tablet-body">
|
||||
<figure class="plate">
|
||||
<div class="plate-frame">
|
||||
<img id="month-image" src="assets/months/vendemiaire.jpg" alt="" width="527" height="713">
|
||||
</div>
|
||||
<figcaption>
|
||||
<h2 id="month-name" class="month-name">—</h2>
|
||||
<p id="month-period" class="month-period"></p>
|
||||
</figcaption>
|
||||
</figure>
|
||||
|
||||
<div class="date-display">
|
||||
<p id="decade-day" class="decade-day">—</p>
|
||||
<p id="republican-date" class="republican-date">—</p>
|
||||
<p id="republican-year" class="republican-year">—</p>
|
||||
<span id="sextile-badge" class="sextile-badge" hidden data-i18n="home.sextileBadge">Année sextile</span>
|
||||
<p class="gregorian-equivalent">
|
||||
<span data-i18n="home.gregorianEquivalent">Équivalent grégorien</span> :
|
||||
<span id="gregorian-equivalent-value">—</span>
|
||||
</p>
|
||||
</div>
|
||||
<img class="fasces" src="assets/fasces.svg" alt="" aria-hidden="true">
|
||||
|
||||
<div class="description-panel">
|
||||
<h2 id="month-name" class="month-name">—</h2>
|
||||
<p id="month-season-suffix" class="month-season-suffix"></p>
|
||||
<p id="month-etymology" class="month-etymology"></p>
|
||||
<p id="month-description" class="month-description"></p>
|
||||
<div class="decree">
|
||||
<div class="date-display">
|
||||
<p id="decade-day" class="decade-day">—</p>
|
||||
<p id="republican-date" class="republican-date">—</p>
|
||||
<p id="republican-year" class="republican-year">—</p>
|
||||
<span id="sextile-badge" class="sextile-badge" hidden data-i18n="home.sextileBadge">Année sextile</span>
|
||||
<p class="gregorian-equivalent">
|
||||
<span data-i18n="home.gregorianEquivalent">Équivalent grégorien</span> :
|
||||
<span id="gregorian-equivalent-value">—</span>
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div class="ornament" aria-hidden="true"></div>
|
||||
|
||||
<div class="description-panel">
|
||||
<p id="month-season-suffix" class="month-season-suffix"></p>
|
||||
<p id="month-etymology" class="month-etymology"></p>
|
||||
<p id="month-description" class="month-description"></p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -80,13 +93,43 @@
|
||||
</form>
|
||||
</section>
|
||||
|
||||
<section id="view-calendar" class="view" hidden>
|
||||
<div class="poster">
|
||||
<header class="poster-head">
|
||||
<h1 data-i18n="calendar.title">Calendrier de la République française</h1>
|
||||
<p class="poster-subtitle" data-i18n="calendar.subtitle">Les douze mois, les trois décades et les jours de l'année</p>
|
||||
<div class="ornament" aria-hidden="true"></div>
|
||||
</header>
|
||||
<div id="poster-grid" class="poster-grid"></div>
|
||||
<div id="poster-feasts" class="poster-feasts"></div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section id="view-about" class="view about-view" hidden>
|
||||
<h1 id="about-title">—</h1>
|
||||
<div id="about-content" class="about-content"></div>
|
||||
</section>
|
||||
</main>
|
||||
|
||||
<dialog id="month-dialog" class="month-dialog">
|
||||
<form method="dialog">
|
||||
<button class="dialog-close" aria-label="Fermer" data-i18n-aria-label="calendar.close">×</button>
|
||||
</form>
|
||||
<figure class="plate">
|
||||
<div class="plate-frame"><img id="dialog-image" src="" alt="" width="527" height="713"></div>
|
||||
<figcaption>
|
||||
<h2 id="dialog-name" class="month-name"></h2>
|
||||
<p id="dialog-period" class="month-period"></p>
|
||||
</figcaption>
|
||||
</figure>
|
||||
<div class="dialog-text">
|
||||
<p id="dialog-etymology" class="month-etymology"></p>
|
||||
<p id="dialog-description" class="month-description"></p>
|
||||
</div>
|
||||
</dialog>
|
||||
|
||||
<footer class="site-footer">
|
||||
<div class="ornament" aria-hidden="true"></div>
|
||||
<p data-i18n="footer.text">Dates calculées selon la règle arithmétique perpétuelle proposée par Gilbert Romme (19 floréal an III / 8 mai 1795).</p>
|
||||
</footer>
|
||||
|
||||
|
||||
@@ -19,10 +19,20 @@
|
||||
const formError = document.getElementById('form-error');
|
||||
|
||||
const viewHome = document.getElementById('view-home');
|
||||
const viewCalendar = document.getElementById('view-calendar');
|
||||
const viewAbout = document.getElementById('view-about');
|
||||
const aboutTitle = document.getElementById('about-title');
|
||||
const aboutContent = document.getElementById('about-content');
|
||||
|
||||
const posterGrid = document.getElementById('poster-grid');
|
||||
const posterFeasts = document.getElementById('poster-feasts');
|
||||
const monthDialog = document.getElementById('month-dialog');
|
||||
const dialogImage = document.getElementById('dialog-image');
|
||||
const dialogName = document.getElementById('dialog-name');
|
||||
const dialogPeriod = document.getElementById('dialog-period');
|
||||
const dialogEtymology = document.getElementById('dialog-etymology');
|
||||
const dialogDescription = document.getElementById('dialog-description');
|
||||
|
||||
const menuToggle = document.getElementById('menu-toggle');
|
||||
const mainNav = document.getElementById('main-nav');
|
||||
const navBackdrop = document.getElementById('nav-backdrop');
|
||||
@@ -34,7 +44,24 @@
|
||||
'about/complementary-days': 'complementaryDays',
|
||||
};
|
||||
|
||||
// Season columns of the full calendar; `image` is the month plate shown in the arch,
|
||||
// `focus` its vertical crop position so that the face stays in the arch.
|
||||
const SEASONS = [
|
||||
{ key: 'autumn', image: 'vendemiaire', focus: '23%', months: ['vendemiaire', 'brumaire', 'frimaire'] },
|
||||
{ key: 'winter', image: 'nivose', focus: '18%', months: ['nivose', 'pluviose', 'ventose'] },
|
||||
{ key: 'spring', image: 'floreal', focus: '18%', months: ['germinal', 'floreal', 'prairial'] },
|
||||
{ key: 'summer', image: 'messidor', focus: '18%', months: ['messidor', 'thermidor', 'fructidor'] },
|
||||
];
|
||||
|
||||
const DECADE_DAY_KEYS = [
|
||||
'primidi', 'duodi', 'tridi', 'quartidi', 'quintidi',
|
||||
'sextidi', 'septidi', 'octidi', 'nonidi', 'decadi',
|
||||
];
|
||||
|
||||
const COMPLEMENTARY_DAY_KEYS = ['virtue', 'genius', 'labour', 'opinion', 'rewards', 'revolution'];
|
||||
|
||||
let lastRepublicanResult = null;
|
||||
let dayNames = {};
|
||||
|
||||
function pad(value) {
|
||||
return String(value).padStart(2, '0');
|
||||
@@ -49,6 +76,13 @@
|
||||
return `${weekdayLabel} ${pad(day)}/${pad(month)}/${year}`.trim();
|
||||
}
|
||||
|
||||
function createElement(tag, className, text) {
|
||||
const element = document.createElement(tag);
|
||||
if (className) element.className = className;
|
||||
if (text !== undefined) element.textContent = text;
|
||||
return element;
|
||||
}
|
||||
|
||||
function closeMenu() {
|
||||
mainNav.classList.remove('open');
|
||||
mainNav.setAttribute('aria-hidden', 'true');
|
||||
@@ -77,7 +111,7 @@
|
||||
const day = complementary.days[result.complementaryDayKey] || {};
|
||||
decadeDay.textContent = complementary.title || '';
|
||||
republicanDate.textContent = day.name || '';
|
||||
monthImage.src = 'assets/months/complementary.svg';
|
||||
monthImage.src = 'assets/complementary.svg';
|
||||
monthImage.alt = day.name || '';
|
||||
monthPeriod.textContent = '';
|
||||
monthName.textContent = day.name || '';
|
||||
@@ -89,7 +123,7 @@
|
||||
const seasonSuffix = (I18N.months.seasonSuffix || {})[month.season] || '';
|
||||
decadeDay.textContent = decadeDays[result.decadeDayKey] || '';
|
||||
republicanDate.textContent = `${result.dayOfMonth} ${month.name || ''}`.trim();
|
||||
monthImage.src = `assets/months/${result.monthKey}.svg`;
|
||||
monthImage.src = `assets/months/${result.monthKey}.jpg`;
|
||||
monthImage.alt = month.name || '';
|
||||
monthPeriod.textContent = month.period || '';
|
||||
monthName.textContent = month.name || '';
|
||||
@@ -97,6 +131,167 @@
|
||||
monthEtymology.textContent = month.etymology || '';
|
||||
monthDescription.textContent = month.description || '';
|
||||
}
|
||||
markToday();
|
||||
}
|
||||
|
||||
/** Highlights the displayed republican date inside the full calendar. */
|
||||
function markToday() {
|
||||
posterGrid.querySelectorAll('.today, .today-row, .is-current').forEach((element) => {
|
||||
element.classList.remove('today', 'today-row', 'is-current');
|
||||
});
|
||||
posterFeasts.querySelectorAll('.today').forEach((element) => element.classList.remove('today'));
|
||||
|
||||
const result = lastRepublicanResult;
|
||||
if (!result) return;
|
||||
|
||||
if (result.isComplementaryDay) {
|
||||
const feast = posterFeasts.querySelector(`[data-feast="${result.complementaryDayKey}"]`);
|
||||
if (feast) feast.classList.add('today');
|
||||
return;
|
||||
}
|
||||
|
||||
const cell = posterGrid.querySelector(
|
||||
`td[data-month="${result.monthKey}"][data-day="${result.dayOfMonth}"]`
|
||||
);
|
||||
if (cell) {
|
||||
cell.classList.add('today');
|
||||
cell.parentElement.firstElementChild.classList.add('today-row');
|
||||
}
|
||||
const monthButton = posterGrid.querySelector(`.month-button[data-month="${result.monthKey}"]`);
|
||||
if (monthButton) monthButton.classList.add('is-current');
|
||||
}
|
||||
|
||||
function buildSeasonTable(season) {
|
||||
const months = I18N.months.months || {};
|
||||
const decadeDays = I18N.months.decadeDays || {};
|
||||
const decades = I18N.t('calendar.decades', []);
|
||||
|
||||
const table = createElement('table', 'season-table');
|
||||
const colgroup = table.appendChild(document.createElement('colgroup'));
|
||||
colgroup.appendChild(createElement('col', 'col-day'));
|
||||
season.months.forEach(() => colgroup.appendChild(document.createElement('col')));
|
||||
|
||||
const headRow = table.createTHead().insertRow();
|
||||
headRow.appendChild(createElement('th', 'day-head', I18N.t('calendar.dayColumn')));
|
||||
season.months.forEach((monthKey) => {
|
||||
const th = createElement('th');
|
||||
th.scope = 'col';
|
||||
const button = createElement('button', 'month-button', (months[monthKey] || {}).name || monthKey);
|
||||
button.type = 'button';
|
||||
button.dataset.month = monthKey;
|
||||
th.appendChild(button);
|
||||
headRow.appendChild(th);
|
||||
});
|
||||
|
||||
const body = table.createTBody();
|
||||
for (let decade = 0; decade < 3; decade += 1) {
|
||||
const decadeRow = body.insertRow();
|
||||
decadeRow.className = 'decade-row';
|
||||
const decadeHead = createElement('th', '', decades[decade] || '');
|
||||
decadeHead.colSpan = season.months.length + 1;
|
||||
decadeRow.appendChild(decadeHead);
|
||||
|
||||
for (let index = 0; index < 10; index += 1) {
|
||||
const day = decade * 10 + index + 1;
|
||||
const row = body.insertRow();
|
||||
if (index === 9) row.className = 'decade-end';
|
||||
|
||||
const dayHead = createElement('th');
|
||||
dayHead.scope = 'row';
|
||||
dayHead.appendChild(createElement('span', 'day-number', String(day)));
|
||||
const decadeDayName = decadeDays[DECADE_DAY_KEYS[index]] || '';
|
||||
const abbreviation = createElement('abbr', '', `${decadeDayName.slice(0, 3)}.`);
|
||||
abbreviation.title = decadeDayName;
|
||||
dayHead.appendChild(abbreviation);
|
||||
row.appendChild(dayHead);
|
||||
|
||||
season.months.forEach((monthKey) => {
|
||||
const cell = createElement('td', '', (dayNames[monthKey] || [])[day - 1] || '');
|
||||
cell.dataset.month = monthKey;
|
||||
cell.dataset.day = String(day);
|
||||
row.appendChild(cell);
|
||||
});
|
||||
}
|
||||
}
|
||||
return table;
|
||||
}
|
||||
|
||||
function buildSeason(season) {
|
||||
const section = createElement('section', 'season');
|
||||
const arch = createElement('div', 'arch');
|
||||
const image = createElement('img');
|
||||
image.src = `assets/months/${season.image}.jpg`;
|
||||
image.alt = '';
|
||||
image.loading = 'lazy';
|
||||
image.style.objectPosition = `50% ${season.focus}`;
|
||||
arch.appendChild(image);
|
||||
section.appendChild(arch);
|
||||
section.appendChild(createElement('h2', 'season-title', I18N.t(`calendar.seasons.${season.key}`)));
|
||||
section.appendChild(buildSeasonTable(season));
|
||||
return section;
|
||||
}
|
||||
|
||||
function buildPosterCenter() {
|
||||
const center = createElement('aside', 'poster-center');
|
||||
const medallion = createElement('div', 'medallion');
|
||||
const inner = createElement('div', 'medallion-inner');
|
||||
const fasces = createElement('img');
|
||||
fasces.src = 'assets/fasces.svg';
|
||||
fasces.alt = '';
|
||||
inner.appendChild(fasces);
|
||||
medallion.appendChild(inner);
|
||||
center.appendChild(medallion);
|
||||
|
||||
const explanation = createElement('div', 'explanation');
|
||||
explanation.appendChild(createElement('h2', '', I18N.t('calendar.explanationTitle')));
|
||||
I18N.t('calendar.explanation', []).forEach((paragraph) => {
|
||||
explanation.appendChild(createElement('p', '', paragraph));
|
||||
});
|
||||
center.appendChild(explanation);
|
||||
return center;
|
||||
}
|
||||
|
||||
function buildFeasts() {
|
||||
const complementary = I18N.months.complementaryDays || { days: {} };
|
||||
const decadeDays = I18N.months.decadeDays || {};
|
||||
posterFeasts.replaceChildren();
|
||||
COMPLEMENTARY_DAY_KEYS.forEach((key, index) => {
|
||||
const feast = createElement('p', 'feast');
|
||||
feast.dataset.feast = key;
|
||||
feast.appendChild(createElement('span', 'feast-day', decadeDays[DECADE_DAY_KEYS[index]] || ''));
|
||||
feast.appendChild(createElement('span', 'feast-name', (complementary.days[key] || {}).name || ''));
|
||||
if (key === 'revolution') {
|
||||
feast.appendChild(createElement('span', 'feast-note', I18N.t('calendar.sextileOnly')));
|
||||
}
|
||||
posterFeasts.appendChild(feast);
|
||||
});
|
||||
}
|
||||
|
||||
function renderCalendarView() {
|
||||
posterGrid.replaceChildren(...SEASONS.map(buildSeason), buildPosterCenter());
|
||||
buildFeasts();
|
||||
markToday();
|
||||
}
|
||||
|
||||
function openMonthDialog(monthKey) {
|
||||
const month = (I18N.months.months || {})[monthKey];
|
||||
if (!month) return;
|
||||
dialogImage.src = `assets/months/${monthKey}.jpg`;
|
||||
dialogImage.alt = month.name;
|
||||
dialogName.textContent = month.name;
|
||||
dialogPeriod.textContent = month.period || '';
|
||||
dialogEtymology.textContent = month.etymology || '';
|
||||
dialogDescription.textContent = month.description || '';
|
||||
monthDialog.showModal();
|
||||
}
|
||||
|
||||
async function loadDayNames() {
|
||||
try {
|
||||
const response = await fetch('data/day-names.json');
|
||||
dayNames = await response.json();
|
||||
} catch (error) {
|
||||
dayNames = {};
|
||||
}
|
||||
}
|
||||
|
||||
function showFormError(messageKey) {
|
||||
@@ -170,18 +365,23 @@
|
||||
|
||||
document.querySelectorAll('.nav-link').forEach((link) => link.classList.remove('active'));
|
||||
|
||||
if (hash in ABOUT_ROUTES) {
|
||||
viewHome.hidden = true;
|
||||
viewHome.hidden = true;
|
||||
viewCalendar.hidden = true;
|
||||
viewAbout.hidden = true;
|
||||
|
||||
let activeHref = '#/';
|
||||
if (hash === 'calendar') {
|
||||
viewCalendar.hidden = false;
|
||||
activeHref = '#/calendar';
|
||||
} else if (hash in ABOUT_ROUTES) {
|
||||
viewAbout.hidden = false;
|
||||
renderAboutView(ABOUT_ROUTES[hash]);
|
||||
const activeLink = document.querySelector(`.nav-link[href="#/${hash}"]`);
|
||||
if (activeLink) activeLink.classList.add('active');
|
||||
activeHref = `#/${hash}`;
|
||||
} else {
|
||||
viewHome.hidden = false;
|
||||
viewAbout.hidden = true;
|
||||
const activeLink = document.querySelector('.nav-link[href="#/"]');
|
||||
if (activeLink) activeLink.classList.add('active');
|
||||
}
|
||||
const activeLink = document.querySelector(`.nav-link[href="${activeHref}"]`);
|
||||
if (activeLink) activeLink.classList.add('active');
|
||||
}
|
||||
|
||||
function bindEvents() {
|
||||
@@ -195,6 +395,18 @@
|
||||
navBackdrop.addEventListener('click', closeMenu);
|
||||
window.addEventListener('hashchange', route);
|
||||
|
||||
posterGrid.addEventListener('click', (event) => {
|
||||
const button = event.target.closest('.month-button');
|
||||
if (button) openMonthDialog(button.dataset.month);
|
||||
});
|
||||
// A click on the ::backdrop targets the dialog itself, outside its box.
|
||||
monthDialog.addEventListener('click', (event) => {
|
||||
const box = monthDialog.getBoundingClientRect();
|
||||
const inside = event.clientX >= box.left && event.clientX <= box.right
|
||||
&& event.clientY >= box.top && event.clientY <= box.bottom;
|
||||
if (!inside) monthDialog.close();
|
||||
});
|
||||
|
||||
convertForm.addEventListener('submit', handleConvertSubmit);
|
||||
todayButton.addEventListener('click', () => {
|
||||
loadToday();
|
||||
@@ -207,6 +419,7 @@
|
||||
|
||||
I18N.onChange((lang) => {
|
||||
langSwitch.textContent = lang.toUpperCase();
|
||||
renderCalendarView();
|
||||
if (lastRepublicanResult) {
|
||||
renderRepublicanResult(lastRepublicanResult);
|
||||
}
|
||||
@@ -220,6 +433,7 @@
|
||||
async function init() {
|
||||
bindEvents();
|
||||
const initialLang = I18N.detectInitialLang();
|
||||
await loadDayNames();
|
||||
await I18N.load(initialLang);
|
||||
langSwitch.textContent = initialLang.toUpperCase();
|
||||
route();
|
||||
|
||||
@@ -39,6 +39,12 @@ const I18N = (() => {
|
||||
element.textContent = value;
|
||||
}
|
||||
});
|
||||
document.querySelectorAll('[data-i18n-aria-label]').forEach((element) => {
|
||||
const value = getByPath(common, element.getAttribute('data-i18n-aria-label'));
|
||||
if (value !== undefined) {
|
||||
element.setAttribute('aria-label', value);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
async function fetchJson(url) {
|
||||
|
||||