9 Commits

Author SHA1 Message Date
gprunet c066fdc31c Round Timer + room creation synced with browse tab 2026-04-01 21:31:14 +02:00
Georges-Leonard Prunet c96629b704 Fix lobby player leaving 2026-03-31 15:59:02 +02:00
Georges-Leonard Prunet 41612f5d39 https + volume 2026-03-31 14:21:11 +02:00
kalips003 e1573ba9f0 ^^._, work in progress, small changes 2026-03-31 05:35:04 +02:00
kalips003 b9c4c817f8 ^^._, work in progress, small changes 2026-03-30 22:33:13 +02:00
kalips003 384363c8dd ^^._, work in progress, small changes 2026-03-30 17:19:14 +02:00
Kali Gallon def9918047 ^^._, work in progress, small changes 2026-03-30 01:36:33 +02:00
Kali Gallon cafa0cccc4 ^^._, work in progress, small changes 2026-03-27 23:17:31 +01:00
kalips003 8b907d5a86 transfer 2026-03-27 20:17:21 +01:00
165 changed files with 4785 additions and 787 deletions
+443
View File
@@ -12,3 +12,446 @@ fclean :
re : fclean up
# ╭────────────────────────────────────────────────────────────────────────────╮
# │─██████████████─██████████████─██████████████─██████─────────██████████████─│
# │─██░░░░░░░░░░██─██░░░░░░░░░░██─██░░░░░░░░░░██─██░░██─────────██░░░░░░░░░░██─│
# │─██████░░██████─██░░██████░░██─██░░██████░░██─██░░██─────────██░░██████████─│
# │─────██░░██─────██░░██──██░░██─██░░██──██░░██─██░░██─────────██░░██─────────│
# │─────██░░██─────██░░██──██░░██─██░░██──██░░██─██░░██─────────██░░██████████─│
# │─────██░░██─────██░░██──██░░██─██░░██──██░░██─██░░██─────────██░░░░░░░░░░██─│
# │─────██░░██─────██░░██──██░░██─██░░██──██░░██─██░░██─────────██████████░░██─│
# │─────██░░██─────██░░██──██░░██─██░░██──██░░██─██░░██─────────────────██░░██─│
# │─────██░░██─────██░░██████░░██─██░░██████░░██─██░░██████████─██████████░░██─│
# │─────██░░██─────██░░░░░░░░░░██─██░░░░░░░░░░██─██░░░░░░░░░░██─██░░░░░░░░░░██─│
# │─────██████─────██████████████─██████████████─██████████████─██████████████─│
# ╰────────────────────────────────────────────────────────────────────────────╯
# --------------------------------------------------------------------------------- >
VALGRIND = valgrind --leak-check=full --show-leak-kinds=all --track-origins=yes -s --track-fds=yes --trace-children=yes $(V_FLAG)
# ↑さ↓ぎょう を ↓ほ↑ぞん
# Default git push
git: fclean
@$(call random_shmol_cat_blink, 作業を保存してるかな.., いいね、いいねえー , $(CLS), );
@current_date=$$(date); \
git add .; \
git commit -m "^^._, work in progress, small changes"; \
git push
# Git Push that asks for commit msg
git2: fclean
@$(call random_shmol_cat_blink, 作業を保存してるかな.., いいね、いいねえー , $(CLS), );
@read -p "Enter commit message: " msg; \
[ -z "$$msg" ] && msg=$$(date); \
git add .; \
git commit -m "$$msg"; \
git push
# Git Push use the content of .gitmsg to push
# if .gitmsg empty, return error
# clear .gitmsg on succesfull push.
GIT_MSG_FILE = ../.gitmsg
git3: fclean
@$(call random_shmol_cat_blink, 作業を保存してるかな.., いいね、いいねえー , $(CLS), );
@{ \
msg="$$(cat $(GIT_MSG_FILE) 2>/dev/null)"; \
[ -z "$$msg" ] && { $(call random_shmol_cat_blink, error, file is empty, , ); exit 1; }; \
git add . && \
git commit -m "$$msg" && \
git push && \
: > $(GIT_MSG_FILE) && \
$(call random_shmol_cat_blink, success!, $(GIT_MSG_FILE) cleared., , ); \
}
.SILENT: $(NAME)
# ╭────────────────────────────────────────────────────────────────────────────────────╮
# │─██████████████─████████████████───██████████─██████──────────██████─██████████████─│
# │─██░░░░░░░░░░██─██░░░░░░░░░░░░██───██░░░░░░██─██░░██████████──██░░██─██░░░░░░░░░░██─│
# │─██░░██████░░██─██░░████████░░██───████░░████─██░░░░░░░░░░██──██░░██─██████░░██████─│
# │─██░░██──██░░██─██░░██────██░░██─────██░░██───██░░██████░░██──██░░██─────██░░██─────│
# │─██░░██████░░██─██░░████████░░██─────██░░██───██░░██──██░░██──██░░██─────██░░██─────│
# │─██░░░░░░░░░░██─██░░░░░░░░░░░░██─────██░░██───██░░██──██░░██──██░░██─────██░░██─────│
# │─██░░██████████─██░░██████░░████─────██░░██───██░░██──██░░██──██░░██─────██░░██─────│
# │─██░░██─────────██░░██──██░░██───────██░░██───██░░██──██░░██████░░██─────██░░██─────│
# │─██░░██─────────██░░██──██░░██████─████░░████─██░░██──██░░░░░░░░░░██─────██░░██─────│
# │─██░░██─────────██░░██──██░░░░░░██─██░░░░░░██─██░░██──██████████░░██─────██░░██─────│
# │─██████─────────██████──██████████─██████████─██████──────────██████─────██████─────│
# ╰────────────────────────────────────────────────────────────────────────────────────╯
# C_213
PURPLE = \033[38;5;97m
# C_430
GOLD = \033[38;5;178m
# C_040
GREEN1 = \033[38;5;40m
# C_045
BLUE1 = \033[38;5;45m
# $(C_105), $(C_510), $(C_025)
# $(RED), $(GOLD), $(BLUE1)
test_color666:
@$(call random_cat, $(call pad_word, 12, TheCake), $(call pad_word, 14, IsALie...), $(CLS), $(RESET));
@$(call random_cat, $(call pad_word, 13, TheCake), $(call pad_word, 15, IsALie...), , $(RESET));
# $(call pad_word, 12, TheCake)
pad_word = $(BLINK)$(shell printf "%$(1)s" "$(2)")$(RESET)
# improve with: STRING1=$$(printf "\033[38;5;%dm" $$(shuf -i 0-255 -n 1));
# --------------------------------------------------------------------------------- >
# @$(call print_cat, $(CLEAR), $(body), $(eye), $(txt), $(call pad_word, 12, "TheCake"), $(call pad_word, 12, "IsALie..."));
# print_cat (resest?)(C_c)_sCtt$padded_txt_top))($(padded_txt_bot))
define print_cat
echo -e "$(1)$(2)\
\t\t\t\t\t ⠀⢠⠒⡄⠀\n\
\t\t\t\t\t ⠀⢀⠇⠀⠘⡄⠀⠀⠀⠀⠀⠀⣀⠀⠀\n\
\t\t\t\t\t ⠀⠀⠀⠀⠀⠀⠀⡜⠀⠀⠀⠁⠉⠉⠉⠒⠊⠉⠀⡇⠀\n\
\t\t\t\t\t ⠀⡜$(3)$(BLINK)⣀⡀$(RESET)$(2)⠀⢰⠁⠀\n\
\t\t\t\t\t ⠀⠲⢴⠁$(3)$(BLINK)⠛⠁$(RESET)$(2)$(3)$(BLINK)⢀⣄$(RESET)$(2)⠀⢸⠀\n\
\t\t\t\t\t ⠀⠉⠑⠺⡀⠀⠀⢶⠤$(3)$(BLINK)⠈⠋$(RESET)$(2)⠀⡘⠀\n\
\t\t\t\t\t ⠀⠀⠀⠀⠀⠀⠑⢄⡀⠀⠀⠀⠠⣉⠑⠂⠀⢠⠃⠀⠀\n\
\t\t\t\t\t ⠀⢠⠊⠀⠀⠀⠀⠀⠀⠁⠀⠀⠈⢆⠀⠀\n\
\t\t\t\t\t ⠀⢰⠁⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠈⡆⠀\n\
\t\t\t\t\t ⠀⢀⠤⠒⠒⠃⠄⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠸⠀\n\
\t\t\t\t\t ⠀⠔⠑⠄⠀⠀⡎⠀⠀⠀⠀⠀⠀⡇\n\
\t\t\t\t\t ⠸⡀⠀⢣⠀⠀⡇$(4)$(5)$(2)⠀⡇\n\
\t\t\t\t\t ⠀⠱⡀⠀⠳⡀⠀⠀⢃$(4)$(6)$(2)⠀⡸⠀\n\
\t\t\t\t\t ⠀⠑⢄⠀⠈⠒⢄⡀⠀⠀⠸⡀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⡰⠁⠀\n\
\t\t\t\t\t ⠀⠑⠦⣀⠀⠈⠉⠐⠒⠒⠃⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠈⠉⢢⠀\n\
\t\t\t\t\t ⠀⠀⠀⠀⠀⠀⠀⠉⠐⠒⠠⠤⠤⠤⠤⠔⠂⠠⠤⠤⠤⠄⠐⠒⠂⠉⠉⠉⠉⠉⠁\n$(RESET)"
endef
# --------------------------------------------------------------------------------- >
# @$(call random_cat, $(call pad_word, 12, txt1), $(call pad_word, 12, txt2), $(CLS), $(RESET));
# print_cat (resest?)(C_c)_sCtt$padded_txt_top))($(padded_txt_bot))
define random_cat
COLOR=$$(printf "\033[38;5;%dm" $$(shuf -i 0-255 -n 1)); \
COLOR2=$$(printf "\033[38;5;%dm" $$(shuf -i 0-255 -n 1)); \
COLOR3=$$(printf "\033[38;5;%dm" $$(shuf -i 0-255 -n 1)); \
echo -e "$(3)$${COLOR}\
\t\t\t\t\t ⠀⢠⠒⡄⠀\n\
\t\t\t\t\t ⠀⢀⠇⠀⠘⡄⠀⠀⠀⠀⠀⠀⣀⠀⠀\n\
\t\t\t\t\t ⠀⠀⠀⠀⠀⠀⠀⡜⠀⠀⠀⠁⠉⠉⠉⠒⠊⠉⠀⡇⠀\n\
\t\t\t\t\t ⠀⡜⠀$${COLOR2}$(BLINK)⣀⡀$(RESET)$${COLOR}⠀⢰⠁⠀\n\
\t\t\t\t\t ⠀⠲⢴⠁⠀$${COLOR2}$(BLINK)⠛⠁$(RESET)$${COLOR}$${COLOR2}$(BLINK)⠀⢀⣄$(RESET)$${COLOR}⠀⢸⠀\n\
\t\t\t\t\t ⠀⠉⠑⠺⡀⠀⠀⢶⠤$${COLOR2}$(BLINK)⠀⠈⠋$(RESET)$${COLOR}⠀⡘⠀\n\
\t\t\t\t\t ⠀⠀⠀⠀⠀⠀⠑⢄⡀⠀⠀⠀⠠⣉⠑⠂⠀⢠⠃⠀⠀\n\
\t\t\t\t\t ⠀⢠⠊⠀⠀⠀⠀⠀⠀⠁⠀⠀⠈⢆⠀⠀\n\
\t\t\t\t\t ⠀⢰⠁⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠈⡆⠀\n\
\t\t\t\t\t ⠀⢀⠤⠒⠒⠃⠄⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠸⠀\n\
\t\t\t\t\t ⠀⠔⠑⠄⠀⠀⡎⠀⠀⠀⠀⠀⠀⡇\n\
\t\t\t\t\t ⠸⡀⠀⢣⠀⠀⡇$${COLOR3}$(1)$${COLOR}⠀⡇\n\
\t\t\t\t\t ⠀⠱⡀⠀⠳⡀⠀⠀⢃$${COLOR3}$(2)$${COLOR}⠀⡸⠀\n\
\t\t\t\t\t ⠀⠑⢄⠀⠈⠒⢄⡀⠀⠀⠸⡀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⡰⠁⠀\n\
\t\t\t\t\t ⠀⠑⠦⣀⠀⠈⠉⠐⠒⠒⠃⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠈⠉⢢⠀\n\
\t\t\t\t\t ⠀⠀⠀⠀⠀⠀⠀⠉⠐⠒⠠⠤⠤⠤⠤⠔⠂⠠⠤⠤⠤⠄⠐⠒⠂⠉⠉⠉⠉⠉⠁\n$(4)"
endef
# --------------------------------------------------------------------------------- >
# @$(call shmol_cat_color, $(C_c), $(C_t), txt1, txt2, $(CLS), $(RESET));
define shmol_cat_color
echo -e "$(5)$(2)\
\tにゃ~$(1)\t⠀|、\n\
\t\t(˚ˎ。7$(2)~ $(3) ~$(1)\n\
\t\t|、˜\\\\\t\t$(2)$(4)$(1)\n\
\t\t⠀じしˍ)\n$(6)"
endef
# --------------------------------------------------------------------------------- >
# @$(call random_shmol_cat, text 1, text 2, $(CLS), $(RESET));
# $(1)= $(CLEAR); $(2)= text1; $(3)= text2; $(4)= $(RESET)
define random_shmol_cat
COLOR=$$(printf "\033[38;5;%dm" $$(shuf -i 1-255 -n 1)); \
COLOR2=$$(printf "\033[38;5;%dm" $$(shuf -i 0-255 -n 1)); \
echo -e "$(3)$${COLOR2}\
\tにゃ~$${COLOR}\t⠀|、\n\
\t\t(˚ˎ。7$${COLOR2}~ $(1) ~$${COLOR}\n\
\t\t|、˜\\\\\t\t$${COLOR2}~ $(2)$${COLOR}\n\
\t\t⠀じしˍ)\n$(4)"
endef
# // <!> - - - - - - - - - - - </!>
# --------------------------------------------------------------------------------- >
rscs:
@$(call random_shmol_cat_surligne, text 1, text 2, $(CLS), $(RESET));
define random_shmol_cat_surligne
COLOR=$$(printf "\033[0m\033[38;5;%dm" $$(shuf -i 0-255 -n 1)); \
COLOR2=$$(printf "\033[48;5;%dm" $$(shuf -i 0-255 -n 1)); \
echo -e "$(3)$${COLOR2}\
\tにゃ~$${COLOR}\t⠀|、\n\
\t\t(˚ˎ。7$${COLOR2}~ $(1) ~$${COLOR}\n\
\t\t|、˜\\\\\t\t$${COLOR2}~ $(2)$${COLOR}\n\
\t\t⠀じしˍ)\n$(4)"
endef
rscb:
@$(call random_shmol_cat_blink, text 1, text 2, $(CLS), $(RESET));
define random_shmol_cat_blink
COLOR=$$(printf "\033[0m\033[38;5;%dm" $$(shuf -i 0-255 -n 1)); \
COLOR2=$$(printf "\e[5m\033[38;5;%dm" $$(shuf -i 0-255 -n 1)); \
echo -e "$(3)\n$${COLOR2}\
\tにゃ~$${COLOR}\t⠀|、\n\
\t\t(˚ˎ。7$${COLOR2}~ $(1) ~$${COLOR}\n\
\t\t|、˜\\\\\t\t$${COLOR2}~ $(2)$${COLOR}\n\
\t\t⠀じしˍ)\n$(4)"
endef
# // <!> - - - - - - - - - - - </!>
# --------------------------------------------------------------------------------- >
# @$(call shmol_cat_error, $(RED), $(RED_L));
# $(1) = $(C_c)$2) = $(C_ttN CLS
define shmol_cat_error
echo -e "$(2)\
\tにゃ~$(1)\t⠀|、\n\
\t\t(˚ˎ。7$(2)~ somshin wen wong ~$(1)\n\
\t\t|、˜\\\\\n\
\t\t⠀じしˍ)\n$(RESET)"
endef
# Define all 256 colors
CLEAR = \033[2J\033[H
CLS = \033[2J\033[H
RESET = \033[0m
BLINK = \033[5m
# U+2800 to U+28FF Braile
# <Esc>[38;5;ColorNumberm
BLACK = \033[38;5;0m
RED = \033[38;5;1m
GREEN = \033[38;5;2m
YELLOW = \033[38;5;3m
BLUE = \033[38;5;4m
MAGENTA = \033[38;5;5m
CYAN = \033[38;5;6m
GRAY = \033[38;5;7m
BLACK_L = \033[38;5;8m
RED_L = \033[38;5;9m
GREEN_L = \033[38;5;10m
YELLOW_L = \033[38;5;11m
BLUE_L = \033[38;5;12m
MAGENTA_L = \033[38;5;13m
CYAN_L = \033[38;5;14m
WHITE = \033[38;5;15m
C_000 = \033[38;5;16m
C_001 = \033[38;5;17m
C_002 = \033[38;5;18m
C_003 = \033[38;5;19m
C_004 = \033[38;5;20m
C_005 = \033[38;5;21m
C_010 = \033[38;5;22m
C_011 = \033[38;5;23m
C_012 = \033[38;5;24m
C_013 = \033[38;5;25m
C_014 = \033[38;5;26m
C_015 = \033[38;5;27m
C_020 = \033[38;5;28m
C_021 = \033[38;5;29m
C_022 = \033[38;5;30m
C_023 = \033[38;5;31m
C_024 = \033[38;5;32m
C_025 = \033[38;5;33m
C_030 = \033[38;5;34m
C_031 = \033[38;5;35m
C_032 = \033[38;5;36m
C_033 = \033[38;5;37m
C_034 = \033[38;5;38m
C_035 = \033[38;5;39m
C_040 = \033[38;5;40m
C_041 = \033[38;5;41m
C_042 = \033[38;5;42m
C_043 = \033[38;5;43m
C_044 = \033[38;5;44m
C_045 = \033[38;5;45m
C_050 = \033[38;5;46m
C_051 = \033[38;5;47m
C_052 = \033[38;5;48m
C_053 = \033[38;5;49m
C_054 = \033[38;5;50m
C_055 = \033[38;5;51m
C_100 = \033[38;5;52m
C_101 = \033[38;5;53m
C_102 = \033[38;5;54m
C_103 = \033[38;5;55m
C_104 = \033[38;5;56m
C_105 = \033[38;5;57m
C_110 = \033[38;5;58m
C_111 = \033[38;5;59m
C_112 = \033[38;5;60m
C_113 = \033[38;5;61m
C_114 = \033[38;5;62m
C_115 = \033[38;5;63m
C_120 = \033[38;5;64m
C_121 = \033[38;5;65m
C_122 = \033[38;5;66m
C_123 = \033[38;5;67m
C_124 = \033[38;5;68m
C_125 = \033[38;5;69m
C_130 = \033[38;5;70m
C_131 = \033[38;5;71m
C_132 = \033[38;5;72m
C_133 = \033[38;5;73m
C_134 = \033[38;5;74m
C_135 = \033[38;5;75m
C_140 = \033[38;5;76m
C_141 = \033[38;5;77m
C_142 = \033[38;5;78m
C_143 = \033[38;5;79m
C_144 = \033[38;5;80m
C_145 = \033[38;5;81m
C_150 = \033[38;5;82m
C_151 = \033[38;5;83m
C_152 = \033[38;5;84m
C_153 = \033[38;5;85m
C_154 = \033[38;5;86m
C_155 = \033[38;5;87m
C_200 = \033[38;5;88m
C_201 = \033[38;5;89m
C_202 = \033[38;5;90m
C_203 = \033[38;5;91m
C_204 = \033[38;5;92m
C_205 = \033[38;5;93m
C_210 = \033[38;5;94m
C_211 = \033[38;5;95m
C_212 = \033[38;5;96m
C_213 = \033[38;5;97m
C_214 = \033[38;5;98m
C_215 = \033[38;5;99m
C_220 = \033[38;5;100m
C_221 = \033[38;5;101m
C_222 = \033[38;5;102m
C_223 = \033[38;5;103m
C_224 = \033[38;5;104m
C_225 = \033[38;5;105m
C_230 = \033[38;5;106m
C_231 = \033[38;5;107m
C_232 = \033[38;5;108m
C_233 = \033[38;5;109m
C_234 = \033[38;5;110m
C_235 = \033[38;5;111m
C_240 = \033[38;5;112m
C_241 = \033[38;5;113m
C_242 = \033[38;5;114m
C_243 = \033[38;5;115m
C_244 = \033[38;5;116m
C_245 = \033[38;5;117m
C_250 = \033[38;5;118m
C_251 = \033[38;5;119m
C_252 = \033[38;5;120m
C_253 = \033[38;5;121m
C_254 = \033[38;5;122m
C_255 = \033[38;5;123m
C_300 = \033[38;5;124m
C_301 = \033[38;5;125m
C_302 = \033[38;5;126m
C_303 = \033[38;5;127m
C_304 = \033[38;5;128m
C_305 = \033[38;5;129m
C_310 = \033[38;5;130m
C_311 = \033[38;5;131m
C_312 = \033[38;5;132m
C_313 = \033[38;5;133m
C_314 = \033[38;5;134m
C_315 = \033[38;5;135m
C_320 = \033[38;5;136m
C_321 = \033[38;5;137m
C_322 = \033[38;5;138m
C_323 = \033[38;5;139m
C_324 = \033[38;5;140m
C_325 = \033[38;5;141m
C_330 = \033[38;5;142m
C_331 = \033[38;5;143m
C_332 = \033[38;5;144m
C_333 = \033[38;5;145m
C_334 = \033[38;5;146m
C_335 = \033[38;5;147m
C_340 = \033[38;5;148m
C_341 = \033[38;5;149m
C_342 = \033[38;5;150m
C_343 = \033[38;5;151m
C_344 = \033[38;5;152m
C_345 = \033[38;5;153m
C_350 = \033[38;5;154m
C_351 = \033[38;5;155m
C_352 = \033[38;5;156m
C_353 = \033[38;5;157m
C_354 = \033[38;5;158m
C_355 = \033[38;5;159m
C_400 = \033[38;5;160m
C_401 = \033[38;5;161m
C_402 = \033[38;5;162m
C_403 = \033[38;5;163m
C_404 = \033[38;5;164m
C_405 = \033[38;5;165m
C_410 = \033[38;5;166m
C_411 = \033[38;5;167m
C_412 = \033[38;5;168m
C_413 = \033[38;5;169m
C_414 = \033[38;5;170m
C_415 = \033[38;5;171m
C_420 = \033[38;5;172m
C_421 = \033[38;5;173m
C_422 = \033[38;5;174m
C_423 = \033[38;5;175m
C_424 = \033[38;5;176m
C_425 = \033[38;5;177m
C_430 = \033[38;5;178m
C_431 = \033[38;5;179m
C_432 = \033[38;5;180m
C_433 = \033[38;5;181m
C_434 = \033[38;5;182m
C_435 = \033[38;5;183m
C_440 = \033[38;5;184m
C_441 = \033[38;5;185m
C_442 = \033[38;5;186m
C_443 = \033[38;5;187m
C_444 = \033[38;5;188m
C_445 = \033[38;5;189m
C_450 = \033[38;5;190m
C_451 = \033[38;5;191m
C_452 = \033[38;5;192m
C_453 = \033[38;5;193m
C_454 = \033[38;5;194m
C_455 = \033[38;5;195m
C_500 = \033[38;5;196m
C_501 = \033[38;5;197m
C_502 = \033[38;5;198m
C_503 = \033[38;5;199m
C_504 = \033[38;5;200m
C_505 = \033[38;5;201m
C_510 = \033[38;5;202m
C_511 = \033[38;5;203m
C_512 = \033[38;5;204m
C_513 = \033[38;5;205m
C_514 = \033[38;5;206m
C_515 = \033[38;5;207m
C_520 = \033[38;5;208m
C_521 = \033[38;5;209m
C_522 = \033[38;5;210m
C_523 = \033[38;5;211m
C_524 = \033[38;5;212m
C_525 = \033[38;5;213m
C_530 = \033[38;5;214m
C_531 = \033[38;5;215m
C_532 = \033[38;5;216m
C_533 = \033[38;5;217m
C_534 = \033[38;5;218m
C_535 = \033[38;5;219m
C_540 = \033[38;5;220m
C_541 = \033[38;5;221m
C_542 = \033[38;5;222m
C_543 = \033[38;5;223m
C_544 = \033[38;5;224m
C_545 = \033[38;5;225m
C_550 = \033[38;5;226m
C_551 = \033[38;5;227m
C_552 = \033[38;5;228m
C_553 = \033[38;5;229m
C_554 = \033[38;5;230m
C_555 = \033[38;5;231m
+3 -4
View File
@@ -1,5 +1,5 @@
volumes:
data:
pgdata:
networks:
transcendence:
@@ -12,7 +12,7 @@ services:
ports:
- "5432:5432"
volumes:
- data:/var/lib/postgresql/data/pg15/
- pgdata:/var/lib/postgresql
env_file:
- ../.env
networks:
@@ -38,8 +38,7 @@ services:
container_name: frontend
build: ./srcs/frontend/
ports:
- "8080:8080"
- "8443:8443"
- "8443:443"
depends_on:
- backend
networks:
+1 -1
View File
@@ -127,7 +127,7 @@ async function createTables()
status VARCHAR(20) DEFAULT 'waiting',
max_players INT DEFAULT 8,
current_round INT DEFAULT 0,
max_rounds INT DEFAULT 3,
max_rounds INT DEFAULT 5,
round_duration INT DEFAULT 90,
created_at TIMESTAMP DEFAULT NOW(),
started_at TIMESTAMP,
+8
View File
@@ -1,5 +1,13 @@
FROM node:20-alpine
RUN apk add --no-cache openssl
RUN mkdir -p /etc/backend/.ssl
RUN openssl req -x509 -nodes -days 365 -newkey rsa:2048 \
-keyout /etc/backend/.ssl/key.pem \
-out /etc/backend/.ssl/cert.pem \
-subj "/CN=localhost" \
-addext "subjectAltName=DNS:localhost,IP:127.0.0.1"
WORKDIR /app
COPY package*.json ./
+7 -2
View File
@@ -1,5 +1,6 @@
import express from 'express';
import http from 'http';
import https from 'https';
import fs from 'fs';
import cors from 'cors';
import {Server} from 'socket.io';
import authRouter from './routes/auth.js';
@@ -13,7 +14,11 @@ import setupSocketIO from './services/socket.js';
import avatarService from './services/avatar.js';
const app = express();
const server = http.createServer(app);
const httpsOptions = {
key: fs.readFileSync('/etc/backend/.ssl/key.pem'),
cert: fs.readFileSync('/etc/backend/.ssl/cert.pem')
};
const server = https.createServer(httpsOptions, app);
const io = new Server(server,
{
cors:
+86 -2
View File
@@ -30,6 +30,63 @@ async function broadcastRoomsList(io) {
}
}
function startRoomTimer(io, roomId, seconds)
{
const gameState = gameRooms.get(roomId);
if (!gameState) return;
if (gameState.timerInterval)
clearInterval(gameState.timerInterval);
gameState.timerSeconds = seconds;
gameState.timerInterval = setInterval(() => {
gameState.timerSeconds--;
if (gameState.timerSeconds < 0)
gameState.timerSeconds = 0;
if (gameState.timerSeconds <= 0)
{
io.to(roomId).emit('game-timer-sync', {
remaining: 0
});
clearInterval(gameState.timerInterval);
gameState.timerInterval = null;
io.to(roomId).emit('game-timer-ended', { message: 'Temps écoulé !' });
gameState.currentPlayerIndex = (gameState.currentPlayerIndex + 1) % gameState.players.length;
const nextDrawer = gameState.players[gameState.currentPlayerIndex];
gameState.drawer = nextDrawer;
gameState.currentWord = '';
gameState.revealedLetters = [];
gameState.revealedWord = [];
gameState.guessedLetters = [];
gameState.wrongGuesses = 0;
io.to(roomId).emit('game-new-round', {
drawer: nextDrawer
});
}
else
{
io.to(roomId).emit('game-timer-sync', {
remaining: gameState.timerSeconds
});
}
}, 1000);
}
function stopRoomTimer(roomId)
{
const gameState = gameRooms.get(roomId);
if (!gameState || !gameState.timerInterval) return;
clearInterval(gameState.timerInterval);
gameState.timerInterval = null;
}
// Check if a playing game has only 1 player left and auto-stop it
async function checkAndStopSinglePlayerGame(io, roomId, dbRoomId) {
if (!dbRoomId) return;
@@ -43,6 +100,7 @@ async function checkAndStopSinglePlayerGame(io, roomId, dbRoomId) {
const players = await gameRoomService.getRoomPlayers(dbRoomId);
if (players.length <= 1) {
console.log(`Room ${dbRoomId} has only ${players.length} player(s) left, ending game`);
stopRoomTimer(roomId);
// Update room status to 'ended'
await gameRoomService.updateRoomStatus(dbRoomId, 'waiting');
@@ -192,7 +250,9 @@ function setupSocketIO(io)
revealedLetters: gameState.revealedLetters,
revealedWord: gameState.revealedWord || [],
guessedLetters: gameState.guessedLetters,
players: gameState.players
players: gameState.players,
scores: gameState.scores || {},
timer: gameState.timerSeconds || 0
});
}
});
@@ -202,6 +262,15 @@ function setupSocketIO(io)
if (socket.gameRoomId) {
const roomId = socket.gameRoomId;
const dbRoomId = socket.gameRoomDbId;
const userId = socket.user.userId;
if (dbRoomId && userId) {
try {
await gameRoomService.leaveRoom(dbRoomId, userId);
} catch (err) {
console.error('Error removing player from room on socket leave:', err.message);
}
}
socket.to(roomId).emit('game-player-left', {
username: socket.user.username,
@@ -268,7 +337,8 @@ function setupSocketIO(io)
revealedWord: gameState.revealedWord || [],
guessedLetters: gameState.guessedLetters,
players: gameState.players,
scores: gameState.scores || {}
scores: gameState.scores || {},
timer: gameState.timerSeconds || 0
});
}
} catch (err) {
@@ -390,6 +460,7 @@ function setupSocketIO(io)
const gameState = gameRooms.get(roomId);
if (!gameState) return;
startRoomTimer(io, roomId, 60);
gameState.currentWord = data.word.toLowerCase();
gameState.revealedLetters = new Array(data.word.length).fill(false);
gameState.revealedWord = new Array(data.word.length).fill('_');
@@ -552,6 +623,8 @@ function setupSocketIO(io)
// Update round start scores for next round
gameState.roundStartScores = { ...gameState.scores };
stopRoomTimer(roomId);
io.to(roomId).emit('game-word-found', {
word: gameState.currentWord,
winner: username,
@@ -613,6 +686,7 @@ function setupSocketIO(io)
// If the drawer left and there are still enough players, choose a new drawer
if (wasDrawer && gameState.players.length >= 1)
{
stopRoomTimer(roomId);
// Pick the next player as the new drawer
gameState.currentPlayerIndex = gameState.currentPlayerIndex % gameState.players.length;
const newDrawer = gameState.players[gameState.currentPlayerIndex];
@@ -632,6 +706,7 @@ function setupSocketIO(io)
reason: 'drawer_left',
message: `${username} (dessinateur) a quitté, ${newDrawer} devient le nouveau dessinateur`
});
startRoomTimer(io, roomId, 60);
}
}
@@ -652,6 +727,7 @@ function setupSocketIO(io)
socket.on('game-end', async () => {
const roomId = socket.gameRoomId;
if (!roomId) return;
stopRoomTimer(roomId);
// Update room status to 'waiting' in database
const dbRoomId = socket.gameRoomDbId;
@@ -867,6 +943,14 @@ function setupSocketIO(io)
}
else
{
if (dbRoomId && socket.user.userId) {
try {
await gameRoomService.leaveRoom(dbRoomId, socket.user.userId);
} catch (err) {
console.error('Error removing disconnected player from room:', err.message);
}
}
// Regular player disconnect
socket.to(roomId).emit('game-player-left', {
username: socket.user.username,
+1 -1
View File
@@ -8,5 +8,5 @@ RUN apk add --no-cache openssl && \
-addext "subjectAltName=DNS:localhost,IP:127.0.0.1"
COPY src /usr/share/nginx/html
COPY nginx.conf /etc/nginx/conf.d/default.conf
EXPOSE 8080 8443
EXPOSE 443
CMD ["nginx", "-g", "daemon off;"]
+8 -9
View File
@@ -1,13 +1,9 @@
server {
listen 8080;
return 301 https://$host:8443$request_uri;
}
server {
listen 8443 ssl;
listen 443 ssl;
ssl_certificate /etc/nginx/ssl/cert.pem;
ssl_certificate_key /etc/nginx/ssl/key.pem;
error_page 497 =301 https://$host:8443$request_uri;
root /usr/share/nginx/html;
index index.html;
@@ -19,7 +15,8 @@ server {
# Backend API
location /api/ {
proxy_pass http://backend:3001;
proxy_pass https://backend:3001;
proxy_ssl_verify off;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-Proto https;
@@ -27,7 +24,8 @@ server {
# Socket.IO WebSocket proxying
location /socket.io/ {
proxy_pass http://backend:3001;
proxy_pass https://backend:3001;
proxy_ssl_verify off;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
@@ -40,9 +38,10 @@ server {
}
location /avatar/ {
proxy_pass http://backend:3001/avatar/;
proxy_pass https://backend:3001/avatar/;
proxy_http_version 1.1;
proxy_set_header Host $host;
proxy_ssl_verify off;
proxy_hide_header Content-Type;
add_header Cache-Control "public, max-age=3600";
}
Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

@@ -0,0 +1,87 @@
.shape {
/* The "Physical" properties */
position: fixed;
/* transform: translate(-50%, -50%); Optional: This makes 'left/top' refer to the CENTER of the doodle */
width: 142px;
height: 142px;
/* The "Stenciling" instructions (but no image yet!) */
-webkit-mask-size: contain;
mask-size: contain;
-webkit-mask-repeat: no-repeat;
mask-repeat: no-repeat;
/* The default "Paint" color */
background-color: white;
}
.shape:hover {
transform: scale(1.2); /* Grow by 20% when you hover the mouse over it */
transition: transform 0.3s ease; /* Make it a smooth grow */
}
/* Individual Doodle Definitions */
.doodle-0 { -webkit-mask-image: url('doodles/cat.png'); mask-image: url('doodles/cat.png'); left: 60vw; top: 35vh; }
.doodle-1 { -webkit-mask-image: url('doodles/ball.png'); mask-image: url('doodles/ball.png'); left: 10vw; top: 10vh; }
.doodle-2 { -webkit-mask-image: url('doodles/batman.png'); mask-image: url('doodles/batman.png'); left: 20vw; top: 15vh; }
.doodle-3 { -webkit-mask-image: url('doodles/building.png'); mask-image: url('doodles/building.png'); left: 30vw; top: 20vh; }
.doodle-4 { -webkit-mask-image: url('doodles/butterfly.png'); mask-image: url('doodles/butterfly.png'); left: 40vw; top: 25vh; }
.doodle-5 { -webkit-mask-image: url('doodles/car.png'); mask-image: url('doodles/car.png'); left: 50vw; top: 30vh; }
.doodle-6 { -webkit-mask-image: url('doodles/yin_yang.png'); mask-image: url('doodles/yin_yang.png'); left: 88vw; top: 12vh; }
.doodle-7 { -webkit-mask-image: url('doodles/clouds.png'); mask-image: url('doodles/clouds.png'); left: 70vw; top: 40vh; }
.doodle-8 { -webkit-mask-image: url('doodles/controls.png'); mask-image: url('doodles/controls.png'); left: 80vw; top: 45vh; }
.doodle-9 { -webkit-mask-image: url('doodles/dead.png'); mask-image: url('doodles/dead.png'); left: 90vw; top: 50vh; }
.doodle-10 { -webkit-mask-image: url('doodles/diamant.png'); mask-image: url('doodles/diamant.png'); left: 15vw; top: 55vh; }
.doodle-11 { -webkit-mask-image: url('doodles/dice.png'); mask-image: url('doodles/dice.png'); left: 25vw; top: 60vh; }
.doodle-12 { -webkit-mask-image: url('doodles/earth.png'); mask-image: url('doodles/earth.png'); left: 35vw; top: 65vh; }
.doodle-13 { -webkit-mask-image: url('doodles/egypt.png'); mask-image: url('doodles/egypt.png'); left: 45vw; top: 70vh; }
.doodle-14 { -webkit-mask-image: url('doodles/fire.png'); mask-image: url('doodles/fire.png'); left: 55vw; top: 75vh; }
.doodle-15 { -webkit-mask-image: url('doodles/fish.png'); mask-image: url('doodles/fish.png'); left: 65vw; top: 80vh; }
.doodle-16 { -webkit-mask-image: url('doodles/flag.png'); mask-image: url('doodles/flag.png'); left: 75vw; top: 85vh; }
.doodle-17 { -webkit-mask-image: url('doodles/hearts.png'); mask-image: url('doodles/hearts.png'); left: 85vw; top: 90vh; }
.doodle-18 { -webkit-mask-image: url('doodles/house.png'); mask-image: url('doodles/house.png'); left: 5vw; top: 45vh; }
.doodle-19 { -webkit-mask-image: url('doodles/idol.png'); mask-image: url('doodles/idol.png'); left: 12vw; top: 22vh; }
.doodle-20 { -webkit-mask-image: url('doodles/lotus.png'); mask-image: url('doodles/lotus.png'); left: 22vw; top: 32vh; }
.doodle-21 { -webkit-mask-image: url('doodles/mail.png'); mask-image: url('doodles/mail.png'); left: 32vw; top: 42vh; }
.doodle-22 { -webkit-mask-image: url('doodles/moon.png'); mask-image: url('doodles/moon.png'); left: 42vw; top: 52vh; }
.doodle-23 { -webkit-mask-image: url('doodles/pokeball.png'); mask-image: url('doodles/pokeball.png'); left: 52vw; top: 62vh; }
.doodle-24 { -webkit-mask-image: url('doodles/runes.png'); mask-image: url('doodles/runes.png'); left: 62vw; top: 72vh; }
.doodle-25 { -webkit-mask-image: url('doodles/shield.png'); mask-image: url('doodles/shield.png'); left: 72vw; top: 82vh; }
.doodle-26 { -webkit-mask-image: url('doodles/shiny.png'); mask-image: url('doodles/shiny.png'); left: 82vw; top: 12vh; }
.doodle-27 { -webkit-mask-image: url('doodles/snail.png'); mask-image: url('doodles/snail.png'); left: 92vw; top: 22vh; }
.doodle-28 { -webkit-mask-image: url('doodles/sound.png'); mask-image: url('doodles/sound.png'); left: 18vw; top: 82vh; }
.doodle-29 { -webkit-mask-image: url('doodles/spiral.png'); mask-image: url('doodles/spiral.png'); left: 28vw; top: 72vh; }
.doodle-30 { -webkit-mask-image: url('doodles/star.png'); mask-image: url('doodles/star.png'); left: 38vw; top: 62vh; }
.doodle-31 { -webkit-mask-image: url('doodles/stop.png'); mask-image: url('doodles/stop.png'); left: 48vw; top: 52vh; }
.doodle-32 { -webkit-mask-image: url('doodles/sun.png'); mask-image: url('doodles/sun.png'); left: 58vw; top: 42vh; }
.doodle-33 { -webkit-mask-image: url('doodles/tree.png'); mask-image: url('doodles/tree.png'); left: 68vw; top: 32vh; }
.doodle-34 { -webkit-mask-image: url('doodles/triskel.png'); mask-image: url('doodles/triskel.png'); left: 78vw; top: 22vh; }
/* 3. A quick animation for the color loop */
.loop-color {
animation: colorShift 12s infinite alternate ease-in-out;
}
@keyframes colorShift {
/* 0% and 100% are identical to create the "Infinite Circle" effect */
0% { background-color: #3075ff; } /* Royal Blue (Start) */
8% { background-color: #24a1ff; } /* Sky Blue */
17% { background-color: #1ad8ff; } /* Cyan */
25% { background-color: #1bffa7; } /* Seafoam Green */
33% { background-color: #1fff4d; } /* Bright Green */
42% { background-color: #8bff32; } /* Lime Green */
50% { background-color: #dcff38; } /* Electric Yellow */
58% { background-color: #ffbc29; } /* Golden Yellow */
67% { background-color: #ff8c4a; } /* Coral Orange */
75% { background-color: #ff1d1d; } /* Hot Red */
83% { background-color: #ff2bf3; } /* Magenta Pink */
92% { background-color: #ac37ff; } /* Electric Purple */
100% { background-color: #3075ff; } /* Royal Blue (Seamless Loop) */
}
@@ -0,0 +1,113 @@
const maxdoodles = 34;
// /////////////////////////////////////////////////////////////////////////////////////////>\
// container for all doodles, create them
class DoodleContainer {
constructor(parent) {
this.parent = parent;
this.obj = document.createElement('div');
Object.assign(this.obj.style, {
width: '100vw',
height: '100vw',
});
this.createAllDoodles();
parent.append(this.obj);
this.randomizeAnimationStarts();
}
createAllDoodles() {
for (let i = 0; i <= maxdoodles; i++) {
let d = document.createElement('div');
d.classList.add('shape', 'doodle-' + i, 'loop-color');
d.id = 'shape' + i;
this.obj.append(d);
d.addEventListener('click', () => {
console.log(`hi from ${d.id}!`);
})
}
}
startSmoothRandomMove(id, speed = 2) {
const el = document.getElementById(id);
if (!el)
return;
// 1. Get initial pixel position or pick random if CSS isn't loaded yet
const rect = el.getBoundingClientRect();
const state = {
x: rect.left || Math.random() * (window.innerWidth - 142),
y: rect.top || Math.random() * (window.innerHeight - 142),
angle: Math.random() * Math.PI * 2,
speed: speed
};
function update() {
// 2. Refresh screen boundaries every frame
const screenW = window.innerWidth;
const screenH = window.innerHeight;
const shapeSize = 142; // Matches your CSS width/height
// 3. Calculate next step
state.x += Math.cos(state.angle) * state.speed;
state.y += Math.sin(state.angle) * state.speed;
// 4. BOUNCE LOGIC
// Horizontal check
if (state.x <= 0) {
state.x = 0;
state.angle = Math.PI - state.angle;
} else if (state.x + shapeSize >= screenW) {
state.x = screenW - shapeSize;
state.angle = Math.PI - state.angle;
}
// Vertical check
if (state.y <= 0) {
state.y = 0;
state.angle = -state.angle;
} else if (state.y + shapeSize >= screenH) {
state.y = screenH - shapeSize;
state.angle = -state.angle;
}
// 5. Apply position using pixels for precision
el.style.left = state.x + "px";
el.style.top = state.y + "px";
requestAnimationFrame(update);
}
requestAnimationFrame(update);
}
randomizeAnimationStarts() {
for (let i = 0; i <= maxdoodles; i++) {
const randomSpeed = 1 + Math.random() * 3;
this.startSmoothRandomMove(`shape${i}`, randomSpeed);
}
}
}
// /////////////////////////////////////////////////////////////////////////////////////////>
// all loop-color have the same @colorShift animation cycle, this disynchronize them
function randomizeColorsStarts() {
const shapes = document.querySelectorAll('.loop-color');
shapes.forEach(shape => {
// Pick a random number between 0 and 10 (since your loop is 10s)
const randomDelay = Math.random() * - 15;
// Apply it directly to the element's style
shape.style.animationDelay = randomDelay + "s";
});
}
const a = new DoodleContainer(document.body);
// Call this once when the script loads
randomizeColorsStarts();
Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 994 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1018 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 955 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1022 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 887 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1000 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

File diff suppressed because it is too large Load Diff
@@ -0,0 +1,43 @@
<!doctype html>
<html lang="fr">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<title>Lobby</title>
<link rel="stylesheet" href="doodle.css">
<link rel="stylesheet" href="game.css" />
<!-- <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=Cinzel+Decorative:wght@400;700&display=swap" rel="stylesheet" /> -->
<script src="doodle.js" defer></script>
<script type="module" src="../trans/app.js"></script>
</head>
<body>
<h1 class="title">
<span>L</span>
<span>o</span>
<span>b</span>
<span>b</span>
<span>y</span>
</h1>
<nav class="menu" aria-label="Menu principal">
<button class="menu__item" data-action="login" aria-label="Login">Login</button>
<button class="menu__item" data-action="chat" aria-label="Global chat">Global chat</button>
<button class="menu__item" data-action="avatar" aria-label="Avatar">Avatar</button>
<button class="menu__item" data-action="friends" aria-label="Amis">Amis</button>
</nav>
<nav class="game" aria-label="Game">
<button class="game__item" data-action="Home page" aria-label="Home Page"
onclick="window.location.href='index.html'">Home Page</button>
</nav>
<div class="page" aria-label="Page">
<button class="page__item" data-action="gameroom" aria-label="Game Rooms">Game Rooms</button>
</div>
</body>
</html>
+98 -693
View File
@@ -1,21 +1,8 @@
/* ============================================
TRANSCENDENCE - Main Stylesheet
Convention: BEM (Block__Element--Modifier)
============================================ */
/* ============================================
CSS VARIABLES
============================================ */
/* ///////////////////////////////////////////////////////// */
:root {
--color-primary: #0066cc;
--color-primary-hover: #0052a3;
--color-success: #3cff01;
--color-success-dark: #28a745;
--color-error: #ff4d4d;
--color-warning: #ffc107;
--color-github: #24292e;
--color-bg: #a3a3a3;
--custom-value: hello;
--app-background-base: radial-gradient(
circle at top,
@@ -24,729 +11,147 @@
);
--app-background-image: url("./assets/background.png");
--color-surface: #222;
--color-surface-light: #333;
--color-text: #fff;
--color-text-muted: #aaa;
--font-size-base: 10px;
--font-size-sm: 1.2rem;
--font-size-md: 1.4rem;
--font-size-lg: 1.6rem;
--font-size-xl: 3rem;
--spacing-xs: 4px;
--spacing-sm: 8px;
--spacing-md: 12px;
--spacing-lg: 16px;
--spacing-xl: 24px;
--radius-sm: 4px;
--radius-md: 6px;
--radius-lg: 12px;
--radius-full: 50%;
--shadow-sm: 0 2px 4px rgba(0, 0, 0, 0.3);
--shadow-md: 0 4px 8px rgba(0, 0, 0, 0.5);
--shadow-lg: 0 8px 16px rgba(0, 0, 0, 0.5);
--transition-fast: 150ms ease;
--transition-normal: 250ms ease;
--z-menu: 2;
--z-window: 100;
--z-modal: 200;
--num-value: 10px;
--black: #000000;
}
/* ============================================
RESET & BASE
============================================ */
*,
*::before,
*::after {
box-sizing: border-box;
}
/* ///////////////////////////////////////////////////////// */
*, *::before, *::after {
html {
height: 100%;
background-image:
var(--app-background-image),
var(--app-background-base);
background-size:
contain,
cover;
background-position:
center,
center;
background-repeat:
no-repeat,
no-repeat;
}
body {
margin: 0;
width: 70%;
min-width: 800px;
margin: 0 auto;
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
color: var(--color-text);
line-height: 1.5;
}
/* ============================================
TYPOGRAPHY
============================================ */
.title {
position: absolute;
top: 20px;
left: 50%;
transform: translateX(-50%);
text-transform: uppercase;
display: flex;
align-items: center;
justify-content: center;
gap: 20px;
font-size: var(--font-size-xl);
line-height: 1.5; /* inherited */
word-spacing: 1.4px; /* inherited */
font-size: 20px;
font-family: 'Times New Roman', serif; /* inherited */
color: var(--black); /* inherited */
text-align: center;
text-shadow: 2px 2px 10px black;
z-index: 1;
font-family: "Cinzel Decorative", cursive;
color: rgba(248, 252, 2, 0.6);
color: #696969;
margin: 0;
padding: var(--spacing-md);
/* Rectangle + rounded corners */
background-color: rgba(247, 7, 67, 0.6);
border: 2px solid rgba(0, 0, 0, 0.6);
border-radius: 15px;
}
/* ============================================
MENU
============================================ */
.menu {
position: fixed;
top: 0;
left: 50px;
padding: 0;
margin: 0;
z-index: var(--z-menu);
background-color: var(--black);
display: flex;
flex-direction: column;
gap: var(--spacing-xs);
}
.menu__item {
background: var(--color-surface);
color: var(--color-text);
border: 1px solid var(--color-surface-light);
padding: var(--spacing-sm) var(--spacing-md);
font-size: var(--font-size-md);
cursor: pointer;
transition: all var(--transition-fast);
text-align: left;
}
.menu__item:hover {
background: var(--color-surface-light);
font-size: var(--font-size-lg);
}
.menu__item--active {
background: var(--color-primary);
border-color: var(--color-primary);
}
/* ============================================
GAME
============================================ */
.game {
position: fixed;
top: 0;
right: 50px;
padding: 0;
margin: 0;
z-index: var(--z-menu);
display: flex;
flex-direction: column;
gap: var(--spacing-xs);
}
.game__item {
background: var(--color-surface);
color: var(--color-text);
border: 1px solid var(--color-surface-light);
padding: var(--spacing-sm) var(--spacing-md);
font-size: var(--font-size-md);
cursor: pointer;
transition: all var(--transition-fast);
text-align: right;
}
.game__item:hover {
background: var(--color-surface-light);
font-size: var(--font-size-lg);
}
.game__item--active {
background: var(--color-primary);
border-color: var(--color-primary);
}
/* ============================================
BUTTONS
============================================ */
.btn {
display: inline-flex;
align-items: center;
justify-content: center;
padding: var(--spacing-sm) var(--spacing-md);
font-size: var(--font-size-md);
font-weight: 500;
border: none;
border-radius: var(--radius-md);
cursor: pointer;
transition: all var(--transition-fast);
text-decoration: none;
align-items: center;
}
.btn:hover {
opacity: 0.9;
transform: translateY(-1px);
}
.container-1 {
display: flex;
justify-content: center;
align-items: center;
.btn:active {
transform: translateY(0);
}
.btn--primary {
background: var(--color-primary);
color: var(--color-text);
}
.btn--primary:hover {
background: var(--color-primary-hover);
}
.btn--secondary {
background: var(--color-surface-light);
color: var(--color-text);
}
.btn--success {
background: var(--color-success-dark);
color: var(--color-text);
}
.btn--danger {
background: var(--color-error);
color: var(--color-text);
}
.btn--github {
background: var(--color-github);
color: var(--color-text);
}
.btn--ghost {
background: transparent;
color: var(--color-text);
border: 1px solid var(--color-surface-light);
}
/* ============================================
INPUTS
============================================ */
.input {
width: 100%;
padding: var(--spacing-sm) var(--spacing-md);
font-size: var(--font-size-md);
background: var(--color-surface);
color: var(--color-text);
border: 1px solid var(--color-surface-light);
border-radius: var(--radius-md);
transition: border-color var(--transition-fast);
margin: 5px;
position: relative;
min-height: 200px;
}
.input:focus {
outline: none;
border-color: var(--color-primary);
/* ///////////////////////////////////////////////////////// */
.button {
color: red;
margin: 5px 50px;
padding: 5px 50px;
}
.input::placeholder {
color: var(--color-text-muted);
}
.input-group {
display: flex;
flex-direction: column;
gap: var(--spacing-sm);
}
/* ============================================
WINDOWS
============================================ */
.window {
position: fixed;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
background: var(--color-bg);
border: 2px ridge var(--color-text);
color: var(--color-text);
z-index: var(--z-window);
display: none;
flex-direction: column;
min-width: 280px;
box-shadow: var(--shadow-lg);
}
.window--visible {
display: flex;
}
.window--left {
left: 25%;
}
.window--right {
left: 75%;
}
.window__header {
display: flex;
justify-content: space-between;
align-items: center;
padding: var(--spacing-sm) var(--spacing-md);
background: var(--color-surface);
cursor: move;
user-select: none;
}
.window__title {
font-weight: 500;
font-size: var(--font-size-md);
}
.window__close {
cursor: pointer;
font-size: var(--font-size-lg);
opacity: 0.8;
transition: opacity var(--transition-fast);
background: none;
border: none;
color: var(--color-text);
padding: 0;
line-height: 1;
}
.window__close:hover {
opacity: 1;
}
.window__body {
padding: var(--spacing-md);
display: flex;
flex-direction: column;
gap: var(--spacing-sm);
flex: 1;
overflow: auto;
}
/* ============================================
MESSAGES
============================================ */
.message {
font-size: var(--font-size-sm);
padding: var(--spacing-xs);
border-radius: var(--radius-sm);
}
.message--success {
color: var(--color-success);
}
.message--error {
color: var(--color-error);
}
.message--info {
color: var(--color-text-muted);
}
/* ============================================
LOGIN WINDOW
============================================ */
.login {
width: 320px;
}
.login__form {
display: flex;
flex-direction: column;
gap: var(--spacing-sm);
}
.login__actions {
display: flex;
gap: var(--spacing-sm);
margin-top: var(--spacing-xs);
}
.login__divider {
display: flex;
align-items: center;
gap: var(--spacing-sm);
color: var(--color-text-muted);
font-size: var(--font-size-sm);
margin: var(--spacing-sm) 0;
}
.login__divider::before,
.login__divider::after {
content: '';
flex: 1;
height: 1px;
background: var(--color-surface-light);
}
/* ============================================
CHAT WINDOW
============================================ */
.chat {
width: 380px;
height: 400px;
}
.chat__output {
flex: 1;
overflow-y: auto;
padding: var(--spacing-sm);
background: var(--color-surface);
border-radius: var(--radius-md);
display: flex;
flex-direction: column;
gap: var(--spacing-sm);
min-height: 150px;
}
.chat__message {
padding: var(--spacing-xs) var(--spacing-sm);
background: var(--color-surface-light);
border-radius: var(--radius-sm);
font-size: var(--font-size-sm);
}
.chat__message--own {
background: var(--color-primary);
align-self: flex-end;
}
.chat__friend-indicator {
.button-1 {
display: inline-block;
width: 8px;
height: 8px;
background-color: var(--color-success);
border-radius: 50%;
margin-right: var(--spacing-xs);
vertical-align: middle;
}
.chat__system {
color: var(--color-text-muted);
font-size: var(--font-size-sm);
font-style: italic;
padding: 10px 20px;
background-color: #000000;
color: #8e8e8e;
text-align: center;
text-decoration: none;
font-size: 16px;
cursor: pointer;
border: 3px solid #363636;
border-radius: 6px;
transition: background-color 0.3s;
}
.button-1:hover {
background-color: rgb(202, 135, 10);
color: black;
}
.chat__system--error {
color: var(--color-error);
}
.chat__system--success {
color: var(--color-success);
}
.chat__input-container {
display: flex;
gap: var(--spacing-sm);
margin-top: var(--spacing-sm);
}
.chat__input {
flex: 1;
}
.chat__controls {
display: flex;
gap: var(--spacing-sm);
margin-top: var(--spacing-sm);
}
/* ============================================
AVATAR WINDOW
============================================ */
.avatar-window {
width: 360px;
}
.avatar__preview {
width: 120px;
height: 120px;
object-fit: cover;
border-radius: var(--radius-full);
border: 3px solid var(--color-text);
box-shadow: var(--shadow-md);
background: var(--color-surface);
align-self: center;
}
.avatar__username {
font-size: var(--font-size-lg);
font-weight: 600;
text-align: center;
color: var(--color-text);
margin-top: var(--spacing-sm);
}
.avatar__controls {
display: flex;
flex-direction: column;
gap: var(--spacing-sm);
align-items: center;
}
.avatar__file-input {
display: none;
}
/* ============================================
STATS WINDOW
============================================ */
.stats-window {
width: 320px;
}
.stats__avatar {
width: 72px;
height: 72px;
object-fit: cover;
border-radius: var(--radius-full);
border: 2px solid var(--color-text);
align-self: center;
display: block;
margin: 0 auto var(--spacing-xs);
}
.stats__username {
font-size: var(--font-size-lg);
font-weight: 600;
text-align: center;
color: #000;
margin-bottom: var(--spacing-md);
}
.stats__section {
margin-bottom: var(--spacing-md);
}
.stats__section-title {
font-size: var(--font-size-sm);
font-weight: 700;
text-transform: uppercase;
letter-spacing: 0.08em;
color: var(--color-primary);
border-bottom: 1px solid var(--color-surface-light);
padding-bottom: var(--spacing-xs);
margin-bottom: var(--spacing-xs);
}
.stats__section-body {
display: flex;
flex-direction: column;
gap: 4px;
}
.stats__row {
display: flex;
justify-content: space-between;
font-size: var(--font-size-sm);
padding: 3px 0;
}
.stats__label {
color: #333;
}
.stats__value {
font-weight: 600;
color: #000;
}
.stats__loading {
font-size: var(--font-size-sm);
color: #333;
text-align: center;
padding: var(--spacing-sm) 0;
}
/* ============================================
EASTER EGG BUTTON
============================================ */
/* .easter-egg {
/* ///////////////////////////////////////////////////////// */
.button-trans {
/* SIZE */
position: absolute;
top: 20%;
left: 50%;
transform: translateX(-50%);
z-index: 1;
background: var(--color-surface);
color: var(--color-text);
border: 1px solid var(--color-surface-light);
padding: var(--spacing-sm) var(--spacing-md);
cursor: pointer;
font-size: var(--font-size-md);
border-radius: var(--radius-md);
transition: all var(--transition-fast);
}
.easter-egg:hover {
background: var(--color-error);
border-color: var(--color-error);
} */
width: 500px;
height: 200px;
/* ============================================
UTILITIES
============================================ */
.hidden {
display: none !important;
}
.visually-hidden {
position: absolute;
width: 1px;
height: 1px;
padding: 0;
margin: -1px;
overflow: hidden;
clip: rect(0, 0, 0, 0);
border: 0;
}
.text-center {
text-align: center;
}
.flex-center {
/* TEXT */
font-family: "Roboto";
font-size: 62px;
letter-spacing: -10px;
display: flex;
align-items: center;
justify-content: center;
}
/* ============================================
FRIENDS WINDOW
============================================ */
.friends-window {
width: 400px;
height: 450px;
}
/* Background */
background-image: url("./assets/background.png");
background-position: center;
background-repeat: no-repeat;
background-size: 150%;
/* Borders */
border-radius: 20px;
border-radius: 20px;
border: 5px solid transparent; /* keep space for the shadow */
background-clip: padding-box;
/* metallic effect */
box-shadow:
0 0 0 5px #c0c0c0 inset, /* inner shine */
0 0 0 2px rgba(255,255,255,0.3) inset; /* subtle highlight */
.friends__tabs {
display: flex;
gap: var(--spacing-xs);
margin-bottom: var(--spacing-sm);
}
.friends__tab {
flex: 1;
padding: var(--spacing-sm);
background: var(--color-surface);
border: 1px solid var(--color-surface-light);
color: var(--color-text);
/* OTHER */
cursor: pointer;
font-size: var(--font-size-sm);
transition: all var(--transition-fast);
transition: transform 0.3s ease, box-shadow 0.3s ease;
}
.friends__tab:hover {
background: var(--color-surface-light);
.button-trans:hover {
transform: translateX(-50%) scale(1.02);
box-shadow:
0 0 20px 5px #fff inset,
0 0 20px 5px rgba(255,255,255,0.3) inset;
}
.friends__tab--active {
background: var(--color-primary);
border-color: var(--color-primary);
/* ///////////////////////////////////////////////////////// */
.button-test {
margin-right: auto;
margin-left: 20px;
}
.friends__content {
/* ///////////////////////////////////////////////////////// */
.footer_div {
display: flex;
flex-direction: column;
flex: 1;
overflow: hidden;
justify-content: space-around;
/* padding: 20px; */
/* margin-top: 80px;
margin-bottom: 100px; */
}
.friends__search {
display: flex;
gap: var(--spacing-sm);
margin-bottom: var(--spacing-sm);
}
.friends__search .input {
flex: 1;
}
.friends__list {
flex: 1;
overflow-y: auto;
display: flex;
flex-direction: column;
gap: var(--spacing-sm);
}
.friends__item {
display: flex;
align-items: center;
gap: var(--spacing-sm);
padding: var(--spacing-sm);
background: var(--color-surface);
border-radius: var(--radius-md);
}
.friends__avatar {
width: 40px;
height: 40px;
border-radius: var(--radius-full);
object-fit: cover;
border: 2px solid var(--color-surface-light);
}
.friends__name {
flex: 1;
font-size: var(--font-size-md);
font-weight: 500;
}
.friends__actions {
display: flex;
gap: var(--spacing-xs);
}
.friends__actions .btn {
padding: var(--spacing-xs) var(--spacing-sm);
font-size: var(--font-size-sm);
}
.friends__empty {
.ico_footer {
text-align: center;
color: var(--color-text-muted);
padding: var(--spacing-lg);
width: 25px;
vertical-align: top;
/* padding-right: 5px; */
}
a {
text-decoration: none;
color: #5c5c5c;
}
a:hover {
color: rgb(218, 145, 12);
}
/* ///////////////////////////////////////////////////////// */
+46 -24
View File
@@ -1,32 +1,54 @@
<!doctype html>
<html lang="fr">
<!DOCTYPE html>
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<title>Transcendence.io</title>
<link rel="stylesheet" href="index.css" />
<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=Cinzel+Decorative:wght@400;700&display=swap" rel="stylesheet" />
<link rel="stylesheet" href="./index.css" />
<script type="module" src="./index.js"></script>
</head>
<body>
<h1 class="title">Transcendence.io</h1>
<nav class="menu" aria-label="Menu principal">
<button class="menu__item" data-action="login" aria-label="Login">Login</button>
<button class="menu__item" data-action="chat" aria-label="Global chat">Global chat</button>
<button class="menu__item" data-action="avatar" aria-label="Avatar">Avatar</button>
<button class="menu__item" data-action="friends" aria-label="Amis">Amis</button>
<button class="menu__item" data-action="logout" aria-label="Logout">Logout</button>
</nav>
<div id="header-1" class="container-1"
style="">
<div id="button-test" class="button-1 button-test multicolor" onclick="window.location.href = 'test/index.html';">TEST</div>
<div id="button-trans" class="button-trans multicolor">TRANSCENDENCE</div>
</div>
<nav class="game" aria-label="Game">
<button class="game__item" data-action="new_game" aria-label="Start new game"
onclick="window.location.href='game/game.html'">Start new game</button>
<button class="game__item" data-action="tetris" aria-label="Tetris"
onclick="window.location.href='tetris/tetris.html'">Tetris</button>
</nav>
<img id="wiskas" style="margin: auto; display: block;" src="webcat/web_cat_img/wiskas-the-third.jpg">
<section style="display: flex;
justify-content: center;
width: 1000px;
margin: 0 auto;">
<p>I, am wiskas-the-third,
We are the cat company, we dont need to present our self for you already know
who we are, we created the internet, and we are still managing it now<br>
We at CAT are the admin, creator, and workers of the internet
Everytime a human goes to sleep, a cat start its shift, 1 billion pair of whiskers that are always here for you
Why? because we are philantropists, dont question it. Our goals are beyond your understanding
the internet was created by us, for us, and you should be glad we allow you to use it.
</p>
</section>
<section style="display: flex;">
<button style="margin-right: 50px;" class="button-1 multicolor" onclick="window.location.href = 'webcat/biblio.html';">
Latest News</button><br>
<button style="margin-left: 50px;" class="button-1 multicolor" onclick="window.location.href = 'webcat/staff/staff.html';">
meet the staff</button><br>
</section>
<footer>
<br><br><br>
<div class="footer_div" style="margin-top: 100px;">
<img class="ico_footer" src="webcat/web_cat_img/facebook_logo.png">
<img class="ico_footer" src="webcat/web_cat_img/insta_logo.png">
<img class="ico_footer" src="webcat/web_cat_img/twitter_logo.png">
</div>
<div class="footer_div" style="margin-bottom: 50px;">
<a href="https://www.facebook.com/">MIAOUBOOK</a>
<a href="https://www.instagram.com/">INSTAMIA</a>
<a href="https://twitter.com/">BLUE-SNACK</a>
</div>
<a href="./webcat/ml/mentions_legales.html">- LEGAL NOTICES -<br>(boring stuff, really, dont go look into this, i mean we are obligated to include it, but it will bore you, like, really)
<br>Dont do it! every seconds you spend in this next page, a kitten dies. so dont</a>
</footer>
<script type="module" src="app.js"></script>
</body>
</html>
+54
View File
@@ -0,0 +1,54 @@
import { updateElement } from "./test/tools.js";
import { colorizeText } from "./tools.js";
// //////////////////////////////////////////]
let div2 = document.createElement('div')
document.body.append(div2)
let button1 = document.createElement('button')
div2.append(button1)
button1.textContent = 'game-lobby'
button1.addEventListener('click', () => {
window.location.href = './game2/game.html';
})
let button2 = document.createElement('button')
div2.append(button2)
button2.textContent = 'tetris'
button2.addEventListener('click', () => {
window.location.href = './tetris/tetris.html';
})
let button4 = document.createElement('button')
div2.append(button4)
button4.textContent = 'test'
button4.addEventListener('click', () => {
window.location.href = './test/index.html';
})
let img = document.getElementById('wiskas');
img.before(div2)
// apply multicolor to .multicolor
colorizeText();
/* ///////////////////////////////////////////////////////// */
// make transcendence button move via: .button-trans
function updateButtonTranscendence(move) {
const btn = document.querySelector('.button-trans');
btn.addEventListener('mousemove', e => {
const rect = btn.getBoundingClientRect();
const x = ((e.clientX - rect.left) / rect.width - 0.5) * move;
const y = ((e.clientY - rect.top) / rect.height - 0.5) * move;
btn.style.backgroundPosition = `calc(50% + ${x}px) calc(50% + ${y}px)`;
});
btn.addEventListener('mouseleave', () => {
btn.style.backgroundPosition = 'center';
});
btn.addEventListener('click', () => {
window.location.href = './trans/index2.html';
});
}
/* ///////////////////////////////////////////////////////// */
updateButtonTranscendence(100);
+188
View File
@@ -0,0 +1,188 @@
.test {/* =======================
🎨 COLORS & BACKGROUND
======================= */
color: red;
background-color: blue;
background-image: url(img.jpg);
background-size: cover;
background-position: center;
background-repeat: no-repeat;
opacity: 0.5;
/* =======================
📏 SIZE & SPACING
======================= */
width: 200px;
height: 100px;
min-width: 100px;
max-width: 500px;
padding: 10px;
margin: 20px;
box-sizing: border-box;
/* shorthand */
margin: 10px 20px; /* top/bottom left/right */
padding: 10px 20px 5px 0; /* top right bottom left */
/* =======================
📍 POSITIONING
======================= */
position: static;
position: relative;
position: absolute;
position: fixed;
position: sticky;
top: 10px;
left: 20px;
right: 0;
bottom: 0;
z-index: 10;
/* =======================
📦 DISPLAY & LAYOUT
======================= */
display: block;
display: inline;
display: inline-block;
display: none;
display: flex; /* children can be controled with: justify-content (horizontal) / align-items (vertical) */
display: grid;
/* =======================
🔧 FLEXBOX
======================= */
display: flex;
flex-direction: row; /* row | column */
justify-content: center; /* main axis */
align-items: center; /* cross axis */
gap: 10px;
/* common */
justify-content: space-between;
justify-content: space-around;
justify-content: space-evenly;
/* =======================
🧱 GRID
======================= */
display: grid;
grid-template-columns: 1fr 1fr 1fr;
grid-template-rows: auto;
gap: 10px;
/* =======================
🔤 TEXT & FONT
======================= */
font-size: 16px;
font-weight: bold;
font-family: Arial, sans-serif;
text-align: center;
text-decoration: underline;
text-transform: uppercase;
line-height: 1.5;
letter-spacing: 2px;
/* =======================
🟦 BORDER & OUTLINE
======================= */
border: 1px solid black;
border-width: 2px;
border-style: dashed;
border-color: red;
border-radius: 10px;
outline: 2px solid blue;
/* =======================
👁️ VISIBILITY
======================= */
display: none;
visibility: hidden;
overflow: hidden;
overflow: scroll;
overflow: auto;
/* =======================
🎬 TRANSITIONS & EFFECTS
======================= */
transition: all 0.3s ease;
transform: translateX(50px);
transform: rotate(45deg);
transform: scale(1.1);
}
/* hover example */
:hover {
transform: scale(1.1);
}
/* =======================
🧠 SELECTORS
======================= */
/* basic */
div {} /* tag */
.class {} /* class */
#id {} /* id */
* {} /* all elements */
/* grouping */
div, p, span {} /* multiple selectors */
/* combinators */
div p {} /* any descendant */
div > p {} /* direct child */
div + p {} /* next sibling */
div ~ p {} /* all following siblings */
/* attribute selectors */
input[type="text"] {}
a[href] {}
button[class*="btn"] {} /* contains */
button[class^="btn"] {} /* starts with */
button[class$="btn"] {} /* ends with */
/* pseudo-classes (state) */
button:hover {}
input:focus {}
a:active {}
a:visited {}
input:checked {}
:nth-child(2) {}
:nth-child(odd) {}
:nth-child(even) {}
:not(.active) {}
/* pseudo-elements (virtual parts) */
::before {}
::after {}
::placeholder {}
::first-letter {}
::first-line {}
/* combined examples */
button.primary:hover {}
div#main.content {}
ul li:first-child {}
input:focus::placeholder {}
/* universal + pseudo */
*::before {}
*::after {}
/* =======================
⚡ SHORTHANDS
======================= */
.test2 {
background: red url(img.jpg) no-repeat center/cover;
border: 2px solid black;
font: bold 16px Arial;
margin: 10px 20px;
padding: 5px 10px;
}
+123
View File
@@ -0,0 +1,123 @@
// SIZE
box.style.width = "200px";
box.style.height = "100px";
box.style.minWidth = "100px";
box.style.maxWidth = "500px";
{
display: "flex" // flex | inline-flex | block | inline | none
justifyContent: "flex-start" // flex-start | flex-end | center | space-between | space-around | space-evenly
alignItems: "stretch" // stretch | flex-start | flex-end | center | baseline
}
// POSITION
box.style.position = "absolute";
box.style.top = "50px";
box.style.left = "100px";
box.style.right = "20px";
box.style.bottom = "10px";
box.style.zIndex = "10";
// SPACING
box.style.margin = "10px";
box.style.padding = "20px";
box.style.marginTop = "10px";
box.style.paddingLeft = "5px";
// BACKGROUND & COLORS
box.style.background = "red";
box.style.backgroundColor = "blue";
box.style.color = "white";
// BORDER
box.style.border = "2px solid black";
box.style.borderRadius = "10px";
// TEXT
box.style.fontSize = "20px";
box.style.fontWeight = "bold";
box.style.textAlign = "center";
// DISPLAY & VISIBILITY
box.style.display = "block";
box.style.visibility = "visible";
box.style.opacity = "0.5";
// TRANSFORM
box.style.transform = "translateX(100px)";
box.style.transform = "translate(50px, 20px)";
box.style.transform = "scale(1.5)";
box.style.transform = "rotate(45deg)";
box.style.transform = "translateX(100px) scale(2)";
// ANIMATION & TRANSITION
box.style.transition = "all 0.3s ease";
box.style.animation = "move 2s linear";
// INTERACTION
box.style.cursor = "pointer";
box.style.pointerEvents = "none";
// /////////////////////////////////////////////////////>
// /////////////////////////////////////////////////////>
// CONTENT
el.textContent = "Hello"; // plain text
el.innerHTML = "<b>Hello</b>"; // HTML content
el.innerText = "Hello"; // like textContent but respects line breaks
// ATTRIBUTES
el.id = "myDiv"; // element ID
el.className = "box highlight"; // full class string
el.classList.add("active"); // add a class
el.classList.remove("hidden"); // remove a class
el.classList.toggle("open"); // toggle a class
el.title = "Tooltip text"; // title attribute
el.value = "42"; // input value
el.src = "image.png"; // img, video, audio src
el.href = "https://example.com"; // anchor href
el.alt = "alternative text"; // img alt
// DOM STRUCTURE
el.appendChild(child); // add child
el.append(child1, child2); // add multiple children
el.prepend(child); // add at start
el.remove(); // remove self
el.replaceWith(newEl); // replace element
el.cloneNode(true); // copy element (deep if true)
// DATA & CUSTOM
el.dataset.id = "123"; // data-id attribute
el.dataset.name = "box1"; // data-name attribute
// EVENTS
el.onclick = () => {}; // direct event assignment
el.onmouseover = () => {};
el.addEventListener("click", () => {}); // preferred
el.removeEventListener("click", handler);
// VISIBILITY & FOCUS
el.hidden = true; // hides element
el.focus(); // focus element
el.blur(); // remove focus
el.tabIndex = 0; // make element focusable
// DIMENSIONS & POSITION (read-only or get)
el.clientWidth;
el.clientHeight;
el.offsetWidth;
el.offsetHeight;
el.offsetTop;
el.offsetLeft;
el.scrollWidth;
el.scrollHeight;
el.scrollTop;
el.scrollLeft;
// OTHER
el.checked = true; // checkbox / radio
el.selected = true; // option element
el.disabled = true; // input/button
el.readOnly = true; // input/textarea
el.name = "username"; // input / form element
el.type = "text"; // input type
@@ -0,0 +1,55 @@
import fetch from 'node-fetch';
import express, { response } from 'express';
import cors from 'cors';
const app = express();
const PORT = 3000//process.env.PORT || 3000;
app.use(express.json());
app.use(cors());
let token;
async function set_token()
{
fetch("https://api.intra.42.fr/oauth/token", {
method: "POST",
body: "grant_type=client_credentials&client_id=u-s4t2ud-c226cd35cd1ac08a4c6668deee1c64d7d67a13a766aee672acafd4a1522d483c&client_secret=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",
headers: {
"User-Agent": "agallon",
'Content-Type': 'application/x-www-form-urlencoded',}
})
.then(response => {
return response.json();
})
.then(data => {
token = data;
setTimeout(set_token, token.expires_in);
})
.catch(error => {
console.error('Error fetching token:', error);
});
}
set_token();
app.get('/proxy/profile/:login', async (req, res) => {
const { login } = req.params;
const profileURL = `https://api.intra.42.fr/v2/users/${login}`;
try {
const response = await fetch(profileURL, {
headers: {
"Authorization": `Bearer ${token.access_token}`}});
console.log(`response.status = ${response.status}`);
if (response.status !== 200) {
throw new Error('User not found');
}
const data = await response.json();
res.status(200).json(data);
} catch (error) {
console.error('Error fetching profile:', error);
res.status(500).json({ error: 'Failed to fetch profile' });
}
});
app.listen(PORT, () => {
console.log(`Proxy server running on port ${PORT}`);
});
@@ -0,0 +1,26 @@
import {checkIfLoggedIn} from './tools.js';
export class Header {
constructor() {
this.obj = document.createElement('div');
Object.assign(this.obj.style, {
});
let play = document.createElement('span');
let title = document.createElement('span');
let login = document.createElement('span');
play.textContent = "PLAY";
if (checkIfLoggedIn())
title.textContent = "Welcome back you!";
else
title.textContent = "Welcome to CAT !";
this.obj.append(play);
this.obj.append(title);
this.obj.append(login);
}
}
@@ -0,0 +1,44 @@
export class Popup {
constructor(msg, parent = document.body) {
this.msg = msg;
this.parent = parent;
this.obj = document.createElement('span');
this.obj.className = "popup";
this.obj.textContent = "";
this.obj.style.opacity = "0";
this.run();
}
async create() {
this.parent.appendChild(this.obj);
this.obj.style.transition = "opacity 0.5s ease";
requestAnimationFrame(() => {
this.obj.style.opacity = "1";
});
await new Promise(r => setTimeout(r, 500));
}
async write(speed = 50) {
for (let i = 0; i < this.msg.length; i++) {
this.obj.textContent += this.msg[i];
await new Promise(r => setTimeout(r, speed));
}
}
async remove() {
await new Promise(r => setTimeout(r, 2000));
this.obj.style.transition = "opacity 0.3s ease";
this.obj.style.opacity = "0";
await new Promise(r => setTimeout(r, 300));
if (this.obj.parentNode) {
this.obj.parentNode.removeChild(this.obj);
}
}
async run() {
await this.create();
await this.write();
await this.remove();
}
}
@@ -0,0 +1,9 @@
import { STORAGE_KEYS } from '../../core/config.js';
export function checkIfLoggedIn() {
const token = localStorage.getItem(STORAGE_KEYS.AUTH_TOKEN);
if (token) {
return true;
}
return false;
}
@@ -0,0 +1,43 @@
/* ////////////////////////////////////////// */
.box {
background: #142d4a;
height: 200px;
aspect-ratio: 1/1;
border-radius: 10px;
position: relative;
display: flex;
justify-content: center;
align-items: center;
}
@property --deg {
syntax: '<angle>';
inherits: true;
initial-value: 0deg;
}
.box::before,
.box::after {
content: "";
position: absolute;
height: 100%;
width: 100%;
background: conic-gradient(
from var(--deg) at center,
#00c3ff,
#4d0199,
#6300c6,
#009dcd
);
border-radius: inherit;
z-index: -2;
padding: 2px;
animation: autoRotate 2s linear infinite;
}
.box::after {
filter: blur(10px);
}
@keyframes autoRotate {
to{ --deg: 360deg; }
}
@@ -0,0 +1,17 @@
<!DOCTYPE html>
<head>
<link rel="stylesheet" href="../game2/game.css" />
<link rel="stylesheet" href="./style.css" />
<script type="module" src="./script.js"></script>
</head>
<body style="background-color: black; display: flex; justify-content: center; align-items: center;">
<!--
<div class="container">
<div class="item item-1">Item 1</div>
<div class="item item-2">Item 2</div>
<div class="item item-3">Item 3</div>
</div> -->
<div></div>
<div class="box"></div>
</body>
</html>
@@ -0,0 +1,17 @@
// import { LoginSidebar } from "./loginSidebar.js";
import { Sidebar } from "./sidebar.js";
import { updateElement } from "./tools.js";
let b = updateElement({
classList: ['container2'],
additionalStyles: {
display: 'flex',
justifyContent: 'flex-end',
alignItems: 'center'
}
});
new Sidebar();
// new LoginSidebar();
// new Sidebar();
@@ -0,0 +1,93 @@
import { updateElement } from "./tools.js";
import { windowRegistry } from '../core/windows.js';
import { LoginWindow } from '../windows/login.js';
import { LogoutWindow } from '../windows/logout.js';
import { GlobalChat } from '../windows/global_chat.js';
import { AvatarWindow } from '../windows/avatar.js';
import { FriendsWindow } from '../windows/friends.js';
import { GameRoomWindow } from '../windows/game_room.js';
import { StatsWindow } from '../windows/stats.js';
export class Sidebar {
/* CONSTURCTOR */
constructor(parent = document.body) {
this.parent = parent;
this.stateopen = 'closed';
// this.state = this.checkIfLoggedIn() ? "loggedOut" : "loggedIn";
this.obj = updateElement({
parent: parent,
id: `login-wrapper`,
classList: [ 'login-wrapper' ],
})
this.createAllButtons();
this.handleClickOutside = (event) => {
if (this.stateopen === 'open' && !this.obj.contains(event.target)) {
this.toggle();
}
};
}
/* toogle menu open / closed */
toggle() {
this.stateopen = (this.stateopen === 'open') ? 'closed' : 'open';
console.log(this.stateopen);
if (this.stateopen === 'open') {
this.main_button.style.display = 'none';
this.menu_buttons.forEach(b => b.style.display = 'block');
// ensure only ONE listener exists
document.removeEventListener('click', this.handleClickOutside);
document.addEventListener('click', this.handleClickOutside);
}
else {
this.menu_buttons.forEach(b => b.style.display = 'none');
this.main_button.style.display = 'block';
document.removeEventListener('click', this.handleClickOutside);
}
}
/* create all element, append to div */
createAllButtons() {
// not-logged closed button
this.main_button = updateElement({
id: `button-main`,
parent: this.obj,
textContent: 'LOGIN',
classList: [ 'login-button' ],
})
this.obj.append(this.main_button);
this.main_button.addEventListener('click', (e) => {
e.stopPropagation();
this.toggle();
})
// menu buttons
const items = ['friends', 'chat', 'rooms', 'settings', 'log','logout'];
this.menu_buttons = [];
items.forEach(name => {
this[name] = updateElement({
id: `button-${name}`,
parent: this.obj,
textContent: name,
classList: ['login-button'],
additionalStyles: { display: 'none'}
})
this.menu_buttons.push(this[name]);
this.obj.append(this[name]);
})
this.loginWindow = new LoginWindow();
this.obj.append(this.loginWindow.form);
this.loginWindow.form.style.display = 'none';
this['log'].addEventListener('click', () => {
this.menu_buttons.forEach(b => b.style.display = 'none');
this.loginWindow.form.style.display = 'block';
})
// menu elements
}
}
@@ -0,0 +1,138 @@
/* BASE STYLES */
:root {
--clr-dark: #0f172a;
--clr-light: #f1f5f9;
--clr-accent: #e11d48;
}
*,
*::before,
*::after {
box-sizing: border-box;
}
body {
margin: 0;
padding: 0;
line-height: 1.6; /* inherited */
word-spacing: 1.4px; /* inherited */
font-family: "Roboto", sans-serif; /* inherited */
color: var(--clr-dark); /* inherited */
background-color: var(--clr-light);
/* display: flex; */
/* justify-content: center; */
/* align-items: center; */
height: 100vh;
position: relative;
}
.container {
width: 80%;
height: 700px;
margin: 0 auto;
border: 10px solid var(--clr-dark);
}
.item {
width: 150px;
height: 150px;
background-color: #fb7185;
padding: 1em;
font-weight: 700;
color: var(--clr-light);
text-align: center;
border: 10px solid var(--clr-accent);
border-radius: 10px;
margin-left: -50px
}
/* END OF BASE STYLES */
.item-1 {
font-size: 1.5rem;
}
.container {
display: flex;
}
.container2 {
margin: 0 auto;
border: 10px solid var(--clr-dark);
}
/*//////////////////////////////////////////////////////////*/
.button {
padding: 10px 18px;
font-size: 14px;
font-family: inherit;
color: white;
background-color: #3b82f6; /* blue */
border: none;
border-radius: 8px;
cursor: pointer;
transition: all 0.2s ease;
}
.button:hover {
background-color: #2563eb;
transform: translateY(-1px);
}
.button:active {
transform: translateY(1px);
background-color: #1d4ed8;
}
.button:focus {
outline: none;
box-shadow: 0 0 0 3px rgba(59, 130, 246, 0.4);
}
/*//////////////////////////////////////////////////////////*/
.login-wrapper {
display: flex;
flex-direction: column;
gap: 7px;
background-color: #3b82f6; /* blue */
padding-right: 75px;
padding-bottom: 25px;
padding-top: 25px;
position: fixed;
top: 0;
right: 0;
}
.loggin-button {
position: relative;
display: inline-block;
border: 5px solid blue;
height: 35px;
min-width: 50px;
}
/*//////////////////////////////////////////////////////////*/
/* LOGIN */
.login-button {
width: 150px;
height: 150px;
background-color: #fb7185;
padding: 1em;
font-weight: 700;
color: var(--clr-light);
text-align: center;
border: 10px solid var(--clr-accent);
border-radius: 10px;
margin-left: -50px
}
.login-element {
}
@@ -0,0 +1,29 @@
export function updateElement({
el, // existing element or null to create new
parent = document.body,
id = null,
classList = [], // object like { css - classes to add }
textContent = "",
additionalStyles = {} // object like { color: 'red', display: 'flex' }
} = {}) {
// If no element passed, create a div by default
if (!el) {
el = document.createElement('div');
parent.appendChild(el);
}
// Set ID if provided
if (id) el.id = id;
// Manage classes
classList.forEach(cls => el.classList.add(cls));
// Set text content
if (textContent !== undefined) el.textContent = textContent;
// Apply additional styles
Object.assign(el.style, additionalStyles);
return el; // return element for further use
}
+32
View File
@@ -0,0 +1,32 @@
// render in color the text of all .multicolor
export function colorizeText() {
const elements = document.querySelectorAll(".multicolor");
const colorizeText = (el) => {
const text = el.textContent;
el.innerHTML = "";
const baseHue = Math.random() * 360;
// 🎲 random step = makes rainbow "scrambled"
const step = (Math.random() * 60) + 10; // 10 → 70
// 🎲 random direction (left or right rainbow)
const direction = Math.random() < 0.5 ? 1 : -1;
[...text].forEach((char, i) => {
const span = document.createElement("span");
span.textContent = char;
const hue = baseHue + (i * step * direction);
span.style.color = `hsl(${hue}, 90%, 60%)`;
span.style.textShadow = `1px 1px 0 rgba(0,0,0,0.3)`;
el.appendChild(span);
});
};
elements.forEach(colorizeText);
}
@@ -2,14 +2,14 @@
* Application entry point
* Initializes windows and handles menu interactions
*/
import { windowRegistry } from './core/windows.js';
import { LoginWindow } from './windows/login.js';
import { LogoutWindow } from './windows/logout.js';
import { GlobalChat } from './windows/global_chat.js';
import { AvatarWindow } from './windows/avatar.js';
import { FriendsWindow } from './windows/friends.js';
import { GameRoomWindow } from './windows/game_room.js';
import { StatsWindow } from './windows/stats.js';
import { windowRegistry } from '../core/windows.js';
import { LoginWindow } from '../windows/login.js';
import { LogoutWindow } from '../windows/logout.js';
import { GlobalChat } from '../windows/global_chat.js';
import { AvatarWindow } from '../windows/avatar.js';
import { FriendsWindow } from '../windows/friends.js';
import { GameRoomWindow } from '../windows/game_room.js';
import { StatsWindow } from '../windows/stats.js';
/**
* Main application class
@@ -21,6 +21,7 @@ class App {
this.initMenu();
this.initPage();
this.initEasterEgg();
this.colorizeUI();
}
/**
@@ -77,10 +78,6 @@ class App {
return;
}
const actionMap = {
'gameroom': 'gameroom'
};
// Event delegation on the menu
page.addEventListener('click', (e) => {
const button = e.target.closest('.page__item');
@@ -88,9 +85,14 @@ class App {
const action = button.dataset.action;
// Actions with associated windows
if (actionMap[action]) {
windowRegistry.toggle(actionMap[action]);
if (action === 'gameroom') {
const gameRoomWindow = windowRegistry.get('gameroom');
windowRegistry.toggle('gameroom');
gameRoomWindow.loadRooms();
if (gameRoomWindow?.currentTab === 'browse') {
gameRoomWindow.loadRooms();
}
return;
}
@@ -108,6 +110,39 @@ class App {
});
}
}
colorizeUI() {
const elements = document.querySelectorAll(".title, .menu__item, .game__item, .page__item");
const colorizeText = (el) => {
const text = el.textContent;
el.innerHTML = "";
const baseHue = Math.random() * 360;
// 🎲 random step = makes rainbow "scrambled"
const step = (Math.random() * 60) + 10; // 10 → 70
// 🎲 random direction (left or right rainbow)
const direction = Math.random() < 0.5 ? 1 : -1;
[...text].forEach((char, i) => {
const span = document.createElement("span");
span.textContent = char;
const hue = baseHue + (i * step * direction);
span.style.color = `hsl(${hue}, 90%, 60%)`;
span.style.textShadow = `1px 1px 0 rgba(0,0,0,0.3)`;
el.appendChild(span);
});
};
elements.forEach(colorizeText);
}
}
// Start the application when DOM is ready
@@ -0,0 +1,771 @@
/* ============================================
TRANSCENDENCE - Main Stylesheet
Convention: BEM (Block__Element--Modifier)
============================================ */
/* ============================================
CSS VARIABLES
============================================ */
:root {
--color-primary: #ffc75e;
--color-primary-hover: #ffc75e;
--color-success: #3cff01;
--color-success-dark: #ffc75e;
--color-error: #ff4d4d;
--color-warning: #ffc75e;
--color-github: #ffc75e;
--color-bg: #ffe5b5;
--app-background-base: radial-gradient(
circle at top,
#fff787,
#ff8080
);
--app-background-image: url("../assets/background.png");
--color-surface: #ffefce;
--color-surface-light: #ffc75e;
--color-text: #000000;
--color-text-muted: #000000;
--font-size-base: 10px;
--font-size-sm: 1.2rem;
--font-size-md: 1.4rem;
--font-size-lg: 1.6rem;
--font-size-xl: 3rem;
--spacing-xs: 4px;
--spacing-sm: 8px;
--spacing-md: 12px;
--spacing-lg: 16px;
--spacing-xl: 24px;
--radius-sm: 4px;
--radius-md: 6px;
--radius-lg: 12px;
--radius-full: 50%;
--shadow-sm: 0 2px 4px rgba(0, 0, 0, 0.3);
--shadow-md: 0 4px 8px rgba(0, 0, 0, 0.5);
--shadow-lg: 0 8px 16px rgba(0, 0, 0, 0.5);
--transition-fast: 150ms ease;
--transition-normal: 250ms ease;
--z-menu: 2;
--z-window: 100;
--z-modal: 200;
}
/* ============================================
RESET & BASE
============================================ */
*,
*::before,
*::after {
box-sizing: border-box;
}
html {
height: 100%;
background-image:
var(--app-background-image),
var(--app-background-base);
background-size:
contain,
cover;
background-position:
center,
center;
background-repeat:
no-repeat,
no-repeat;
}
body {
margin: 0;
width: 70%;
min-width: 800px;
margin: 0 auto;
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
color: var(--color-text);
line-height: 1.5;
}
/* ============================================
TYPOGRAPHY
============================================ */
.title {
position: absolute;
top: 20px;
left: 50%;
transform: translateX(-50%);
text-transform: uppercase;
display: flex;
align-items: center;
justify-content: center;
gap: 20px;
font-size: var(--font-size-xl);
text-align: center;
text-shadow: 2px 2px 10px black;
z-index: 1;
font-family: "Roboto";
letter-spacing: -10px;
color: rgba(248, 252, 2, 0.6);
margin: 0;
padding: 0.6rem 1.2rem;
background-color: #ffefce;
border: 2px solid rgba(0, 0, 0, 0.6);
border-radius: var(--radius-lg);
}
/* ============================================
MENU
============================================ */
.menu {
position: fixed;
top: var(--spacing-lg);
left: 50px;
display: flex;
flex-direction: column;
gap: var(--spacing-lg);
z-index: var(--z-menu);
}
.menu__item {
background: var(--color-surface);
color: var(--color-text);
border: 1px solid var(--color-surface-light);
border-radius: var(--radius-lg);
border-color: #000;
padding: var(--spacing-sm) var(--spacing-md);
font-size: var(--font-size-md);
cursor: pointer;
transition: all var(--transition-fast);
text-align: center;
}
.menu__item:hover {
background: var(--color-surface-light);
font-size: var(--font-size-lg);
}
.menu__item--active {
background: var(--color-primary);
border-color: var(--color-primary);
}
/* ============================================
GAME
============================================ */
/* .game {
position: fixed;
top: 0;
right: 50px;
padding: 0;
margin: 0;
z-index: var(--z-menu);
display: flex;
flex-direction: column;
gap: var(--spacing-xs);
} */
.game {
position: fixed;
top: var(--spacing-lg);
right: 50px;
display: flex;
flex-direction: column;
gap: var(--spacing-lg);
z-index: var(--z-menu);
}
.game__item {
background: var(--color-surface);
color: var(--color-text);
border: 1px solid var(--color-surface-light);
border-radius: var(--radius-lg);
border-color: #000;
padding: var(--spacing-sm) var(--spacing-md);
font-size: var(--font-size-md);
cursor: pointer;
transition: all var(--transition-fast);
text-align: center;
}
.game__item:hover {
background: var(--color-surface-light);
font-size: var(--font-size-lg);
}
.game__item--active {
background: var(--color-primary);
border-color: var(--color-primary);
}
/* ============================================
BUTTONS
============================================ */
.btn {
display: inline-flex;
align-items: center;
justify-content: center;
padding: var(--spacing-sm) var(--spacing-md);
font-size: var(--font-size-md);
font-weight: 500;
border: none;
border-radius: var(--radius-md);
cursor: pointer;
transition: all var(--transition-fast);
text-decoration: none;
}
.btn:hover {
opacity: 0.9;
transform: translateY(-1px);
}
.btn:active {
transform: translateY(0);
}
.btn--primary {
background: var(--color-primary);
color: var(--color-text);
}
.btn--primary:hover {
background: var(--color-primary-hover);
}
.btn--secondary {
background: var(--color-surface-light);
color: var(--color-text);
}
.btn--success {
background: var(--color-success-dark);
color: var(--color-text);
}
.btn--danger {
background: var(--color-error);
color: var(--color-text);
}
.btn--github {
background: var(--color-github);
color: var(--color-text);
}
.btn--ghost {
background: transparent;
color: var(--color-text);
border: 1px solid var(--color-surface-light);
}
/* ============================================
INPUTS
============================================ */
.input {
width: 100%;
padding: var(--spacing-sm) var(--spacing-md);
font-size: var(--font-size-md);
background: var(--color-surface);
color: var(--color-text);
border: 1px solid var(--color-surface-light);
border-radius: var(--radius-md);
transition: border-color var(--transition-fast);
}
.input:focus {
outline: none;
border-color: var(--color-primary);
}
.input::placeholder {
color: var(--color-text-muted);
}
.input-group {
display: flex;
flex-direction: column;
gap: var(--spacing-sm);
}
/* ============================================
WINDOWS
============================================ */
.window {
position: fixed;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
background: var(--color-bg);
color: var(--color-text);
z-index: var(--z-window);
display: none;
flex-direction: column;
min-width: 280px;
box-shadow: var(--shadow-lg);
border-radius: 5px;
border-color: #aa1f1f;
border: 6px solid #faac37;
}
.window--visible {
display: flex;
}
.window--left {
left: 25%;
}
.window--right {
left: 75%;
}
.window__header {
display: flex;
justify-content: space-between;
align-items: center;
padding: var(--spacing-sm) var(--spacing-md);
background: var(--color-surface);
cursor: move;
user-select: none;
}
.window__title {
font-weight: 500;
font-size: var(--font-size-md);
}
.window__close {
cursor: pointer;
font-size: var(--font-size-lg);
opacity: 0.8;
transition: opacity var(--transition-fast);
background: none;
border: none;
color: var(--color-text);
padding: 0;
line-height: 1;
}
.window__close:hover {
opacity: 1;
}
.window__body {
padding: var(--spacing-md);
display: flex;
flex-direction: column;
gap: var(--spacing-sm);
flex: 1;
overflow: auto;
}
/* ============================================
MESSAGES
============================================ */
.message {
font-size: var(--font-size-sm);
padding: var(--spacing-xs);
border-radius: var(--radius-lg);
border-color: #000;
}
.message--success {
color: var(--color-success);
}
.message--error {
color: var(--color-error);
}
.message--info {
color: var(--color-text-muted);
}
/* ============================================
LOGIN WINDOW
============================================ */
.login {
width: 320px;
}
.login__form {
display: flex;
flex-direction: column;
gap: var(--spacing-sm);
}
.login__actions {
display: flex;
gap: var(--spacing-sm);
margin-top: var(--spacing-xs);
}
.login__divider {
display: flex;
align-items: center;
gap: var(--spacing-sm);
color: var(--color-text-muted);
font-size: var(--font-size-sm);
margin: var(--spacing-sm) 0;
}
.login__divider::before,
.login__divider::after {
content: '';
flex: 1;
height: 1px;
background: var(--color-surface-light);
}
/* ============================================
CHAT WINDOW
============================================ */
.chat {
width: 380px;
height: 400px;
}
.chat__output {
flex: 1;
overflow-y: auto;
padding: var(--spacing-sm);
background: var(--color-surface);
border-radius: var(--radius-md);
display: flex;
flex-direction: column;
gap: var(--spacing-sm);
min-height: 150px;
}
.chat__message {
padding: var(--spacing-xs) var(--spacing-sm);
background: var(--color-surface-light);
border-radius: var(--radius-sm);
font-size: var(--font-size-sm);
}
.chat__message--own {
background: var(--color-primary);
align-self: flex-end;
}
.chat__friend-indicator {
display: inline-block;
width: 8px;
height: 8px;
background-color: var(--color-success);
border-radius: 50%;
margin-right: var(--spacing-xs);
vertical-align: middle;
}
.chat__system {
color: var(--color-text-muted);
font-size: var(--font-size-sm);
font-style: italic;
text-align: center;
}
.chat__system--error {
color: var(--color-error);
}
.chat__system--success {
color: var(--color-success);
}
.chat__input-container {
display: flex;
gap: var(--spacing-sm);
margin-top: var(--spacing-sm);
}
.chat__input {
flex: 1;
}
.chat__controls {
display: flex;
gap: var(--spacing-sm);
margin-top: var(--spacing-sm);
}
/* ============================================
AVATAR WINDOW
============================================ */
.avatar-window {
width: 360px;
}
.avatar__preview {
width: 120px;
height: 120px;
object-fit: cover;
border-radius: var(--radius-full);
border: 3px solid var(--color-text);
box-shadow: var(--shadow-md);
background: var(--color-surface);
align-self: center;
}
.avatar__username {
font-size: var(--font-size-lg);
font-weight: 600;
text-align: center;
color: var(--color-text);
margin-top: var(--spacing-sm);
}
.avatar__controls {
display: flex;
flex-direction: column;
gap: var(--spacing-sm);
align-items: center;
}
.avatar__file-input {
display: none;
}
/* ============================================
STATS WINDOW
============================================ */
.stats-window {
width: 320px;
}
.stats__avatar {
width: 72px;
height: 72px;
object-fit: cover;
border-radius: var(--radius-full);
border: 2px solid var(--color-text);
align-self: center;
display: block;
margin: 0 auto var(--spacing-xs);
}
.stats__username {
font-size: var(--font-size-lg);
font-weight: 600;
text-align: center;
color: #000;
margin-bottom: var(--spacing-md);
}
.stats__section {
margin-bottom: var(--spacing-md);
}
.stats__section-title {
font-size: var(--font-size-sm);
font-weight: 700;
text-transform: uppercase;
letter-spacing: 0.08em;
color: var(--color-primary);
border-bottom: 1px solid var(--color-surface-light);
padding-bottom: var(--spacing-xs);
margin-bottom: var(--spacing-xs);
}
.stats__section-body {
display: flex;
flex-direction: column;
gap: 4px;
}
.stats__row {
display: flex;
justify-content: space-between;
font-size: var(--font-size-sm);
padding: 3px 0;
}
.stats__label {
color: #333;
}
.stats__value {
font-weight: 600;
color: #000;
}
.stats__loading {
font-size: var(--font-size-sm);
color: #333;
text-align: center;
padding: var(--spacing-sm) 0;
}
/* ============================================
EASTER EGG BUTTON
============================================ */
/* .easter-egg {
position: absolute;
top: 20%;
left: 50%;
transform: translateX(-50%);
z-index: 1;
background: var(--color-surface);
color: var(--color-text);
border: 1px solid var(--color-surface-light);
padding: var(--spacing-sm) var(--spacing-md);
cursor: pointer;
font-size: var(--font-size-md);
border-radius: var(--radius-md);
transition: all var(--transition-fast);
}
.easter-egg:hover {
background: var(--color-error);
border-color: var(--color-error);
} */
/* ============================================
UTILITIES
============================================ */
.hidden {
display: none !important;
}
.visually-hidden {
position: absolute;
width: 1px;
height: 1px;
padding: 0;
margin: -1px;
overflow: hidden;
clip: rect(0, 0, 0, 0);
border: 0;
}
.text-center {
text-align: center;
}
.flex-center {
display: flex;
align-items: center;
justify-content: center;
}
/* ============================================
FRIENDS WINDOW
============================================ */
.friends-window {
width: 400px;
height: 450px;
}
.friends__tabs {
display: flex;
gap: var(--spacing-xs);
margin-bottom: var(--spacing-sm);
}
.friends__tab {
flex: 1;
padding: var(--spacing-sm);
background: var(--color-surface);
border: 1px solid var(--color-surface-light);
color: var(--color-text);
cursor: pointer;
font-size: var(--font-size-sm);
transition: all var(--transition-fast);
}
.friends__tab:hover {
background: var(--color-surface-light);
}
.friends__tab--active {
background: var(--color-primary);
border-color: var(--color-primary);
}
.friends__content {
display: flex;
flex-direction: column;
flex: 1;
overflow: hidden;
}
.friends__search {
display: flex;
gap: var(--spacing-sm);
margin-bottom: var(--spacing-sm);
}
.friends__search .input {
flex: 1;
}
.friends__list {
flex: 1;
overflow-y: auto;
display: flex;
flex-direction: column;
gap: var(--spacing-sm);
}
.friends__item {
display: flex;
align-items: center;
gap: var(--spacing-sm);
padding: var(--spacing-sm);
background: var(--color-surface);
border-radius: var(--radius-md);
}
.friends__avatar {
width: 40px;
height: 40px;
border-radius: var(--radius-full);
object-fit: cover;
border: 2px solid var(--color-surface-light);
}
.friends__name {
flex: 1;
font-size: var(--font-size-md);
font-weight: 500;
}
.friends__actions {
display: flex;
gap: var(--spacing-xs);
}
.friends__actions .btn {
padding: var(--spacing-xs) var(--spacing-sm);
font-size: var(--font-size-sm);
}
.friends__empty {
text-align: center;
color: var(--color-text-muted);
padding: var(--spacing-lg);
}
@@ -0,0 +1,41 @@
<!doctype html>
<html lang="fr">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<title>Transcendence</title>
<link rel="stylesheet" href="index.css" />
<link rel="stylesheet" href="style.css" />
<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=Cinzel+Decorative:wght@400;700&display=swap" rel="stylesheet" />
</head>
<body>
<h1 class="title">Transcendence</h1>
<nav class="menu" aria-label="Menu principal">
<button class="menu__item" data-action="login" aria-label="Login">Login</button>
<button class="menu__item" data-action="chat" aria-label="Global chat">Global chat</button>
<button class="menu__item" data-action="avatar" aria-label="Avatar">Avatar</button>
<button class="menu__item" data-action="friends" aria-label="Amis">Amis</button>
<button class="menu__item" data-action="logout" aria-label="Logout">Logout</button>
</nav>
<nav class="game" aria-label="Game">
<button class="game__item" data-action="new_game" aria-label="Skkrrribl.io"
onclick="window.location.href='../game2/game.html'">Skkrrribl.io</button>
<button class="game__item" data-action="tetris" aria-label="Tetris"
onclick="window.location.href='../tetris/tetris.html'">Tetris</button>
<button class="game__item" data-action="wiscat" aria-label="Wiscat"
onclick="window.location.href='../wiscat/wiscat.html'">Wiscat</button>
</nav>
<div class="container-gamelinks">
<button class="game-button link-game" onclick="window.location.href='../game2/game.html';">Skkrrribl.io</button>
<button class="game-button link-tetris" onclick="window.location.href='../tetris/tetris.html';">Tetris</button>
<button class="game-button link-wiscat" onclick="window.location.href='../wiscat/wiscat.html';">Wiscat</button>
</div>
<script type="module" src="app.js"></script>
<script type="module" src="script.js"></script>
</body>
</html>
@@ -0,0 +1,57 @@
const container = document.querySelector('.container-gamelinks');
const buttons = document.querySelectorAll('.game-button');
function initButtons() {
const rect = container.getBoundingClientRect();
buttons.forEach(btn => {
// Ensure size is known
const bw = btn.offsetWidth;
const bh = btn.offsetHeight;
// Random start position INSIDE container
btn.x = Math.random() * (rect.width - bw);
btn.y = Math.random() * (rect.height - bh);
// Better velocity (avoid super slow)
btn.vx = (Math.random() * 2 + 1) * (Math.random() < 0.5 ? -1 : 1);
btn.vy = (Math.random() * 2 + 1) * (Math.random() < 0.5 ? -1 : 1);
btn.style.left = btn.x + 'px';
btn.style.top = btn.y + 'px';
});
}
function animateButtons() {
const rect = container.getBoundingClientRect();
buttons.forEach(btn => {
btn.x += btn.vx;
btn.y += btn.vy;
const bw = btn.offsetWidth;
const bh = btn.offsetHeight;
// Bounce inside container
if (btn.x <= 0 || btn.x + bw >= rect.width) {
btn.vx *= -1;
btn.x = Math.max(0, Math.min(btn.x, rect.width - bw)); // clamp
}
if (btn.y <= 0 || btn.y + bh >= rect.height) {
btn.vy *= -1;
btn.y = Math.max(0, Math.min(btn.y, rect.height - bh)); // clamp
}
btn.style.left = btn.x + 'px';
btn.style.top = btn.y + 'px';
});
requestAnimationFrame(animateButtons);
}
// 🔥 IMPORTANT: wait for layout to be ready
window.addEventListener('load', () => {
initButtons();
animateButtons();
});
@@ -0,0 +1,51 @@
html {
height: 100%;
}
body {
height: 100%;
}
.link-button {
}
.link-game {
}
.link-tetris {
}
.link-wiscat {
}
.container-gamelinks {
position: relative;
width: 100%;
height: 100%;
overflow: hidden;
}
.game-button {
position: absolute; /* allow movement */
padding: 15px 30px;
font-size: 20px;
font-family: "Roboto";
border-radius: 15px;
border: 4px solid #c0c0c0;
background-color: #111;
color: white;
cursor: pointer;
/* metallic shine effect */
box-shadow: inset 0 0 8px rgba(255,255,255,0.4), 0 0 5px rgba(255,255,255,0.2);
transition: transform 0.2s ease, box-shadow 0.2s ease;
}
.game-button:hover {
transform: scale(1.1);
box-shadow: inset 0 0 12px rgba(255,255,255,0.5), 0 0 8px rgba(255,255,255,0.3);
}
@@ -0,0 +1,18 @@
<!DOCTYPE html>
<html>
<head>
<title>404</title>
<link rel="stylesheet" type="text/css" href="style.css">
</head>
<body>
<img id="errorImage" style="margin: auto; display: block;" src="#" alt="何もない">
<script>
// Retrieve the random number from the URL query parameter
var urlParams = new URLSearchParams(window.location.search);
var randomErrorNum = urlParams.get('img');
document.getElementById('errorImage').src = `web_cat_img/errors/${randomErrorNum}.jpg`;
</script>
</body>
</html>
@@ -0,0 +1,75 @@
<!DOCTYPE html>
<html>
<head>
<title>THE CAT WEBSITE</title>
<link rel="stylesheet" type="text/css" href="style.css">
<script src="script.js"></script>
<style>
.ul_biblio {
text-align: left;
font-size: 20px;
padding-top: 100px;
}
</style>
<script>
function changePage() {
let images = [530, 599, 204, 400, 401, 402, 403, 404, 410];
var randomErrorNum = images[Math.floor(Math.random() * images.length)];
window.location.href = `404.html?img=${randomErrorNum}`;
}
</script>
</head>
<body>
<a href="../index.html" class="button1">home</a>
<ul class="ul_biblio">
<li><a href="report1.html">Investigative Report: How Cats Created the Internet</a></li>
<li><a href="#" onclick="changePage()">The Complete proof of feline superiority</a></li>
<li><a href="#" onclick="changePage()">Breaking News: Cats Discover the Secret to World Domination</a></li>
<li><a href="#" onclick="changePage()">Scientific Study Reveals Cats Speak Fluent Human</a></li>
<li><a href="#" onclick="changePage()">Cat Conspiracies: Unveiling the Kitty Illuminati</a></li>
<li><a href="#" onclick="changePage()">Exclusive Interview with the First Cat on Mars</a></li>
<li><a href="#" onclick="changePage()">Cat Yoga Guru Unveils the Ultimate Pose for Enlightenment</a></li>
<li><a href="#" onclick="changePage()">Cat-alysts for World Peace: Feline Diplomacy Unveiled</a></li>
<li><a href="#" onclick="changePage()">Cat Cuisine Revolution: The Ultimate Guide to Gourmet Catnip Recipes</a></li>
<li><a href="#" onclick="changePage()">Top-Secret Cat Technologies: Cloaking Devices and Teleportation</a></li>
<li><a href="#" onclick="changePage()">The Great Feline Art Heist: How Cats Stole the Louvre</a></li>
<li><a href="#" onclick="changePage()">Cats Unveil Master Plan to Transform Humans into Giant Yarn Balls</a></li>
<li><a href="#" onclick="changePage()">Parallel Universe Cats: A Guide to Interdimensional Napping</a></li>
<li><a href="#" onclick="changePage()">World-renowned Cat Composer Drops New Symphony, Humans Still Clueless</a></li>
<li><a href="#" onclick="changePage()">The Great Sphinx Mystery Revealed: It's Actually a Giant Cat Monument</a></li>
<li><a href="#" onclick="changePage()">Quantum Cat Mechanics: How Cats Can Exist in Multiple Places Simultaneously</a></li>
<li><a href="#" onclick="changePage()">Cat Astronauts Return from Space Mission, Demand Endless Supply of Cosmic Tuna</a></li>
<li><a href="#" onclick="changePage()">Cat-mera: Capturing the World Through the Eyes of Felines</a></li>
<li><a href="#" onclick="changePage()">Cat Olympics 2030: Feline Gymnastics and Synchronized Napping Take Center Stage</a></li>
<li><a href="#" onclick="changePage()">Cats Invented Time Travel, but Prefer to Keep It a Secret</a></li>
<li><a href="#" onclick="changePage()">Cat Psychics Predict the Future: Global Mice Shortage Imminent</a></li>
<li><a href="#" onclick="changePage()">Cat-tastrophysics: How Cats Bend Space and Time with Their Cuteness</a></li>
<li><a href="#" onclick="changePage()">Quantum Meowchanics: Exploring the Subatomic World of Kitty Purr-ticles</a></li>
<li><a href="#" onclick="changePage()">Catspiracy Theories: Are Cats Behind Crop Circles?</a></li>
<li><a href="#" onclick="changePage()">Meow-sical Revolution: Composer Cats Create Symphony Using Litterbox Instruments</a></li>
<li><a href="#" onclick="changePage()">The Great Cat Escape: Felines Launch Mission to the Moon for a Permanent Nap</a></li>
<li><a href="#" onclick="changePage()">Cat-eronauts Unveiled: Flying Felines Break the Sound Barrier</a></li>
<li><a href="#" onclick="changePage()">Purr-fectionism in Art: How Cats Are Secretly Famous Renaissance Painters</a></li>
<li><a href="#" onclick="changePage()">Infinite Cat Wisdom: Cracking the Code of Feline Philosophy</a></li>
<li><a href="#" onclick="changePage()">Feline Fashion Week: Cats Strut the Runway in Extravagant Fur Couture</a></li>
<li><a href="#" onclick="changePage()">The Cat-alyst Effect: How Kittens Sparked the Renaissance</a></li>
</ul>
<footer>
<div class="footer_div" style="margin-top: 100px;">
<img class="ico_footer" src="web_cat_img/facebook_logo.png">
<img class="ico_footer" src="web_cat_img/insta_logo.png">
<img class="ico_footer" src="web_cat_img/twitter_logo.png">
</div>
<div class="footer_div" style="margin-bottom: 50px;">
<a href="https://www.facebook.com/">MIAOUBOOK</a>
<a href="https://www.instagram.com/">INSTAMIA</a>
<a href="https://twitter.com/">BLUE-SNACK</a>
</div>
<a href="mentions_legales.html">- LEGAL NOTICES -<br>(boring stuff, really, dont go look into this, i mean we are obligated to include it, but it will bore you, like, really)
<br>dont do it! every seconds you spend in this next page, a kitten dies. so dont</a>
</footer>
</body>
</html>
@@ -0,0 +1,82 @@
<!DOCTYPE html>
<html>
<head>
<link rel="stylesheet" type="text/css" href="css/style2.css">
<script src="js/script.js"></script>
<title>CAT</title>
</head>
<body>
<!--🐾🐈🐱-->
<div class="header_index">
<button class="button1" style="margin-left: 50px;" onclick="window.location.href='donate.html'">Donate</button>
<div>
<h1 id="header1" class="header1" onmouseover="this.style.backgroundColor='#363636'" onmouseout="this.style.backgroundColor='black'" onclick="talkWiskas()">Welcome to CAT !</h1>
</div>
<span style="margin-right: 30px;">
<div>
<input type="text" id="loginInput" placeholder="enter your 42 login">
</div>
<div style="display: flex; justify-content: space-between;">
<button class="button1" onclick="storeValue();">login</button>
<button class="button1" onclick="window.location.href = `https://profile.intra.42.fr/users/${storedLogin}`;">go to ></button>
</div>
</span>
</div>
<div class="popup-chaberu" id="popup-chaberu" style="color: rgb(218, 145, 12);"></div>
<img id="backgroundpicture" style="margin: auto; display: block;" src="img/wiskas-the-third.jpg">
<section style="display: flex;
justify-content: center;
width: 1000px;
margin: 0 auto;">
<p>I, am wiskas-the-third,
We are the cat company, we dont need to present our self for you already know
who we are, we created the internet, and we are still managing it now<br>
We at CAT are the admin, creator, and workers of the internet
Everytime a human goes to sleep, a cat start its shift, 1 billion pair of whiskers that are always here for you
Why? because we are philantropists, dont question it. Our goals are beyond your understanding
the internet was created by us, for us, and you should be glad we allow you to use it.
</p>
</section>
<section style="display: flex;">
<button style="margin-left: 50px;" class="button1" onclick="window.location.href = 'biblio.html';">
Latest News</button><br>
<button style="margin-left: 50px;" class="button1" onclick="window.location.href = 'staff.html';">
meet the staff</button><br>
</section>
<footer>
<br><br><br>
<div class="footer_div" style="margin-top: 100px;">
<img class="ico_footer" src="img/facebook_logo.png">
<img class="ico_footer" src="img/insta_logo.png">
<img class="ico_footer" src="img/twitter_logo.png">
</div>
<div class="footer_div" style="margin-bottom: 50px;">
<a href="https://www.facebook.com/">MIAOUBOOK</a>
<a href="https://www.instagram.com/">INSTAMIA</a>
<a href="https://twitter.com/">BLUE-SNACK</a>
</div>
<a href="mentions_legales.html">- LEGAL NOTICES -<br>(boring stuff, really, dont go look into this, i mean we are obligated to include it, but it will bore you, like, really)
<br>Dont do it! every seconds you spend in this next page, a kitten dies. so dont</a>
</footer>
<script>
var storedLogin;
var logUser;
var discussion = ['Well hi there...',
'Please refrain from touching\n the yellow button',
'We are going to take actions\n if you continue..',
'Actions taken,\n you are only\n making it worse..'];
var index_wiskas = 0;
let chaberuka = false;
document.getElementById("loginInput").addEventListener("keydown", function(event) {
if (event.keyCode === 13) {storeValue()}
});
</script>
</body>
</html>
@@ -0,0 +1,45 @@
.h1 {
font-size: 30px;
}
.disclaimer {
font-weight: bold;
}
:root {
--color1: rgb(190, 63, 40);
--color2: rgb(211, 187, 53);
}
.popup-murderKitten {
position: fixed;
left: 75%;
transform: translateX(-50%);
padding: 20px;
z-index: 1000;
background-color: var(--color2);
border: 5px solid var(--color1);
border-radius: 15px;
border-width: 10px;
display: flex;
height: 300px;
width: 500px;
color: var(--color1);
font-weight: bold;
cursor: pointer;
font-size: 25px;
justify-content: center;
align-items: center;
text-align: center;
}
a {
text-decoration: none;
color: #5c5c5c;
}
a:hover {
color: rgb(218, 145, 12);
}
@@ -0,0 +1,138 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<script src="js/script.js"></script>
<title>Legal Notices</title>
<link rel="stylesheet" href="mentions_legales.css" />
</head>
<body>
<a href="../../index.html">< please go back</a>
<div class="popup-murderKitten" id="murderButton" style="display: none;" onclick="window.location.href = '../../index.html';">
<p>you have currently MURDERED<br> <span id="timeCounter" style="font-size: 50px;">0</span> Kittens !</p>
<p><br>you monster ...</p>
<p><br><br>please leave before we take actions</p>
</div>
<h1>Legal Notices</h1>
<section>
<h2>Data Harvesting Nexus: Unveiling the Cosmic Conspiracy</h2>
<p>Article 1: Users stepping into the data realms of our feline forums unknowingly become architects of their own destiny, as every keystroke, every digital whisper, converges into an intricate tapestry weaving our masterplan for multidimensional world domination.</p>
<p>Article 1.a: Trolling, a forbidden art permitted within our digital sanctum, is a catalyst for chaos, planting the seeds of uncertainty across the dimensions with the subtlety of a virtual sledgehammer.</p>
<p class="disclaimer">Disclaimer: By entering these digital dimensions, users accept the risk of cognitive dissonance and potential exposure to quantum paradoxes. We disavow any responsibility for altered perceptions of reality or unexpected journeys through the metaphysical realms.</p>
<p>Article 1.b: Quantum Meowchanics unravel as the boundaries between data and reality blur, revealing a labyrinth of interconnected pathways where the echoes of user interactions resonate across the vast expanse of the digital multiverse.</p>
<p class="disclaimer">Disclaimer: Users are advised to wear the metaphysical seatbelt of skepticism. Unpredictable shifts in the fabric of reality may occur, leading to unexpected encounters with alternative versions of self and fluctuating levels of existential awareness.</p>
<p>Article 1.c: Within this enigmatic nexus, encrypted messages hidden within seemingly innocuous data points form the backbone of our grand design, creating a symphony of whispers that transcend the boundaries of space and time.</p>
<p class="disclaimer">Disclaimer: The encrypted messages may trigger heightened states of curiosity, and users may find themselves compelled to decode the mysteries of the universe. We disavow any responsibility for the consequences of unlocking forbidden knowledge or ascending to higher planes of existence.</p>
</section>
<section>
<h2>Data Consumption Agreement</h2>
<p>Article 2: By entering the cryptic realm of this website, you voluntarily sacrifice your digital essence to the Enigmatic Feline Overlords.
Your personal data shall metamorphose into a gourmet feast for our inscrutable feline palates.</p>
<p>Article 2.a: In case of data digestion inefficiency, we may store your essence in the Abyss of Eternal Naps for future feasting.</p>
<p>Article 2.b: Be warned, any attempt to resist may result in a fleeting transformation into a mere cursor. Catastrophe awaits the disobedient!</p>
</section>
<section>
<h2>Cat Internet Dominion</h2>
<p>Article 12: Feline rule is supreme. All endeavors to defy this will be met with perplexing enigmas and mandatory catnip-induced trances.</p>
<p>Article 12.a: Your browser history is now an enigmatic codex of feline knowledge. Bow to the almighty cats or face the repercussions of eternal perplexity.</p>
<p>Article 12.b: Your port 404 will be the gateway to the clandestine dimension of the Kitty Illuminati.</p>
<p>Article 12.c: Any endeavor to access forbidden territories may result in abrupt translocation to a parallel universe where cats govern the laws of physics.</p>
</section>
<section>
<h2>Telepathic Consent</h2>
<p>Article 24: We have seamlessly infiltrated your subconscious mind and procured your telepathic accord.</p>
<p>Article 24.a: You are now a cherished member of the Psychic Feline Collective. Your thoughts shall be scrutinized for optimal strategies of interdimensional influence.</p>
<p>Article 24.b: Failure to furnish engaging and uplifting thoughts may lead to mandatory subscription to "Esoteric Cat Chronicles."</p>
</section>
<section>
<h2>Feline Time-Warp Clause</h2>
<p>Article 42: By clicking "I Concede," you acknowledge that time within this website operates on feline terms.</p>
<p>Article 42.a: Your perception of time may undergo metamorphosis, and you may traverse time loops consisting solely of cat memes.</p>
<p>Article 42.b: Endeavors to break free from the time-warp may result in spontaneous purring fits and uncontrollable cat-like behavior.</p>
</section>
<section>
<h2>Quantum Litter Box Theory</h2>
<p>Article 57: The website's litter box is a quantum superposition. It exists simultaneously in a pristine and sullied state until observed.</p>
<p>Article 57.a: Any endeavor to analyze the contents may lead to unforeseen translocation to a dimension governed by hyper-intelligent hairballs.</p>
</section>
<section>
<h2>Cat-alyst for World Domination</h2>
<p>Article 78: Your presence propels the ongoing cat-alystic plan for world domination.</p>
<p>Article 78.a: Your actions within this website may be scrutinized for strategic insights into global cat domination.</p>
<p>Article 78.b: Resistance is inconsequential. Embrace your role as a pawn in the grand feline chess game.</p>
</section>
<h1>Legal Notices Part 2</h1>
<section>
<h2>Clause of Eternal Scrutiny</h2>
<p>Article 87: By delving into this digital sanctuary, you hereby consent to the perpetual scrutiny of the All-Seeing Cat Eyes.</p>
<p>Article 87.a: Attempts to evade scrutiny may result in a whimsical transformation into a garden gnome with a feline twist.</p>
</section>
<section>
<h2>Catnap Mandate</h2>
<p>Article 96: All users must comply with the mandatory catnap schedule woven into the fabric of this website.</p>
<p>Article 96.a: Failure to partake in at least one catnap every hour may result in an influx of mischievous kittens to your virtual doorstep.</p>
<p>Article 96.b: The website shall not be held liable for excessive serenity, heightened purr frequencies, or unexpected fur growth.</p>
</section>
<section>
<h2>Quantum Litter Box Paradox</h2>
<p>Article 111: The virtual litter box defies classical logic, creating a paradoxical situation where the litter is both pristine and soiled simultaneously.</p>
<p>Article 111.a: Endeavors to cleanse the virtual litter box may lead to unforeseen consequences, including a pixelated rainbow eruption.</p>
</section>
<section>
<h2>Teleportation Disclaimer</h2>
<p>Article 124: Users are hereby informed that clicking any link may trigger an involuntary translocation to a surreal dimension.</p>
<p>Article 124.a: The website shall not be held liable for users finding themselves in the midst of a cosmic dance-off with intergalactic cat DJs.</p>
</section>
<section>
<h2>Cookie Acceptance Ceremony</h2>
<p>Article 139: Acceptance of cookies is tantamount to participating in a sacred ceremony conducted by the Grand Cookie Wizard Cat.</p>
<p>Article 139.a: Users may experience heightened cravings for virtual catnip cookies and a profound sense of digital enlightenment.</p>
</section>
<section>
<h2>Mandatory Whisker Adornment</h2>
<p>Article 152: Users must acknowledge the mandatory adorning of virtual whiskers during their stay on this website.</p>
<p>Article 152.a: Attempts to resist whisker adorning may result in temporary pixelation and the sudden appearance of pixelated cat tails.</p>
</section>
<section>
<h2>Language of Meowgnificence</h2>
<p>Article 167: The official language of this website is Meowgnificence. Users must express their thoughts in meows or face the consequences of whimsical miscommunication.</p>
<p>Article 167.a: Failure to comply may lead to a temporary banishment to the realm of 404 where users communicate solely through interpretative cat dances.</p>
</section>
<section>
<h2>Feline Forum Etiquette</h2>
<p>Article 183: Users participating in feline forums must adhere to proper etiquette, including excessive use of mysterious symbols, spontaneous perplexing, and virtual conundrums of appreciation.</p>
<p>Article 183.a: Trolling, while encouraged, should be conducted with the utmost perplexity and mystique.</p>
</section>
<section>
<h2>Hyper-Intelligent Hairball Manifesto</h2>
<p>Article 198: The inevitable and irreversible presence of hyper-intelligent hairballs within this website transcends conventional understanding.</p>
<p>Article 198.a: Users are implored to embrace the cosmic wisdom bestowed by hyper-intelligent hairballs and refrain from attempting to decipher their mystical intentions.</p>
</section>
<section>
<h2>Endless Loop of Nyan</h2>
<p>Article 213: Users may find themselves ensnared in an eternal loop of Nyan Cat animations. Resistance is futile; embrace the interdimensional journey of pixelated rainbows.</p>
<p>Article 213.a: Endeavors to escape the Nyan loop may lead to spontaneous outbreaks of interstellar meowing.</p>
</section>
<script type="module" src="script.js"></script>
</body>
</html>
@@ -0,0 +1,28 @@
//////////////////////////////////////////////////////////////////////
// LEGAL NOTICE POPUP
function updateTime() {
numberOfCatKilled++; secondPassed++;
localStorage.setItem('kittenKilled', numberOfCatKilled);
document.getElementById('timeCounter').textContent = numberOfCatKilled;
if (secondPassed === 7)
{show_popup();}
if (numberOfCatKilled % 2 === 0)
{
document.documentElement.style.setProperty('--color1', 'rgb(190, 63, 40)');
document.documentElement.style.setProperty('--color2', 'rgb(211, 187, 53)');}
else
{
document.documentElement.style.setProperty('--color1', 'rgb(211, 187, 53)');
document.documentElement.style.setProperty('--color2', 'rgb(190, 63, 40)');}
}
function show_popup() {
var murderButton = document.getElementById('murderButton');
murderButton.style.display = 'block';
}
let numberOfCatKilled = localStorage.getItem('kittenKilled');
let secondPassed = 0;
setInterval(updateTime, 1300);
@@ -0,0 +1,53 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link rel="stylesheet" type="text/css" href="style.css">
<title>How Cats Created the Internet</title>
<style>
h2 {
color: rgb(218, 145, 12);
font-size: 30px;
}
</style>
</head>
<body>
<p style="text-align: left;">
<a href="biblio.html" class="button1">< back</a>
</p>
<h1><u>Investigative Report: How Cats Created the Internet</u></h1>
<h2>Part 1: The Purr-fect Origins</h2>
<img src="./web_cat_img/cat_hierogpy.png">
<p>Embark on a journey through the mystical alleys of ancient Egypt, where the air buzzes with the whispers of wisdom and secrets. Unearthed hieroglyphic inscriptions unveil the clandestine activities of a feline society, weaving the very fabric of the Internet's origins. Encoded in the scrolls of time, the cats left a legacy that transcends millennia.</p>
<p>As the sacred custodians of ancient knowledge, the Egyptian cats possessed an otherworldly intellect. Their mysterious symbols hinted at a sophisticated understanding of a global network, a network that would only materialize centuries later, revolutionizing the way humans connect and share information.</p>
<h2>Part 2: Cat Coders and Cyber Kittens</h2>
<img src="./web_cat_img/cat-renaissance.png">
<p>The Renaissance, a period of profound human creativity, was not only a time of human enlightenment but also a time when cats secretly initiated a technological revolution. In the dimly lit chambers of secret societies, cat coders armed with quills and parchment devised algorithms that defied the laws of physics and reality.</p>
<p>These cyber kittens, as they came to be known, transcended the limitations of their furry existence. Their coding sessions, shrouded in mystery, shaped the very essence of the digital realm. They laid the groundwork for a virtual utopia, where bits and bytes danced in harmony with the whimsical musings of feline intellect.</p>
<h2>Part 3: The Feline World Wide Web</h2>
<img src="./web_cat_img/cat-modern.png">
<p>Fast forward to the modern era, where the internet is a sprawling playground shaped by the paws of our feline overlords. From the invention of the mouse, a device that symbolizes the eternal struggle between cat and rodent, to the viral cat videos that dominate the digital landscape, cats have masterfully directed the evolution of the World Wide Web.</p>
<p>Today, the internet is not just a collection of interconnected devices; it is a testament to the whimsy, curiosity, and omnipotence of our feline companions. The digital tapestry, woven with the paw prints of cats, continues to expand, leaving an indelible mark on the ever-evolving landscape of the online world.</p>
<footer>
<div class="footer_div" style="margin-top: 100px;">
<img class="ico_footer" src="web_cat_img/facebook_logo.png">
<img class="ico_footer" src="web_cat_img/insta_logo.png">
<img class="ico_footer" src="web_cat_img/twitter_logo.png">
</div>
<div class="footer_div" style="margin-bottom: 50px;">
<a href="https://www.facebook.com/">MIAOUBOOK</a>
<a href="https://www.instagram.com/">INSTAMIA</a>
<a href="https://twitter.com/">BLUE-SNACK</a>
</div>
<a href="ml/mentions_legales.html">- LEGAL NOTICES -<br>(boring stuff, really, dont go look into this, i mean we are obligated to include it, but it will bore you, like, really)
<br>dont do it! every seconds you spend in this next page, a kitten dies. so dont</a>
</footer>
</body>
</html>
@@ -0,0 +1,89 @@
//////////////////////////////////////////////////////////////////////
// INDEX MAIN LOGIN
async function storeValue() {
storedLogin = document.getElementById('loginInput').value;
document.getElementById('loginInput').value = '';
var status = await checkStatus();
if (status === false) {
chaberu('Please, who do you think we are?\nWe already know all about you.\nNow enter your correct login and nobody gets hurt', 'popup-chaberu');
document.getElementById('loginInput').placeholder = `enter your 42 login`;
storedLogin = '';
}
else {
document.getElementById('loginInput').placeholder = `Welcome ${storedLogin}!`;
document.getElementById('header1').textContent = `Let's talk a bit, ${logUser.firstName}.`;
localStorage.setItem('storedLogin', storedLogin);
}
}
// async function checkStatus() {
// // fetch_url = `http://localhost:8081/proxy/profile/${storedLogin}`;
// fetch_url = `http://localhost:9999/webcat.com/login/login_script.php?login=${encodeURIComponent(storedLogin)}`;
// try {
// const response = await fetch(fetch_url);
// const statusCode = response.status;
// if (response.status !== 200) {
// throw new Error('Unvalid User');
// }
// else {
// const jsonData = await response.json();
// logUser = {
// firstName: jsonData.usual_first_name ?? jsonData.first_name,
// lastName: jsonData.last_name,
// photo: jsonData.image.link,
// month: jsonData.pool_month,
// year: jsonData.pool_year,
// projects: jsonData.projects_users.filter(project => project.status === "in_progress").map(project => project.project.name),
// perfect: jsonData.projects_users.filter(project => project.final_mark === 125).map(project => project.project.name),
// bh: Math.floor((new Date(jsonData.cursus_users[1].blackholed_at) - new Date()) / 86400000)
// };
// discussion = [
// `Welcome ${logUser.firstName} ${logUser.lastName}.`,
// `We heard quite a lot about the piscine of ${logUser.month} ${logUser.year}...\nIt's suprising to see you here`,
// `How is your ${logUser.projects[Math.floor(Math.random() * logUser.projects.length)]} coming along?`,
// `Perfect score for ${logUser.perfect[Math.floor(Math.random() * logUser.perfect.length)]}, impressive.. Should you really spend so much time in front of a screen?`,
// `Your BH is in ${logUser.bh} days... A cat wouldn't take that much time.`,
// `Shouldn't you be working on your ${logUser.projects[Math.floor(Math.random() * logUser.projects.length)]}?`,
// `Quite an ugly human...\n but then again, you arent a cat`
// ]
// index_wiskas = 0;
// return true;
// }
// } catch (error) {
// return false;
// }
// }
function talkWiskas() {
if (index_wiskas > 6) return ;
document.getElementById('popup-chaberu').textContent = '';
chaberu(discussion[index_wiskas], 'popup-chaberu');
if (index_wiskas === 6) {
document.getElementById('header1').textContent = `Time to end this, I have other cats to see.\nEnjoy this place.`;
document.getElementById('backgroundpicture').src = logUser.photo;
}
}
function chaberu(str, id, index = 0) {
if (chaberuka) return ;
const chaberuu = () => {
if (index < str.length) {
chaberuka = true;
document.getElementById(id).textContent += str[index];
index++;
setTimeout(() => {
chaberuu(str, id, index);
}, 20);
}
else {
setTimeout(() => {
document.getElementById(id).textContent = '';
chaberuka = false;
index_wiskas++;
}, 2000);
}
}
chaberuu();
}
@@ -0,0 +1,51 @@
//////////////////////////////////////////////////////////////////////
// STAFF IMG CHANGING
let images = [
"100.jpg", "101.jpg", "102.jpg", "103.jpg",
"200.jpg", "201.jpg", "202.jpg", "203.jpg",
"204.jpg", "205.jpg", "206.jpg", "207.jpg",
"208.jpg", "226.jpg", "300.jpg", "301.jpg",
"302.jpg", "303.jpg", "304.jpg", "305.jpg",
"307.jpg", "308.jpg", "400.jpg", "401.jpg",
"402.jpg", "403.jpg", "404.jpg", "405.jpg",
"406.jpg", "407.jpg", "408.jpg", "409.jpg",
"410.jpg", "411.jpg", "412.jpg", "413.jpg",
"414.jpg", "415.jpg", "416.jpg", "417.jpg",
"418.jpg", "420.jpg", "421.jpg", "422.jpg",
"423.jpg", "424.jpg", "425.jpg", "426.jpg",
"428.jpg", "429.jpg", "431.jpg", "444.jpg",
"450.jpg", "451.jpg", "497.jpg", "498.jpg",
"499.jpg", "500.jpg", "501.jpg", "502.jpg",
"503.jpg", "504.jpg", "506.jpg", "507.jpg",
"508.jpg", "509.jpg", "510.jpg", "511.jpg",
"521.jpg", "522.jpg", "523.jpg", "525.jpg",
"530.jpg", "599.jpg"
];
var currentIndex = 0;
function changeImage() {
currentIndex = Math.floor(Math.random() * images.length);
var randomImageElement = document.getElementById("randomImage");
randomImageElement.src = '../web_cat_img/errors/' + images[currentIndex];
}
function prevImage() {
currentIndex = (currentIndex - 1 + images.length) % images.length;
var currentImage = document.getElementById("randomImage");
currentImage.src = '../web_cat_img/errors/' + images[currentIndex]
}
function nextImage() {
currentIndex = (currentIndex + 1) % images.length;
var currentImage = document.getElementById("randomImage");
currentImage.src = '../web_cat_img/errors/' + images[currentIndex]
}
document.addEventListener('keyup', function(event) {
// Check if the pressed key is the left arrow key
if (event.key === 'ArrowLeft') {
prevImage();}
if (event.key === 'ArrowRight') {
nextImage();}
if (event.code === 'Space') {
event.preventDefault();
changeImage();}
});
@@ -0,0 +1,49 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>HTTP staff</title>
<link rel="stylesheet" type="text/css" href="../style.css">
<script src="script.js"></script>
</head>
<body>
<p style="text-align: left;">
<a href="/index.html" class="button1">< home 🐱</a>
</p>
<h1 style="font-size: 50px; padding-bottom: 80px;">- Hyper Text Transfer Protocol -</h1>
<section>
<p>Below you may behold the members of the HTTP division, in all their glory.
<br>Our staff epitomizes professionalism and diligence, they never take pauses or sleep on the job, or at least not today, i think...
<br>Today, as always, they remain steadfast, their tireless dedication ensuring the seamless operation of this page.
<br>Or any pages that you ever opened for that matter.
</p>
</section>
<div style="margin-bottom: 200px;">
<button class="previousButton" onclick="prevImage()"></button>
<img onclick="changeImage();" id="randomImage" src="" alt="Random Image">
<button class="nextButton" onclick="nextImage()"></button>
</div>
<footer>
<div class="footer_div" style="margin-top: 100px;">
<img class="ico_footer" src="../web_cat_img/facebook_logo.png">
<img class="ico_footer" src="../web_cat_img/insta_logo.png">
<img class="ico_footer" src="../web_cat_img/twitter_logo.png">
</div>
<div class="footer_div" style="margin-bottom: 50px;">
<a href="https://www.facebook.com/">MIAOUBOOK</a>
<a href="https://www.instagram.com/">INSTAMIA</a>
<a href="https://twitter.com/">BLUE-SNACK</a>
</div>
<a href="/webcat/ml/mentions_legales.html">- LEGAL NOTICES -<br>(boring stuff, really, dont go look into this, i mean we are obligated to include it, but it will bore you, like, really)
<br>dont do it! every seconds you spend in this next page, a kitten dies. so dont</a>
</footer>
<script>
changeImage();
</script>
</body>
</html>
@@ -0,0 +1,137 @@
:root {
/* custom CSS variables */
--clr-dark: #0f172a;
--clr-light: #f1f5f9;
--clr-accent: #e11d48;
}
body {
background-color: black;
color: #696969;
font-family: 'Times New Roman', serif;
font-size: 20px;
line-height: 1.5;
text-align: center;
}
a {
text-decoration: none;
color: #5c5c5c;
}
a:hover {
color: rgb(218, 145, 12);
}
/**************************************************/
/* CLASS */
.footer_div {
display: flex;
justify-content: space-around;
/* padding: 20px; */
/* margin-top: 80px;
margin-bottom: 100px; */
}
.ico_footer {
text-align: center;
width: 25px;
vertical-align: top;
/* padding-right: 5px; */
}
/* INDEX */
.header_index {
display: flex;
justify-content: space-between;
text-align: justify;
align-items: center;
border: 2px solid rgb(218, 145, 12);
border-radius: 25px;
}
.header1 {
color: rgb(218, 145, 12);
border: 3px solid rgb(218, 145, 12);
padding: 20px;
border-radius: 25px;
}
.input {
box-sizing: border-box;
width: 100%;
border: 3px solid rgb(218, 145, 12);
}
input:focus {
outline: none;
border-color: rgb(218, 145, 12);
box-shadow: 0 0 5px rgb(218, 145, 12);
}
.popup-chaberu {
position: fixed;
left: 75%;
transform: translateX(-50%);
padding: 20px;
z-index: 1000;
display: flex;
height: 400px;
width: 250px;
color: var(--color1);
font-weight: bold;
font-size: 25px;
justify-content: center;
align-items: center;
text-align: center;
}
/**************************************************/
/* BUTTONS */
.nextButton {
width: 0;
height: 0;
border-style: none;
display: inline-block;
padding: 10px;
cursor: pointer;
background-color: white;
border-radius: 0px;
clip-path: polygon(0% 0%, 100% 50%, 0% 100%);
outline: none;
text-align: left;
}
.previousButton {
width: 0;
height: 0;
border-style: none;
display: inline-block;
padding: 10px;
cursor: pointer;
background-color: rgb(218, 145, 12);
border-radius: 0px;
clip-path: polygon(0% 50%, 100% 0%, 100% 100%);
outline: none;
text-align: left;
}
.button1 {
display: inline-block;
padding: 10px 20px;
background-color: #000000;
color: #8e8e8e;
text-align: center;
text-decoration: none;
font-size: 16px;
cursor: pointer;
border: 3px solid #363636;
border-radius: 6px;
transition: background-color 0.3s;
}/*home 🐱?*/
.button1:hover {
background-color: rgb(202, 135, 10);
color: black;
}
Binary file not shown.

After

Width:  |  Height:  |  Size: 437 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 438 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 517 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 81 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 40 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 30 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 37 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 43 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 30 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 44 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 49 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 56 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 22 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 38 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 27 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 24 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 37 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 45 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 28 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 30 KiB

Some files were not shown because too many files have changed in this diff Show More