diff --git a/.editorconfig b/.editorconfig index c53a523..8b1af71 100644 --- a/.editorconfig +++ b/.editorconfig @@ -6,7 +6,7 @@ end_of_line = lf insert_final_newline = true trim_trailing_whitespace = true indent_style = space -indent_size = 2 +indent_size = 4 [*.md] trim_trailing_whitespace = false \ No newline at end of file diff --git a/.well-known/security.txt b/.well-known/security.txt new file mode 100644 index 0000000..a87daed --- /dev/null +++ b/.well-known/security.txt @@ -0,0 +1,4 @@ +Contact: mailto:admin@doughmination.win +Expires: 2030-01-01T00:00:00.000Z +Preferred-Languages: en +Canonical: https://c.stupid.cat/.well-known/security.txt diff --git a/404.html b/404.html new file mode 100644 index 0000000..b1be62a --- /dev/null +++ b/404.html @@ -0,0 +1,22 @@ + + + + + + + + Oooops! + + + + + +
+

You stumbled into the void!

+

Not sure if you was trying to find this or not, but looks like we're both confused.

+ + + + ↩ Click me to go to the homepage +
+ \ No newline at end of file diff --git a/88x31/index.html b/88x31/index.html index f244340..94fc3da 100644 --- a/88x31/index.html +++ b/88x31/index.html @@ -64,6 +64,7 @@ Music 88x31 Guestbook + ASCII diff --git a/Archive.zip b/Archive.zip new file mode 100644 index 0000000..2fb05d3 Binary files /dev/null and b/Archive.zip differ diff --git a/ascii.txt b/ascii.txt new file mode 100644 index 0000000..0f72d90 --- /dev/null +++ b/ascii.txt @@ -0,0 +1,180 @@ + :Xt8 8XX%;;  + . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ;8.8 S8S;@SXXS;Xt . . . . . . . . . . . . . . . . . . . . . . . . .  + . . . . . . . . . . . %.X.tt @ 8t. . . . . . . . . . . . . . . :8.8;Xt@X@8888888888:8: . . . . . . . . . + . . . . . . . . . . . . . . . . . . . . 8S.SX%8Xttt8 t%. . . . . . . . . . . . . . . . . . . . . . . . . . . . S..;;t8888888888888888SX8 . . . . . . . . . . . . . . . .  + . . . . . . . . . . . .:8S888888888XXt8;X.8; . . . . . . . . . . . . . ;8S 8SS888888888@@888888888;X: . . . . . . . . .  + . . . . . . . . . . . . . . . . . . . . .%;88@8888XXXX8888XXt@8 @S%. . . . . . . . . . . . . . . . . . . . . . . . .8; 8;@@88888888888S88@8X8@8888@%% . . . . . . . . . . . . . . . . . + . . . . . . . . . . . . . . . . . . . . 88X888888888@tt@@888888X;;8@8: . . . . . . . . . . . . . . . . . . . . . .X X:@8888888888888S8@S8S8@88S8@88% . . . . . . . . . . . . . . . .  + . . . . . . . . . . ; ;8888888888888XS;@@888888Xt8S@:S. . . . . . . . . . . . . . . . . . .:8@t%@@8888888888888X888t@8888S:88@8888@ . . . . . . . . . . . . . . . .  + . . . . . . . . . . . . . . . . . . . . .t;88888888@8@88888@8%SSX8888888Xt@SS%%. . . . . . . . . . ;%@8;XX88888888888888X8S8X;SX%%8 :X8888;8X. . . . . . . . . . + . . . . . . . . . . . . . . . . . . .%SS888@@X88@88S@S8@@888@;S@8888888@SX.8XX . . . . . . . . . . . . . . . . . ..t;:;88888888888@88888@8888 t:S%:888Xtt8.888S8 . . . . . . . . . . . . . . . .  + . . . . . . . . . . .  t88@X8t8.88X888X8888@888XtX@888888888X;8 t8. . . . . . . . . . . .@t;t;888888888@8888888SX88.S 8;%:: ... tStS.@8%t . . . . . . . . .  + . . . . . . . . . . . . . . . . . . . %tSS888%S.8.8 S8S@88@X8S8@@8Xt%8@888888888@StS@tt. . . . . . . . . . . . . S..tXX888888@88@888888@t8@8;S@:t;%8 ;8X%8..8t88t8S8 . . . . . . . . . . . . . . .  + . . . . . . . . . . . . . . . . . . . S8X88;X.;8.SX:;t;8:X8S;88X@8888;S8888888888888t;X;t . . . . . . . . . . . . ::@.X8888@88@88888888@8X;8@S8:8.S%%t. .%XX@XX ;%%8S8@S . . . . . . . . . . . . .  + . . . . . . . . . . . . . . . . . . . S@8888@8::XSt;;tXXtt8888@88@8888S;@8888888888888StXStt . . . . . . . . . t :t@888888888888888888@St8888S8;S%%t8. tXX88t8 :tS;S8@8: . . . . . . . . . . . . + . . . . . . . . . . S:8St%;%.%. .. .:X;;8888X8@@8888t%88888@888888888X;8  X. . . .....:..:.:... . . @88t8888888888@888@88@88X;@88@X8;8;%%tS8. %XS88%. ;SS88888X . . . . . . . . . . . . .  + . . . . . . . . . . . . . . . . . . . . SS:S:%S;: .SXStS :t%88888X@8@8888@;X8@88888888888888X:8@S ..:t%@8Xt: :;%%SXXXXSS%t;: :%X8X%;:t8;888888888@88888888888X:@88888S8S8;StS@. .XS;; 8@%X:X8@8 . . . . . . . . . . . . . .  + . . . . . . . . . . 88;;%S%8 ;t@8S888 8S:S:X88X@888888@tX@8888888888888888Xt8 : .;%S@@8888888888X S..tXSX888888@XSStSSS88888888@88888@888@88X;@88888X88S8SS%SX%. .%; @XXtX88@X: . . . . . . . . . . . . .  + . . . . . . . . . . . . . . . . . . . . :%8XS%%t: %88888%8 @Xt88;8S8888888888X;@@88@888888888888888;X@ @88888X :@8XttXtSt%SXXXXXXXXXXStt%ttt;;;;;tXX@8888888888@S;888888888@t@;St%@@8@tt;%8XXS888888Xt. . . . . . . . . . . . . . + . . . . . . . . . . . . . . . S8%S%%%%. :t88;8. 8@ttS888888888888888;X@888888@8888888@Stt:..:;;tt;.. :@@8888888888888888888888888888@Xt;..:t8@888@88S;8@88888@@8S888;%%S@X8XS8SXSSS88S8@8@X@ . . . . . . . . . . . . .  + . . . . . . . . . . . . . . . 8@S.St%%S .S :SS %S%S%:@;S@X88888888888tX@888@8@XXS@8X%t X888XS%t%%@8X .@8@X@88888888888888888888888888888@X%%;:;t8@8X;8@88888@88@;8Xt%%X8888XXX%%SS8888S@8S88 . . . . . . . . . . . . .  + . . . . . . . . . . . . . . . 88@SS%%%St. :8S%%%S888888888888888888X;Xt88. X;:%@XS8888@888888888888@S.X @X888@88@888@8888888888888888888888@%t::;X888888@8:8S8%S%tX8XS;;;%X8@%S8888X888;. . . . . . . . . . . . . + . . . . . . . . . . . . . . . . . . . 8888tt%@XS@: :XXX8S%%%;X88@8@888888@888X;;8 .S888888@@XXX888Xttt%%SXX8888888X. 8@88888888888888@888888888888@X;;;;::....;888@88X88.8:;:. XX%8S888@88:@ . . . . . . . . . . . . . .  + . . . . . . . . . . . . . . . . .X888;SSSXXS888888@@8@X@@%%t;8S888@@888@X;X8.8.S888@@8@8S:::tX8@X;.:..:.:::;;%SX@88SX@@88888@8888@88888@888888@X;::SSX@@XXSt%t;:;%@8%X88 @ . . @%:8t88888;X. . . . . . . . . . . .  + . . . . . . . . . . . . . . ;8XX88tSSS@X@88@88S:;:. .8%%;8XSS8SSSXX ;t@8@@@88@888@%:.:%XXX% ..:... ..:..::;tSS:8X8@8888888888888888@88@;:;8@8888888@X@X8888%; ;8 : :S88X. . 8St@8X888t:% . . . . . . . . . . . .  + . . . . . . . . . . . . . . . . X8S8888tSSS@88X8X. . 8X888tX%8S.888@Xt:S88@88@@%.;t.::..t%%%%%%SSS%%;. :..::.::.:888@XStttttttt%Xt8@8@;:;888888888888888888@8@;;;.8. .@8@88@8 :tS888888S8S . . . . . . . . . . . . . .  + . . . . . . . . . . . . . . . . . . 88S8888S.%SS88S; X;8X8 ;%88@St:.:S8@@X%tt ;;.%88@8X%t%%%%%SS%;:.;%t: ..:.. ;%t;::;%SSSSS;tt;t;:::::888888888888888888888X88%:t..S888tXSS. 8S8X8@88X@@. . . . . . . . . . . . . + . . . . . . . . . . . . . @XX8X888;S%S8. t88@X8t S:8 :X8@St::.:.:t%t;;S@88SSX@%%%X8SSSSSSSS@888@8@S;:%; :.;;@:88X@88@8888@888@@8888S:::t888888888888888X@888@@8%;;tX8S;SSX 8S;XS888@t@ . . . . . . . . . . . . .  + . . . . . . . . . . . . . . . . tt88XX8:8;%%. .88888XStt.88S88@%::.:......;S8XS%@X%X@%SSS8SSSSSSSSSX8@88@88@S %t :.%8.X@8X;88XS8@888888X;888@88t:.X88888888888S@8888888@8X:;SXS.X@ 8@888@888tt . . . . . . . . . . . . . .  + . . . . . . . . . . . . . . . :t888S @.St;. ;88X88S8@888 @@Xt:.:.: ;%.S8@S%S%X@SX@SS%S8XSSSSSSSSSX@88@88@88X %; :8%;;88@8XSX;;;t;;;;;tt:::::;t:. .S88888888S888@888888888tt;@8t% . 88:88@@8@;  . . . . . . . . . . .  + . . . . . . . . . . . . . . . . . :t8X88StS%@ %8888888%;St@Xt:..:...tt; XX%SS%SSXXS@XS%SS8XSSSSSSSSSSX@888@888@88 %:X@8S.XS;;S8S: X@88@@XXX8X t888St%%t:.:S888888X@8888888888@8S::. ;X88S8888@;% . . . . . . . . . . . . . . + . . . . . . . . . . . . . . tt88888:8.. S888888%.:@X;.:.:...%S:;%@X%S%SS%S8SXXSS%%@XSSSSSSSSSSSX@8@888@8888StS8tX8. .XS8SXSSSXSXSSXSXXSS88.X888888@;:.;888S888888888888@X88;;.. @88.X@X888:X. . . . . . . . . . . .  + . . . . . . . . . . . . . . . . %;888tS tX. ..SS88888 %St.:.....t%.;SSX@%S%SS%S8SX@%%%tS8@@@@XXSSSSSSS@88@888@8@8SXS%X88:: %XSXSXSXSXSXXSXSXXSXS@8  XX;ttX;t;.:X@88888888888X@8888t;;888X88888888:@. . . . . . . . . . . .  + . . . . . . . . . . . . . . . .S;8888.8tX ;S888S8%%:..:.. :%;:SXXS@@%S%S%SS8X@Xtt;;%8888@888@8@XXSXX8@88@888X;8:8@888;t8SSXSXSXSXSXSXSXXSXSXXS%%S8@ :; .S8X:.:S8888888XX888888@@:;888X@88888@:;S . . . . . . . . . . . . . + . . . . . . . . . . . . . . . X;88X8;8;% .;%@88 t:.:..:.%%:8@XXXX8t%%SSS%8SXX;;;;t8888@88@88@88@XSX@88@888tX%:888888X: %XSXSXXSXXSXSXSXSXXSXXSXSXSS8 ; SSS@8 X:.S8888S@8888888888;:t@88888888.;% . . . . . . . . . . . .  + . . . . . . . . . . . . . . . . . S;8@888%S%; X%%8St: : : ;% X88XXXX8t%S%S%S@XX@;;;;;@88888@88@88@888@X@888@ :8t8@888888t:.SXSXXSXSXSXSXXSXSXSXSXSXXSXXXX8  @XSSX8.S:S@X8888888888888;;X8888888@: : . . . . . . . . . . . .  + . . . . . . . . . . . . . . S;888888tXt t@8 :.:: .%.X88S8XS@8t%%%S%S@X@S;;;;;8888@888@88888@8@@X@@%8@@88@88@88888:.X@XXSXSXSXSXXSXSXSXSXSXXSXSXSXS%%X8. 8XSXXX S.;88888888888888S.;888888@.@ . . . . . . . . . . . . .  + . . . . . . . . . . . .;S8StttX8X;. .%;88888S8XSX. t88:: ::S 88S88@XX8%%%S%SSX@XX;;;;;X88@88@8888@8@88888X%8@.;888888X8888::XX. %SXSXXSXSXSXSXXSXSXSXSXSXSXSXXSXS@:XXSX%%SS@ ;8888888888888t:t88888@.8 . . . . . . . . . . . .  + . . . . . . . . . . . .t8.%88@8888888888@;:@@;. ;;8888X888t@t:. ;8...:.S 88888@SX8S%S%SS%S8@8;;;;;S8888888@8@888888XX@88X%8S888888X888;;t8S8 888@SXSXSXSXSXSXXSXSXSXSXSXSXSXSX8  @SXXXS8.t;X888888888888;:X8@88X.% . . . . . . . . . . . .  + . . . . . . . . . %:8X88@@@XXXXSXXXSXSXX@8888ttX;888888@X@;XX%8SS8;  .%:X8X8@SXX8X%S%S%SS888:;;;;S888@8@888@888XS88%tt@8888@888888888:t SXSSt8.SS% tXSXXSXSXXSXSXSXXSXXSXSXSXSX%t8: SSXXXSS 8.t888888X8888;:X888S:@: . . . . ..:::.. . . . . . . .  + . . . . . . . . . . @ X X X XSX8@XXSSSSXXXSS@8::@88888@88888t8XX@;X t%tXXXXXXXX@%S%S%SS888t;;;;%8888888@888@%S8;.:8@@888X88@8888888:: ;XSXSXS@.S:;@SXSXSXXSXSXSXXSXSXSXSXSXSXSXXX8. XSXSXSS@;..@88X%8888@8.:888S; % . . . .%8t:S88888S.%@; . . . . . .  + . . . . . . . . . . . ::::.:.:;@X:8.:. XSS@8@SXXSSS;@888888@8S@@88X8@:S8@t:%XSXSSX8tS%SSS%@88X;;;;t888888@Xt:.;8S%t888@88888%@8X88888X.S tSXXSXSXSX ;@.@SXSXSXSXSXXSXSXSXSXXSXSXSXSXSS8; SSXSXSX@S8.;@@8888888;:S88tX888 .t8t:X8888888@@@@88888@.8t. . . . . .  + . . . . . . . :SS.@8@88@XXSS%SXSSSXSXSXS@;@888888888888X8X8;;88@%XS8  8SXS%%%%@888:;%S@t.%8.t8XS%X8S88@@8888888888@8@888@:;t8%XSXSXSXSXS%8 t XSXSXSXSXSXSXSXXSXSXSXXSXSXSXXS8:.@SXSXSXXXS8.;88888888..88tt@@8@8.S8@88XXSXSXXXSXX@8888888@S X8. . . . . .  + . . . . . . . . . . . ;S8 88XXXXXSXSXSXXSXXSXSXSXS8Xt8888888888888888t;@88X8:%%;tX@X. 888 8 @ SXtt:.:ttS88X8@XX8888888888888S8888;:% SX@SXSXSXXSXSXS%8t:8SXSXSXSXSXSXSXSXXSXSXSXXSXSXXX8t SXXSXSXSS@;..88888S8;:t8tt%@8 X8@XSXSXXX@888@S 88Xt;:.:...;@ . . . . . . + . . . . . . . . . . tSt888SSSXSXSXSXXSXSXSXSXSXSXSS8S%8@88888888888888X;;8888S8888@t%@%%t;S%StSS;@@88888@X88888S88888888888888S88X:%;8%SX88SXXSXSXSXSXXX8 .@XXSXXSXXSXSXSXSXSXXSXSXSXSXSXX8: %SXSXSXXX8 S.X8@X88@.:Xt@:;X@8XSXXSX@88XXX S X 8S X@; . . . . .  + . . . . . . . t%X@8@SXSXXSXSXSXXSXSXSXSXSXXSXSXS88t88888888888888888t:.t88XS88@8@@@@@8S8X@@X8@88888888888888:X8888888888888X:;8 XXXXXSX88XSXSXSXSXSXSS%8..@XSXXSXSXXSXSXSXSXSXSXXSXSXSXX8; tXXSXSXSSS8X.:88888.:;; SXt.S8XXSXSSSXSX%%S%S%XX@8888;%X: . . . . . . .  + . . . . . . . . . .@XX@XXXSXSXSXSXSXSXSXSXSXSXXSXSXXSX@8;88888888888888888t;t;.;8S8888888888S@888;8888888888888888S;88888888888S..8 %%XXSXSXX@@@XSXXSXXSXSXSXXXSt XSSXSXSXSXXSXSXSXSXSXSXSXSXXX  8SSXSXSXSXS88.;888X.t8X8SS ; SXXSXXXSXSXXSXSSXSSXXSSS@@ @X: . . . . . . + . . . . . . . . .@X@8XSXSXSXSXSXXSXSXSXSXSXSXSXSXSXSXS8@;8888888888888888%;X88tt::S888888888@S888;8888888888888888@:88888888S:;S8@X%XSXSXSXSSX8S@SXSXSXSXSXXSXSX8  @XSXSXSXSXXSXXSXXSXSXSXSXSSSX; %XSXSXSXSXSXS.;88:;@88XSS% ;.8XXSSXSXXSXSXXSXXSXSXXXSSS888;8; . . . .  + . . . . . . :%8@@SXSXSXSXSXSXSXSXXSXSXSXSXSXSXSXSXS8X.:8888@8888888888%;X8888%:;S::;SX88888;88@8;8888888888888888;@88X;;;;8S. .%S@SXSXSXSXXSX8S8SXSXSXSXSXSXXSSS8 .XXXSXXSXSXSXSXSXSXXSXXSXXSXS:8XSXXSXSXSXSXS.;t%SXSXSXSS%S%:XSXSXXSSXSXSXSXSXSXSXSXSXSXS@88t8: . . .  + . . . . . . . . tX SSXSXXSXSXSXXSXSXXSXSXXSXSXSXSXSXSXSX@8 SX888888@888888@;;8888@;;8888X::. :X8%@888;888888888888888@;;...X8;t@XSSX%X %XSXXSXSXXSSX %SXSXXSXXSXSXXSXXS@t:8XSXSXSXSXXSXSXSXSXSXSXSS8S tXSXSXXSXSXS ::t %SXSXSXSXS.%XSXXSXSXSXSXSXSXSXSXSXSXSXSXSSX8 %S . . . . . + . . . . . . :X88%XSXXSXSXSXXSXSXXSXSXXSXSXXSXSXSXSXXS8SS8t@8@8888888@88@;:8888@;:@8888888@;:.:ttttt;;tXtXtX;tttt;;t8XX8XS%%: S@888@X;8SXSXSXXSSXSXXSXXSXSXSXSXSXSXSXSX8 . XSXSXSXSXSXXSXSXSXSXSXX8; tXSXXSXSXSXSX .XSSXSXSXSXSS@%;8XSXSXSXSXSXXSXXSXSXSXSXXSXSXSSS88.S . . .  + . . . . . . .88@XSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXXSXXSXSXX8XX8;8888@888888@t;@8888S.S888888X;;@; SSXS@@S  .... XS@8@X8;; 8888XSSXSXXS8tt8SSXXSXSXSXSXX SXSXSXSXSXSXSXSXXSSXX: 8XXSXSXXSXSXXSXSXXSXSX XSXSXSXXSXSX%%XSXSXSXSXXSXXX8;.XXSXSXXSXXSXSXSXSXXSXXSXSXXSXSSSX8XtX. . . .  + . . . . . . @ @SXSXSXSXSXSXXSXSXSXSXSXSXSXSXSXSXSXSXSX8S@XS%:8888888@888X:t8888@..888888::@ XS%XXXXSXS%%SSSXS%%XSXXXX ;8%SSXSXSXSXS@ S.. %XSXSXXSXSXXSX %XSXSXXSXXSXSXSXSXXS@ t %XSXSXSXXSXSXXSXSXX%X;8XSXSXSXSXXSXXSXSXSXSXSXSXSSS ;SSXSXSXXSXSXSXSXXSXSXSXSXSXSXXXSXXS8 8 . .  + . . . . . . ::@@SXSXSXSXSXSXSXSXSXXSXSXSXSXSXSXSXSXSXSXS@8SXX:.@888888888@;;88888;:X8888;;8 8SSXSXSSXXSXSXSXSXSXSXSXSS8t tXXXSXSXSX@ .%:S%.@SXSXSXSXXSSXSX SSXXSXSXSXSXSXSXSXSSS8 X@SXSXSXSXXSXSXXSXSSt8SXSXSXSXSXSXSXSXXSXXSXSXSXX%X.:8XSXXSXSXSXSXSXSXSXSXSXSXSXSSXXSXSSXX:% . . . + . . . . . . @8@XXSXXSXSXSXSXSXSXSXSXSXXSXSXSXSXXSXXSXSXS@S@XSX@;@888@888@8S:X8888X.;888t;@SXSSXSXXSXXSXSXSXSXXSXSXSXSX@. SXSSXSXXS8 :8Xtt;t::XSXSXSXSXXSXSS8 8SXSXXSXSXXSXXSXSXXSSS8 . 8XSXSXSXSXSXSXSS@X8SSXSXSXXSXXSXSXSXSXSXSXXSXSXS8% SXSXSXSXSXXSXSXSXSXXSXXSXSXXSXSXSXSX8X;; .  + . . . . . . @X8SSXSXSXSXSXXSXXSXSXXSXSXSXSXXSXXSXSXSXSXXS8@XSXS88;88888888@::8888@;.888;;:8SXSXSXSXSXSXSXSXSXSXSXXSXXSSX%@SXXSXXSSX%:tt;t;t;t%t8XSXXSXSXSXSXS8 8XSXSXSXSXXSXSXSXSXSXS%@ ; XSXSXSXSXSXSXS@SSSXSXXSXSXSXSXXSXSXSXSXSXSXSXSX :8SXSXSXSXSXSXSXSXXSXSXSXSXSXSXSXSXXXXX :: . .  + . . .888SXSXXSXSXSXSXXSXSXXSXSXXSXSXSXSXSXSXSXSXSXX@8SXSXXS;88888@88S.X8888X:;8@.;:@XSXXSXSXSXSXSXSXXSXSXXSXSXSX@:.@SXSXSS8 S 8;t;t;;t;X8;8XSXSXSXSXXSXS8 8XXSXXSXSXSXSXXSXXSXSXSS8  @SXXSXSXSXXS8S;8XXSXSXSXSXXSXSXXSXSXXSXXSXSX%8% %XSXXSXSXSXSXSXSXSXSXSXXSXSXSXSXSSXSSS@XS . . + . . . . . . . ..:X@SXSXSXSXSXXSXSXSXXSXSXSXSXSXSXSXSXSXXSXXSXS@S@XSXSX ;88888888:t88888;:@t:S:8XSXSXSXXSXSXXSXXSXXSXSXSXSXXS ;8SXSXS8 : %tt;t;;t;;ttX8:8XSXSXSXSXSXSSS8S8XSXSXSXSXXSXSXSXSXSSXS%X8. X@XSXXSXSS@SS SSXSXSXSXSXSXXSXSXXSXSXSXSXSXX.:8SXSXSXXSXSXXSXSXSXSXXSXSXSXSXXSXXSXSXS8Xt.  + . . . . ; SXSXSXSXSXXSXSXSXSXSXSXSXSXSXXSXXSXSXSXSXSXSX8SXSXSXS8t@8888888t8@888X:...tSSXSXSXSXSXSXXSXSXSXSXSXSXSXXSS@: %SXSS8t:: 8@;t;t;t;t;;;%8t8XSXXSXSXSXSXSX8 @SXSXXSXSXSXSXSXSXXSXSXSXX8;tXXSXSXXSX: ;8SSXXSXXSXSXSXSXXSXSXSXSXXSXSS8S tXSXXSXSXXSXSXXSXSXSXSXSXXSXSXSXSXSXSXX@ %. .  + . . . . ..SXXXSXSXSXSXSXSXXSXSXSXSXSXXSXXSXXSXSXXSXSXSXSX@S@SXSXSS@8;88@88888%X.8;Xt..S8S8SXSXSXSXSXSXSXSXSXSXXSXSXSXSX%;8XXSXStS8.S.t;;t;t;t;t;tt88t8XSXSXXSXSXSXSSS88XXSXSXSXSXXSXSXSXSXSXXSXX8X:. XXSXS ;; %SXSXSXSXXSXSXSXSXSXXSXSXSXSS8t.@SXSXSXXSXSXXSXSXXSXSXSXSXSXSXXSXSXSXXSSXS:: . + . . . .:S@SXSXXSXSXSXSXSXSXXSXSXSXSXSXSXSXSXXSXSXXSXSX@ X8XSXSXSS.t8@8@888;t;%t%S .8%X tSXXSXXSXXSXSXSXSXSXSXSXXSXSX8% %SS8; %t8;8X;t;t;;t;t;t;ttX ;XXSXSXSXSXXSXSXS@88XXXSXSXSXSXXSXSXSXSXSSXSSS@@..S8S 888t8XSXSXSXSXSXSXSXSXXSXSXSXXSXXS t@SXSXSXSXSXSXSXXSXSXXSXSXSXSXSXSXSXXSXSXSXXS%  + . . . . . @ SXSXXSXSXXSXSXSXSXSXSXXSXXSXXSXSXSXSXSXXSXSXXSSXX8SXSSSS%8@888S8.8;;;.;S8 @.S.SXSXSXSXXSXSXXSXXSXXSXSXSXSXXS :@SSSS X;t X8%t;t;t;;t;;t;;tt% %XXXSXSXXSXSXSXXXX@8@SXSXSXSXSXSXSXSXSXXSXXXSXSS8.t .@; XXSXSXXSXSXXSXSXSXSXSXSXXSXSXSS8S %SXSXSXSXSXSXSXSXSXSXSXXSXXSXSXSXSXSXSXXSXXS:  + . . . .X88SXXSXSXSXSXSXXSXXSXSXSXXSXSXSXSXSXSXSXSXSXSXSSX@X@%%tttt;88@tS.8@ 88@XX8SXX@@ %SXSXSXSXSXSXSXSXXSXSXXSXSXSX8: t@ :888Xt;:88;t;;t;t;t;;t;;;t%::%XXSXSXSXSXSXSXSXX@XXXSXXSXSXXSXSXSXSXSXSXSXSXSX8 : S;: %XSXSXSXSXSXXSXXSXSXXSXSXSXSS8t XXSXXSXXSXSXSXSXSXSXSXSXSXSXSXSXXSXSXXSXSXXS::. + . . . S88SXSXSXSXSXSXXSXSXSXSXXSXSXSXSXSXSXXSXXSXSXS8 8XX8 :;888888@8;8:88X 88@S%;88 t%@SXSXSXSXSXSXSXSXSXSXXSXSXXSXS X8: ;X @@ S8 8888St;;;t;t;tt;;t;88.8XSXSXSXSXSXSXSXSXXXXSXSXXSXSXXSXSXSXSXSXSXSXS%SS8% %S8SXSXXSXSXXSXSXSXSXSXSXSXXSXXX.;8SXSXSXSXSXXSXXSXSXXSXXSXSXSXXSXSXSXSXSXSXSXXS; + . . . ..;SSXSXSXSXSXSXSXSXXSXSXSXSXSXSXXSXXSXSXSXSXSXXS8SS8.X88@@@88S@8:88t;;::XXX@888@8 XXSXXSXXSXSXXSXXSXSXSXSXSXSXS@: %8X8Xtt%XStSXX@8@8. 88t;;;;t;t;t;%ttXXSXSXSXSXSXSXSXSXSXXSXSXSXSXSXSXSXSXSXSXSXSXXSXXSX@:%:8SSXSXXSXSXSXSXXSXSXSXSXSXSS %@SXSXSXSXXSXSXSXSXSXXSXSXXSXSXSXSXXSXSXSXXSXX . + . . . . 8 SSXSXSXSXXSXSXSXSXSXXSXSXSXSXSXSXSXSXSXSXSXS@SXS8 ;8 8@8@@@:::t%%%ttXS@X8@888@8 tXSXSXSXSXXSXSXSXSXSXSXSX@8 StX:::;;;t;:.:;..  ;XX8@8; 8X;;t;;t;%: XSXSXXSXXSXXSXXSXX8XXSXSXXSXSXXSXXSXSXXSXXSXSXSXSS@8S . 8@SSXSXSXSXSXSXXSXSXSXSX%@@;8XSXXSXSXSXSXSXXSXSXSXSXSXSXSXSXSXSXSXXSXSX%X  + . . .S8@SXSXSXSXSXSXXSXSXSXSXSXXSXXSXSXXSXSXXSXXSXS8 %SX  888S88:8@8@:;;ttSXS@@XX8@@8@88XSXSXSXSXSXSXXSXSXXSXX8X ;t: S8: 88@X@8S8 :.tX88 .XXt.%@888% 8%;t;;;% . SXSXSXSXSXXSXSX@ 8XXSXSXSXSXSXSXSXSXSXSXSXSXSXXSXSSX8 S8XXSXXSXSXSXSXXSXXSXS8St 8SXSXSXSXSXSXSXSXSXSXXSXSXXSXXSXSXSXSXSXSXSSS + . . . . . tXSXXSXXSXSXSXSXXSXSXSXSXSXSXSXSXSXXSXSXSXS@ %S8 .tS88Xt. S:. .@X%@@@@X8X@8SXXt8XXSXXSXXSXSXSXSXXSXS@8@888@S8S;X;tt8% :t. . : .%%8S:  .SX@88t;t;tt8 .8SXSXSXSXSXSXSSt8; @SXSXXSXSXSXSXXSXSXSXSXSXXSXSXSXSS%S8 t; XXSXSXXSXXSXSXSXSS8X:8 XSXSXXSXXSXXSXXSXSXSXSXXSXSXSXSXXSXSXSXSXXSX + . X@@SXXSXSXSXSXXSXXSXSXXSXSXSXSXSXXSXXSXSXSXSXX88X@ XS%8%88t%t;.S8%. .%8X@@8@@XSS%@;8SXXSXSXSXSXSXSXSXSXXSXSXSXSS :tS8%:. .XSS.t@@XX@@888Xt:XS;. .%8.t%;tttX% SXSXSXSXSXSXSXS8 : S8@SXSXXSXXSXSXXSXSXSXSXSXSXXSXSXXSX88 88XSXSXSXSXSXXS8%;@8 %SXSXXSXSXSXSXSXXSXSXSXSXXSXSXSXXSXSXSXSXSX + . . . . . :X@SXSXSXSXSXXSXSXSXSXSXSXXSXXSXXSXSXSXSXSXSXS@X@XX8X 8t88888;8t%t:.8%. :SXSXX%SSS8%8XSXSXSXSXXSXSXSXSXSXSXSXXSX@.@t. :t8@%XtX8t;;t;t;;tt;;;t%X8: 8.:SX8:t;;t;X  @XSXXSXSXXSXSSS8 S%:. @8@XXSXSXSXSXXSXSXSXSXSXSXSXSXSXSt%S8S 88@XSXXSXS@:;8S8XXSXSXSXSXSXSXXSXSXXSXSXSXSXXSXSXSXXSXSXSXS + . 8 %XSXSXSXSXSXSXSXSXXSXSXSXXSXSXSXSXSXSXSXXSXS88S8 X %;8@888SS.8tS%%;.8; .8S8X%SS8S8XXSXSXSXSXSXXSXSXSXSXSXSXSX88 : XS;;t;8888;t;t;;t;;t;t;tttt:;888.. 88;t;t;;@8% %SSXSXSXSXXSSS@ % X@ ;%% X8@@SSXSSXSXSXSXSXSXSXSXSXSXXSXXS%S@@.;;.X8XXSXX.X tX XSXSXSXXSXSXSXSXXSXSXXSXSXSXSXSXXSXSXXSXSX + . . . .:S8SXSXXSXSXSXSXSXSXSXSXXSXSXSXSXSXXSXSXSXSXXS@8XXS S;S88888@SX888%S%%t;S8: ;8SX%t8t8XSXSXXSXXSXSXXSXXSXXSXXSXS% .;8X;;t;;;.8%t;t;t;t;tt;;t;t;t;tttt8;S; 8tt;t;t;%S8.S@SXXSXXSXXXSSX@. 8X88@S .;%St S88888@888888888888888@@X X ;;; XXSXS S.8%8XXSXSXSXSXXSXSXSXSXSXSXSXSXSXXSXSXSXSXSXXS + . . :SXSXXSXSXXSXSXXSXXSXSXSXSXSXSXXSXSXSXXSXXSXSX@8S8@::@888888888@8@X8tX%%%tS8: .t8ttXt8SXSXSXXSXSXSXSXSXXSXSXSX%  8;%t;t;t;ttX88S%XX@XXX%t;t;tt;tt;ttttt%8%.;8t;tttttt88%:8XXSXSSSXXSSSS8;S%8@tt;.   ..8S. @ 8@X8@ X S X @SXX@8888SSXX@@XSSXSXS %  SX@8XSXSXSXSXSXXSXSXSXSXSXXSXXSXSXSXXSXSXSXS + . . . SX8XXSXXXSXSXSXSXXSXSXXSXSXSXSXSXSXSXXSXSXSXSXS8@S :;8888888888888@@8Xt8%%%%:8; .8;X:8XSXXSXSXSXSXSXSXSXSXSXS%. @; :t;t;t;;X888t%X88 SSXXSt8%;t;ttttttttt@:: 8%tttt;tt X.t:8XSXXXSXXSXS@:   ::.:;tS:@888 X. ;t8;@%.%%S%SXXSXXXXSXXSXXSXSXSXS% ;8 8S8@XSXXSXSXSXSXSXSXXSXSXSXXSXSXSXXSXSXXSXSX + . . .:SXSXX@8SXSXSXXSXSXSXSXSXXSXXSXSXXSXSXSXSXSXSXX@X88;8888888888888888@8X88tS%t;@S. S%;8XSXSXSXSXSXXSXXSXSXSXS%..%8;X;t;t;tt;888@ttt%SX%SX88 SSSS 8@ttttttttXt..8Stttttt@t@8 S8XSXS8.8...;8XSS 88@@ S8%;;8%%%t::8S.%St.%XSXSXSXSXSXSXXXSXSXXX%SXX8 %X8@XSXSXXSXXSXSXXSXSXXSXSXSXSXXSXSXSXSXSXS + . ..: %SXX @XXSXSXSXSXSXXSXSXSXSXSXSXSXSXSXSXXSXSXSXX@X:8888888888888888@888888tS%%t:8: St8SXSXSXS88SSXSXSXSXSXS;:;SS St;;t%S88 8 888888XStS@XXStS8 88@88%ttttt%8 t%tttt%8:XSt%Xt % 88S@: 88SSX8 8X  8tt;t;;%t.X%S88 @;:X%:SXSXSXSXSXS8@SXXSSXSSS t 8X88SXSXSXXSXSXXSXSXSXSXSXSXSXSXSXSXXSXSXXS + . . 8 %SXX XSXSXSXSXXSXSXSXXSXSXSXXSXSXXSXSXSXSXXSXSX t@88888@88888888888888@88@tX%%t:8: ;XXSXSXXSX88SXSXSXSXXSXt;:SXS 8St8 88S88S;SSS@8X@@:8 8%t%%SX%:8SX88X%%%tSX;. 8Xt%t@8.SXS8SX;X.%.%:.;SXSXXS%@ ;..tt;;t;t;t;:S tX8;8XXS.@ %XSXXSXXSX8@SXSXXSSX@ ;@SS@8XSXSXSXSXSXSXSXSXSXSXSXSXXSXSXXSXSXXSXX + . .X88XX8.;%SXSXSXSXSXSXSXXSXSXXSXSXXSXSXSXXSXSXSXSXSXS;88888888888888888888888X@88t%%St8:.8 tXSXSXSS tSXXSXXSXS% .SXSX:;.88@%; ...  . :S88S@8 8@%%t%t X88X%%%t%X: 8%%t888@S@;%XttX% tS 88@SXSSS8 :%8tt;t;t;;:tXSXX@8X8XS%..;SSXXSXSS8@XSXSXSS@X t8 SX@XSXXSXSXSXSXSXSXXSXXSXXSXSXSXSXSXSXSXSS + . . 8X8@8.S:%8XXXSXSXXSXXSXSXSXSXSXSXSXSXSXXSXSXXSXSXSX ;88888888@88888888888888@88@88SXS%:@t8.XXSXSXS @SXSXXSXSXS..%XS8S..:.:.  ...::;:;:..  ;X8888 8S%;8888S%%%%%8 . @%%8888 X%%%8 .: 8SX8 88888%.8.Stt;t; @ ;XSSSXXSXSX%..tSSXSXS@@SXSXSXS8S %X @SXSXSXSXSXXSXSXXSXSXSXXSXSXSXXSXSXSXSXSXX + . 8 @@ ;8t@ 8XSXSXXSXSXSXSXSXSXSXSXSXSXSXSXSXXSXSXXSX@@;88888@8888@8888888888888888@88tS%%SX8:8XXSXSSS %XSXSXSXSt:;SXS :.   .;8888@@XXSXXX@8@;:. ;S8@S@SS:S@X%%%%%S8 8XS S8 8%%S8 .8 %SXSt%%X8@.X;:;:;SS ttt;; 88SSXXXSXXSXSXS:t:SXXSX@@XSXSXSS8%.XS 8XSXSXSXSXSXSXXSXSXSXSXSXSXSXSXSXSXXSXSXSX + . :t@8 8%: 8.8XSXSXSXSXSXSXSXSXXSXXSXSXXSXXSXSXSXSXSXS@;@888888888888@88@88@8888888888@8%S%%t8S tXSXSSX SXSXSXSXS..%XSS@8  .S8XS@SSXXS@XXXXXSSSS; tt8X :@888888XS%SS%S8 @SS8:X8XSS8 .@X8:@XSXSXSS8::% XX @ :8XS%t X8SXSXSXSXSXSXSS.t;SSXSS@SXSXSXS8%.@%XXSXSXSXXSXXSXSXSXXSXSXSXSXXSXSXXSXSXSXXSXS + . ;SS;:X:S. X:8SXSXSXSXSXSXXSXXSXSXSXXSXSXSXSXSXSXXSXSX::888888888@88888888888888888888888tS%XtX XXSXXS8.@XSXSXXS%.:SXSXSX;..@SX@XX@X@8%t;tXSXXS8% XSS;. :%8 88SSSSSSX8. 888Xt8XSX; ;XS% %8SXSXSX@:S88888 8 % 88XSXSXSXSXXSXSXXSt::SX@ %XSXSXXXX.t8SSXSXXSXSXXSXSXSXXSXSXXSXSXSXXSXSXSXSXXSXSXX + S@Xt88. . X;8XXSXSXSXXSXSXXSXSXXSXSXSXXSXSXSXSXSXSXS88;88888@8888888@888@888@88888888@8XS.SSX%%XSXSXS8t8SXSXSXS%:;SXXSS8@..8SXXXX@X@;::::XSXX@: :S@@ t:. ;X%8@XXXt8XS8 88 :XXXS8 @SSS888XXSXS@ttX8888888XS@X8SXS88XSXSXSXSXSXXSXSS;:tS@ tXSXXSSXS t8SX tSXXSXSXSXSXXSXSXSXSXXSXXSXSXSXXSXSXSXXSS + .S.SX. . . .8t8XSXSXSXSXXSXSXSXSXSXSXSXSXSXXSXXSXSXXSS8XX88888888888@8888888888888888888X8S:SSSX8:@SXSX8% ;XSXSXS;:%XSXXS8;@.XXXX@XXS8:....tS@XXt%;:% S;S@S::%::8%8@X88@X88 @XXXXX8 8@XX88SXSXSXS;8S8t88888XS%%S%%SXX8XSXSXXSXSXSXSXXXS .%8 tXSXSXXS%@X tX@SXSXSXSXSXXSXSXSXXSXSXXSXSXSXXSXSXSXSXSXX + . .S:SSXSXSXSXSXSXSXSXXSXSXSXXSXSXSXSXSXXSXXSS:@8888888@8888888@888@888@88888888X88%S%ttS%SXSS8S XXSXXSX;:%SXSSS8;tX.8XSXXXXX ..SXXXX8:8SSX:.888@8S S@8 88t88t88S 88@@@88 8888@88SSSS8.8;;%S@888XXS888S888@@8SXXSXSXSXSXSXSSXS%..S.XSXSXSXXS8%.XSXXSXSXSXSXSXSXSXSXSXSXSXSXSXXSXSXSXXSXSXSX + . . . . ;@ %XSXXSXSXSXSXSXSXSXXSXSXSXXSXSXSXSXSSXS ;8888@888888888888888888888888888888@8t%%@8;8SXX8%S8SSXSXSt:tXSXXS8%.t;@XXSXSXS  XXXXXX XXS8:S...:S88t% 88888tSS8S 8888888S 8888888%SS8t@:.. ....:%@@@8%tt@8XSXSXSXXSXSXSXXSXS::8t tSXSXSXXX.t8S@SXSXSXSXXSXSXXSXSXSXSXSXSXSXSXSXXSXSXXSXS + . . ;:@XSXSXSXSXXSXXSXSXSXSXSXXSXSXXSXXSXXSX% ;@888888888@888@888@88@888@888888888S8;S%t:@ %XS8tS %SXSXSt:tSXSXS8%%8.t8SXXXX@ :@XXXSSX@SX8:: .:;; 8 88SSXX@ 88S888X 8888S8;:X8SS;.  ...::.::.:. :S%%.8XSXSXSXSXXSXSXSXXt:S@ @SXSXSXSS@S 8SXXSXSXSXSXXSXSXXSXSXSXSXSXSXSXSXSXXSXSXX + . . . . 8.XSXSXSXXSXSXSXSXXSXSXXSXSXSXSXSXSXSXSXS.:888888@8888888888888888@888888888888S.S%X%%;XSX8t8S%SXSXX%;:SXSXX8t88;tt@XXXX@8tX8XXXXXX88XX@;;S . .tt 88X@X@8 888XX@@ 888X@8%SX;8tX@8888XXX :88@X8 tS:... .@;@XXSXXSXXSXSXSX% .S8; XSXSXXS@:; @XSXSXXSXSXSXSXSXSXSXXSXXSXXSXXSXSXSXSXSXS + . . . :8.XSXSXSXSXSXSXXSXSXXSXSXSXSXSXSXSXSXXSS:.@88@88888888@888@8888888888@888888X88@:SS8S@:8X@t8S%8SXSXS;S%XSXSX.;88 8tX8XXXSX8XXXXXSXSXXX8;  t88888@@888S 888888S 8888.8;%X88SSX8:.@XXS; S%@8XS;%t..  @8SXSXSXSXSXXSSS. SX8tt8SXSXSS8t;@SXSXSXSXXSXSXSXSXSXSXXSXXSXSXSXSXSXSXSXSX + . . . .%;8SXSXSXXSXSXSXSXSXSXSXSXSXSXXSXXSXSXXS::@8888888@88888888888@8888@888888888S88%S%S@X8 @X:S:8.@SXSXt;;SXSXS . 8 8tX88@@8S@XXXSXXXS@8;8; . . .St88888888S 8888% 8888 t@XXtSXX8:. .@X@..8S @:888XS%S8 .8@XXXSXSXSXXSXXS8:.SS8 .; tSXXSX t SXSXSXXSXSXXSXSXXSXXSXSXSXSXSXSXXSXXSXSXS + . . . :@.@SXSXSXSXXSXSXSXSXSXSXXSXXSXSXSXSXSXS :888888@8888888@88888888@88888@88888888tStXS8t8 @8S8t@;8XSXS:.%SXSS8tX 8 88;%8%8888888@8%%t:: . .t8;8 8%8888S ; : 88888XS8@8SS@t:. .8Xt@8:X8XX...:;@:;X SSSXSXSXSXSXSXS8  .SX@8@8.; SSSSSX;.@SXXSXSXSXSXSXSXXSXSXSXSXSXXSXSXSXSXSXXS + . . . 8;XSXSXSXXSXSXXSXSXXSXXSXSXSXSXSXSXSXSSX;@88@888888@8888888@8888888888888888888X:%S8:. 8.8tS;@X%@SSX%..SXSX@S8 888S S8888 :X8X%t8 Xt:8%::%8:8 88888888S 8 8 88X:X ttSXXX;.  :@@ :;@Xt@. :8t88%XXSXSXXSXSXSXSS @. SXS8SS@S;S %SSXXS:8SSXSXSXSXSXXSXSXSXSXSXSXSXSXSXXSXSXSXX + . . . . .:%.8SXSXSXSXXSXSXXSXSXSXSXSXSXXSXXSXSXS8tX888888888888888@888888888@888@8888X8S8%%%8XS :8 :8888XS tXS;S.SXSX:8.888888888X8 8 8888888 . 8 8S8%888888 88 8 8 88888.:X8XXXS. .8XSS ;8@% .S @t8SXSXSXXSXSXXSXSS8:X:.S@%8SXSX8 .: 8@X@::X@SXSXXSXXSXSXSXSXXSXXSXXSXSXSXSXXSXSX + . . . t8.XXSXSXSXSXSXSXSXXSXSXXSXXSXSXSXXSXS@8;888888@8888@88888888@88888888888888X88t%%Xt% %@@S@8X8S.8SX;@:SSS8@8 %88888888:S8888XSS 8S 8% 8 8 88888@88@ . 888888888S 888 8;888XXXX888SX@@SS8:8: ; 8t;8SSXSXSXSXSXSXSXS@.:%:tS8 SSXXX%%S8..:: S t; @XXSXSXSXSXXSXSXSXSXSXSXXSXSXSXSXS@ + . . . . 8;XSXSXSXSXSXSXSXSXSXXSXSXSXSXSXSXXSXX%:8888@8888888888888@8888@888@88888888;8t%S@SX @t8@.8@888% tX;8;SXX..S88888888888 888888888888X8888888 88S888. 8888888888% 88888:8SSXXSXXXXSXX@XX8@ tS;S%:XXXSXSXSXSXSXSXXS tS..SS8XXXSXSXSS8 %8@ :%S@S% tXSXSXSXSXSXSXXSXSXSXSXSXXSXSXSXS + . . . . .:;:8XXSXSXSXXSXXSXSXSXSXSXSXXSXSXSXSXX.:@88888888@888@88@8888888888888@8888X88t%%X%t 8;%888X88;8 8X:X%tS8@@;S888888888S888888 S888S888888888S888 888888888 88S 88888 @S8888888@XXX8X. %.XXX@X tSXSXXSXSXXSXXSS8;:S:;SX@SXXSXSXXX @SXSS888 @ %XSXSXXSXSXXSXSXSXXSXSXSXSXSXXSX8; + . . . ;@:8SXSXXSXSXSXSXXSXSXSXSXSXSXXSXSXSS8X;888888@88888888888888888@888888888X888;S8Xt .@t%;S88X8:%.  .XX X S tS 8888888888S@88888888S888S8 888 888S 8 88 888888888 8 8888 8 888 .;@8St8;X8@ .88@8XSXXSXSXXSXSXSS8t;@..SSXX@SXSXSXS8XXSXSXSSS%%%SXXSXSXXSXSXSXSXXSXSXXSXXSXXSXS8.8 + . . . . . . X %SXSXSXSXSXSXSXSXSXXSXSXSXSXSXXSXXXt.8888888888888888888@88@88888@88888888.%%XS; :.tS%S8888  8 8XXt8% ;; 8 88888888S8XS8 88888888S888S888X S 88@88888 8%88888X 8X8888888 8 8 8 8 888 :8 8;8SXSXSXXSXSXSXS@:%@ .%SXX 8XXSXSXX @SXSXSXSXXSXXSXXSXSXSXSXXSXSXSXSXSXSXSXSXSX t + . . . t;8SXSXSXXSXXSXSXSXSXXSXXSXSXXSXSXSX XS888@88888@88@888@8888888888888888888.tSS8. ;S%X888@8%;88 8%S8:.@% .X%%88S XXSS8S@888888S888S%%888S 8S888%88S%8 88888.:8S88888S8888888888 8S 8 8S88S..%SXSXSXSXSXSXS@ %  .tXXSXX8XXSXSX8SXSXXSXXSXSXSXSXSXSXSXSXSXSXSXSXXSXSXSXSXSX8 X. + . . . . . ..:8XXSXSXXSXSXXSXXSXSXSXSXXSXSXSXX%%;.@888888@8888888888888888@8888888888tS%SS@ 8;%%t88S8t88 888 8X.8S ; SXS8%8XX %88@888S888888t 8 8S8888888X88 8%8@@8 8 88S8888888888%88888888888@ tXSXSXSXSXSXS8.;8..tX8XX8 @SXSXS8 SSXSXSXSXSXXSXXSXSXSXXSXSXXSXSXSXSXXSXSXSX8: .  + . . . . . . ;S XSXSXSXSXSXSXSXSXSXSXXSXSXSXXSXXX8X;8888888888888@88888@888888@888X8;8t%%%8; .@t%XSS88S:.8888 888%S%@;S.8 .. .XX:8 % 88X:88%S ; 8 8888888%8888@SXS8888 8 8 8 8888888888%8 88888888888X88SXSXSXXSXSXS@:%8..%XX8XS@X8XSXSXS8SXSXSXSXSXSXXSXSXXSXSXXSXSXSXXSXSXSXSXXSXX @;  + . . . . 8.XSXSXSXSXXSXSXSXSXSXSXSXSXXSXSSXSX t@888@88888@888888@888888888888S888StXS8 t:%S%8@88t888X8%888%888 @@88S tS 88888888888 8888 88888 8S8 8 8X88 8%8S8S888 888 8888SSX@XSXSXSXSXXS8.;8 .%XSX8@S8 XXSXS8 %SXXSXSXSXXSXSXSXSXSXSXSXSXSXSXSXXSXSXSXSXS.8.  + . . . . . . .t:8SXSXSXSXSXXSXSXXSXXSXSXSXSXXSXSSS.;@888888@8888888888888@8888888 8.8:%%8; .8;%S888%%XS@8888888888S888 X88@XXX%8@S SX %S 8S888@8888888888888888888888 t88888% 888 888888888 888 88S@SXXSXSXSXSXS @ .%SXSXX88X8X8SXS@XXSXSXSXXSXSXSXSXSXSXXSXSXSXSXXSXXSXSXXSXSX8:S  + . . . . :8.@XSXXSXSXSXSXXSXXSXSXXSXSXSXSXXSXSt.X88888888888@88888@8888888X88:S tXS@ S:%SS888@;.SX@8 888 8S888888888S 888XS8;:S S88%8888@88888888888888 8888888888888X@8 8888 ;888 888S8S888888@8X8XSXSXSXSSX@@::tSXSXSXS@8X8 XSXS88SXSXSXSXSXSXSXSXXSXSXSXXSXXSXSXSXSXSXSXSX@:X. .  + . . . . . . 8 SSXSXSXXSXSXSXSXSXSXSXSXSXSXXSXSXX8S:@88@8888@888888@88888888@8.8::t%X@; :@t%S8XXS%t8SXX8 88 88888888 8 8@8888X @ 88888%8 88888 8 88888888888888888888 88X88888 8 8S S S88888S88888 88% tXXSXSXSSt:  ;SSXSXSXSXX8@8X8XS@@@SXXSXSXSXSXSXXSXSXSXSXSXSXSXSXSXSXSXSXSXX  t  + . . . . . X:@SXSXSXSXXSXSXSXSXSXSXSXXSXSXSXSXXS X;88888888888@888888888@.8ttS%t@X; :8t%SS8X@S.8XSSX8 888888888S88888888 8 88SX888888888888S88888888888888888888888888:8 888888888S %% 8S8S888 %XSSS%;: .t%SXSXSXSXSXSX888 @SX8@XSXSXSXSXSXXSXSXSXSXSXXSXXSXSXXSXXSXSXSXSX @ . .  + . . . . . . . .@:@XSXSXXSXSXXSXSXSXXSXXSXSXSXXSXSXSS 8:888@8888888888888888SS 8;%;@St 8;%SS8X8X tXXSXX888888888888 88%88888888%888888 888888888888888888888888888888888888888888888S88 8S S SX88XSt::.::.:88@XXSXSXXSXSXSXSX88S8X@8XXSXSXSXXSXSXSXSXXSXXSXSXSXSXXSXSXSXSXXSX8;.  + . . . . . .8 SSXSXSXSXSXSXSXXSXSXSXSXSXXSXSXXSS8X8t;t88888@888888888888X:8 %;@XS .@;tSS8@8S ;SXSSSX@8888888888888888S888888888888888888888888888888888888888888888888888888888 8888888 8 : :t8 %XSXSXSXXSXSXXSXSXS88 @X8@XSXSXSXSXSXXSXSXSXSXSXSXSXSXSXSXSXSXXSXSX Xt . .  + . . . . . ;;8SXSXSXSXSXSXSXSXXSXSXSXSXSXSXSXXX8X@8@:t8@888888888XS 8%St;;;88; :8;%S%8S8:X%XSXXXSXS  8888888888888888888888888888888888888888888888X888X888X88@88888888888888888888888888888 8X;;8X@@ ;.@@XXS@XSXSXSXSXSXXSXX@8S8X@XSXSXSXSXSXSXSXXSXSXSXSXXSXXSXSXSXSXSXSXXS @  + . . . . . . t% %SXSXSXXSXXSXSXSXSXXSXSXSXSXSXS8S@SXSX X.;@888888@X8S8 8;t;XXX. ;Xt%%%888tSSSXXSXSXXSX 88888888888888888888888888@8888X@88888888888888888X888@8888888SX@88888888888888 888%888888@88 ;S;@XXSXXS8SXSXSXSXSXSXXSXS8 8@SXSXSXXSXSXSXSXSXSXXSXXSXSXSXSXXSXXSXSXXS8;. . . . + . . . . . . ::8XSXXSXSXSXSXXSXSXSXSXXSXSXXSXXX8XXSXSS8 @.:t888@8:888:;;.@8;..t8:;;;;8X88.SXXSS88SSSX%8888888@888888888888888@88X888888888888888;8XXXSS%SS%SS%%SX@@@888888888@8@8888888888888888%S%%t 8@XS@XSS@8SXSXSXXSXSXSXSXS@SSXXSXSXSXSXXSXXSXSXXSXSXSXSXSXSXSXSXSXXSXSX S% .  + . . . . . . . t %XSXSXSXSXSXSXSXXSXSXSXSXXSXSX8@XXSXSXXXX@S;8t%S88@88@ @t::%8S...;t8@S;S8:@SXSS tSXXS8:t888S888X8888X@888888S88888888X;88 %S%%%%%ttttttt%ttttttt%t%SSSX@@888S8X88888888888888X:888 S8XXSX%8SX8XXSXSXSXSXXSXSXSXS8 %XSXXSXSXSXSXSXSXSXSXSXSXXSXSXSXSXSXSXSXS8.8 . .  + . . . . . ::@XSXSXXSXXSXSXSXSXXSXSXSXSXS8S@XSXSXSXSXSX@S@Xt@@888X S S ..:;tSX888XSX8;@XSXS :@XSSX 8X%@@%888888%S88888888@8@X@XS:XS@;8 St888@@S;;;;;t;tt;;ttt;ttt%t%%%SXXX8888X88@88888888888%@%%8@XSS SX8SXXSXSXSXSXSXXSXSXXX8XSXSXSXSXSXSXSXXSXSXXSXSXSXXSXSXXSXSXXS@.8: . . + . . . . . . . . S;8SXSXSXSXSXSXXSXXSXSXXSXSXS@X8SXSXSXSXSXSXSXSS%%88888X888X@SX@SX@8S8.t X8;8X8X@S8SSXS8 XXS%X8@@@8888@XXt8@XXXXSSS%%SX%%%%@888X8 88888S88X@%t;t;;tt;%tttS8tXX%X@88%88XX@888888888 Xt 8@SXS %SSXS8XXSXSXXSXXSXSXSXS8@XXSXSXSXSXXSXXSXSXXSXSXSXXSXSXXSXSXXSXS8:S . .  + . . . . . . S:XSXSXSXXSXSXSXSXSXSXSXSXXSX@8SSXSXXXSXXSXSXSSS%%.XSX8@X88X@@@@@88888.;:88t8.XS 88S8S8X 8 8X8t%%%SSSS%;@SS%%S%%%%%%:Stt%tSt88 88XS:tS 888 888S;tt;@88X88888XS%%SXXt8888888@88888tStS%XXXX%X8t8X8SSXSXXSXSXSXSXSXSXX@8XXSXSXXSXSXSXSXXSXSXSXXSXSXXSXSXXSXSXX 8; .  + . . . ;X8 . . .% SSXSXXSXSXXSXSXSXSXSXSXSXX8XXXSXX@@XXSXSXXSXSSS%8 8XX@8XXX@@@888X888 %@88; X8 :888@X ; 8 888 ;t%t%%%SS%%%%tt%t%tt%%%tttt%%t:%t;;ttttt%@@X888%;;%%8888888::S%S%%;XXX@@@8%88S888@ 8 S%%X8 8S@@8 t8 @SXSXSXSXSXSXXSXSX@SXXSXSXSXSXSXSXSXSXSXXSXSXSXSXSXSXSXSS@;. . . . . + . . . . t. t% t XSXXSSXSXSXSXXSXSXSXXSXSX8X@SXSXS8 8S88XSXSXXSS%tt.8S888@888S@XX8X@S8 @88;%8@%@888 X;8.;8 8888Xttt:St%tttttt:Stt:%ttt:%ttt;t;t;t;t;;t;;t;t%t;t%;tS8t @XttS%%t%SS%SSSS;@@88%88 S %%% XX8:88X@S88S@SXSXSXXSXSXSXSXSXX88XXSXSXSXXSXXSXSXSXSXSXSXSXSXSXSXSXXS8;8 .  + . . . . .%.St. . . @:@XSXSXSXSXSXSXSXXSXSXSXX8S@XSXSXS8 88 X8SXXSXSSSS%8@88@88S88@X8X8@88.S88888@888888S.@8X. 8X.8 88@t%tt;tttttt%ttt%tt;t%t;;t;t;t;;t;t;;t;t;t;t;t;t;t%%;;ttttttttt%%%%:XSSSXX8@8X 8 S%t@.8XS.8@@8 88:@XSXXSXSXXSXSXSXSSX88SXSXSXSXSXSXSXSXXSXSXXSXSXSXSXSXSXSS:%. . . ...  + . . . t;SS8. . . t;8XSXSXXSXXSXXSXSXSXXSXS8%@XSXSXSS8 88X8@S8SXSXSSX..888888 .@8S8@8X8@888888888888888X888.8 8 8888X%t;t;t;;;t;t;;t;t;t;;t;t;;t;;t;t;;t;t;t;t;;t;t;t;t;t;;;;tttttttt%%X%SSS%@ t S% 8 %;88 t@. S8@S S8XSXSXSXXSXSXXSXSXXS@X8SXSXXSXXSXSXXSXSXSXSXSXXSXXSXXSXSX ; @8@. + . . . . S.  S; . :8.@XSXXSXSXSXSXSXSXXSXSX8X8XSXSXSXS8 8S8 X@8 X X:tX@8888St88S@@8X8S888@88X8@88@@88X8888@8t8888888888@t%;;t;t;%;t;t;;t;t;;t;t;;t;t;;t;t;t;;t;t;t;;t;t;t;tt;t;;t;tttt;%%%tSS@88.X%%% 8 :88S;SSS8@88t88;8SXSXSXSXXSXSXXSXSX8X@XSXSXSXSXXSXSXSXXSXSXSXSXSXSXSXS%@ t . . .:;.@ + . . @.@t Xt . . ..;8SXSXSXSXSXSXSXSXSXSXX8X@XSXSXXSXX@ X8S%8XS@88XX  .%:X8XX.8tX8@@8@8XS@@8X@@88@8@8@8@88@S8888S 888 888S@%;ttt;t;;t;t;t;t;;t;t;t;t;t;t;;t;t;;t;t;;t;;t;;t;;t;tt;tttStt88X8@ @ . SS% 8.X8888%@888@8888.XSXSXSXSXSXSXSXSXSX8X@XSXSXSXSXSXXSXSXSXXSXSXSXSXSXXXS8:8. .:S + . . . ..8.XS8t.. . @: ;XSXSXSXSXXSXXSXXSXSX8X@SXXSXSXSXSS@ XXSXSXSXXSStttX@SXSXS88 S88X8@@X @8S8@8@8@@@888@@@8SttSX88888888888XStt;t;t;;%;t;;%t;t;t;;t;t;t;t;t;;t;t;;%t;t;;t;;t;t;;t;;tt:@888; SS %Xt %%% %S8X888888@@8888XXSXSXXSXSXSXSXSXSXXX8@XXSXSXSXSXSXSXSXXSXSXXSXXSXXSSXS8;.. . . S: + . . S.XSXX@.%8: t; S%XSXSXSXSXSXSXSXSXSXX8@@SXSXSXSXXSXS8 XX@SXSXSXXSXSXSXSXXXSX@.8X@8X8 XS8X8X8@88@8X8X8X8X8%8%%S888 8S8S8S8 888;;;tt%;t;t%;;t;t;t;t;;t;;t;;t;t;;t%;;t;t;t;t;t;t;;;;X@8 :8X %t%S %8S. X t8X8X88888@@88X@X8XXSXSXSXXSXSXSXSSSX88XXSXXSXXSXSXSXSXSXSXSXSXXSXXSXSX Xt . .:8 + . . . . .@.@SXSX@@ S88X S8XXSXXSXSXXSXSXSXSXSX8@8SXSXSXSXXSXSXSSX @@8@XXSSXSXXX888SXSX @@8XXX : @8@8S8X8X8S8X8@8@88t8tttSX8888S888 88888Xt;;t;;t;;t;t;;t;t;t;;t;t;t;t;tt;;t;t;;t;t;t;;;X888S 88:88@%:%% X8@@tXS.;8X@8X8@@8@@8X@XXX8SXSXSXSXSXXSXSXXXSX8@@SXSXSXSXXSXXSXSXXSXSXSXSSXSXSS@.@; . @  + . % SSXXSSS%X88@SSSXSXSXSXXSXSXXSXSXXS8%8SXSXSXSXSXSXSXSX%S S X @X8888@S X8XSXS8S88@8%@tX;8@@8S8@8X8X888@X8S8 Xt;t%tX88 888%888 88X 8;;t;t;t;t;t;;t;;t;t;t;t;t;tt%;t;t;t;t;;;:t8888%8S8 8;8SX8X: 8888888SS88X8@8X8X8@888 %XS8SSXXSXSXSXSXXSSXSXS8XXSXSXSXSXSXSXSXSXSXXSXSXXSXSXXS8t;. . .;8; + . . . . ;;8SXSXXXSXSXSXXSXSXSXSXSXSXSXSXSX8X8XSXSXSXXSXSXSXSXXX%X@ XS X X S @88SXSX@:888S.tSS@X@8S8888X8S8@@88@@8X ;t;tt%%@8@S888S8 88@888%8X;;t;t;;t;t;t;t%;t;;t;t%tt;t;t;;t;;SX 8X@ 8X@XS%8:8;.;8@8t@8@8S8S8888X8S8@8@8X888X%@SX@8XSXSXXSXSXSXXSXSXXX8@XXXXXSXSXSXSXXSXXSXSXXSXSXXSSX@8.88;:;@:S 8 + . . . ;@ 8XXSSXSXSXSXSXSXSXSXSXSXSXSXX8X8XSXSXSXXSXSXXSXSXSSXSX%S8@@ X88@XXSXSX8t888 8%SXX;8@8 X@@S .88888888X@t;t;t;ttSX88888X888 88 88 88S;;t;t%;t;t%;t;t;tStt;t;t;;t88XXX%88.8888X8X8;8;8t X888@8@@8@8888@8S8X8X888Xt@8S8SXX8X8SXSXSXXSXSXSXSXSXS8X88@SXSXSXXSXSXSXSXSXSXSXSXXXSXSX8 X 8@SX + . . . @;S.;8XXSXXSXSXSXSXSXSXSXSXXSXXX@S@XXSXXSXSXSXSXSXSXSXXSXSXSXSX 8SSXXSXSXSX.8X.8XXXSS8S8%8t @88S8S@88@8XXX8.;;;t;t;t;t@88 8888 8888888888t;t%;t;t;;t;;tttt;;t;t:t8X .;88.:88t88888S8%S8;8t888@8X8X88@888@8X8X88888@8:X8XS@XXX8S@SXXSXSXSXXSXSXSXX8S8XXSXXSXSXSXSXSXSXSXSXSXSSXSXXXSt%St%SXXS + . . . 8.; @ XXSXSXSXSXSXSXSXSXXSXSXX8X8XSXS@8XSXSXSXXSXSXXSXSXSXSXXX@8XXXSXSXXS8  X8XXXSXXS S XXX;8@ S @8X8S8S t8S;t;;t;t;t;tS888888888 888 888SS8X%;;t;t;t;t;t;;t;;X88% 8S@St;8;;88t88888S8%SXX% @@8S8S8X8X888@8S@888X@@@.%.@ SX8@XX8@@8@XSXSXSX@@8XXSXX8S 8XSXSXSXXSXSXSXXSXXSXSXXSXSSXSXSXSXXSXS + . . . t. S@XSXSXSXXSXXSXSXSXSXSXX8@8XSXSX88XSXSXSXSXSXXSXSXSXXSXSXS8@SXSXSXSXXXSSXXXSXSXSS88SSXX8@8S@X8@8S8X; ;.X;;t;t;;t;t;t@888S8S8 8%888888 88@888;;;t;t;;;;;88@:88888SXS8:8t8:88S88888S8XX@8 S8@8@@8@@8X8XX@8@8888.%8%8X8@XXXXX8SSX88888888@ X@SXSXXXX8 S@SXSXSXSXXSXSXSXSXSXSXSXXSXSXSXSXSXSX + . . . . X8t SSXSXSXSXSXSXSXXSXX8S8XSXSXS88XXSXXSXSXSXSXSXXSXSXSXX 8SXSXSXXSXSXSXSXSXSXSXXXXXSXSSSXX@;8@8888S S;@tt;t;;t;;t;t;ttS88%8S8888 8 888 88 8 88@;:.::t88  X@@8XSttXS%%t8;8t88%8S88SX8S@XX @8@88888@8@888SS8888%X%@8SXXSXX@XX@8XSSSSXSX8S88@XSXSSXSS8. SSXSXSXSXSXSXXSXSXXSXXSXSXSXSXSXSXS@ + . . . .;8S  88XSXSXSXXSXSXX8@@8XXSXS@88XXSXSXSXXSXSXSXSXSXSXS@ @@SXXSXSXSXSXSXSXSXSXSXSXSXXSXXXSX X8@S X8 S :@t;t;t;t;t;;t;;ttS@88888%8888S88 8S88%8888 8X8XS;8 :Xt;X@X88;SX :8%888X888X@8X8@@8 @88888@tS8XX@8X.;8888X8;SXSXSXSX88@888@8888@8@X@88XSXXSXXX8 8XXSXXSXXSXSXSXXSXSXSXSXSXSXSXSXSX@ + . . . @:8S SX88@XXX88@8XSSXSX@88XXSXSXSXXSXSXXSXSXSXSXS8: SXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXS8S8X % X SSS  S;;t;t;t;t;;t;;;tt@888 8S8 8888888 88 8 88888 8 88 ;:8@X@888@@8@8@.8S ;S888X@X8X8X8@8888S  8@@@8; @@88%888XSXSXSXX8@XXSSXSXSSSXSX@88XSXSXSXS%8. @@SXSXSXSXSXSXSXXSXSXSXSXSXSXSXS@ + . . . . . .S:@ ::: SX8XSSXXSX8S8SSXSXSXXSXSXXSXSXXSXSXS8%@8SXSXSXXSXSXXSXXSXSXSXXSXSXSXSXSXS8: StX%.S X ::8;t;t;;t;;t;t;t;t;%S@88888888.8 8 8 8 888%8 8888 8XS:888888@X8S@88S%ttS@;@t:S@@8@8X 88@8:SXX %8@8S 88;88SXXSXSXSXSXX88SXSXXSXXSXXSXX8@@SXSXSXXX8 :; %SXSXXSXSXSXSXSXXSXXSXXSXSXX@: + . . . . . ;8%X@8@SXSXSXX@88SXSXSXSXSXSXSXSXXSXSXXS8t@ SSXSXXSXSXXSXSXSXSXXSXSXSXXSXXSXSXSX%X8:. @S 8888S;t;t;;t;t;t;t;;t;t;%8888 8 888 88888%8 88888 888SX:888888888888@XX@88X%X%@88%.X8;8S8S8X.%@X .X8S 8@8.S:XXXSXXSXXSXX@8XXSXSXSXSXSXXX888XSXSXSX%XX 8 8@XSXSXSXSXSXSXSXSXSXX8X @; + . . . . . . .;@%;@88XXSXSXX@%.%8XXXSXSXSXSXSXSXSXSXSXXSS8S8;XSX8X@SXSX@@ %XSXSXSXSXSXXSXSXSXSXSXXS@8 @S @ :%8 ;;;t;t;t;t;;t;t;t;;tt%88888888%888 888 8888X 8888@8:888888888888888888@@@@888@8XSS;X8S%8 %S8X S.X. SSS8@@SXSXSXSXSXSXX8XXSXSXSXSXSXSXX888SXSXSXSSS8t;:8 XX8888@@@@888X S 8XtX.  +tS: . . . .;8 8@8@XXXSXXSX8@X888SXSXSXSXXSXSXSXSXSXSXSXS8%8XXS@ XS8SSX@t8t8XSXXSXSXSXSXSXSXSXXSXSXSS8S @X 8X%88%t;t;;t;t;t;t;t;;t;;t;t%S8@X8 8888 888%88S888 8%8S8t888888888888888888888888888888@888  S%88S X XS8XSXSXXSXSXSXSXSXX@ XSXSXSXSXSXSXSXS@S8SXSXSXXXX@8;. X.@ ::;t;%;:SX:8;  +@X; %@8X%t;;;;ttS88S:;S888@XXSXSXSX@@:8S;8@XSXSXSXSXSXSXXSXXSXSXSXS@ 88t@8.@8 %@S:88X %XSXSXSXXSXXSXSX88SSXSXSX8 @S @ St;88%;t;t;t;;t;t;;t;t;t;t;;t;ttS88888S888%8888 8X8888 8;8888888888888888888888888888888888 XS X@@8S 8 X@XSXXSXSXX88SXSXSX%8X@XXSXSXSXSXSXSXXX8X8XXSXSSXS@8SS; ;S@888@S;: . . .  +X:XXXX@@@8@@@888888@XXSXXXXSXSX@@t%8::%8@XSXSXSXSXSXSXXSXSXSXXSXXSX @8X8XS8@S8 %88@@%XXXXSXSX8@XSXSXX@.8X8XXSX@XS @X :%tt8X;t;;t;;t;t;;tt%;t;t;;t;t;t;;%SX@8888888888888888888S:888888888888888888888888888888888% SS @@@XX 8 @@XSXSXSXS :@XXSXSXS8@;XXXSXXSXSXSXSXSX@@S8@SXXSXSXX88.8. . . .  + .@.88XXSXSXXSXXXSXSXSXSSSX@88@;S. tt8XSXSXXSXSXSXSXSXSXXSXSXSXSX8X88S;8888.;88888SX8.8XSXX %XXXXSXS tS %XSXS @S Xtt;;;X%;;t;t;t;t;t;ttt;;t;t;t;;t;t;;t;t%%%SS@88@;8%88@%t88X8:888888888888888888888888888888888; @S @S8 8 8 @SXSXSXSX:8 tSXSXSXX8t:@SXSXXSXXSXSXSXSX8S@8@SXSXSXSS@8;X . . . .  + .%8%.%X88@8@X@@@@8888X% t8S: :X@8XSXSXSXSXSXXSXXSXSXSXSXSXSX@;8@88888@XX8@8X8XX;8.XSX8.%8X8 SXSX%8 ;8SSX@SS @X%@888;%t;t;t;t;t;;t;t;t;t;t%;t;t;;t;t;t;;;t;tttStt%t%%;t;;888 tt88S@888888888888888888888888888X: @S8X8: @ 88SXSXX8X8%8:8SXS@ @X8@8%tXXSXSXSXSXSXSXXX88@%88XXSXXSXS@@:@t . . .  + . . :tS888@@8888X%:. . ..@X8XXSXSXXSXSXXSXSXSXSXSXSXSXXSX 8@8X@@8X8@8S8S8S888X8S8.@8 @ S S.@8Xt8 XS8  S 8 %%@@XSS8S;;t;;t;;t;t;t;;t;t%;t;t;t;;t;t;t;t;t;;tt%tttttt;ttS.;;;t;tt;S888888888888888888888888888X. XXX@XX;S 88XXS8 @8888 tXS8X8.@8.X%XtSXSXSXXSXSXSSXSS88:X:88@SXSXXXX@@tt@;. . .  + . . . : 8XXSXSXXSXSXSXSXSXSXSXXSXXSXSXS8S8@8X8X8S8X888X8S8X8tX8%88XX;8S8 @8@888XS8t: SX S;8888S88@;;t;;t;t;;t;t;t;t;t;;t;;t;t;;t;t;t;t;;tttttt;t;;:8 %;XS;t88:S888888888888888888888888888%  X@ X88.SX 8XS@;SS888:XSX @88 S88@t@;XSXXSXSXXSXXSXXXX8%t;;8@@XSSXSSXSX8X;@:. .  + . . . . . . . .8S8@SXXSXSXSXSXSXSXSXXSXSXSXSXSXSX 8@@@8X8@8@8X8X8XX@8X%;@8@8XS88;.@88@88@8 %@;. @:S8:%X888@88888;t;t;tt%;t;;t;;t;t;tt%;t;t;;t;;t;t;;;tt;t;;t;%8S%S;8:8:S8;888888888888888888888888888X;; @.888X 8 ;8X@t: @88@8XS @8@S@8 @8S8 SSXSXXSXSXSXSXSXX8@X:;8:%88@XXSXXSXXX%.:X8@XSttt + . . . . . .8X8@XSXSXSXSXSXSXSXSXXSXSXXSXSXSXXS8S888X8888@8S@@8X8X8X888X8888888X@888@8@;%8XS% %%888tt88888888888 8%;ttt;;t;t;t;t;;t%;t;t;t;;t;;t;t;t;;t;t;t;%8 8%;%@.%;t8:@8888888888888888888888@XS8SX::@8888X 8.X@SX;8@88;8.%8888XS8@8888X:SSXSXSXSXSXSXSXXX8X8. :@X.tX888@XXXXSXXX@X8@S + . . . . . :;@@XSXSXSXXSXSXSXSXSXSXSXXSXSXXSXSXS @8@8@88X@888S8X8@8X8S8X8X8X8X8X8X8X8X@888S@X SX888@8:t@8888@88@88%88S;;t;t;;t;t;t;t;t;;t;;t;t;t;t;t;t;t;t;t;;%88%;88XS;;S;.8888888888888888888888%;..;888888888SS8S88t88@88888888@@88 8t888888.SSXSXSXSXSXSXSSXX@@:: :S@:tX888888@S:%@; + . . . . . .8t8@SXSXSXXSXSXSXSXXSXXSXSXSXSXSXSXXXX 88@X8X8:888tS888@@8X8S@@8S8X8@8X8X8@@88X@@X  S8@8888S:X8888888888S@XX 8X;;t;t;;t%;t;;t;;tt%;t;t;;t;;t;;t;t;t;tStt;@@88;tt%8t8888888888888888888;t@8888888888X8@888@t88888888888888@@@S:t8888888%;SXSXXSXSXSXXSXSXX8%8 . ..::;t%t;;..  + . . . . .X;8@XXSXSXXSXSXSXXSXSXSXSXSXSXSXSXSXXX.%.88@8X@  @Xt@8888S88@8@XS8@X@88@8SX@888@8X8XX@8@888888t:8888888888@8@88S8@8S;;tt%;t;t;t;tttt;t;;t%;t;t;t;;t;;t;t;;;St@@;;;;;8;@888888888888888@:S@88@@@@888@8@@8X888888888@@88@8888X88@8S888888888;%SXSXSXSXSXSXSXXXX8;S . . .  + . . . . . @88XXSXSXSXSXSXSXSXSXSXXSXSXSXSXXSXX8@%8;X8@@8@S8:888X88@X:8X8SXS%88@t8@8SX X8@@8S@@888888888888;:888888888888X@88S888%;t;t;;t;;t;t;t;;tt%;t;t;t;t;;t;t;;tt;S.@@;t;t;8;8888888888888888;;888888@8888X888X8X8X8@8@8X8@8@8X8X88@888 8888888888XtSXSXXSXSXSXSXSXXX888 . . .  + . . . . . % 8@XSXSXSXSXSXSXSXSXSXXSXSXXSXXSXSXX% X88.888X88X8:8 SX@8@ :8@8S%8@8:8t8X8 X:88@@8XXSXX@8888888888:;8888888888888@X@@8X88X;;t;;t;t;;t;t;t;t;;t;;t;;t;t;t;t;;;S;88;;t;;@t:888888888888888:@888@88@88X8X88X8S8X8@8@8@888888@@8@8@888;@888888888@8:SXSXSXSXSXSXSXSXX@8;;. . . . . . + . . . t:88XXSXSXSXSXSXSXSXSXSXSXSXSXSXSXXX%.tX8888;@8@8@8 %  %SS@X XS8@@XXX@ S@@Xt8%8X8X8X8@888Xt%%t;;;;;t%t;;X@88888888888888888@% S;t;t;t%t;;t;;t;t;;t;;t;t;t;;t;t;;X%88tt;t;t8@:8888888888888:;88888@8@88888@@8S8@8@8@@88X8X8X8X8S8S8@8@t@8888888888888.XSXSXSXSXSXSXSXXX88X. . .  + . . . SX8XSXSXSXSXSXSXSXSXSXSXXSXSXXSXSXX8 SX888888tX8X@88X%%%XS@X888@888@S%t8% SS8SX @@@8X888888XX@@@8888888X....:;8888888888888X@8@88;t;t%;;t;t;t;t;t;t;t%t;t;t;t;t;t8@88t;t;tt; ;X888888888888:@88@888@88@8.X8X8X88S8X8@@X8S8S8S8X8@8@8@8 888888X888888@8:SSXSXXSXXSXSXSXXXX@.: . . . .  + . . . :X@8SXSXSXSXSXXSXSXSXXSXXSXSXXSXSXX8%%@88888888:X8@8X:XXSXSS8@:@8X88.SX S% XSSX@:88S@8X888888888888888@888:;88X;;t8888888888888@8@8@t;;t;t;;t;t;;t;tt%;;t;;t;;t;t;8@;X;t;t;;t% t88888888888X.88888@88@@ 8 ;8X8X8S8@8S8@8X8X8X8X8S8@@88S @88888888888@X@@S;SXSXSXSXSXSXSSXSX8tX .  + . . . .8X8XXXSXSXSXSXSXSXXSXSXXSXSXSXSXS@8S;88X%@888888.@8@@X@XSXSXSX.XS8S8X8X8@@XS@ tX@ X@X@@@888888888888888888888t;@8@88t;t888888888888888@t;t;;t;tt%;t;t;;t;t;t;t%t;;;t 88t;t;;t;t:S;:8888888888:;@888888S.88 X8S88S88X8X@X8@XX8@8@888@@t.;@88888888888X%X@X@S%XSXSXSXSXSXXSXXX@8.t . . . .  + . .S@@XXSXSXXSXSXSXSXSXSXXSXSXSXXSXX88.@8888@8888888%t88X %SXXXSXSXXS8@8 %@ X tSXSS8 .@@@8888888888888888888888888t:X88@@8t;t8888888888@X88X;;t;t;ttt;t;;t;t;;t;t%;;tt;t8X ;;;t;t;;t;;X%@88888888:X888888%:8@;.X X88X  8@S888@8X .88@S:S888 8tX888888888888@@@8@@8%XXXSXSXSXSXSXSXXX8St  + . . .t 8XXSXSXSXSXSXXSXXSXSXSXSXSXXSXX8X.S88888888888888@ X@S8SXSSXXSXXXX@S@8S8 @@XXSXS8 %8@88@888888888888888888888888S.t8888@8;;@8888888888X88%t;t;t;t;t;t;t;;t;t;t;t;;t;8888;t;t;;t;;;X S888888888.X8888SS: .XS:88t.8Xt @@%88S@8t% @@8 @S88S8t@888888888888888888888.XXXSXXSXSXSXXSXXX8X8. . . .  + . :%88SXSXSXSXSXSXSXXSXSXXSXSXSXSX@@;t8888888888888888:S8. .XXSXXSXSXSXSX  SXXS @@SXSX@.88@8@888888888888888888888888888t;X8888@8;;888888888@888X;;t;t;;t;;t%t;t;;t;;t;t;; 88;;t;;t;t88 88 t8888888X.8@@@@@88@8@.8@X@XSXS 8.8S8S@%@S88%@%X:88XX@@:888888888888888888888XtXXSXSXXSXSXSXSXX@8 t .  + . . .: @XXSXSXSXXSXSXXSXSXSXSXSXXSXSX8%S8888888888888888S S:8.@ SXSXSXSXSXSXS@8X@ @ @8SXSXSt88@888888888888888888888888888888S.;888888t:X888888888S8:;t;;t;t;tt%;;t;t;t;t;t;;X8@S;t;t;;%%%8%%;8@@888888;;888888888@.8XXSXSXS% XXS8XS8XS@@@SXS S X.@. @888888888888888888X888.XXSXSXSXSXSXSXSSX8St. . + S;8@SXSXSXXSXSXXSXSXSXXSXSXSXSXX;t8888888888888888: 8S@88S88@SXSXSXSXSXSXSXS@X 8 8XSXS S8@88888888888888888888888888888888@;;@8888@X.t888888888t88;t;;t;;t;;t;t;;t%;t;;t;88 t;;t;t8%88t;ttt@:@88888tt888888888;X@SXSXXSXSXX@XS8 XXSXSSXSXSX8X tS88:88888888888888888888888t;%XSXXSXSXSXSXSXS8@8 .  + . .:%88XXSXSXXSXSXSXSXSXSXSXSXXSX%% @888888888888888%8XS@888888.XSXSXSXXSXXSXSXSS8 8 8 SSX%8X888888888888888888888888888888888888@::@88888;;888888888t ;;t;t;t;t;t;;tt%;t;t;;8tX8tt;;8S8@Xt;t;t;% t88888;S88888888% tXSXXSXSXSX8XXSS%XSXSXXSXSXXX %@@%;.8888888888888888888888888;;SSXSXXSXSXSXSXX@8.: .  + .:@@SXSXSXSXSXSXXSXSXSXSXSXSXS. @@@@88888888@8888%8:@88888888@@SXSXXSXSXSXSXSXS@X 8 @@SSXX.88888888888888888888888888888888888888t:;88888tt88888888S8X;;t;t;;t;;t;t;;t;t;t%8S%tt;;8S@St%t;t;;t:88t@888:t@8888888@%XSXSXSXSXXX8XSXSXSXSXSXXSXSSXX88S%8t.8888888888888888888888X@@t%XSXSXSXXSXSXXSXX@.:  + .t.8XSXSXSXSXSXSXSXSXXSXXSXXSS; %8SXX;;@88888888@SSt88888888888@;8SXSXSXXSXSXXSXS@XX 8 8SXS8.@888888888888888888888888888888888888@8t;S88@@Xt8888888@;X8t;t;t;t;t;t;t;t;;t;8X:X;;t;88ttt%t;t;t;tt8;@888:@8888888t8XSXX8@XSXSX8@SXSXXXSXXSXSXSX@%8888@@: @8888888888888888888@8@@@XS%XXSXXSXSXXSXSXSX8.t  + .888SXSXSXXSXSXSXSXSXSXSXSXSSt t8@@@@@XX8888888t 8t8@8888888888@XX:@S8@XSXSXXSXXSXSX 8 8:X;@@@S8 .SXSX8888888888888888888888888888888@@8S:;8888;8888888X:8tt;;t;;t;t%;t;;t;;% :8;t;;tS%ttttt;;t;t;tS::888.S8888888 t888:;8SXS8.;8XS@St %SXSXX8  X88888X%8%.@88888888888888@88@8@@@XXSX.@XSXSXSXSXSXSXSX888. + 88@XSXSXXSXSXXSXXSXXSXSXSXSX. X88888@88X@888888St8@88@XX@8@@XXSXSSX %XXSXSXSXSXSXSX8S 8 S@@;;SS%%S@8X888888888888888888888888888888888888t::8@8;8888888:@@;t;t;ttStt;;t;t;8t8@;;t;t;t%%ttt;t;t;;;;8@.;88.S888888X88.@%@ SXS8t8.XS@.8X8SXS@S%8XX88888888S; %888888888888888@88@8@@XXXS8X8SXSXXSXSXSXSXSX888 +@88XSXSXSXSXSXSXSXXSXSXXSXXt.;88888888@X;tX88XXt8@X@8@888@XXS8@SXS8XS %SXSXSXSXSXSXS@XX 8 t8888@%t;;S88888888888888888888888888888888888888@8t;t8@;888888;t.;;t;ttt;t;t;t;;888;;t;t;t;;t;t;;;;%X888%8.;;@8.S888888@ tX@88%SXSS88 %X%88 SS@S%888888888888@%@8t8888888@8@@@@8@8@8@@@@@XXX@S@8XXSXSXSXXSXSXSX88 +8@SXSXXSXSXSXSXSXSXSXSXSX%::@888888888X;. @88tXS@X@S8@8@8SS@88888@888S.XSXSXXSXSXXSXS8 8 @;@8888888888888888888888888888888888888888888888888X88;t;;888888.:%;;t;;t;t;t;;%S;:@;;t;;t;;tS88%8 88tXXS X:8 :@@:8888888X88888 8%888@;t888;@8 X@88888888888888S@: @8@8@@@@@@@@@@@8@@XSX@XXXSX@:@8@SXSXXSXSXXSXSX@ +XXSXXSXSXXSXSXXSXSXSXXSX%.;888888888888Xt%8.8S@XSXXXXXSXXX8XSSXX%tX@@S@ SSXSXSXXSXSXXS8 @ X%8888888888888888888888888888888888888888888888888888@8t;:X8888.88;t;t;t;;t;;tX;%8:;;;;;S8 88S8SX8%:tt888888S8.8@;88888888888@888@8888888@  S88888888888888888Xt@8%@8@8@@@@X@@@@@@@8@@@@@@@@@@8t@8@XSXSXSXSXSXSXS +XXSXSXSXSXSXXSXSXXSXSXS%.S8888888888888S @S@@XSSS@XSSXSXXSS@@SX%XSSSSXSS XSXSXSXSXSSXS@@ 8  S88888888888888888888888888888888888888888888888888888@8t:;t@8:tS;;;t;;t;;t8:8%;S %8StX888%:@8;;%X8888888888@:;8:;t%8888@8@@@8@@@8888888XS888@8888888888888888%8.8@8@@@@XX%SXX@@@@@@@@@@@@@@XX;@@8@XSXSXSXSXSXSX +XXSXSXSXSXXSXSXXSXSXSSt;8888888888888XSSX8888888888@@XSSXSXSSXSXX@X@XSSS%;@SXSXSXSXXSXSS8 @% @888888888888888888888888888888888888888888888888888888@8X8%t;t: 8888 X@8@8%:;t@8S 8 ;@888888888888888888. @;888%%@8%8@8XX888X%X8@8@8X88888888888888888888888X%X8t@@@@XXSt%XXX@@@@@@@X@@XX@@@8;@X88XSXSXXSXXSXS +XXXSXSXXSXSXSXSXSXSXStt8888888888888@..8888888888888@SSXSSSSXSXSXSS@S8@@8XXSSXSXXSXSXSXSS@ X @8888888888888888888888888888888888888888888888888888888S8X@8:;%@8@88@ttSt::..X88888888888888888888888S ;;@8XXXSX8%.S8@888S8;8@@@888S8X@St8888888888888888888SS.8@@@X@XXXXX@@X@@@@@@@@X@@X@X@SX@S88XSXSXSXSXSX +XSXSXXSXSXSXSXSXSXXStSXX@@8888888888S.8888888888888888XXXSSSSXXXXX8X@S@X88@X 8XSXSXSXXSXSX8 8 .@8888888888888888888888888888888888888888888888888888888X888:.: :8; 8S:%:S 888@888X888888888888888;% 8tS88XSX888XX8%8@ @:t88S@X@XS8X8@8:t@888888888888888888StX@@XXX@XXX@X@@X@X@@@@@X@X@@@X@ @XX8@XXSXXSXSXS +XXSXSXSXSXXSXSXSXSX 8S;:tX@@888888X88;@8888888888888888@SSXSXSX888888888888@8X.8SSXXSXSXSXSX@S t8888888888888888888888888888888888888888888888888888888888:.S t88;@X88888@8SS:8888888888888t;@8@X%.t%X@S%S;;S 8;X S %X@ XX@;:X88@8@888@:@888888888888888888SS:X@@@@@@@X@@X@XSSXX@X@@X@XXX@X8:8SX@8XXSXSXXSX +XXXSXSXSXSXSXXSXXX.@%: .%S@88888XS8@;888888888888888888XXSXX@88888888888888888@ @SSXSXXXSXSS8X% .888888888888888888888888888888888888888888888888888888888::@8888. @XS88888S;:S888888888t8 StS88 .88 . %@X8.XXSS%XSX@XSX:888@888:;8888888888888888888XX8X@@@@@@@@@@X@XXX@X@XX@X@X@XXS@@XXX88SXSXSXSX +XXSXSXXSXSXXSXSXX.8@@St:SX@X@@8@@XSX :888888888888888888XS@X@88888888888888888888S.@@SSSXSXXXXX8@S :@88888888888888888888888888888888888888888888888888888t;.X888;8%t8 @@X   8.%8888%.S88S X8888:X;:. . . ..  8XXSXXSXSXXSS8 X8888888@:@888888888888888888SX;8@@@@@@@@X@@XXX@@XX@XX@XXXXStS.@XSX8@XSXSXXS +XXSXXSXSXXSXSXXX;8@@@X@S@@@X@@@@8XX%@.888888888888888888XS@8888888888888888888888888@; 88XSSSXXXSX@8X t8888888888888888888888888888888888888888888888888@::.@ .S@ 8 @@ t@t8t;X:S88X X88888888@; 8S8@8S8@88@@X@S@@XXSXSXXSXX8;8888888888;:8888888888888888888XXX:X@@@X@X@@X@X@XX@XX@XXXXXXSSt8SXXSX88SXXSXS +XXSXSXSXSXSXSX@.@@@@@XX@@@@@@888@8@X%:888888888888888888XSS88888888888888888888888888888@; 8@X%SSSXX%%X88S :X@8888888888888888888888888888888888888888888S:;:@:8:8 @8@S 88tX.@@;8;8888888888888t%.;SSSSXSX%%t%SXS@8SXSXXSXSS8S888888888888.t@88888888888888888@X. X@@X@@@XXSS@XX@XXXXXXXXXXXX%X.8SXSX8@SXSXX +XXSXSXXSXSXSX@ 8@@X@XStXX@@@@@@@@@8XtXtX8888888888888888X@888888888888888888888888888888888@Stt.: SSXXXXS   t88888888888888888888888888888888888888888888S:@.. X ;S888@8X X XS@@X88888888888888;X.t%tXt@SX@8@8@8X@8SSXSX@XX@t:888888888888tt8888888888888888888S8X.X@X@XX@St%XXXXXXXXXXXXXXXSSSS@XXSXX8XXSXS +XXSXXSXSXXSX@.8X@@X@XStX@@@@@XX@@88@8%.88888888888888888@8888888888888888888888888888888888888@S8XS888888X@8888888888888888888888888888888888888888888888@.S:.X8;t S8 S@S:8888:@88888@%: tSX88888.S8%8tXStXt88S8t8X88XSX@@S :t8888888888888:t@88888888888888888SXtS@XX@X@XXXXXXXXXXXXXXXXXSXXXS@t@SXSXX8XXSX +XXXSXSXSXSX@;8@@@@@@@@SSXXXX@@@@8X888 :88888888888888888@888888888888888888888888888888888888888XX8;888888888888888888888888888888888888888888888888888888;;t.%Xt.@XX8@:8 88tt@ .S8S X8X %@8888S %888888888@S8888888:X8@XXS.%@888888888888@:@888888888888888888t@.8XXX@XXXXXXXXXXXXXXXSXSXSSXSX.8XSXSX@8XXS +XSXSXSXXSXXS@XX@X@@X@X%tSXSSXX@@88@8@%:88888888888888888@@888888888888888888888888888888888888888@S8t888888888888888888888888888888888888888888888888888888::..: X @:SS.Xt.;%X8S; :%888888888888:8.S@S8X@XX@@8XXXX@888tSSX88:888888888888888;;@88888888888888888X%X8;XXXXXXXXXXXXXXXSXSXXSXSXSXSS8XSXXSX8@SX +XXSXSXSXSX@XXX@X@X@@@XXSXXXXX@@@8@88@S8;@888888888888888XX8888888888888888888888888888888888888888@XS8t88888888888888888888888888888888888888888888888888888;:.:%8:ttSt;;::XS88888888888888888888.8 t8@@X@X88@@@X@@S8@X8;8@@888888888888888@8:S888888888888888888St;SSXXXXXXXXXXSXSXXSXSSXSSSSSS8XXXSXXSX8@S diff --git a/ascii/index.html b/ascii/index.html new file mode 100644 index 0000000..4607f5e --- /dev/null +++ b/ascii/index.html @@ -0,0 +1,74 @@ + + + + + + + + ASCII — Clove Twilight + + + + + + + + + + + + + + + +
+
+

ASCII Me

+

rendered straight from ascii.txt

+
+ +
+
+ + + + ascii.txt +
+
loading…
+
+
+ + + + + + \ No newline at end of file diff --git a/assets/theme/linkin.gif b/assets/theme/linkin.gif deleted file mode 100644 index 9680449..0000000 Binary files a/assets/theme/linkin.gif and /dev/null differ diff --git a/assets/theme/linkin.png b/assets/theme/linkin.png new file mode 100644 index 0000000..2a8949f Binary files /dev/null and b/assets/theme/linkin.png differ diff --git a/cool-people/index.html b/cool-people/index.html index 1002f22..f7f3e97 100644 --- a/cool-people/index.html +++ b/cool-people/index.html @@ -77,6 +77,7 @@ Music 88x31 Guestbook + ASCII diff --git a/css/404.css b/css/404.css new file mode 100644 index 0000000..02134aa --- /dev/null +++ b/css/404.css @@ -0,0 +1,73 @@ +/* ============================================================ + 404 PAGE — "you stumbled into the void" + Matches main.css design system (accent color, surfaces, fonts) + ============================================================ */ + +.four-zero-four { + position: relative; + z-index: 1; + width: 100%; + max-width: 460px; + text-align: center; + padding: 2rem 1.5rem; + border-radius: 20px; + background: var(--surface-0); + border: 1px solid var(--surface-1); + box-shadow: 0 10px 40px rgba(17, 17, 27, 0.35); +} + +.four-zero-four img { + display: block; + max-width: 200px; + width: 100%; + height: auto; + margin: 0 auto 1.25rem; + border-radius: 14px; +} + +.four-zero-four h1 { + margin: 0 0 0.75rem; + font-size: 1.8rem; + font-weight: 700; + color: rgb(var(--accent-rgb)); + transition: color 0.6s ease; +} + +.four-zero-four p { + margin: 0 0 1.75rem; + color: var(--subtext-0); + font-size: 0.95rem; + line-height: 1.5; +} + +.four-zero-four a { + display: inline-flex; + align-items: center; + gap: 0.4rem; + padding: 0.55rem 1.1rem; + border-radius: 999px; + background: var(--surface-1); + border: 1px solid var(--surface-2); + color: var(--text); + font-size: 0.9rem; + text-decoration: none; + transition: transform 0.15s ease, border-color 0.15s ease, + background 0.15s ease, box-shadow 0.15s ease; +} + +.four-zero-four a:hover { + transform: translateY(-2px); + background: var(--surface-2); + border-color: rgb(var(--accent-rgb)); + box-shadow: 0 6px 20px rgba(var(--accent-rgb), 0.22); +} + +@media (max-width: 560px) { + .four-zero-four { + padding: 1.5rem 1.25rem; + } + + .four-zero-four h1 { + font-size: 1.5rem; + } +} \ No newline at end of file diff --git a/css/ascii.css b/css/ascii.css new file mode 100644 index 0000000..26052ba --- /dev/null +++ b/css/ascii.css @@ -0,0 +1,130 @@ +/* ============================================================ + ascii.css — standalone page that renders /ascii.txt (ANSI art) + in full colour via ansi_up, styled to match main.css's terminal + aesthetic (Catppuccin surfaces, Comic Code, rounded card chrome). + ============================================================ */ + +/* This page scrolls — ascii art can be tall/wide, unlike the locked hub */ +html:has(.ascii-wrap), +body:has(.ascii-wrap) { + height: auto; + min-height: 100dvh; + overflow-y: auto; +} + +body:has(.ascii-wrap) { + align-items: flex-start; +} + +body:has(.ascii-wrap) .ascii-wrap { + max-width: 100%; +} + +.ascii-wrap { + position: relative; + z-index: 1; + width: 100%; + max-width: 1100px; + margin: 0 auto; + padding: 2.5rem 1.25rem 4.5rem; + display: flex; + flex-direction: column; + align-items: center; +} + +.ascii-wrap .hub-header { + margin-bottom: 1.5rem; +} + +/* ---- the "terminal card" wrapping the art ---- */ +.ascii-frame { + width: 100%; + max-width: 100%; + background: var(--mantle); + border: 1px solid var(--surface-1); + border-radius: 14px; + box-shadow: 0 18px 50px -20px rgba(0, 0, 0, 0.7); + overflow: hidden; +} + +.ascii-frame-bar { + display: flex; + align-items: center; + gap: 0.5rem; + padding: 0.55rem 0.85rem; + background: var(--surface-0); + border-bottom: 1px solid var(--surface-1); +} + +.ascii-dot { + width: 10px; + height: 10px; + border-radius: 50%; + flex-shrink: 0; + opacity: 0.85; +} + +.ascii-dot.red { + background: var(--red); +} + +.ascii-dot.yellow { + background: var(--yellow); +} + +.ascii-dot.green { + background: var(--green); +} + +.ascii-frame-title { + margin-left: 0.4rem; + font-size: 0.75rem; + color: var(--subtext-0); + font-family: 'Comic Code', ui-monospace, monospace; + letter-spacing: 0.02em; +} + +/* ---- the actual art ---- */ +.ascii-art { + margin: 0; + padding: 1rem; + font-family: ui-monospace, 'Cascadia Mono', 'JetBrains Mono', Menlo, Consolas, monospace; + /* tiny + tight so dense ascii fits without forcing horizontal scroll + on smaller screens; scrolls if it still doesn't fit */ + font-size: clamp(2.6px, 0.85vw, 7px); + line-height: 1.05; + white-space: pre; + overflow-x: auto; + overflow-y: hidden; + color: var(--text); + background: var(--crust); + text-shadow: 0 0 1px rgba(0, 0, 0, 0.4); + /* default colour before ansi_up's inline styles kick in / if it fails */ +} + +.ascii-art::-webkit-scrollbar { + height: 10px; +} + +.ascii-art::-webkit-scrollbar-thumb { + background: var(--surface-1); + border-radius: 999px; +} + +.ascii-art.ascii-error { + font-size: 0.95rem; + white-space: normal; + color: var(--red); + text-align: center; + padding: 2.5rem 1rem; +} + +@media (max-width: 640px) { + .ascii-wrap { + padding: 1.5rem 0.75rem 3rem; + } + + .ascii-art { + font-size: clamp(2.2px, 1.6vw, 5px); + } +} \ No newline at end of file diff --git a/css/base.css b/css/base.css new file mode 100644 index 0000000..de90215 --- /dev/null +++ b/css/base.css @@ -0,0 +1,152 @@ +/* ============================================================ + base.css — global reset, custom cursors, and the background watermark layers. Loaded on every page. + ============================================================ */ + +/* ============================================================ + 1. BASE & RESET + ============================================================ */ +* { + box-sizing: border-box; +} + +/* Default cursor lives on so it INHERITS down the tree. + Setting it on `*` paints it directly onto every element, which beats + inheritance and makes children of links/buttons (spans, icons, imgs) + fall back to the default cursor instead of the pointer. */ +html { + cursor: url('/assets/cursor/default_0.png') 3 3, auto; +} + +/* Smooth cross-fade between pages */ +@view-transition { + navigation: auto; +} + +::view-transition-old(root), +::view-transition-new(root) { + animation-duration: 0.35s; + animation-timing-function: ease; +} + +@media (prefers-reduced-motion: reduce) { + + ::view-transition-old(root), + ::view-transition-new(root) { + animation: none; + } +} + +html, +body { + height: 100%; + overflow: hidden; +} + +html { + background: linear-gradient(135deg, var(--base) 0%, var(--mantle) 60%, var(--crust) 100%); +} + +body { + font-family: 'Comic Code', sans-serif; + display: flex; + justify-content: center; + align-items: center; + height: 100vh; + height: 100dvh; + margin: 0; + padding: 1.5rem 1rem; + background: linear-gradient(135deg, var(--base) 0%, var(--mantle) 60%, var(--crust) 100%); + color: var(--text); +} + + +/* clickable */ +a, +button, +[role="button"], +[role="link"], +[data-href], +label[for], +select, +summary, +.pc-name--link, +#oneko { + cursor: url('../assets/cursor/pointer_0.png'), pointer; +} + +/* text entry / editing */ +input:not([type="button"]):not([type="submit"]):not([type="checkbox"]):not([type="radio"]), +textarea, +[contenteditable="true"] { + cursor: url('../assets/cursor/text_0.png'), text; +} + +/* loading */ +[aria-busy="true"], +.is-loading { + cursor: url('../assets/cursor/wait_0.png'), wait; +} + +/* busy but interactive */ +.is-progress { + cursor: url('../assets/cursor/progress_0.png'), progress; +} + +/* help */ +[title]:not(a):not(button), +.help { + cursor: url('../assets/cursor/help_0.png'), help; +} + +/* disabled */ +:disabled, +[disabled], +[aria-disabled="true"] { + cursor: url('../assets/cursor/not-allowed_0.png'), not-allowed; +} + +/* draggable */ +[draggable="true"] { + cursor: url('../assets/cursor/openhand_0.png'), grab; +} + +/* crosshair / zoom (if you use them) */ +.crosshair { + cursor: url('../assets/cursor/crosshair_0.png'), crosshair; +} + +.zoom-in { + cursor: url('../assets/cursor/zoom-in_0.png'), zoom-in; +} + +.zoom-out { + cursor: url('../assets/cursor/zoom-out_0.png'), zoom-out; +} + +/* Estrogen watermark blended into the background */ +body::before { + content: ""; + position: fixed; + inset: 0; + background: url(/assets/theme/estrogen.svg) center / cover no-repeat; + filter: invert(86%) sepia(8%) saturate(900%) hue-rotate(190deg) brightness(105%); + opacity: 0.05; + pointer-events: none; + z-index: 0; +} + +/* Miku chibi tucked into the bottom-right corner */ +body::after { + content: ""; + position: fixed; + right: 0.5rem; + bottom: 0.5rem; + width: clamp(96px, 14vw, 168px); + aspect-ratio: 564 / 547; + background: url(/assets/theme/miku.png) center / contain no-repeat; + opacity: 0.18; + pointer-events: none; + z-index: 0; +} + + diff --git a/css/main.css b/css/main.css index 8c294d5..35b7b96 100644 --- a/css/main.css +++ b/css/main.css @@ -1,4798 +1,40 @@ /* ============================================================ - main.css — single stylesheet for c.stupid.cat - Merged from style.css + discord-styles.css - - Sections: - 1. Base & reset (all pages) - 2. Shared layout & header (all pages) - 3. Link hub (index page) - 4. Discord widget (shared, top-left) - 5. Page nav (shared, bottom-left) - 6. System badges (shared, bottom-right) - 7. Theme switcher (shared, top-right) - 8. dev-info page - 9. Changelog page - 10. Secret cat modes (toast + picker modal) - 11. Projects page - 12. Responsive overrides - 13. Friends Page + main.css — import manifest for c.stupid.cat + The stylesheet itself now lives split across css/base.css, + css/shared/*.css, and css/pages/*.css — this file just pulls + it all together in the right order. See REORG-README.md for + the full breakdown of what moved where. ============================================================ */ +/* fonts + theme variables (Catppuccin flavours) */ @import url(/css/fonts.css); @import url(/css/themes/frappe.css); @import url(/css/themes/latte.css); @import url(/css/themes/mocha.css); @import url(/css/themes/macchiato.css); -/* ============================================================ - 1. BASE & RESET - ============================================================ */ -* { - box-sizing: border-box; -} - -/* Default cursor lives on so it INHERITS down the tree. - Setting it on `*` paints it directly onto every element, which beats - inheritance and makes children of links/buttons (spans, icons, imgs) - fall back to the default cursor instead of the pointer. */ -html { - cursor: url('/assets/cursor/default_0.png') 3 3, auto; -} - -/* Smooth cross-fade between pages */ -@view-transition { - navigation: auto; -} - -::view-transition-old(root), -::view-transition-new(root) { - animation-duration: 0.35s; - animation-timing-function: ease; -} - -@media (prefers-reduced-motion: reduce) { - - ::view-transition-old(root), - ::view-transition-new(root) { - animation: none; - } -} - -html, -body { - height: 100%; - overflow: hidden; -} - -html { - background: linear-gradient(135deg, var(--base) 0%, var(--mantle) 60%, var(--crust) 100%); -} - -body { - font-family: 'Comic Code', sans-serif; - display: flex; - justify-content: center; - align-items: center; - height: 100vh; - height: 100dvh; - margin: 0; - padding: 1.5rem 1rem; - background: linear-gradient(135deg, var(--base) 0%, var(--mantle) 60%, var(--crust) 100%); - color: var(--text); -} - - -/* clickable */ -a, -button, -[role="button"], -[role="link"], -[data-href], -label[for], -select, -summary, -.pc-name--link, -#oneko { - cursor: url('../assets/cursor/pointer_0.png'), pointer; -} - -/* text entry / editing */ -input:not([type="button"]):not([type="submit"]):not([type="checkbox"]):not([type="radio"]), -textarea, -[contenteditable="true"] { - cursor: url('../assets/cursor/text_0.png'), text; -} - -/* loading */ -[aria-busy="true"], -.is-loading { - cursor: url('../assets/cursor/wait_0.png'), wait; -} - -/* busy but interactive */ -.is-progress { - cursor: url('../assets/cursor/progress_0.png'), progress; -} - -/* help */ -[title]:not(a):not(button), -.help { - cursor: url('../assets/cursor/help_0.png'), help; -} - -/* disabled */ -:disabled, -[disabled], -[aria-disabled="true"] { - cursor: url('../assets/cursor/not-allowed_0.png'), not-allowed; -} - -/* draggable */ -[draggable="true"] { - cursor: url('../assets/cursor/openhand_0.png'), grab; -} - -/* crosshair / zoom (if you use them) */ -.crosshair { - cursor: url('../assets/cursor/crosshair_0.png'), crosshair; -} - -.zoom-in { - cursor: url('../assets/cursor/zoom-in_0.png'), zoom-in; -} - -.zoom-out { - cursor: url('../assets/cursor/zoom-out_0.png'), zoom-out; -} - -/* Estrogen watermark blended into the background */ -body::before { - content: ""; - position: fixed; - inset: 0; - background: url(/assets/theme/estrogen.svg) center / cover no-repeat; - filter: invert(86%) sepia(8%) saturate(900%) hue-rotate(190deg) brightness(105%); - opacity: 0.05; - pointer-events: none; - z-index: 0; -} - -/* Miku chibi tucked into the bottom-right corner */ -body::after { - content: ""; - position: fixed; - right: 0.5rem; - bottom: 0.5rem; - width: clamp(96px, 14vw, 168px); - aspect-ratio: 564 / 547; - background: url(/assets/theme/miku.png) center / contain no-repeat; - opacity: 0.18; - pointer-events: none; - z-index: 0; -} - - -/* ============================================================ - 2. SHARED LAYOUT & HEADER (all pages) - ============================================================ */ -.hub { - position: relative; - z-index: 1; - width: 100%; - max-width: 460px; -} - -.pfp { - width: 96px; - height: 96px; - border-radius: 50%; - object-fit: cover; - border: 3px solid var(--yellow); - box-shadow: 0 4px 18px rgba(245, 194, 231, 0.25); - margin-bottom: 0.75rem; -} - -.hub-header { - text-align: center; - margin-bottom: 2.25rem; -} - -.hub-header h1 { - margin: 0; - font-size: 2rem; - font-weight: 700; - color: rgb(var(--accent-rgb)); - transition: color 0.6s ease; -} - -.tagline { - margin: 0.35rem 0 0; - color: var(--subtext-0); - font-size: 0.95rem; - letter-spacing: 0.04em; - text-transform: uppercase; -} - -.pronouns { - margin: 0.35rem 0 0; - color: var(--mauve); - font-size: 0.95rem; - letter-spacing: 0.04em; - text-transform: lowercase; -} - - -/* ============================================================ - 3. LINK HUB (index page) - ============================================================ */ -.links { - display: grid; - grid-template-columns: repeat(auto-fit, 72px); - gap: 0.9rem; - justify-content: center; -} - -.link-card { - position: relative; - display: flex; - align-items: center; - justify-content: center; - width: 72px; - height: 72px; - border-radius: 16px; - background: var(--surface-0); - border: 1px solid var(--surface-1); - color: var(--text); - text-decoration: none; - transition: transform 0.15s ease, border-color 0.15s ease, - background 0.15s ease, box-shadow 0.15s ease; -} - -.link-card:hover { - transform: translateY(-3px); - background: var(--surface-1); - border-color: rgb(var(--accent-rgb)); - box-shadow: 0 6px 20px rgba(var(--accent-rgb), 0.22); -} - -.icon { - width: 30px; - height: 30px; - flex-shrink: 0; - filter: brightness(0) invert(1); - transition: filter 0.15s ease; -} - -.link-card:hover .icon { - filter: none; -} - -/* Tooltip revealed on hover */ -.link-text { - position: absolute; - bottom: calc(100% + 10px); - left: 50%; - transform: translateX(-50%) translateY(4px); - display: flex; - flex-direction: column; - align-items: center; - gap: 0.1rem; - padding: 0.5rem 0.75rem; - border-radius: 10px; - background: var(--crust); - border: 1px solid rgb(var(--accent-rgb)); - box-shadow: 0 6px 18px rgba(17, 17, 27, 0.55); - white-space: nowrap; - line-height: 1.3; - opacity: 0; - pointer-events: none; - transition: opacity 0.15s ease, transform 0.15s ease; - z-index: 10; -} - -.link-text::after { - content: ""; - position: absolute; - top: 100%; - left: 50%; - transform: translateX(-50%); - border: 6px solid transparent; - border-top-color: rgb(var(--accent-rgb)); -} - -.link-card:hover .link-text, -.link-card:focus-visible .link-text { - opacity: 1; - transform: translateX(-50%) translateY(0); -} - -.link-title { - font-weight: 500; - font-size: 0.95rem; - color: var(--text); -} - -.link-sub { - font-size: 0.78rem; - color: var(--subtext-0); -} - - -/* ============================================================ - 5. PAGE NAV (shared, pinned top-left) - ============================================================ */ -.nav { - position: fixed; - left: 1rem; - top: 1rem; - z-index: 6; -} - -.nav-links { - display: flex; - flex-direction: column; - align-items: flex-start; - gap: 0.4rem; -} - -.nav-link { - position: relative; - display: inline-flex; - align-items: center; - padding: 0.3rem 0.7rem; - border-radius: 999px; - background: var(--surface-0); - border: 1px solid var(--surface-1); - color: var(--subtext-1); - font-size: 0.8rem; - text-decoration: none; - transition: transform 0.15s ease, border-color 0.15s ease, - background 0.15s ease, color 0.15s ease; -} - -.nav-link:hover { - border-color: rgb(var(--accent-rgb)); - color: var(--text); - transform: translateX(2px); -} - -.nav-link.selected { - background: rgb(var(--accent-rgb)); - border-color: rgb(var(--accent-rgb)); - color: var(--crust); - font-weight: 700; - margin-left: 14px; -} - -.nav-link.is-a-dev { - background: var(--surface-1); - border-color: var(--surface-2); - color: var(--text); -} - -.nav-link.is-a-dev:hover { - border-color: var(--saphire); - transform: translateX(2px); -} - -/* Triangle pointing at the selected item */ -.nav-link.selected::before { - content: ""; - position: absolute; - left: -14px; - top: 50%; - transform: translateY(-50%); - border: 6px solid transparent; - border-left-color: rgb(var(--accent-rgb)); -} - - -/* ============================================================ - 6. SYSTEM BADGES (shared, pinned bottom-right) - ============================================================ */ -.badges { - position: fixed; - right: 1rem; - bottom: 1rem; - display: flex; - flex-direction: column; - align-items: flex-end; - gap: 0.4rem; - pointer-events: none; - z-index: 5; -} - -.badge { - display: inline-flex; - align-items: center; - gap: 0.4rem; - padding: 0.3rem 0.6rem; - border-radius: 999px; - background: var(--surface-0); - border: 1px solid rgba(var(--accent-rgb), 0.45); - color: var(--subtext-1); - font-size: 0.75rem; - white-space: nowrap; - transition: border-color 0.6s ease, box-shadow 0.6s ease; -} - -.badge:hover { - border-color: rgb(var(--accent-rgb)); - box-shadow: 0 4px 14px -6px rgba(var(--accent-rgb), 0.5); -} - -.badge-icon { - width: 15px; - height: 15px; - filter: invert(78%) sepia(36%) saturate(640%) hue-rotate(280deg) brightness(105%); -} - - -/* ============================================================ - 7. THEME SWITCHER (shared, icon button top-right) - ============================================================ */ -.beta-bar { - position: fixed; - top: 1rem; - right: 1rem; - z-index: 7; - display: flex; - align-items: center; - gap: 0.5rem; -} - -/* cat-collection button icon: the classic oneko idle frame, scaled down - from the 256x128 sprite sheet (idle frame lives at -96px,-96px) */ -.beta-cat-icon { - width: 22px; - height: 22px; - display: block; - background-image: url('/assets/oneko/classics/classic.png'); - background-repeat: no-repeat; - background-size: 176px 88px; - background-position: -66px -66px; - image-rendering: pixelated; -} - -.beta-btn { - display: inline-flex; - align-items: center; - justify-content: center; - padding: 0.35rem; - border-radius: 999px; - background: var(--surface-0); - border: 1px solid var(--surface-1); - cursor: url('../assets/cursor/pointer_0.png'), pointer; - transition: border-color 0.15s ease, transform 0.15s ease; -} - -.beta-btn:hover { - border-color: var(--pink); - transform: translateY(2px); -} - -.beta-icon { - width: 22px; - height: 22px; - display: block; -} - - -/* ============================================================ - 8. dev-info PAGE - ============================================================ */ -/* Let only the dev-info page scroll; link hub stays locked */ -html:has(.dev-info), -body:has(.dev-info) { - height: auto; - min-height: 100dvh; - overflow-y: auto; -} - -body:has(.dev-info) { - align-items: flex-start; -} - -body:has(.dev-info) .hub { - max-width: 860px; -} - -.dev-info { - display: flex; - flex-wrap: wrap; - justify-content: center; - gap: 0.5rem; - margin: 0 auto; - padding-bottom: 4.5rem; -} - -/* Simple Icons rendered via CSS mask so colour is theme-driven. - Markup: */ -.tech-icon { - position: relative; - width: 30px; - height: 30px; - display: inline-block; - transition: transform 0.15s ease, filter 0.15s ease; -} - -/* The icon shape — masked so the label (::after) stays visible */ -.tech-icon::before { - content: ""; - position: absolute; - inset: 0; - background-color: currentColor; - -webkit-mask: var(--si) center / contain no-repeat; - mask: var(--si) center / contain no-repeat; -} - -.tech-icon:hover { - transform: translateY(-2px) scale(1.12); - filter: drop-shadow(0 4px 8px currentColor); -} - -/* Hover label — pulls text from aria-label, tinted to match the icon */ -.tech-icon::after { - content: attr(aria-label); - position: absolute; - bottom: calc(100% + 8px); - left: 50%; - transform: translateX(-50%) translateY(4px); - padding: 0.25rem 0.5rem; - border-radius: 6px; - background: var(--crust); - border: 1px solid currentColor; - color: var(--text); - font-size: 0.72rem; - line-height: 1; - white-space: nowrap; - pointer-events: none; - opacity: 0; - transition: opacity 0.15s ease, transform 0.15s ease; - z-index: 10; -} - -.tech-icon:hover::after { - opacity: 1; - transform: translateX(-50%) translateY(0); -} - -/* Catppuccin accent classes — pull from the active flavour's vars */ -.tech-icon.rosewater { - color: var(--rosewater); -} - -.tech-icon.pink { - color: var(--pink); -} - -.tech-icon.mauve { - color: var(--mauve); -} - -.tech-icon.red { - color: var(--red); -} - -.tech-icon.maroon { - color: var(--maroon); -} - -.tech-icon.peach { - color: var(--peach); -} - -.tech-icon.yellow { - color: var(--yellow); -} - -.tech-icon.green { - color: var(--green); -} - -.tech-icon.teal { - color: var(--teal); -} - -.tech-icon.sky { - color: var(--sky); -} - -.tech-icon.sapphire { - color: var(--saphire); -} - -.tech-icon.blue { - color: var(--blue); -} - -.tech-icon.lavender { - color: var(--lavender); -} - - -/* ============================================================ - 10. SECRET CAT MODES (toast + picker modal) - ============================================================ */ -.cat-toast { - position: fixed; - left: 50%; - bottom: 4.5rem; - transform: translateX(-50%) translateY(8px); - z-index: 2147483647; - padding: 0.4rem 0.9rem; - border-radius: 999px; - background: var(--crust); - border: 1px solid var(--pink); - color: var(--text); - font-size: 0.8rem; - white-space: nowrap; - opacity: 0; - pointer-events: none; - transition: opacity 0.2s ease, transform 0.2s ease; -} - -.cat-toast.show { - opacity: 1; - transform: translateX(-50%) translateY(0); -} - -.cat-picker { - position: fixed; - inset: 0; - z-index: 2147483646; - display: flex; - align-items: center; - justify-content: center; - padding: 1rem; - background: rgba(17, 17, 27, 0.65); - backdrop-filter: blur(2px); -} - -.cat-picker[hidden] { - display: none; -} - -.cat-picker-panel { - width: min(94vw, 430px); - max-height: 82vh; - overflow-y: auto; - background: var(--base); - border: 1px solid var(--surface-1); - border-radius: 16px; - padding: 1rem; - box-shadow: 0 16px 48px rgba(0, 0, 0, 0.55); -} - -.cat-picker-head { - display: flex; - align-items: center; - justify-content: space-between; - margin-bottom: 0.85rem; - font-weight: 700; - color: var(--pink); -} - -.cat-picker-close { - background: none; - border: none; - color: var(--subtext-0); - font-size: 1.35rem; - line-height: 1; - cursor: url('../assets/cursor/pointer_0.png'), pointer; - padding: 0 0.25rem; -} - -.cat-picker-close:hover { - color: var(--text); -} - -.cat-grid { - display: flex; - flex-direction: column; - gap: 1rem; -} - -.cat-section-title { - margin: 0 0 0.55rem; - font-size: 0.72rem; - font-weight: 700; - letter-spacing: 0.04em; - text-transform: uppercase; - color: var(--mauve); - border-bottom: 1px solid var(--surface-1); - padding-bottom: 0.3rem; -} - -.cat-section-items { - display: grid; - grid-template-columns: repeat(3, 1fr); - gap: 0.6rem; -} - -.cat-option { - display: flex; - flex-direction: column; - align-items: center; - gap: 0.3rem; - padding: 0.75rem 0.4rem 0.6rem; - border-radius: 12px; - background: var(--surface-0); - border: 1px solid var(--surface-1); - color: var(--text); - font-family: inherit; - font-size: 0.74rem; - text-align: center; - cursor: url('../assets/cursor/pointer_0.png'), pointer; - transition: transform 0.15s ease, border-color 0.15s ease; -} - -.cat-option:hover:not(.locked) { - transform: translateY(-2px); - border-color: var(--pink); -} - -.cat-option.current { - border-color: var(--pink); - box-shadow: inset 0 0 0 1px var(--pink); -} - -.cat-option.locked { - cursor: url('../assets/cursor/default_0.png'), default; - opacity: 0.75; -} - -.cat-preview { - /* 30px window + the -97px,-97px position = the idle frame inset 1px on - every side, so no preview can catch pixels from neighbouring frames */ - width: 30px; - height: 30px; - margin: 7px 1px 11px; - background-repeat: no-repeat; - image-rendering: pixelated; - transform: scale(1.7); - transform-origin: center; -} - -.cat-name { - font-weight: 500; -} - -.cat-hint { - margin: 0.85rem 0 0; - font-size: 0.68rem; - color: var(--subtext-0); - text-align: center; -} - - -/* ============================================================ - 11. Projects PAGE - ============================================================ */ -/* On the projects page the header sits closer to the sections */ -body:has(.project-grid) .hub-header { - position: relative; - z-index: 1; - margin-bottom: 0.25rem; -} - -/* FIX: project-grid and friend-grid pages need scrolling — was missing */ -html:has(.project-grid), -html:has(.friend-grid) { - height: auto; - min-height: 100dvh; - overflow-y: auto; - overflow-x: hidden; -} - -body:has(.project-grid), -body:has(.friend-grid) { - height: auto; - min-height: 100dvh; - align-items: flex-start; - overflow-x: hidden; - overflow-y: visible; -} - -.section { - position: relative; - z-index: 1; - display: flex; - flex-direction: column; - align-items: center; - gap: 1.5rem; - width: 100%; -} - -.section-title { - margin: 0; - font-size: 1.1rem; - font-weight: 500; - letter-spacing: 0.08em; - text-transform: uppercase; - color: var(--mauve); -} - -.section-subtitle { - margin: -1.1rem 0 0; - font-size: 1.1rem; - font-weight: 500; - letter-spacing: 0.08em; - text-transform: lowercase; - color: var(--surface-2); -} - -/* ---- Project cards (horizontal: avatar left, title + status + bio) ---- */ -.project-grid { - margin-bottom: 1.5rem; - display: grid; - grid-template-columns: repeat(auto-fill, minmax(280px, 1fr)); - gap: 1rem; - width: 100%; - max-width: 640px; -} - -.project-card { - display: flex; - align-items: flex-start; - gap: 0.9rem; - padding: 1rem; - border-radius: 16px; - background: var(--surface-0); - border: 1px solid var(--surface-1); - color: var(--text); - text-decoration: none; - transition: transform 0.15s ease, border-color 0.15s ease, - background 0.15s ease, box-shadow 0.15s ease; -} - -.project-card:hover, -.project-card:focus-visible { - transform: translateY(-3px); - background: var(--surface-1); - border-color: rgb(var(--accent-rgb)); - box-shadow: 0 6px 20px rgba(var(--accent-rgb), 0.22); -} - -.project-card-img { - width: 56px; - height: 56px; - flex-shrink: 0; - border-radius: 14px; - object-fit: cover; - border: 2px solid var(--yellow); - box-shadow: 0 4px 14px rgba(var(--accent-rgb), 0.22); -} - -.project-card-body { - display: flex; - flex-direction: column; - gap: 0.35rem; - min-width: 0; -} - -.project-card-head { - display: flex; - align-items: center; - gap: 0.5rem; - flex-wrap: wrap; -} - -.project-card-title { - font-weight: 600; - font-size: 1rem; - color: var(--text); -} - -.project-card-status { - font-size: 0.66rem; - font-weight: 600; - letter-spacing: 0.04em; - text-transform: uppercase; - padding: 0.15rem 0.55rem; - border-radius: 999px; - background: var(--crust); - border: 1px solid var(--green); - color: var(--green); - white-space: nowrap; -} - -.project-card-status.closed { - border-color: var(--red); - color: var(--red); -} - -.project-card-bio { - margin: 0; - font-size: 0.85rem; - line-height: 1.45; - color: var(--subtext-0); -} - -/* Italic + dimmed until you replace it with a real description */ -.project-card-bio.is-placeholder { - font-style: italic; - opacity: 0.65; -} - - -/* ============================================================ - 12. RESPONSIVE OVERRIDES - ============================================================ */ - -/* Shrink to fit narrow / short screens so the hub never scrolls */ -@media (max-width: 420px), -(max-height: 640px) { - .hub-header { - margin-bottom: 1.25rem; - } - - .hub-header h1 { - font-size: 1.6rem; - } - - .pfp { - width: 72px; - height: 72px; - margin-bottom: 0.5rem; - } - - .links { - grid-template-columns: repeat(auto-fit, 60px); - gap: 0.6rem; - } - - .link-card { - width: 60px; - height: 60px; - border-radius: 13px; - } - - .icon { - width: 26px; - height: 26px; - } -} - -/* Cat picker: 2 columns on very narrow screens */ -@media (max-width: 420px) { - .cat-grid { - grid-template-columns: repeat(2, 1fr); - } -} - -/* Mobile layout — single vertical scroll, stacked widgets */ -@media (max-width: 640px) { - - html { - height: auto; - /* Single vertical scroll root on mobile; clip horizontal overflow - so the absolutely-positioned link tooltips can't pan the page. */ - overflow-x: hidden; - overflow-y: auto; - } - - body, - body:has(.dev-info), - body:has(.project-grid), - body:has(.friend-grid) { - flex-direction: column; - justify-content: flex-start; - align-items: center; - gap: 1rem; - height: auto; - min-height: 100dvh; - overflow-x: hidden; - overflow-y: visible; - padding: 1.25rem 1rem 2rem; - } - - /* 1 — Top bar: the two single-item widgets, side by side */ - .topbar { - order: 1; - display: flex; - flex-direction: row; - flex-wrap: wrap; - align-items: center; - justify-content: center; - gap: 0.6rem; - width: 100%; - } - - /* FIX: the presence card injected by discord.js replaces #discord - with .presence-card (position:fixed by default in api.css). Inside - .topbar on mobile it must flow normally. */ - .topbar .presence-card, - .topbar .beta-bar { - position: static; - inset: auto; - } - - /* FIX: presence-card max-width so it doesn't overflow narrow screens */ - .topbar .presence-card { - max-width: min(100%, 320px); - width: 100%; - } - - /* 2 — Main content */ - .hub, - body:has(.dev-info) .hub, - body:has(.project-grid) .hub, - body:has(.friend-grid) .hub { - order: 2; - width: 100%; - max-width: 100%; - } - - /* 3 — Page nav as a centered group */ - .nav { - order: 3; - position: static; - inset: auto; - width: 100%; - } - - .nav-links { - flex-direction: row; - flex-wrap: wrap; - justify-content: center; - gap: 0.5rem; - } - - /* The selected-item pointer triangle / offset only makes sense in - the vertical desktop nav — drop it on mobile */ - .nav-link.selected { - margin-left: 0; - } - - .nav-link.selected::before { - display: none; - } - - /* 4 — System badges, centered and wrapping */ - .badges { - order: 4; - position: static; - inset: auto; - width: 100%; - flex-direction: row; - flex-wrap: wrap; - align-items: center; - justify-content: center; - /* FIX: restore pointer-events on mobile so pokéball and badges are tappable */ - pointer-events: auto; - } - - /* FIX: hide tooltips on touch (they'd stick on tap) */ - .link-card:hover .link-text { - opacity: 0; - pointer-events: none; - } - - .hub-header { - margin-bottom: 1.5rem; - } - - /* Keep the dev-info / projects / friends content from butting up - against the nav below it */ - .dev-info, - .project-grid, - .friend-grid { - padding-bottom: 1rem; - } - - /* FIX: bot sections need a bit of breathing room */ - .section+.section { - margin-top: 1.5rem; - } - - /* FIX: narrow waka bar label column so bars aren't crushed */ - .waka-bar-row { - grid-template-columns: 5rem 1fr auto; - } - - /* FIX: terminal height — respect short landscape viewports */ - .terminal { - width: 94vw; - height: clamp(300px, 65dvh, 70vh); - } -} - -/* Very narrow phones — squeeze waka bar name column further */ -@media (max-width: 380px) { - .waka-bar-row { - grid-template-columns: 4rem 1fr auto; - gap: 0.4rem; - } - - .waka-bar-val { - font-size: 0.66rem; - } - - /* Single column + slightly smaller avatars on very small screens */ - .project-grid { - grid-template-columns: 1fr; - } - - .project-card-img { - width: 48px; - height: 48px; - } -} - - -/* ============================================================ - 12. HIDDEN POKÉBALL (unlocks the Pokémon cats once clicked) - ============================================================ */ -/* Small, low-contrast and tucked among the badges so it has to be - hunted for. Still clickable — that's the whole point of finding it. */ -#pokeball-secret { - width: 14px; - height: 14px; - opacity: 0.18; - align-self: center; - cursor: url('../assets/cursor/default_0.png'), default; - pointer-events: auto; - /* parent .badges sets none — re-enable here */ - image-rendering: auto; - transition: opacity 0.2s ease, transform 0.2s ease; - -webkit-user-drag: none; - user-select: none; -} - -#pokeball-secret:hover { - opacity: 0.85; - transform: scale(1.15); -} - -#pokeball-secret.found { - opacity: 1; - cursor: url('../assets/cursor/default_0.png'), default; - filter: drop-shadow(0 0 4px var(--red)); -} - - -/* ============================================================ - 12. dev-info / Dev Info PAGE - ============================================================ */ -/* Let the coding-stats page scroll; link hub stays locked */ -html:has(.waka), -body:has(.waka) { - height: auto; - min-height: 100dvh; - overflow-y: auto; -} - -body:has(.waka) { - align-items: flex-start; -} - -.waka { - position: relative; - z-index: 1; - width: 100%; - max-width: 640px; - margin: 0 auto; - padding-bottom: 4.5rem; -} - -.waka .hub-header { - margin-bottom: 1.5rem; -} - -.waka-meta { - margin: 0.5rem 0 0; - font-size: 0.72rem; - letter-spacing: 0.03em; - color: var(--subtext-0); -} - -.waka-section { - background: var(--surface-0); - border: 1px solid var(--surface-1); - border-radius: 16px; - padding: 0.85rem 1.25rem 0.95rem; - margin-bottom: 0.7rem; -} - -.waka-section .section-title { - text-align: left; - font-size: 0.82rem; - margin-bottom: 1rem; -} - -/* ---- headline total + weekly chart ---- */ -.waka-total { - text-align: center; -} - -.waka-total-num { - font-size: 2.1rem; - font-weight: 700; - color: rgb(var(--accent-rgb)); - line-height: 1.1; -} - -.waka-total-sub { - font-size: 0.78rem; - text-transform: uppercase; - letter-spacing: 0.05em; - color: var(--subtext-0); - margin-bottom: 1.1rem; -} - -.waka-week { - display: flex; - align-items: flex-end; - justify-content: space-between; - gap: 0.5rem; - height: 120px; -} - -.waka-day { - flex: 1 1 0; - display: flex; - flex-direction: column; - align-items: center; - gap: 0.4rem; - height: 100%; -} - -.waka-day-track { - flex: 1; - width: 100%; - max-width: 34px; - display: flex; - align-items: flex-end; - background: var(--surface-1); - border-radius: 7px; - overflow: hidden; -} - -.waka-day-fill { - width: 100%; - min-height: 3px; - background: rgb(var(--accent-rgb)); - border-radius: 7px 7px 0 0; - transition: height 0.5s ease; -} - -.waka-day-label { - font-size: 0.66rem; - color: var(--subtext-0); -} - -/* ---- ranked horizontal bars (languages / projects / editors / os) ---- */ -.waka-bars { - display: flex; - flex-direction: column; - gap: 0.6rem; -} - -.waka-bar-row { - display: grid; - grid-template-columns: 7.5rem 1fr auto; - align-items: center; - gap: 0.7rem; -} - -.waka-bar-name { - font-size: 0.82rem; - color: var(--text); - white-space: nowrap; - overflow: hidden; - text-overflow: ellipsis; -} - -.waka-bar-track { - height: 9px; - background: var(--surface-1); - border-radius: 999px; - overflow: hidden; -} - -.waka-bar-fill { - display: block; - height: 100%; - width: 0; - background: rgb(var(--accent-rgb)); - border-radius: 999px; - transition: width 0.6s ease; -} - -.waka-bar-val { - font-size: 0.74rem; - color: var(--subtext-0); - white-space: nowrap; - font-variant-numeric: tabular-nums; -} - -/* ---- two-up grid for editors + OS on wider screens ---- */ -.waka-grid2 { - display: grid; - grid-template-columns: 1fr 1fr; - gap: 1.1rem; -} - -.waka-grid2 .waka-section { - margin-bottom: 0; -} - -@media (max-width: 560px) { - .waka-grid2 { - grid-template-columns: 1fr; - gap: 0; - } - - .waka-grid2 .waka-section { - margin-bottom: 1.1rem; - } - - .waka-bar-row { - grid-template-columns: 5.5rem 1fr auto; - } -} - -/* ---- empty / setup state ---- */ -.waka-empty { - font-size: 0.85rem; - color: var(--subtext-0); - line-height: 1.5; - margin: 0; -} - -.waka-setup { - background: var(--surface-0); - border: 1px solid var(--surface-1); - border-radius: 16px; - padding: 1.25rem 1.4rem 1.5rem; - text-align: left; -} - -.waka-steps { - margin: 0.9rem 0 1.2rem; - padding-left: 1.2rem; - display: flex; - flex-direction: column; - gap: 0.5rem; - font-size: 0.85rem; - line-height: 1.45; - color: var(--text); -} - -.waka-steps code { - background: var(--surface-1); - padding: 0.05rem 0.35rem; - border-radius: 6px; - font-size: 0.8rem; -} - -.waka-steps a, -.waka-empty a, -.waka-credit a { - color: rgb(var(--accent-rgb)); - text-decoration: none; -} - -.waka-steps a:hover, -.waka-empty a:hover, -.waka-credit a:hover { - text-decoration: underline; -} - -.waka-setup-btn { - display: inline-block; - padding: 0.45rem 1rem; - border-radius: 999px; - background: rgb(var(--accent-rgb)); - color: var(--crust); - font-size: 0.82rem; - font-weight: 600; - text-decoration: none; - transition: transform 0.15s ease, filter 0.15s ease; -} - -.waka-setup-btn:hover { - transform: translateY(-1px); - filter: brightness(1.05); -} - -.waka-credit { - text-align: center; - font-size: 0.72rem; - color: var(--subtext-0); - margin: 1.4rem 0 0; -} - -/* ---- collapsible dropdown sections (details/summary) ---- */ -details.waka-section { - /* keep the card padding tight when collapsed; expands via [open] below */ - padding-bottom: 0.85rem; - transition: padding-bottom 0.15s ease; -} - -details.waka-section[open] { - padding-bottom: 1.15rem; -} - -/* The clickable header row */ -summary.section-title { - display: flex; - align-items: center; - justify-content: space-between; - gap: 0.5rem; - cursor: url('../assets/cursor/pointer_0.png'), pointer; - list-style: none; - user-select: none; - margin-bottom: 0; - transition: margin-bottom 0.15s ease, color 0.15s ease; -} - -/* Hide the native disclosure triangle (both engines) */ -summary.section-title::-webkit-details-marker { - display: none; -} - -summary.section-title::marker { - content: ""; -} - -summary.section-title:hover { - color: rgb(var(--accent-rgb)); -} - -summary.section-title:focus-visible { - outline: 2px solid rgb(var(--accent-rgb)); - outline-offset: 3px; - border-radius: 6px; -} - -/* Custom chevron that flips when the section is open */ -summary.section-title::after { - content: ""; - flex: none; - width: 0.5rem; - height: 0.5rem; - margin-right: 0.15rem; - border-right: 2px solid currentColor; - border-bottom: 2px solid currentColor; - transform: rotate(45deg); - transition: transform 0.2s ease; -} - -details.waka-section[open]>summary.section-title { - margin-bottom: 0.75rem; -} - -details.waka-section[open]>summary.section-title::after { - transform: rotate(-135deg); -} - -/* Tech-stack icons sit inside a collapsible card now: drop the big - page-bottom padding the standalone .dev-info block used. */ -.tech-stack .dev-info { - padding-bottom: 0; - justify-content: flex-start; -} - -/* ---- about / setup + badges section ---- */ -.about-badges { - display: flex; - flex-wrap: wrap; - gap: 0.5rem; - margin-bottom: 1rem; -} - -/* The .badge chips are reused here in normal page flow (the fixed-position - .badges container is gone); make sure they stay interactive + visible. */ -.about-badges .badge { - pointer-events: auto; -} - -.about-list { - margin-top: 0.25rem; -} - -/* hidden pokéball now lives inside the dev-info Setup section */ -.about-setup #pokeball-secret { - display: block; - margin: 0.9rem auto 0; -} - -/* ---- hardware spec list ---- */ -.hw-item { - text-decoration: none; - color: var(--text); -} - -.hw-intro { - margin: 0 0 0.9rem; - font-size: 0.8rem; - color: var(--subtext-0); -} - -.hw-list { - display: flex; - flex-direction: column; - gap: 0.55rem; - margin: 0; -} - -.hw-row { - display: grid; - grid-template-columns: 8rem 1fr; - gap: 0.7rem; - align-items: baseline; -} - -.hw-row dt { - font-size: 0.72rem; - text-transform: uppercase; - letter-spacing: 0.05em; - color: var(--subtext-0); -} - -.hw-row dd { - margin: 0; - font-size: 0.88rem; - color: var(--text); -} - -@media (max-width: 560px) { - .hw-row { - grid-template-columns: 6rem 1fr; - } -} - - -/* ============================================================ - 14. TERMINAL HOMEPAGE (+ 88x31 button wall) - ============================================================ */ -.terminal { - position: relative; - z-index: 1; - width: min(92vw, 600px); - /* locked height — the box must not resize between boot and ready, or as - command output is appended (the inner .t-output scrolls instead) */ - height: min(62vh, 460px); - display: flex; - flex-direction: column; - padding: 1rem 1.15rem 1.15rem; - background: var(--mantle); - border: 1px solid var(--surface-1); - border-radius: 14px; - box-shadow: 0 18px 50px -20px rgba(0, 0, 0, 0.7); - font-family: 'Comic Code', ui-monospace, 'JetBrains Mono', Menlo, monospace; - font-size: 0.86rem; - line-height: 1.5; - color: var(--text); - overflow: hidden; - /* lets .t-banner size itself off the terminal's width (cqw), not the - viewport, so the ascii always fits regardless of the loaded font */ - container-type: inline-size; -} - -body:has(.terminal) .hub { - max-width: min(92vw, 600px); - width: 100%; -} - -body:has(.terminal) .hub .terminal { - width: 100%; - margin: 0 auto; -} - -/* ---- boot log ---- */ -.t-boot { - margin: 0; - white-space: pre-wrap; - word-break: break-word; - font-size: 0.78rem; - color: var(--subtext-0); - max-height: 72vh; - overflow: hidden; -} - -.t-boot[hidden] { - display: none; -} - -.b-line { - display: block; -} - -.b-time { - color: var(--overlay-0); -} - -.b-info { - color: var(--blue); - font-weight: 700; -} - -.b-ok { - color: var(--green); - font-weight: 700; -} - -/* ---- main terminal ---- */ -.t-main { - display: flex; - flex-direction: column; - flex: 1; - /* fill the fixed-height terminal so .t-output scrolls */ - min-height: 0; -} - -.t-main[hidden] { - display: none; -} - -.t-banner { - margin: 0 0 0.5rem; - color: rgb(var(--accent-rgb)); - /* scale to the terminal's width (1cqw = 1% of it) so the 42-char banner - always fits; capped so it never gets oversized on a wide terminal */ - font-size: min(0.78rem, 1.9cqw); - line-height: 1.04; - white-space: pre; - overflow: hidden; - text-shadow: 0 0 14px rgba(var(--accent-rgb), 0.35); -} - -.t-greet { - margin-bottom: 0.7rem; - color: var(--subtext-1); -} - -.t-greet b { - color: rgb(var(--accent-rgb)); -} - -.t-dim { - color: var(--subtext-0); -} - -.t-accent { - color: rgb(var(--accent-rgb)); -} - -.t-inputline { - display: flex; - align-items: center; - gap: 0.5rem; - padding-bottom: 0.55rem; - border-bottom: 1px solid var(--surface-0); -} - -.t-prompt { - color: var(--green); - white-space: nowrap; - font-weight: 700; -} - -.t-path { - color: var(--blue); - font-weight: 700; -} - -.t-input { - flex: 1; - min-width: 0; - background: transparent; - border: none; - outline: none; - color: var(--text); - font: inherit; - caret-color: rgb(var(--accent-rgb)); -} - -.t-output { - margin-top: 0.6rem; - min-height: 0; - flex: 1; - overflow-y: auto; - display: flex; - flex-direction: column; - gap: 0.6rem; -} - -.t-echo { - color: var(--subtext-0); -} - -.t-result { - white-space: pre-wrap; - word-break: break-word; - margin-top: 0.15rem; -} - -.t-entry.is-error .t-result { - color: var(--red); -} - -/* hyfetch trans-flag block */ -.hf-c1 { - color: #5bcefa; -} - -.hf-c2 { - color: #f5a9b8; -} - -.hf-c3 { - color: #ffffff; -} - -.hf-pad { - color: transparent; -} - -/* ---- 88x31 button wall (lives on the dedicated /88x31 page) ---- */ -.button-wall { - display: flex; - flex-wrap: wrap; - justify-content: center; - gap: 0.6rem; - margin: 0 auto; -} - -.button-wall a { - display: block; - line-height: 0; -} - -.button-wall img { - width: 132px; - height: 46px; - border: 1px solid var(--surface-1); - border-radius: 2px; - transition: transform 0.12s ease, border-color 0.12s ease; -} - -.button-wall a:hover img, -.button-wall img:hover { - transform: translateY(-2px); - border-color: rgb(var(--accent-rgb)); -} - -/* ---- boot reveal of side chrome (homepage terminal) ---- */ -.nav, -.badges { - transition: opacity 0.6s ease, transform 0.6s ease; -} - -body.term-booting .nav, -body.term-booting .badges { - opacity: 0; - transform: translateY(8px); -} - -body.term-chrome-in .nav, -body.term-chrome-in .badges { - opacity: 1; - transform: none; -} - -/* ---- 88x31 page: scrolls like the other content pages ---- */ -html:has(.button-page), -body:has(.button-page) { - height: auto; - min-height: 100dvh; - overflow-y: auto; -} - -body:has(.button-page) { - align-items: flex-start; -} - -body:has(.button-page) .hub { - max-width: 560px; -} - -.button-page { - display: flex; - justify-content: center; - padding-bottom: 4.5rem; -} - -@media (max-width: 640px) { - .terminal { - width: 94vw; - height: clamp(300px, 65dvh, 70vh); - } - - .button-wall { - max-width: 100%; - } -} - - -/* ---- terminal: socials list (svg icon + clickable link) ---- */ -.t-socials-hint { - margin-bottom: 0.4rem; -} - -.t-socials { - display: flex; - flex-direction: column; - gap: 0.1rem; -} - -.t-social { - display: grid; - grid-template-columns: 18px 6.5rem 6rem 1fr; - align-items: center; - gap: 0.55rem; - padding: 0.22rem 0.4rem; - border-radius: 6px; - text-decoration: none; - color: var(--text); - border: 1px solid transparent; -} - -.t-social:hover { - background: var(--surface-0); - border-color: rgba(var(--accent-rgb), 0.4); -} - -.t-social-ic { - width: 16px; - height: 16px; - object-fit: contain; -} - -.t-social-key { - color: rgb(var(--accent-rgb)); -} - -.t-social-label { - color: var(--text); -} - -.t-social-sub { - white-space: nowrap; - overflow: hidden; - text-overflow: ellipsis; -} - -/* the "Opening …" confirmation line */ -.t-social-open { - display: inline-flex; - align-items: center; - gap: 0.4rem; - grid-template-columns: none; - padding: 0; - border: none; -} - -.t-social-open:hover { - background: transparent; -} - - -/* ---- terminal: ls-style socials list + social card ---- */ -.t-ls { - display: grid; - grid-template-columns: repeat(auto-fill, minmax(7rem, 1fr)); - gap: 0.1rem 1.2rem; -} - -.t-ls-item { - color: rgb(var(--accent-rgb)); -} - -.t-ls-foot { - margin-top: 0.6rem; -} - -.t-ls-foot b { - color: var(--text); -} - -.t-social-card { - display: flex; - flex-direction: column; - gap: 0.35rem; -} - -.t-sc-head { - display: flex; - align-items: center; - gap: 0.45rem; -} - -.t-sc-head .t-social-ic { - width: 18px; - height: 18px; -} - -.t-sc-url { - color: var(--blue); - text-decoration: none; - word-break: break-all; -} - -.t-sc-url:hover { - text-decoration: underline; -} - -.t-sc-ask { - margin-top: 0.2rem; -} - -.t-sc-ask b { - color: var(--text); -} - -.t-social-open { - display: inline-flex; - align-items: center; - gap: 0.4rem; - color: var(--text); - text-decoration: none; -} - -.t-social-open .t-social-ic { - width: 16px; - height: 16px; -} - - -/* ---- hyfetch: arch logo + info, side by side ---- */ -.hf { - display: flex; - gap: 1.1rem; - align-items: flex-start; - flex-wrap: wrap; -} - -.hf-logo { - margin: 0; - white-space: pre; - line-height: 1.02; - font-size: 0.62rem; -} - -.hf-info { - margin: 0; - white-space: pre; -} - -/* ============================================================ - 13. Friends Page - ============================================================ */ - -body:has(.friend-grid) .hub-header { - position: relative; - z-index: 1; - margin-bottom: 2rem; -} - -.friend-grid { - display: flex; - flex-wrap: wrap; - /* flex-wrap centres EVERY row, including a partial last row (a lone card - sits centred rather than stuck to the left as it did with CSS grid) */ - justify-content: center; - align-items: flex-start; - margin-bottom: 1.5rem; - gap: 1.1rem; - width: 100%; -} - -/* allow the cool-people page to scroll even before friends.js injects the - .friend-grid elements that the :has() rule keys on */ -html:has(.friends-wrap), -body:has(.friends-wrap) { - height: auto; - min-height: 100dvh; - overflow-y: auto; -} - -body:has(.friends-wrap) { - align-items: flex-start; -} - -body:has(.friends-wrap) .hub { - max-width: 960px; -} - -#friends-root { - display: flex; - flex-direction: column; - gap: 2rem; - padding-bottom: 4.5rem; -} - -/* ---- Lanyard friend cards ---- */ -.friend-card { - position: relative; - display: flex; - flex-direction: column; - width: 210px; - border-radius: 14px; - background: var(--surface-0); - border: 1px solid var(--surface-1); - overflow: hidden; - transition: transform 0.15s ease, border-color 0.15s ease, box-shadow 0.15s ease; -} - -.friend-card:hover { - transform: translateY(-3px); - border-color: rgb(var(--accent-rgb)); - box-shadow: 0 8px 22px -12px rgba(var(--accent-rgb), 0.5); -} - -/* Nitro profile gradient — recolours the card body (mirrors the /discord card) */ -.friend-card.has-profile-grad { - background: linear-gradient(180deg, rgb(var(--fc-grad-1-rgb)) 0%, rgb(var(--fc-grad-2-rgb)) 100%); - border-color: rgba(var(--fc-grad-1-rgb), 0.6); -} - -/* Hovered card lifts above its neighbours and lets its text un-truncate so - long names / usernames / custom statuses expand in full instead of being - chopped off with an ellipsis. The body becomes an absolutely-positioned - overlay, so the card grows DOWNWARD without resizing its grid slot — - neighbouring cards stay exactly where they are. */ -/* Expansion is gated on .is-hovering (added by JS) rather than :hover so the - card's flow height can be pinned BEFORE .fc-main is taken out of flow — - otherwise the card collapses, the page reflows, and hover ping-pongs - (the "vibrating page" bug). */ -.friend-card.is-hovering { - overflow: visible; - z-index: 5; -} - -.friend-card.is-hovering .fc-main { - position: absolute; - left: 0; - right: 0; - top: 54px; - /* sit directly under the banner strip */ - background: inherit; - /* carry the card surface / Nitro gradient */ - border-bottom-left-radius: 14px; - border-bottom-right-radius: 14px; - box-shadow: 0 10px 24px -14px rgba(17, 17, 27, 0.8); -} - -.friend-card.is-hovering .fc-name, -.friend-card.is-hovering .fc-user, -.friend-card.is-hovering .fc-custom-text { - white-space: normal; - overflow: visible; - text-overflow: clip; - overflow-wrap: anywhere; - /* break long unbroken usernames / handles */ -} - -/* banner strip — Nitro banner image / accent colour / default wash */ -.fc-banner { - height: 54px; - background: - linear-gradient(135deg, rgba(var(--accent-rgb), 0.45), rgba(var(--accent-rgb), 0.12)); - background-size: cover; - background-position: center; - /* keep the banner corners rounded even on hover, when the card switches - to overflow:visible and no longer clips them to the card radius */ - border-top-left-radius: 14px; - border-top-right-radius: 14px; -} - -.friend-card.has-banner .fc-banner { - background-size: cover; - background-position: center; -} - -.fc-main { - display: flex; - align-items: flex-start; - gap: 0.7rem; - padding: 0.6rem 0.85rem 0.85rem; -} - -.fc-avatar { - position: relative; - flex-shrink: 0; - width: 56px; - height: 56px; - margin-top: -30px; -} - -.fc-pfp { - width: 56px; - height: 56px; - border-radius: 50%; - object-fit: cover; - border: 3px solid var(--surface-0); - background: var(--surface-0); - display: block; -} - -/* avatar decoration / frame overlay (Discord cosmetic) */ -.fc-deco { - position: absolute; - top: 50%; - left: 50%; - width: 76px; - height: 76px; - transform: translate(-50%, -50%); - pointer-events: none; -} - -.fc-deco[hidden] { - display: none; -} - -/* status dot — colour driven by data-status on the card */ -.fc-status { - position: absolute; - right: -1px; - bottom: -1px; - width: 15px; - height: 15px; - border-radius: 50%; - border: 3px solid var(--surface-0); - background: var(--blue); -} - -.friend-card[data-status="online"] .fc-status { - background: var(--green); -} - -.friend-card[data-status="idle"] .fc-status { - background: var(--yellow); -} - -.friend-card[data-status="dnd"] .fc-status { - background: var(--red); -} - -.friend-card[data-status="offline"] .fc-status { - background: var(--overlay-0); -} - -.friend-card[data-status="unconnected"] .fc-status { - background: var(--blue); -} - -.fc-id { - display: flex; - flex-direction: column; - gap: 0.15rem; - min-width: 0; - padding-top: 0.1rem; -} - -.fc-name-row { - display: flex; - flex-wrap: wrap; - align-items: center; - gap: 0.15rem 0.3rem; - min-width: 0; -} - -/* name claims the full first line (so a clan tag never truncates it); the - tag chip wraps onto its own line just beneath when there isn't room */ -.fc-name-row .fc-name { - flex: 1 1 100%; - min-width: 0; -} - -/* Discord server (clan) tag chip */ -.fc-tag { - display: inline-flex; - align-items: center; - gap: 0.15rem; - flex-shrink: 0; - padding: 0.05rem 0.3rem; - border-radius: 5px; - background: var(--surface-2); - font-size: 0.56rem; - font-weight: 700; - letter-spacing: 0.02em; - color: var(--text); -} - -.fc-tag[hidden] { - display: none; -} - -.fc-tag-badge { - width: 12px; - height: 12px; - display: block; -} - -.fc-name { - font-size: 0.95rem; - font-weight: 700; - color: var(--text); - text-decoration: none; - white-space: nowrap; - overflow: hidden; - text-overflow: ellipsis; -} - -a.fc-name:hover { - color: rgb(var(--accent-rgb)); -} - -/* Nitro display-name gradient (clipped to the text). Keep the tier heart in - ::before painted normally so it stays its solid colour. */ -.fc-name.is-gradient { - -webkit-background-clip: text; - background-clip: text; - color: transparent; - -webkit-text-fill-color: transparent; -} - -.fc-name.is-gradient::before { - -webkit-text-fill-color: initial; - color: var(--text); -} - -/* tier hearts (match the old friend-name prefixes) */ -.fc-name::before { - content: "🩵 "; -} - -.fc-name.known::before { - content: "💛 "; -} - -.fc-name.wife::before { - content: "🖤 "; -} - -.fc-name.close::before { - content: "🤍 "; -} - -.fc-user { - font-size: 0.72rem; - color: var(--subtext-0); - white-space: nowrap; - overflow: hidden; - text-overflow: ellipsis; -} - -.fc-user:empty { - display: none; -} - -/* custom status (Discord activity type 4) */ -.fc-custom { - position: relative; - align-self: flex-start; - display: inline-flex; - align-items: center; - gap: 0.3rem; - max-width: 100%; - font-size: 0.72rem; - color: var(--subtext-1); - margin-top: 0.45rem; - min-width: 0; - padding: 0.3rem 0.5rem; - background: var(--surface-1); - border-radius: 11px; - border-top-left-radius: 4px; -} - -/* Discord-style thought-bubble tail: two little circles rising to the name */ -.fc-custom::before, -.fc-custom::after { - content: ""; - position: absolute; - background: var(--surface-1); - border-radius: 50%; - pointer-events: none; -} - -.fc-custom::before { - width: 7px; - height: 7px; - top: -4px; - left: 9px; -} - -.fc-custom::after { - width: 4px; - height: 4px; - top: -8px; - left: 7px; -} - -.fc-custom[hidden] { - display: none; -} - -.fc-custom-emoji { - width: 14px; - height: 14px; - display: block; - flex: none; -} - -.fc-custom-emoji-uni { - font-size: 0.8rem; - line-height: 1; - flex: none; -} - -.fc-custom-text { - white-space: nowrap; - overflow: hidden; - text-overflow: ellipsis; -} - -.fc-badges { - display: inline-flex; - align-items: center; - flex-wrap: wrap; - gap: 0.2rem; - margin-top: 0.1rem; -} - -.fc-badges:empty { - display: none; -} - -.fc-badge { - width: 16px; - height: 16px; - display: block; -} - -.fc-badge-link { - display: inline-flex; - line-height: 0; -} - -/* ---- Alts (active + dead) ---- */ -.fc-name.active-alt::before { - content: "🎭 "; -} - -.fc-name.dead-alt::before { - content: "💀 "; -} - -/* dead alts: banned accounts — greyed out, name struck through, no status */ -.friend-card.tier-dead-alt .fc-pfp { - filter: grayscale(1) brightness(0.6); -} - -.friend-card.tier-dead-alt .fc-name { - color: var(--overlay-1); - text-decoration: line-through; -} - -.friend-card.tier-dead-alt .fc-status { - display: none; -} - -/* the "struck off" diagonal slash across the avatar */ -.friend-card.tier-dead-alt .fc-avatar::after { - content: ""; - position: absolute; - left: 50%; - top: 50%; - width: 132%; - height: 4px; - background: var(--red); - border-radius: 2px; - transform: translate(-50%, -50%) rotate(-45deg); - box-shadow: 0 0 0 2px var(--surface-0); - pointer-events: none; -} - -/* ===================================================================== - * MUSIC PAGE (/music) — merged in from music.css. - * Hero classes are .mdc-* to avoid colliding with the .dc-* discord - * widget already defined above. Other classes (.lyrics, .rc-*, .sec-*, - * .top-*, .ly-*, .music-*) are unique to this page. - * ===================================================================== */ - -/* Let the music page scroll; the link hub stays locked (same pattern as - .dev-info above). Without this, html,body{overflow:hidden} - from the homepage layout traps the page. */ -html:has(.music-wrap), -body:has(.music-wrap) { - height: auto; - min-height: 100dvh; - overflow-y: auto; -} - -body:has(.music-wrap) { - align-items: flex-start; -} - -.music-wrap { - max-width: 880px; - margin: 0 auto; - padding: 2.6rem 1.25rem 5rem; - font-family: 'Comic Code', ui-monospace, monospace; -} - -.music-head { - margin: 0 0 1.6rem; -} - -.music-head h1 { - font-size: clamp(1.7rem, 5vw, 2.4rem); - margin: 0 0 0.2rem; - color: rgb(var(--accent-rgb)); - letter-spacing: -0.02em; - transition: color 0.5s ease; -} - -.music-head p { - margin: 0; - color: var(--subtext-0); - font-size: 0.95rem; -} - -/* ---- now playing hero -------------------------------------------------- */ -.mdc { - display: grid; - grid-template-columns: 132px 1fr; - gap: 1.1rem; - align-items: center; - background: var(--mantle); - border: 1px solid var(--surface-0); - border-radius: 18px; - padding: 1.1rem; - position: relative; - overflow: hidden; - text-decoration: none; -} - -/* a soft wash of the album accent behind the hero */ -.mdc::before { - content: ""; - position: absolute; - inset: 0; - background: radial-gradient(120% 140% at 0% 0%, - rgba(var(--accent-rgb), 0.18), transparent 60%); - opacity: 0; - transition: opacity 0.6s ease; - pointer-events: none; -} - -#music.is-live .mdc::before { - opacity: 1; -} - -.mdc-art { - width: 132px; - height: 132px; - border-radius: 12px; - object-fit: cover; - background: var(--surface-0); - box-shadow: 0 8px 24px rgba(0, 0, 0, 0.35); -} - -.mdc-art:not(.has-art) { - display: grid; -} - -.mdc-art:not(.has-art)::after { - content: "♪"; - color: var(--overlay-0); - font-size: 2.4rem; - display: grid; - place-items: center; - height: 100%; -} - -.mdc-meta { - min-width: 0; - position: relative; -} - -.mdc-state { - display: inline-flex; - align-items: center; - gap: 0.4rem; - font-size: 0.7rem; - text-transform: uppercase; - letter-spacing: 0.08em; - color: var(--subtext-0); - margin-bottom: 0.35rem; -} - -#music.is-live .mdc-state { - color: rgb(var(--accent-rgb)); -} - -.mdc-title { - display: block; - font-size: 1.3rem; - font-weight: 700; - color: var(--text); - margin: 0 0 0.15rem; - line-height: 1.2; - white-space: nowrap; - overflow: hidden; - text-overflow: ellipsis; -} - -.mdc-title:hover { - color: rgb(var(--accent-rgb)); -} - -.mdc-artist { - display: block; - color: var(--subtext-1); - font-size: 0.95rem; -} - -.mdc-album { - display: block; - color: var(--subtext-0); - font-size: 0.82rem; - margin-top: 0.1rem; -} - -.mdc-progress { - margin-top: 0.8rem; - display: flex; - align-items: center; - gap: 0.6rem; -} - -.mdc-bar { - flex: 1; - height: 6px; - border-radius: 999px; - background: var(--surface-0); - overflow: hidden; -} - -.mdc-fill { - display: block; - height: 100%; - width: 0%; - background: rgb(var(--accent-rgb)); - border-radius: 999px; - transition: width 0.4s linear; -} - -.mdc-time { - font-size: 0.72rem; - color: var(--subtext-0); - font-variant-numeric: tabular-nums; -} - -/* ---- lyrics (the centrepiece) ------------------------------------------ */ -.sec-title { - font-size: 0.78rem; - text-transform: uppercase; - letter-spacing: 0.07em; - color: var(--subtext-0); - margin: 2.4rem 0 0.7rem; - font-weight: 500; -} - -.sec-row { - display: flex; - align-items: baseline; - justify-content: space-between; - gap: 0.8rem; - margin: 2.4rem 0 0.7rem; -} - -.sec-row .sec-title { - margin: 0; -} - -.ly-lock { - font-family: inherit; - font-size: 0.72rem; - letter-spacing: 0.04em; - cursor: url('../assets/cursor/pointer_0.png'), pointer; - border-radius: 999px; - padding: 0.28rem 0.8rem 0.28rem 0.7rem; - background: var(--surface-0); - color: var(--subtext-1); - border: 1px solid transparent; - display: inline-flex; - align-items: center; - gap: 0.4rem; - transition: color 0.15s ease, border-color 0.15s ease, background 0.15s ease; -} - -/* Spotify-style equalizer bars (replaces the old status dot) */ -.ly-bars { - display: inline-flex; - align-items: flex-end; - gap: 2px; - width: 13px; - height: 11px; - flex-shrink: 0; -} - -.ly-bars i { - flex: 1; - height: 100%; - border-radius: 1px; - background: currentColor; - transform-origin: bottom; - transform: scaleY(0.4); - opacity: 0.55; -} - -.ly-lock.is-locked { - color: rgb(var(--accent-rgb)); - border-color: rgba(var(--accent-rgb), 0.4); - background: rgba(var(--accent-rgb), 0.1); -} - -.ly-lock.is-locked .ly-bars i { - opacity: 1; - animation: ly-eq 0.9s ease-in-out infinite; -} - -.ly-lock.is-locked .ly-bars i:nth-child(2) { - animation-delay: 0.15s; -} - -.ly-lock.is-locked .ly-bars i:nth-child(3) { - animation-delay: 0.3s; -} - -.ly-lock.is-locked .ly-bars i:nth-child(4) { - animation-delay: 0.45s; -} - -@keyframes ly-eq { - - 0%, - 100% { - transform: scaleY(0.3); - } - - 50% { - transform: scaleY(1); - } -} - -@media (prefers-reduced-motion: reduce) { - .ly-lock.is-locked .ly-bars i { - animation: none; - transform: scaleY(0.65); - } -} - -.ly-lock:not(.is-locked):hover { - color: var(--text); - border-color: var(--surface-1); -} - -.lyrics { - position: relative; - /* anchor offsetTop for the follow scroll */ - height: 340px; - overflow-y: auto; - scroll-behavior: smooth; - overscroll-behavior: contain; - border-radius: 16px; - background: var(--crust); - border: 1px solid var(--surface-0); - padding: 1.4rem 1.4rem; - scrollbar-width: thin; - scrollbar-color: var(--surface-1) transparent; - /* fade the top + bottom so lines drift in and out */ - -webkit-mask-image: linear-gradient(180deg, transparent, #000 14%, #000 86%, transparent); - mask-image: linear-gradient(180deg, transparent, #000 14%, #000 86%, transparent); -} - -.lyrics::-webkit-scrollbar { - width: 8px; -} - -.lyrics::-webkit-scrollbar-thumb { - background: var(--surface-1); - border-radius: 999px; -} - -.ly-line { - margin: 0; - padding: 0.32rem 0; - font-size: 1.18rem; - line-height: 1.4; - color: var(--overlay-0); - transition: color 0.3s ease, opacity 0.3s ease, transform 0.3s ease; -} - -.is-synced .ly-line { - opacity: 0.55; -} - -.is-synced .ly-line.is-active { - color: rgb(var(--accent-rgb)); - opacity: 1; - font-weight: 700; - transform: translateX(2px); -} - -.ly-static { - color: var(--subtext-1); - opacity: 1; - font-size: 1.05rem; -} - -.ly-note { - color: var(--subtext-0); - font-size: 0.95rem; - text-align: center; - margin: 0; - padding-top: 1rem; -} - -.lyrics.is-instrumental, -.lyrics.is-empty, -.lyrics.is-loading { - display: grid; - place-content: center; - height: 180px; - -webkit-mask-image: none; - mask-image: none; -} - -.lyrics.is-instrumental .ly-note { - color: rgb(var(--accent-rgb)); - font-size: 1.2rem; -} - -/* ---- recently played --------------------------------------------------- */ -.recent { - list-style: none; - margin: 0; - padding: 0; - display: grid; - gap: 0.35rem; -} - -.rc-item a { - display: grid; - grid-template-columns: 44px 1fr auto; - gap: 0.7rem; - align-items: center; - text-decoration: none; - padding: 0.45rem 0.55rem; - border-radius: 12px; - transition: background 0.15s ease; -} - -.rc-item a:hover { - background: var(--surface-0); -} - -.rc-art { - width: 44px; - height: 44px; - border-radius: 8px; - object-fit: cover; - background: var(--surface-0); -} - -.rc-art-blank { - display: grid; - place-items: center; - color: var(--overlay-0); - font-size: 1.1rem; -} - -.rc-text { - min-width: 0; -} - -.rc-name { - display: block; - color: var(--text); - font-size: 0.92rem; - white-space: nowrap; - overflow: hidden; - text-overflow: ellipsis; -} - -.rc-artist { - display: block; - color: var(--subtext-0); - font-size: 0.78rem; - white-space: nowrap; - overflow: hidden; - text-overflow: ellipsis; -} - -.rc-when, -.rc-now { - font-size: 0.72rem; - white-space: nowrap; -} - -.rc-when { - color: var(--subtext-0); -} - -.rc-now { - color: rgb(var(--accent-rgb)); - font-weight: 700; -} - -.is-now { - background: rgba(var(--accent-rgb), 0.08); - border-radius: 12px; -} - -.rc-note { - color: var(--subtext-0); - font-size: 0.86rem; - padding: 0.6rem 0.4rem; - line-height: 1.5; -} - -.rc-note code { - background: var(--surface-0); - color: var(--text); - padding: 0.1rem 0.35rem; - border-radius: 6px; - font-size: 0.9em; -} - -/* ---- top artists ------------------------------------------------------- */ -.top-chips { - list-style: none; - margin: 0; - padding: 0; - display: flex; - flex-wrap: wrap; - gap: 0.5rem; -} - -.top-chip a { - display: inline-flex; - align-items: baseline; - gap: 0.45rem; - background: var(--mantle); - border: 1px solid var(--surface-0); - border-radius: 999px; - padding: 0.35rem 0.8rem; - text-decoration: none; - transition: border-color 0.15s ease; -} - -.top-chip a:hover { - border-color: rgb(var(--accent-rgb)); -} - -.top-rank { - color: rgb(var(--accent-rgb)); - font-weight: 700; - font-size: 0.78rem; -} - -.top-name { - color: var(--text); - font-size: 0.85rem; -} - -.top-plays { - color: var(--subtext-0); - font-size: 0.72rem; -} - -.music-back { - display: inline-block; - margin-top: 2.6rem; - font-size: 0.85rem; - color: rgb(var(--accent-rgb)); -} - -/* ---- responsive -------------------------------------------------------- */ -@media (max-width: 560px) { - .mdc { - grid-template-columns: 96px 1fr; - gap: 0.85rem; - padding: 0.9rem; - } - - .mdc-art { - width: 96px; - height: 96px; - } - - .mdc-title { - font-size: 1.1rem; - } - - .lyrics { - height: 300px; - } - - .ly-line { - font-size: 1.05rem; - } -} - -@media (prefers-reduced-motion: reduce) { - .mdc-fill { - transition: none; - } - - .ly-line { - transition: color 0.15s ease; - } -} - -/* ============================================================ - 15. VISITOR COUNTER (#visitor-counter) - Fixed to top-right, below .beta-bar (theme + cat buttons). - ============================================================ */ -#visitor-counter { - position: fixed; - top: 4rem; - /* clears the ~48px beta-bar + gap */ - right: 1rem; - z-index: 6; - display: flex; - flex-direction: column; - align-items: center; - gap: 4px; -} - -#visitor-counter .vc-label { - font-size: 0.65rem; - letter-spacing: 0.06em; - text-transform: lowercase; - color: var(--subtext-0); - font-family: 'Comic Code', ui-monospace, monospace; -} - -/* Boot reveal: fade in with the rest of the chrome */ -#visitor-counter { - transition: opacity 0.6s ease, transform 0.6s ease; -} - -body.term-booting #visitor-counter { - opacity: 0; - transform: translateY(8px); -} - -body.term-chrome-in #visitor-counter { - opacity: 1; - transform: none; -} - -/* Mobile: static in topbar flow */ -@media (max-width: 640px) { - #visitor-counter { - position: static; - margin: 0 auto; - } - - .topbar #visitor-counter { - order: 2; - } -} - - -/* ============================================================ - 16. PRESENCE CARD + /discord + /api EMBED (merged from player.css) - ============================================================ */ -html[data-theme="mocha"] { - color-scheme: dark; - --rosewater: #f5e0dc; - --flamingo: #f2cdcd; - --pink: #f5c2e7; - --accent-rgb: 245, 194, 231; - --mauve: #cba6f7; - --red: #f38ba8; - --maroon: #eba0ac; - --peach: #fab387; - --yellow: #f9e2af; - --green: #a6e3a1; - --teal: #94e2d5; - --sky: #89dceb; - --saphire: #74c7ec; - --blue: #89b4fa; - --lavender: #b4befe; - --text: #cdd6f4; - --subtext-0: #a6adc8; - --subtext-1: #bac2de; - --overlay-0: #6c7086; - --overlay-1: #7f849c; - --overlay-2: #9399b2; - --surface-0: #313244; - --surface-1: #45475a; - --surface-2: #585b70; - --base: #1e1e2e; - --mantle: #181825; - --crust: #11111b; -} - -html[data-theme="macchiato"] { - color-scheme: dark; - --rosewater: #f4dbd6; - --flamingo: #f0c6c6; - --pink: #f5bde6; - --accent-rgb: 245, 189, 230; - --mauve: #c6a0f6; - --red: #ed8796; - --maroon: #ee99a0; - --peach: #f5a97f; - --yellow: #eed49f; - --green: #a6da95; - --teal: #8bd5ca; - --sky: #91d7e3; - --saphire: #7dc4e4; - --blue: #8aadf4; - --lavender: #b7bdf8; - --text: #cad3f5; - --subtext-0: #a5adcb; - --subtext-1: #b8c0e0; - --overlay-0: #6e738d; - --overlay-1: #8087a2; - --overlay-2: #939ab7; - --surface-0: #363a4f; - --surface-1: #494d64; - --surface-2: #5b6078; - --base: #24273a; - --mantle: #1e2030; - --crust: #181926; -} - -html[data-theme="frappe"] { - color-scheme: dark; - --rosewater: #f2d5cf; - --flamingo: #eebebe; - --pink: #f4b8e4; - --accent-rgb: 244, 184, 228; - --mauve: #ca9ee6; - --red: #e78284; - --maroon: #ea999c; - --peach: #ef9f76; - --yellow: #e5c890; - --green: #a6d189; - --teal: #81c8be; - --sky: #99d1db; - --saphire: #85c1dc; - --blue: #8caaee; - --lavender: #babbf1; - --text: #c6d0f5; - --subtext-0: #a5adce; - --subtext-1: #b5bfe2; - --overlay-0: #737994; - --overlay-1: #838ba7; - --overlay-2: #949cbb; - --surface-0: #414559; - --surface-1: #51576d; - --surface-2: #626880; - --base: #303446; - --mantle: #292c3c; - --crust: #232634; -} - -html[data-theme="latte"] { - color-scheme: light; - --rosewater: #dc8a78; - --flamingo: #dd7878; - --pink: #ea76cb; - --accent-rgb: 234, 118, 203; - --mauve: #8839ef; - --red: #d20f39; - --maroon: #e64553; - --peach: #fe640b; - --yellow: #df8e1d; - --green: #40a02b; - --teal: #179299; - --sky: #04a5e5; - --saphire: #209fb5; - --blue: #1e66f5; - --lavender: #7287fd; - --text: #4c4f69; - --subtext-0: #6c6f85; - --subtext-1: #5c5f77; - --overlay-0: #9ca0b0; - --overlay-1: #8c8fa1; - --overlay-2: #7c7f93; - --surface-0: #ccd0da; - --surface-1: #bcc0cc; - --surface-2: #acb0be; - --base: #eff1f5; - --mantle: #e6e9ef; - --crust: #dce0e8; -} - - -/* ===================================================================== - * 2. STANDALONE PAGE STAGE - * Only the dedicated /api pages use .api-stage; it centers a single - * card on a Catppuccin gradient. The homepage never sets data-theme - * or .api-stage, so its fixed top-left card is untouched. - * ===================================================================== */ -html[data-theme] body.api-body { - margin: 0; - min-height: 100vh; - font-family: 'Comic Code', ui-monospace, system-ui, sans-serif; - color: var(--text); - background: linear-gradient(135deg, var(--base) 0%, var(--mantle) 60%, var(--crust) 100%); -} - -.api-stage { - min-height: 100vh; - display: flex; - align-items: center; - justify-content: center; - padding: 1.5rem; -} - -/* On the stage, the card sits in flow & centered instead of fixed. */ -.api-stage .presence-card { - position: static; - margin: 0; - max-width: 320px; - width: 100%; -} - -.api-empty { - text-align: center; - color: var(--subtext-0); - font-size: 0.9rem; - max-width: 420px; - line-height: 1.5; -} - -.api-empty a { - color: rgb(var(--accent-rgb)); -} - - -/* ===================================================================== - * 3. PRESENCE CARD (unified Discord-style profile pill) - * Lifted verbatim from main.css §13 so the card is self-contained. - * ===================================================================== */ -.presence-card { - --dc-accent: 245, 194, 231; - position: fixed; - top: 1rem; - left: 1rem; - z-index: 6; - width: max-content; - max-width: 280px; - background: var(--surface-0); - border: 1px solid var(--surface-1); - border-radius: 16px; - box-shadow: 0 8px 26px -12px rgba(17, 17, 27, 0.7); - overflow: hidden; - transition: border-color 0.2s ease, box-shadow 0.2s ease; -} - -.presence-card[hidden] { - display: none; -} - -.presence-card.has-accent { - border-color: rgba(var(--dc-accent), 0.5); - box-shadow: 0 8px 26px -12px rgba(var(--dc-accent), 0.6); -} - -/* ---- header (always visible) ---- */ -.pc-head { - display: flex; - align-items: center; - gap: 0.6rem; - padding: 0.5rem 0.7rem; -} - -.pc-avatar { - position: relative; - width: 40px; - height: 40px; - flex-shrink: 0; -} - -.pc-av-img { - width: 40px; - height: 40px; - border-radius: 50%; - object-fit: cover; - display: block; - /* solid fill behind the avatar — many PFPs (incl. Clove's) are partly - transparent, and Discord shows a solid backdrop rather than the banner. */ - background: var(--crust); -} - -/* avatar decoration / frame overlay (Discord cosmetic) */ -.pc-av-deco { - position: absolute; - top: 50%; - left: 50%; - width: 54px; - height: 54px; - transform: translate(-50%, -50%); - pointer-events: none; -} - -.pc-av-deco[hidden] { - display: none; -} - -.pc-status { - position: absolute; - right: -1px; - bottom: -1px; - width: 12px; - height: 12px; - border-radius: 50%; - border: 2.5px solid var(--surface-0); - background: var(--overlay-0); -} - -.presence-card[data-status="online"] .pc-status { - background: var(--green); -} - -.presence-card[data-status="idle"] .pc-status { - background: var(--yellow); -} - -.presence-card[data-status="dnd"] .pc-status { - background: var(--red); -} - -.presence-card[data-status="offline"] .pc-status { - background: var(--overlay-0); -} - -.pc-id { - display: flex; - flex-direction: column; - gap: 0.05rem; - min-width: 0; -} - -.pc-name { - font-size: 0.92rem; - font-weight: 700; - color: rgb(var(--accent-rgb)); - white-space: nowrap; - overflow: hidden; - text-overflow: ellipsis; - transition: color 0.5s ease; -} - -.pc-user { - font-size: 0.7rem; - color: var(--subtext-0); - white-space: nowrap; -} - -.pc-user:empty { - display: none; -} - -/* status word (Online / Idle / Do Not Disturb / Offline) */ -.pc-status-text { - font-size: 0.7rem; - font-weight: 600; - white-space: nowrap; - color: var(--overlay-1); -} - -.pc-status-text:empty { - display: none; -} - -.pc-status-text::before { - content: ""; - display: inline-block; - width: 7px; - height: 7px; - border-radius: 50%; - margin-right: 0.3rem; - vertical-align: baseline; - background: var(--overlay-0); -} - -.presence-card[data-status="online"] .pc-status-text { - color: var(--green); -} - -.presence-card[data-status="online"] .pc-status-text::before { - background: var(--green); -} - -.presence-card[data-status="idle"] .pc-status-text { - color: var(--yellow); -} - -.presence-card[data-status="idle"] .pc-status-text::before { - background: var(--yellow); -} - -.presence-card[data-status="dnd"] .pc-status-text { - color: var(--red); -} - -.presence-card[data-status="dnd"] .pc-status-text::before { - background: var(--red); -} - -.presence-card[data-status="offline"] .pc-status-text { - color: var(--overlay-1); -} - -.presence-card[data-status="offline"] .pc-status-text::before { - background: var(--overlay-0); -} - -/* ---- expandable sections ---- */ -.pc-sections { - display: flex; - flex-direction: column; - gap: 0.4rem; - padding: 0 0.6rem 0.6rem; - transition: opacity 0.2s ease; -} - -.presence-card:not(.has-sections) .pc-sections { - display: none; -} - -.pc-row { - display: flex; - align-items: center; - gap: 0.55rem; - padding: 0.4rem 0.5rem; - border-radius: 10px; - background: var(--mantle); - border: 1px solid transparent; - color: var(--text); - text-decoration: none; - transition: border-color 0.15s ease, transform 0.15s ease; -} - -a.pc-row:hover, -.pc-row--stack:hover { - border-color: rgba(var(--dc-accent), 0.55); - transform: translateX(2px); -} - -.pc-row-text { - display: flex; - flex-direction: column; - gap: 0.04rem; - min-width: 0; -} - -.pc-row-kind { - font-size: 0.6rem; - text-transform: uppercase; - letter-spacing: 0.05em; - color: var(--subtext-0); -} - -.pc-row-title { - font-size: 0.8rem; - font-weight: 500; - white-space: nowrap; - overflow: hidden; - text-overflow: ellipsis; - max-width: 200px; -} - -.pc-row-sub { - font-size: 0.7rem; - color: var(--subtext-0); - white-space: nowrap; - overflow: hidden; - text-overflow: ellipsis; - max-width: 200px; -} - -.pc-row-title:empty, -.pc-row-sub:empty { - display: none; -} - -.pc-row-elapsed { - font-size: 0.62rem; - color: var(--subtext-0); - margin-top: 0.1rem; -} - -.pc-row-elapsed:empty { - display: none; -} - -/* artwork / icons */ -.pc-art, -.pc-row-ic-img { - width: 38px; - height: 38px; - border-radius: 7px; - object-fit: cover; - flex-shrink: 0; -} - -.pc-row-ic.pc-dot { - width: 9px; - height: 9px; - border-radius: 50%; - flex-shrink: 0; - margin: 0 0.5rem; - background: rgb(var(--accent-rgb)); -} - -.pc-dev .pc-row-ic.pc-dot { - background: var(--blue); - border-radius: 2px; -} - -.pc-game .pc-row-ic.pc-dot { - background: var(--green); -} - -.pc-stream .pc-row-ic.pc-dot { - background: var(--mauve); -} - -/* custom status */ -.pc-custom { - position: relative; - align-self: flex-start; - background: var(--surface-1); - border: none; - padding: 0.5rem 0.7rem; - gap: 0.4rem; - align-items: flex-start; - border-radius: 13px; - border-top-left-radius: 4px; - margin-top: 0.3rem; -} - -/* Discord-style thought-bubble tail */ -.pc-custom::before, -.pc-custom::after { - content: ""; - position: absolute; - background: var(--surface-1); - border-radius: 50%; - pointer-events: none; -} - -.pc-custom::before { - width: 9px; - height: 9px; - top: -5px; - left: 12px; -} - -.pc-custom::after { - width: 5px; - height: 5px; - top: -11px; - left: 9px; -} - -.pc-custom:hover { - transform: none; - border-color: transparent; -} - -.pc-emoji { - width: 18px; - height: 18px; - flex-shrink: 0; - margin-top: 0.05rem; -} - -.pc-custom-text { - font-size: 0.74rem; - color: var(--subtext-0); - max-width: 230px; - white-space: normal; - overflow-wrap: anywhere; - line-height: 1.35; -} - -/* spotify progress */ -.pc-spotify .pc-row-title { - color: var(--green); -} - -.pc-progress { - display: flex; - flex-direction: column; - gap: 0.15rem; - margin-top: 0.25rem; - width: 180px; -} - -.pc-bar { - height: 4px; - border-radius: 999px; - background: var(--surface-1); - overflow: hidden; -} - -.pc-fill { - display: block; - height: 100%; - width: 0; - border-radius: 999px; - background: rgb(var(--dc-accent)); -} - -.pc-times { - display: flex; - justify-content: space-between; - font-size: 0.58rem; - color: var(--subtext-0); - font-variant-numeric: tabular-nums; -} - -@media (max-width: 640px) { - .presence-card { - max-width: calc(100vw - 2rem); - } - - .api-stage .presence-card { - max-width: 100%; - } -} - -/* ---- extended Lanyard fields ---- */ -.pc-name-row { - display: flex; - align-items: center; - gap: 0.35rem; - min-width: 0; -} - -.pc-name-row .pc-name { - min-width: 0; -} - -/* gradient display name (display_name_styles) */ -.pc-name.is-gradient { - -webkit-background-clip: text; - background-clip: text; - color: transparent; - -webkit-text-fill-color: transparent; -} - -/* server tag chip (primary_guild) */ -.pc-tag { - display: inline-flex; - align-items: center; - gap: 0.2rem; - flex-shrink: 0; - padding: 0.05rem 0.35rem; - border-radius: 6px; - background: var(--surface-2); - font-size: 0.58rem; - font-weight: 700; - letter-spacing: 0.03em; - color: var(--text); -} - -.pc-tag[hidden] { - display: none; -} - -.pc-tag-badge { - width: 14px; - height: 14px; - display: block; -} - -/* username + active-platform indicators */ -.pc-sub-row { - display: flex; - align-items: center; - gap: 0.35rem; -} - -.pc-platforms { - display: inline-flex; - align-items: center; - gap: 0.2rem; - color: var(--subtext-0); -} - -.pc-plat { - width: 12px; - height: 12px; - display: inline-flex; -} - -.pc-plat svg { - width: 12px; - height: 12px; - display: block; -} - -/* KV meta line (location, etc.) */ -.pc-meta { - display: flex; - align-items: center; - gap: 0.25rem; - margin-top: 0.1rem; - font-size: 0.66rem; - color: var(--subtext-0); -} - -.pc-meta[hidden] { - display: none; -} - -.pc-pin { - font-size: 0.7rem; - line-height: 1; -} - -/* stacked rows (activity rows that carry buttons) */ -.pc-row--stack { - flex-direction: column; - align-items: stretch; - gap: 0.4rem; -} - -.pc-row-link { - display: flex; - align-items: center; - gap: 0.55rem; - min-width: 0; - color: var(--text); - text-decoration: none; -} - -/* activity icon with small corner badge (assets.small_image) */ -.pc-ic-wrap { - position: relative; - flex-shrink: 0; - width: 38px; - height: 38px; -} - -.pc-ic-wrap .pc-row-ic-img { - width: 38px; - height: 38px; -} - -.pc-ic-badge { - position: absolute; - right: -3px; - bottom: -3px; - width: 16px; - height: 16px; - border-radius: 50%; - border: 2px solid var(--mantle); - object-fit: cover; -} - -/* activity buttons (labels from presence) */ -.pc-buttons { - display: flex; - flex-wrap: wrap; - gap: 0.35rem; -} - -.pc-btn { - font-size: 0.66rem; - padding: 0.22rem 0.55rem; - border-radius: 6px; - background: var(--surface-1); - color: var(--text); - text-decoration: none; - border: 1px solid transparent; - transition: border-color 0.15s ease, background 0.15s ease; -} - -.pc-btn:hover { - border-color: rgb(var(--dc-accent)); - background: var(--surface-2); -} - -/* profile badges */ -.pc-badges { - display: inline-flex; - align-items: center; - gap: 0.2rem; - flex-wrap: wrap; - margin-top: 0.15rem; -} - -.pc-badges:empty { - display: none; -} - -.pc-badge { - width: 16px; - height: 16px; - display: block; -} - -.pc-badge-link { - display: inline-flex; - line-height: 0; -} - -/* wishlist star + panel */ -.pc-star { - margin-left: auto; - align-self: flex-start; - background: none; - border: none; - cursor: url('../assets/cursor/pointer_0.png'), pointer; - font-size: 0.95rem; - line-height: 1; - color: var(--subtext-0); - padding: 0.1rem 0.15rem; - transition: color 0.15s ease, transform 0.15s ease; -} - -.pc-star:hover { - color: rgb(var(--accent-rgb)); - transform: scale(1.12); -} - -.pc-star.on { - color: var(--yellow); -} - -.pc-wishlist { - display: none; -} - -.presence-card.show-wishlist .pc-wishlist { - display: block; - border-top: 1px solid var(--surface-1); - margin: 0 0.6rem; - padding: 0.6rem 0 0.7rem; -} - -.pc-wishlist-title { - font-size: 0.62rem; - text-transform: uppercase; - letter-spacing: 0.05em; - color: var(--subtext-0); - margin-bottom: 0.45rem; -} - -.pc-wl-item { - display: flex; - align-items: center; - gap: 0.45rem; - padding: 0.25rem 0.4rem; - border-radius: 8px; - text-decoration: none; - color: var(--text); -} - -a.pc-wl-item:hover { - background: var(--mantle); -} - -.pc-wl-ic { - width: 22px; - height: 22px; - border-radius: 5px; - object-fit: cover; -} - -.pc-wl-text { - display: flex; - flex-direction: column; - line-height: 1.2; - min-width: 0; -} - -.pc-wl-name { - font-size: 0.8rem; -} - -.pc-wl-type { - font-size: 0.6rem; - text-transform: uppercase; - letter-spacing: 0.04em; - color: var(--subtext-0); -} - -.pc-wl-price { - margin-left: auto; - padding-left: 0.5rem; - font-size: 0.72rem; - color: var(--subtext-1); - white-space: nowrap; -} - -.pc-wl-item.is-owned { - opacity: 0.5; -} - -.pc-wl-empty { - font-size: 0.78rem; - color: var(--subtext-0); - margin: 0; -} - -/* Discord profile gradient (Catppuccin is the fallback) */ -.presence-card.has-profile-grad { - background: linear-gradient(180deg, rgb(var(--pc-grad-1-rgb)) 0%, rgb(var(--pc-grad-2-rgb)) 100%); -} - -.presence-card.has-profile-grad:not(.has-accent) { - border-color: rgba(var(--pc-grad-1-rgb), 0.6); -} - -.presence-card.has-profile-grad .pc-row { - background: rgba(17, 17, 27, 0.55); -} - - -/* ===================================================================== - * 4. EXTRAS (banner, bio, connected accounts — used on the /discord page) - * ===================================================================== */ -.pc-banner { - display: block; - width: 100%; - height: 96px; - object-fit: cover; - margin: 0; -} - -.pc-banner[hidden] { - display: none; -} - -/* solid/accent banner fallback when there's no Nitro banner image */ -.presence-card.has-banner-color::before { - content: ""; - display: block; - height: 64px; - background: var(--pc-banner-color, var(--surface-1)); -} - -/* when a banner is present, lift the avatar up over it */ -.presence-card.has-banner .pc-head, -.presence-card.has-banner-color .pc-head { - margin-top: -22px; -} - -.presence-card.has-banner .pc-avatar, -.presence-card.has-banner-color .pc-avatar { - width: 56px; - height: 56px; -} - -.presence-card.has-banner .pc-av-img, -.presence-card.has-banner-color .pc-av-img { - width: 56px; - height: 56px; - border: 3px solid var(--surface-0); -} - -.presence-card.has-banner .pc-av-deco, -.presence-card.has-banner-color .pc-av-deco { - width: 72px; - height: 72px; -} - -.pc-bio { - margin: 0 0.7rem 0.5rem; - padding: 0.5rem 0.6rem; - border-radius: 10px; - background: var(--mantle); - font-size: 0.74rem; - line-height: 1.4; - color: var(--subtext-1); - white-space: pre-wrap; - overflow-wrap: anywhere; -} - -.pc-bio[hidden] { - display: none; -} - -.pc-connections { - display: flex; - flex-wrap: wrap; - gap: 0.35rem; - margin: 0 0.7rem 0.6rem; -} - -.pc-connections[hidden] { - display: none; -} - -.pc-conn { - display: inline-flex; - align-items: center; - gap: 0.3rem; - padding: 0.2rem 0.5rem; - border-radius: 999px; - background: var(--surface-1); - border: 1px solid transparent; - color: var(--text); - font-size: 0.66rem; - text-decoration: none; - transition: border-color 0.15s ease, background 0.15s ease; -} - -a.pc-conn:hover { - border-color: rgb(var(--accent-rgb)); - background: var(--surface-2); -} - -.pc-conn-type { - text-transform: uppercase; - letter-spacing: 0.04em; - font-size: 0.56rem; - color: var(--subtext-0); -} - -.pc-conn-check { - color: var(--green); - font-weight: 700; -} - - -/* ===================================================================== - * 5. /discord PAGE STAGE (centered, slightly wider card) - * ===================================================================== */ -html:has(.presence-stage), -body:has(.presence-stage) { - height: auto; - min-height: 100dvh; - overflow-y: auto; -} - -body:has(.presence-stage) { - padding: 0; -} - -.presence-stage { - min-height: 100dvh; - display: flex; - flex-direction: column; - align-items: center; - justify-content: center; - padding: 1.5rem; -} - -.presence-intro { - text-align: center; - margin: 0 0 1.25rem; -} - -.presence-intro h1 { - margin: 0; - font-size: 1.8rem; - color: rgb(var(--accent-rgb)); -} - -.presence-intro p { - margin: 0.3rem 0 0; - font-size: 0.9rem; - color: var(--subtext-0); -} - -/* pronouns chip (shown on the card sub-row) */ -.pc-pronouns { - padding: 0.05rem 0.4rem; - border-radius: 6px; - background: var(--surface-2); - font-size: 0.6rem; - font-weight: 600; - color: var(--subtext-1); - white-space: nowrap; -} - -.pc-pronouns[hidden] { - display: none; -} - - -/* ===================================================================== - * 6. /discord PAGE — big "fills the page" presence card - * ===================================================================== */ -.presence-stage .presence-card { - position: static; - margin: 0; - width: 100%; - max-width: 680px; - border-radius: 20px; -} - -/* tall Nitro banner */ -.presence-stage .pc-banner { - height: 220px; -} - -.presence-stage .presence-card.has-banner-color::before { - height: 150px; -} - -/* header — roomier, big overlapping avatar */ -.presence-stage .pc-head { - gap: 1rem; - padding: 0.9rem 1.4rem; - align-items: flex-end; -} - -/* keep the identity column bottom-aligned to the avatar's visible lower - half, whether or not a custom-status bubble is present */ -.presence-stage .presence-card.has-custom .pc-head { - align-items: flex-end; -} - -/* only the avatar pokes up into the banner; the name/identity block stays - in the solid area below it */ -.presence-stage .presence-card.has-banner .pc-head, -.presence-stage .presence-card.has-banner-color .pc-head { - margin-top: 0; -} - -.presence-stage .presence-card.has-banner .pc-avatar, -.presence-stage .presence-card.has-banner-color .pc-avatar { - margin-top: -60px; -} - -.presence-stage .pc-avatar, -.presence-stage .presence-card.has-banner .pc-avatar, -.presence-stage .presence-card.has-banner-color .pc-avatar { - width: 120px; - height: 120px; -} - -.presence-stage .pc-av-img, -.presence-stage .presence-card.has-banner .pc-av-img, -.presence-stage .presence-card.has-banner-color .pc-av-img { - width: 120px; - height: 120px; - /* solid dark plate + ring so the banner sits clearly BEHIND the avatar - (the PFP itself is partly transparent) */ - background: var(--crust); - border: 6px solid var(--crust); -} - -.presence-stage .pc-av-deco, -.presence-stage .presence-card.has-banner .pc-av-deco, -.presence-stage .presence-card.has-banner-color .pc-av-deco { - width: 152px; - height: 152px; -} - -.presence-stage .pc-status { - width: 24px; - height: 24px; - border-width: 5px; -} - -/* identity block — bigger type */ -.presence-stage .pc-name { - font-size: 1.5rem; -} - -.presence-stage .pc-user { - font-size: 0.9rem; -} - -.presence-stage .pc-badges { - margin-top: 0.3rem; -} - -.presence-stage .pc-badge { - width: 22px; - height: 22px; -} - -/* bio + connections — wider, padded to match */ -.presence-stage .pc-bio { - margin: 0 1.4rem 0.8rem; - padding: 0.7rem 0.9rem; - font-size: 0.88rem; -} - -.presence-stage .pc-connections { - margin: 0 1.4rem 0.9rem; - gap: 0.5rem; -} - -.presence-stage .pc-conn { - font-size: 0.74rem; - padding: 0.3rem 0.65rem; -} - -/* activity rows — larger artwork + text */ -.presence-stage .pc-sections { - gap: 0.6rem; - padding: 0 1.4rem 1.1rem; -} - -.presence-stage .pc-row { - padding: 0.7rem 0.8rem; - border-radius: 14px; -} - -.presence-stage .pc-art, -.presence-stage .pc-row-ic-img, -.presence-stage .pc-ic-wrap, -.presence-stage .pc-ic-wrap .pc-row-ic-img { - width: 56px; - height: 56px; -} - -.presence-stage .pc-row-title { - font-size: 0.95rem; - max-width: none; -} - -.presence-stage .pc-row-sub { - font-size: 0.82rem; - max-width: none; -} - -.presence-stage .pc-progress { - width: 100%; -} - -.presence-stage .pc-custom-text { - font-size: 0.86rem; - max-width: none; -} - -/* wishlist + star scale up a touch */ -.presence-stage .pc-star { - font-size: 1.2rem; -} - -@media (max-width: 720px) { - .presence-stage .presence-card { - max-width: 100%; - } -} - -@media (max-width: 480px) { - .presence-stage .pc-banner { - height: 150px; - } - - .presence-stage .pc-avatar, - .presence-stage .presence-card.has-banner .pc-avatar, - .presence-stage .presence-card.has-banner-color .pc-avatar { - width: 92px; - height: 92px; - } - - .presence-stage .pc-av-img, - .presence-stage .presence-card.has-banner .pc-av-img, - .presence-stage .presence-card.has-banner-color .pc-av-img { - width: 92px; - height: 92px; - } - - .presence-stage .presence-card.has-banner .pc-head, - .presence-stage .presence-card.has-banner-color .pc-head { - margin-top: 0; - } - - .presence-stage .presence-card.has-banner .pc-avatar, - .presence-stage .presence-card.has-banner-color .pc-avatar { - margin-top: -46px; - } - - .presence-stage .pc-name { - font-size: 1.25rem; - } -} - -/* ===================================================================== - * lanyard.cafe keyring (webring) — embed.js injects #lc-embed with all - * styles inline, so every override here needs !important. Re-themes the - * default cream/brown look to Catppuccin and the site font, keeping the - * widget floating in the bottom-left (which is otherwise empty chrome). - * ===================================================================== */ -#lc-embed { - font-family: 'Comic Code', 'Quicksand', system-ui, sans-serif !important; - left: 1rem !important; - bottom: 1rem !important; - z-index: 5 !important; -} - -#lc-embed>section { - margin-bottom: 0 !important; -} - -/* the card */ -#lc-embed>section>div { - background: var(--surface-0) !important; - border: 1px solid rgba(var(--accent-rgb), 0.45) !important; - border-radius: 14px !important; - box-shadow: 0 10px 26px -16px rgba(0, 0, 0, 0.7) !important; -} - -/* prev / random / next buttons */ -#lc-embed a { - background: var(--surface-1) !important; - border-radius: 10px !important; - font-weight: 600 !important; - transition: transform 0.12s ease, background 0.12s ease, color 0.12s ease !important; -} - -#lc-embed a:nth-child(1), -#lc-embed a:nth-child(3) { - color: rgb(var(--accent-rgb)) !important; -} - -#lc-embed a:nth-child(2) { - color: var(--lavender) !important; -} - -#lc-embed a:hover { - background: var(--surface-2) !important; - transform: translateY(-2px) !important; -} - -/* the "you are at " line */ -#lc-embed p { - color: var(--subtext-0) !important; -} - -#lc-embed p span { - color: rgb(var(--accent-rgb)) !important; -} - -/* On mobile the body is a single flex column and every other floating - widget (nav, badges, presence card) is reflowed into it. The keyring, - left fixed, floated over the nav pills when scrolled to the bottom — so - here we drop it into the column too, last and centered. */ -@media (max-width: 640px) { - #lc-embed { - position: static !important; - inset: auto !important; - order: 6 !important; - width: 100% !important; - margin: 0 !important; - z-index: auto !important; - display: flex !important; - justify-content: center !important; - } - - #lc-embed>section>div { - min-width: 0 !important; - } -} - -/* ===================================================================== - * fronting.js — "currently fronting" box (sits below the terminal) - * ===================================================================== */ -.fronting-card { - position: relative; - z-index: 1; - width: 100%; - margin: 0.9rem auto 0; - padding: 0.85rem 1rem; - background: var(--mantle); - border: 1px solid var(--surface-1); - border-radius: 14px; - box-shadow: 0 18px 50px -22px rgba(0, 0, 0, 0.6); -} - -.fronting-card[hidden] { - display: none; -} - -.fr-head { - display: flex; - align-items: center; - gap: 0.45rem; - margin-bottom: 0.7rem; - font-size: 0.72rem; - font-weight: 600; - letter-spacing: 0.06em; - text-transform: uppercase; - color: var(--subtext-0); -} - -.fr-dot { - width: 8px; - height: 8px; - border-radius: 50%; - background: var(--green); - box-shadow: 0 0 0 0 rgba(166, 227, 161, 0.55); - animation: fr-pulse 2.4s ease-out infinite; -} - -@keyframes fr-pulse { - 0% { - box-shadow: 0 0 0 0 rgba(166, 227, 161, 0.5); - } - - 70% { - box-shadow: 0 0 0 7px rgba(166, 227, 161, 0); - } - - 100% { - box-shadow: 0 0 0 0 rgba(166, 227, 161, 0); - } -} - -@media (prefers-reduced-motion: reduce) { - .fr-dot { - animation: none; - } -} - -.fr-members { - display: flex; - flex-wrap: wrap; - gap: 0.6rem; -} - -.fr-member { - --fr-accent: var(--pink); - display: flex; - align-items: center; - gap: 0.6rem; - flex: 1 1 auto; - min-width: 0; - padding: 0.5rem 0.75rem 0.5rem 0.5rem; - border-radius: 12px; - background: var(--surface-0); - border: 1px solid var(--surface-1); - border-left: 3px solid var(--fr-accent); - color: var(--text); -} - -.fr-av { - width: 38px; - height: 38px; - border-radius: 50%; - object-fit: cover; - flex: 0 0 auto; - border: 2px solid var(--fr-accent); - background: var(--crust); -} - -.fr-av--empty { - display: inline-block; -} - -.fr-meta { - display: flex; - flex-direction: column; - min-width: 0; - line-height: 1.25; -} - -.fr-name { - font-weight: 600; - color: var(--text); - white-space: nowrap; - overflow: hidden; - text-overflow: ellipsis; -} - -.fr-pronouns { - font-size: 0.74rem; - color: var(--subtext-0); -} - -.fr-empty { - font-size: 0.82rem; - color: var(--subtext-0); - font-style: italic; -} - - -/* ============================================================ - 14. Selfies page - ============================================================ */ - -/* Let the gallery scroll (the default layout locks the viewport). Keyed on - the wrapper class so it scrolls even before selfies.js injects the grid — - mirrors the .friends-wrap rule used by the cool-people page. */ -html:has(.selfies-wrap), -body:has(.selfies-wrap) { - height: auto; - min-height: 100dvh; - overflow-y: auto; -} - -body:has(.selfies-wrap) { - align-items: flex-start; -} - -body:has(.selfies-wrap) .hub { - max-width: 960px; -} - -body:has(.selfies-wrap) .hub-header { - position: relative; - z-index: 1; - margin-bottom: 2rem; -} - -.selfie-grid { - display: grid; - grid-template-columns: repeat(auto-fill, minmax(160px, 1fr)); - gap: 0.9rem; - width: 100%; - margin-bottom: 1.5rem; - padding-bottom: 4.5rem; -} - -.selfie-thumb { - margin: 0; - padding: 0; - border: 1px solid var(--surface-1); - border-radius: 14px; - overflow: hidden; - background: var(--surface-0); - aspect-ratio: 1 / 1; - display: block; - transition: transform 0.15s ease, border-color 0.15s ease, - box-shadow 0.15s ease; -} - -.selfie-thumb img { - width: 100%; - height: 100%; - object-fit: cover; - display: block; -} - -.selfie-thumb:hover, -.selfie-thumb:focus-visible { - transform: translateY(-3px); - border-color: rgb(var(--accent-rgb)); - box-shadow: 0 6px 20px rgba(var(--accent-rgb), 0.22); - outline: none; -} - -.selfie-empty { - grid-column: 1 / -1; - text-align: center; - color: var(--subtext-0); - font-style: italic; - padding: 3rem 1rem; -} - -/* ---- Lightbox ---- */ -.lightbox { - position: fixed; - inset: 0; - z-index: 9999; - display: flex; - align-items: center; - justify-content: center; - padding: 1.5rem; - background: color-mix(in srgb, var(--crust) 86%, transparent); - -webkit-backdrop-filter: blur(6px); - backdrop-filter: blur(6px); -} - -.lightbox[hidden] { - display: none; -} - -.lightbox.is-open { - animation: lightbox-fade 0.18s ease; -} - -@keyframes lightbox-fade { - from { - opacity: 0; - } - - to { - opacity: 1; - } -} - -.lightbox-img { - max-width: min(92vw, 1100px); - max-height: 86vh; - object-fit: contain; - border-radius: 12px; - border: 2px solid rgba(var(--accent-rgb), 0.55); - box-shadow: 0 12px 40px rgba(0, 0, 0, 0.5); -} - -.lightbox-close, -.lightbox-nav { - position: fixed; - display: flex; - align-items: center; - justify-content: center; - border: 1px solid var(--surface-1); - background: color-mix(in srgb, var(--surface-0) 85%, transparent); - color: var(--text); - border-radius: 999px; - line-height: 1; - transition: background 0.15s ease, border-color 0.15s ease, - transform 0.15s ease; -} - -.lightbox-close:hover, -.lightbox-nav:hover, -.lightbox-close:focus-visible, -.lightbox-nav:focus-visible { - background: var(--surface-1); - border-color: rgb(var(--accent-rgb)); - outline: none; -} - -.lightbox-close { - top: 1rem; - right: 1rem; - width: 2.6rem; - height: 2.6rem; - font-size: 1.8rem; -} - -.lightbox-nav { - top: 50%; - transform: translateY(-50%); - width: 3rem; - height: 3rem; - font-size: 2rem; -} - -.lightbox-nav:hover { - transform: translateY(-50%) scale(1.06); -} - -.lightbox-prev { - left: 1rem; -} - -.lightbox-next { - right: 1rem; -} - -.lightbox-nav[hidden] { - display: none; -} - -/* Freeze the page behind the lightbox while it's open */ -body.lightbox-open { - overflow: hidden; -} - -@media (prefers-reduced-motion: reduce) { - - .selfie-thumb, - .lightbox-close, - .lightbox-nav { - transition: none; - } - - .lightbox.is-open { - animation: none; - } - - .lightbox-nav:hover { - transform: translateY(-50%); - } -} - -@media (max-width: 560px) { - .selfie-grid { - grid-template-columns: repeat(auto-fill, minmax(110px, 1fr)); - gap: 0.6rem; - } - - .lightbox-nav { - width: 2.6rem; - height: 2.6rem; - font-size: 1.6rem; - } -} - -/* ---- Captions (thumbnails + lightbox) ---- */ -.selfie-item { - margin: 0; - display: flex; - flex-direction: column; - gap: 0.45rem; -} - -.selfie-caption { - text-align: center; - font-size: 0.8rem; - line-height: 1.35; - color: var(--subtext-0); - overflow-wrap: anywhere; -} - -.lightbox-figure { - margin: 0; - display: flex; - flex-direction: column; - align-items: center; - gap: 0.8rem; - max-width: min(92vw, 1100px); -} - -/* leave room beneath the image for the caption line */ -.lightbox-img { - max-height: 80vh; -} - -.lightbox-caption { - margin: 0; - text-align: center; - color: var(--text); - font-size: 0.95rem; - line-height: 1.4; - max-width: min(92vw, 1100px); - overflow-wrap: anywhere; -} - -.lightbox-caption[hidden] { - display: none; -} - - -/* ============================================================ - 15. Cool-people friend cards — mini presence cards - Each friend is a full presence card (built by discord.js's - PresenceCard factory) but smaller than the big /discord one. - The BASE .presence-card is already compact (≈280px); we just - un-fix it from the corner so the cards tile in .friend-grid, - and re-add the tier hearts / dead-alt treatment on pc-* markup. - ============================================================ */ -.presence-card.is-mini { - position: static; - top: auto; - left: auto; - right: auto; - bottom: auto; - z-index: auto; - margin: 0; - width: 300px; - /* clearly smaller than the 680px /discord card */ - max-width: 100%; -} - -/* keep things tidy at the small size */ -.presence-card.is-mini .pc-banner { - height: 84px; -} - -.presence-card.is-mini .pc-bio { - max-height: 6.5em; - overflow-y: auto; -} - -/* the friend name can open a personal site */ -.presence-card.is-mini .pc-name--link { - text-decoration: none; -} - -.presence-card.is-mini .pc-name--link:hover { - text-decoration: underline; -} - -/* ---- tier hearts (ported from the old .fc-name prefixes) ---- */ -.presence-card.is-mini .pc-name::before { - content: "🩵 "; -} - -.presence-card.is-mini.tier-known .pc-name::before { - content: "💛 "; -} - -.presence-card.is-mini.tier-wife .pc-name::before { - content: "🖤 "; -} - -.presence-card.is-mini.tier-close .pc-name::before { - content: "🤍 "; -} - -.presence-card.is-mini.tier-active-alt .pc-name::before { - content: "🎭 "; -} - -.presence-card.is-mini.tier-dead-alt .pc-name::before { - content: "💀 "; -} - -/* gradient names clip text to transparent — keep the heart visible */ -.presence-card.is-mini .pc-name.is-gradient::before { - -webkit-text-fill-color: initial; - color: var(--text); -} - -/* ---- dead alts: greyed, struck through, no live status ---- */ -.presence-card.is-mini.tier-dead-alt .pc-av-img { - filter: grayscale(1) brightness(0.6); -} - -.presence-card.is-mini.tier-dead-alt .pc-name { - color: var(--overlay-1); - text-decoration: line-through; -} - -.presence-card.is-mini.tier-dead-alt .pc-status { - display: none; -} - - -/* ============================================================ - 16. Top artists — artist avatar in each chip (Deezer images) - ============================================================ */ -.top-chip a { - align-items: center; -} - -.top-art { - width: 34px; - height: 34px; - border-radius: 50%; - object-fit: cover; - flex: none; - display: inline-flex; - align-items: center; - justify-content: center; - background: var(--surface-0); - color: var(--subtext-0); - font-size: 0.95rem; - overflow: hidden; -} - -.top-text { - display: inline-flex; - flex-direction: column; - line-height: 1.2; - min-width: 0; -} - - -/* connection brand logos (replaces the old text type label) */ -.pc-conn-ic { - width: 14px; - height: 14px; - display: block; - flex: none; -} - -.presence-card.is-mini .pc-conn-ic { - width: 13px; - height: 13px; -} - -.friends-disclaimer { - margin: 2.5rem auto 0; - max-width: 60ch; - text-align: center; - font-size: .8rem; - line-height: 1.5; - opacity: .6; -} - -.friends-disclaimer a { - color: inherit; - text-decoration: underline; -} - -.obsessions { - display: grid; - grid-template-columns: repeat(auto-fit, minmax(280px, 1fr)); - gap: 1rem; - margin-bottom: 2rem; -} - -.obsession-embed { - width: 100%; - border: none; -} \ No newline at end of file +/* base */ +@import url(/css/base.css); + +/* shared chrome — used across most/all pages */ +@import url(/css/shared/layout.css); +@import url(/css/shared/nav.css); +@import url(/css/shared/badges.css); +@import url(/css/shared/theme-switcher.css); +@import url(/css/shared/visitor-counter.css); +@import url(/css/shared/keyring.css); +@import url(/css/shared/presence-card.css); +@import url(/css/shared/responsive.css); + +/* standalone / error pages */ +@import url(/css/404.css); +@import url(/css/ascii.css); + +/* per-page styles */ +@import url(/css/pages/index.css); +@import url(/css/pages/88x31.css); +@import url(/css/pages/dev-info.css); +@import url(/css/pages/projects.css); +@import url(/css/pages/cool-people.css); +@import url(/css/pages/music.css); +@import url(/css/pages/selfies.css); diff --git a/css/pages/88x31.css b/css/pages/88x31.css new file mode 100644 index 0000000..299a3f3 --- /dev/null +++ b/css/pages/88x31.css @@ -0,0 +1,58 @@ +/* ============================================================ + 88x31.css — the /88x31 button wall page. + ============================================================ */ + +/* ---- 88x31 button wall (lives on the dedicated /88x31 page) ---- */ +.button-wall { + display: flex; + flex-wrap: wrap; + justify-content: center; + gap: 0.6rem; + margin: 0 auto; +} + +.button-wall a { + display: block; + line-height: 0; +} + +.button-wall img { + width: 132px; + height: 46px; + border: 1px solid var(--surface-1); + border-radius: 2px; + transition: transform 0.12s ease, border-color 0.12s ease; +} + +.button-wall a:hover img, +.button-wall img:hover { + transform: translateY(-2px); + border-color: rgb(var(--accent-rgb)); +} +/* ---- 88x31 page: scrolls like the other content pages ---- */ +html:has(.button-page), +body:has(.button-page) { + height: auto; + min-height: 100dvh; + overflow-y: auto; +} + +body:has(.button-page) { + align-items: flex-start; +} + +body:has(.button-page) .hub { + max-width: 560px; +} + +.button-page { + display: flex; + justify-content: center; + padding-bottom: 4.5rem; +} + +@media (max-width: 640px) { + .button-wall { + max-width: 100%; + } +} diff --git a/css/pages/cool-people.css b/css/pages/cool-people.css new file mode 100644 index 0000000..7119cf0 --- /dev/null +++ b/css/pages/cool-people.css @@ -0,0 +1,522 @@ +/* ============================================================ + cool-people.css — the /cool-people page. Friend cards are + built from the shared .presence-card (see shared/presence- + card.css) — this file only adds the .is-mini sizing + tier + heart variants used here. + ============================================================ */ + +/* ============================================================ + 13. Friends Page + ============================================================ */ + +body:has(.friend-grid) .hub-header { + position: relative; + z-index: 1; + margin-bottom: 2rem; +} + +.friend-grid { + display: flex; + flex-wrap: wrap; + /* flex-wrap centres EVERY row, including a partial last row (a lone card + sits centred rather than stuck to the left as it did with CSS grid) */ + justify-content: center; + align-items: flex-start; + margin-bottom: 1.5rem; + gap: 1.1rem; + width: 100%; +} + +/* allow the cool-people page to scroll even before friends.js injects the + .friend-grid elements that the :has() rule keys on */ +html:has(.friends-wrap), +body:has(.friends-wrap) { + height: auto; + min-height: 100dvh; + overflow-y: auto; +} + +body:has(.friends-wrap) { + align-items: flex-start; +} + +body:has(.friends-wrap) .hub { + max-width: 960px; +} + +#friends-root { + display: flex; + flex-direction: column; + gap: 2rem; + padding-bottom: 4.5rem; +} + +/* ---- Lanyard friend cards ---- */ +.friend-card { + position: relative; + display: flex; + flex-direction: column; + width: 210px; + border-radius: 14px; + background: var(--surface-0); + border: 1px solid var(--surface-1); + overflow: hidden; + transition: transform 0.15s ease, border-color 0.15s ease, box-shadow 0.15s ease; +} + +.friend-card:hover { + transform: translateY(-3px); + border-color: rgb(var(--accent-rgb)); + box-shadow: 0 8px 22px -12px rgba(var(--accent-rgb), 0.5); +} + +/* Nitro profile gradient — recolours the card body (mirrors the /discord card) */ +.friend-card.has-profile-grad { + background: linear-gradient(180deg, rgb(var(--fc-grad-1-rgb)) 0%, rgb(var(--fc-grad-2-rgb)) 100%); + border-color: rgba(var(--fc-grad-1-rgb), 0.6); +} + +/* Hovered card lifts above its neighbours and lets its text un-truncate so + long names / usernames / custom statuses expand in full instead of being + chopped off with an ellipsis. The body becomes an absolutely-positioned + overlay, so the card grows DOWNWARD without resizing its grid slot — + neighbouring cards stay exactly where they are. */ +/* Expansion is gated on .is-hovering (added by JS) rather than :hover so the + card's flow height can be pinned BEFORE .fc-main is taken out of flow — + otherwise the card collapses, the page reflows, and hover ping-pongs + (the "vibrating page" bug). */ +.friend-card.is-hovering { + overflow: visible; + z-index: 5; +} + +.friend-card.is-hovering .fc-main { + position: absolute; + left: 0; + right: 0; + top: 54px; + /* sit directly under the banner strip */ + background: inherit; + /* carry the card surface / Nitro gradient */ + border-bottom-left-radius: 14px; + border-bottom-right-radius: 14px; + box-shadow: 0 10px 24px -14px rgba(17, 17, 27, 0.8); +} + +.friend-card.is-hovering .fc-name, +.friend-card.is-hovering .fc-user, +.friend-card.is-hovering .fc-custom-text { + white-space: normal; + overflow: visible; + text-overflow: clip; + overflow-wrap: anywhere; + /* break long unbroken usernames / handles */ +} + +/* banner strip — Nitro banner image / accent colour / default wash */ +.fc-banner { + height: 54px; + background: + linear-gradient(135deg, rgba(var(--accent-rgb), 0.45), rgba(var(--accent-rgb), 0.12)); + background-size: cover; + background-position: center; + /* keep the banner corners rounded even on hover, when the card switches + to overflow:visible and no longer clips them to the card radius */ + border-top-left-radius: 14px; + border-top-right-radius: 14px; +} + +.friend-card.has-banner .fc-banner { + background-size: cover; + background-position: center; +} + +.fc-main { + display: flex; + align-items: flex-start; + gap: 0.7rem; + padding: 0.6rem 0.85rem 0.85rem; +} + +.fc-avatar { + position: relative; + flex-shrink: 0; + width: 56px; + height: 56px; + margin-top: -30px; +} + +.fc-pfp { + width: 56px; + height: 56px; + border-radius: 50%; + object-fit: cover; + border: 3px solid var(--surface-0); + background: var(--surface-0); + display: block; +} + +/* avatar decoration / frame overlay (Discord cosmetic) */ +.fc-deco { + position: absolute; + top: 50%; + left: 50%; + width: 76px; + height: 76px; + transform: translate(-50%, -50%); + pointer-events: none; +} + +.fc-deco[hidden] { + display: none; +} + +/* status dot — colour driven by data-status on the card */ +.fc-status { + position: absolute; + right: -1px; + bottom: -1px; + width: 15px; + height: 15px; + border-radius: 50%; + border: 3px solid var(--surface-0); + background: var(--blue); +} + +.friend-card[data-status="online"] .fc-status { + background: var(--green); +} + +.friend-card[data-status="idle"] .fc-status { + background: var(--yellow); +} + +.friend-card[data-status="dnd"] .fc-status { + background: var(--red); +} + +.friend-card[data-status="offline"] .fc-status { + background: var(--overlay-0); +} + +.friend-card[data-status="unconnected"] .fc-status { + background: var(--blue); +} + +.fc-id { + display: flex; + flex-direction: column; + gap: 0.15rem; + min-width: 0; + padding-top: 0.1rem; +} + +.fc-name-row { + display: flex; + flex-wrap: wrap; + align-items: center; + gap: 0.15rem 0.3rem; + min-width: 0; +} + +/* name claims the full first line (so a clan tag never truncates it); the + tag chip wraps onto its own line just beneath when there isn't room */ +.fc-name-row .fc-name { + flex: 1 1 100%; + min-width: 0; +} + +/* Discord server (clan) tag chip */ +.fc-tag { + display: inline-flex; + align-items: center; + gap: 0.15rem; + flex-shrink: 0; + padding: 0.05rem 0.3rem; + border-radius: 5px; + background: var(--surface-2); + font-size: 0.56rem; + font-weight: 700; + letter-spacing: 0.02em; + color: var(--text); +} + +.fc-tag[hidden] { + display: none; +} + +.fc-tag-badge { + width: 12px; + height: 12px; + display: block; +} + +.fc-name { + font-size: 0.95rem; + font-weight: 700; + color: var(--text); + text-decoration: none; + white-space: nowrap; + overflow: hidden; + text-overflow: ellipsis; +} + +a.fc-name:hover { + color: rgb(var(--accent-rgb)); +} + +/* Nitro display-name gradient (clipped to the text). Keep the tier heart in + ::before painted normally so it stays its solid colour. */ +.fc-name.is-gradient { + -webkit-background-clip: text; + background-clip: text; + color: transparent; + -webkit-text-fill-color: transparent; +} + +.fc-name.is-gradient::before { + -webkit-text-fill-color: initial; + color: var(--text); +} + +/* tier hearts (match the old friend-name prefixes) */ +.fc-name::before { + content: "🩵 "; +} + +.fc-name.known::before { + content: "💛 "; +} + +.fc-name.wife::before { + content: "🖤 "; +} + +.fc-name.close::before { + content: "🤍 "; +} + +.fc-user { + font-size: 0.72rem; + color: var(--subtext-0); + white-space: nowrap; + overflow: hidden; + text-overflow: ellipsis; +} + +.fc-user:empty { + display: none; +} + +/* custom status (Discord activity type 4) */ +.fc-custom { + position: relative; + align-self: flex-start; + display: inline-flex; + align-items: center; + gap: 0.3rem; + max-width: 100%; + font-size: 0.72rem; + color: var(--subtext-1); + margin-top: 0.45rem; + min-width: 0; + padding: 0.3rem 0.5rem; + background: var(--surface-1); + border-radius: 11px; + border-top-left-radius: 4px; +} + +/* Discord-style thought-bubble tail: two little circles rising to the name */ +.fc-custom::before, +.fc-custom::after { + content: ""; + position: absolute; + background: var(--surface-1); + border-radius: 50%; + pointer-events: none; +} + +.fc-custom::before { + width: 7px; + height: 7px; + top: -4px; + left: 9px; +} + +.fc-custom::after { + width: 4px; + height: 4px; + top: -8px; + left: 7px; +} + +.fc-custom[hidden] { + display: none; +} + +.fc-custom-emoji { + width: 14px; + height: 14px; + display: block; + flex: none; +} + +.fc-custom-emoji-uni { + font-size: 0.8rem; + line-height: 1; + flex: none; +} + +.fc-custom-text { + white-space: nowrap; + overflow: hidden; + text-overflow: ellipsis; +} + +.fc-badges { + display: inline-flex; + align-items: center; + flex-wrap: wrap; + gap: 0.2rem; + margin-top: 0.1rem; +} + +.fc-badges:empty { + display: none; +} + +.fc-badge { + width: 16px; + height: 16px; + display: block; +} + +.fc-badge-link { + display: inline-flex; + line-height: 0; +} + +/* ---- Alts (active + dead) ---- */ +.fc-name.active-alt::before { + content: "🎭 "; +} + +.fc-name.dead-alt::before { + content: "💀 "; +} + +/* dead alts: banned accounts — greyed out, name struck through, no status */ +.friend-card.tier-dead-alt .fc-pfp { + filter: grayscale(1) brightness(0.6); +} + +.friend-card.tier-dead-alt .fc-name { + color: var(--overlay-1); + text-decoration: line-through; +} + +.friend-card.tier-dead-alt .fc-status { + display: none; +} + +/* the "struck off" diagonal slash across the avatar */ +.friend-card.tier-dead-alt .fc-avatar::after { + content: ""; + position: absolute; + left: 50%; + top: 50%; + width: 132%; + height: 4px; + background: var(--red); + border-radius: 2px; + transform: translate(-50%, -50%) rotate(-45deg); + box-shadow: 0 0 0 2px var(--surface-0); + pointer-events: none; +} + +/* ============================================================ + 15. Cool-people friend cards — mini presence cards + Each friend is a full presence card (built by discord.js's + PresenceCard factory) but smaller than the big /discord one. + The BASE .presence-card is already compact (≈280px); we just + un-fix it from the corner so the cards tile in .friend-grid, + and re-add the tier hearts / dead-alt treatment on pc-* markup. + ============================================================ */ +.presence-card.is-mini { + position: static; + top: auto; + left: auto; + right: auto; + bottom: auto; + z-index: auto; + margin: 0; + width: 300px; + /* clearly smaller than the 680px /discord card */ + max-width: 100%; +} + +/* keep things tidy at the small size */ +.presence-card.is-mini .pc-banner { + height: 84px; +} + +.presence-card.is-mini .pc-bio { + max-height: 6.5em; + overflow-y: auto; +} + +/* the friend name can open a personal site */ +.presence-card.is-mini .pc-name--link { + text-decoration: none; +} + +.presence-card.is-mini .pc-name--link:hover { + text-decoration: underline; +} + +/* ---- tier hearts (ported from the old .fc-name prefixes) ---- */ +.presence-card.is-mini .pc-name::before { + content: "🩵 "; +} + +.presence-card.is-mini.tier-known .pc-name::before { + content: "💛 "; +} + +.presence-card.is-mini.tier-wife .pc-name::before { + content: "🖤 "; +} + +.presence-card.is-mini.tier-close .pc-name::before { + content: "🤍 "; +} + +.presence-card.is-mini.tier-active-alt .pc-name::before { + content: "🎭 "; +} + +.presence-card.is-mini.tier-dead-alt .pc-name::before { + content: "💀 "; +} + +/* gradient names clip text to transparent — keep the heart visible */ +.presence-card.is-mini .pc-name.is-gradient::before { + -webkit-text-fill-color: initial; + color: var(--text); +} + +/* ---- dead alts: greyed, struck through, no live status ---- */ +.presence-card.is-mini.tier-dead-alt .pc-av-img { + filter: grayscale(1) brightness(0.6); +} + +.presence-card.is-mini.tier-dead-alt .pc-name { + color: var(--overlay-1); + text-decoration: line-through; +} + +.presence-card.is-mini.tier-dead-alt .pc-status { + display: none; +} + + diff --git a/css/pages/dev-info.css b/css/pages/dev-info.css new file mode 100644 index 0000000..fdc2835 --- /dev/null +++ b/css/pages/dev-info.css @@ -0,0 +1,531 @@ +/* ============================================================ + dev-info.css — the /dev-info page: tech-stack icons, hardware + list, and the WakaTime stats cards. + ============================================================ */ + +/* ============================================================ + 8. dev-info PAGE + ============================================================ */ +/* Let only the dev-info page scroll; link hub stays locked */ +html:has(.dev-info), +body:has(.dev-info) { + height: auto; + min-height: 100dvh; + overflow-y: auto; +} + +body:has(.dev-info) { + align-items: flex-start; +} + +body:has(.dev-info) .hub { + max-width: 860px; +} + +.dev-info { + display: flex; + flex-wrap: wrap; + justify-content: center; + gap: 0.5rem; + margin: 0 auto; + padding-bottom: 4.5rem; +} + +/* Simple Icons rendered via CSS mask so colour is theme-driven. + Markup: */ +.tech-icon { + position: relative; + width: 30px; + height: 30px; + display: inline-block; + transition: transform 0.15s ease, filter 0.15s ease; +} + +/* The icon shape — masked so the label (::after) stays visible */ +.tech-icon::before { + content: ""; + position: absolute; + inset: 0; + background-color: currentColor; + -webkit-mask: var(--si) center / contain no-repeat; + mask: var(--si) center / contain no-repeat; +} + +.tech-icon:hover { + transform: translateY(-2px) scale(1.12); + filter: drop-shadow(0 4px 8px currentColor); +} + +/* Hover label — pulls text from aria-label, tinted to match the icon */ +.tech-icon::after { + content: attr(aria-label); + position: absolute; + bottom: calc(100% + 8px); + left: 50%; + transform: translateX(-50%) translateY(4px); + padding: 0.25rem 0.5rem; + border-radius: 6px; + background: var(--crust); + border: 1px solid currentColor; + color: var(--text); + font-size: 0.72rem; + line-height: 1; + white-space: nowrap; + pointer-events: none; + opacity: 0; + transition: opacity 0.15s ease, transform 0.15s ease; + z-index: 10; +} + +.tech-icon:hover::after { + opacity: 1; + transform: translateX(-50%) translateY(0); +} + +/* Catppuccin accent classes — pull from the active flavour's vars */ +.tech-icon.rosewater { + color: var(--rosewater); +} + +.tech-icon.pink { + color: var(--pink); +} + +.tech-icon.mauve { + color: var(--mauve); +} + +.tech-icon.red { + color: var(--red); +} + +.tech-icon.maroon { + color: var(--maroon); +} + +.tech-icon.peach { + color: var(--peach); +} + +.tech-icon.yellow { + color: var(--yellow); +} + +.tech-icon.green { + color: var(--green); +} + +.tech-icon.teal { + color: var(--teal); +} + +.tech-icon.sky { + color: var(--sky); +} + +.tech-icon.sapphire { + color: var(--saphire); +} + +.tech-icon.blue { + color: var(--blue); +} + +.tech-icon.lavender { + color: var(--lavender); +} + + +/* ============================================================ + 12. dev-info / Dev Info PAGE + ============================================================ */ +/* Let the coding-stats page scroll; link hub stays locked */ +html:has(.waka), +body:has(.waka) { + height: auto; + min-height: 100dvh; + overflow-y: auto; +} + +body:has(.waka) { + align-items: flex-start; +} + +.waka { + position: relative; + z-index: 1; + width: 100%; + max-width: 640px; + margin: 0 auto; + padding-bottom: 4.5rem; +} + +.waka .hub-header { + margin-bottom: 1.5rem; +} + +.waka-meta { + margin: 0.5rem 0 0; + font-size: 0.72rem; + letter-spacing: 0.03em; + color: var(--subtext-0); +} + +.waka-section { + background: var(--surface-0); + border: 1px solid var(--surface-1); + border-radius: 16px; + padding: 0.85rem 1.25rem 0.95rem; + margin-bottom: 0.7rem; +} + +.waka-section .section-title { + text-align: left; + font-size: 0.82rem; + margin-bottom: 1rem; +} + +/* ---- headline total + weekly chart ---- */ +.waka-total { + text-align: center; +} + +.waka-total-num { + font-size: 2.1rem; + font-weight: 700; + color: rgb(var(--accent-rgb)); + line-height: 1.1; +} + +.waka-total-sub { + font-size: 0.78rem; + text-transform: uppercase; + letter-spacing: 0.05em; + color: var(--subtext-0); + margin-bottom: 1.1rem; +} + +.waka-week { + display: flex; + align-items: flex-end; + justify-content: space-between; + gap: 0.5rem; + height: 120px; +} + +.waka-day { + flex: 1 1 0; + display: flex; + flex-direction: column; + align-items: center; + gap: 0.4rem; + height: 100%; +} + +.waka-day-track { + flex: 1; + width: 100%; + max-width: 34px; + display: flex; + align-items: flex-end; + background: var(--surface-1); + border-radius: 7px; + overflow: hidden; +} + +.waka-day-fill { + width: 100%; + min-height: 3px; + background: rgb(var(--accent-rgb)); + border-radius: 7px 7px 0 0; + transition: height 0.5s ease; +} + +.waka-day-label { + font-size: 0.66rem; + color: var(--subtext-0); +} + +/* ---- ranked horizontal bars (languages / projects / editors / os) ---- */ +.waka-bars { + display: flex; + flex-direction: column; + gap: 0.6rem; +} + +.waka-bar-row { + display: grid; + grid-template-columns: 7.5rem 1fr auto; + align-items: center; + gap: 0.7rem; +} + +.waka-bar-name { + font-size: 0.82rem; + color: var(--text); + white-space: nowrap; + overflow: hidden; + text-overflow: ellipsis; +} + +.waka-bar-track { + height: 9px; + background: var(--surface-1); + border-radius: 999px; + overflow: hidden; +} + +.waka-bar-fill { + display: block; + height: 100%; + width: 0; + background: rgb(var(--accent-rgb)); + border-radius: 999px; + transition: width 0.6s ease; +} + +.waka-bar-val { + font-size: 0.74rem; + color: var(--subtext-0); + white-space: nowrap; + font-variant-numeric: tabular-nums; +} + +/* ---- two-up grid for editors + OS on wider screens ---- */ +.waka-grid2 { + display: grid; + grid-template-columns: 1fr 1fr; + gap: 1.1rem; +} + +.waka-grid2 .waka-section { + margin-bottom: 0; +} + +@media (max-width: 560px) { + .waka-grid2 { + grid-template-columns: 1fr; + gap: 0; + } + + .waka-grid2 .waka-section { + margin-bottom: 1.1rem; + } + + .waka-bar-row { + grid-template-columns: 5.5rem 1fr auto; + } +} + +/* ---- empty / setup state ---- */ +.waka-empty { + font-size: 0.85rem; + color: var(--subtext-0); + line-height: 1.5; + margin: 0; +} + +.waka-setup { + background: var(--surface-0); + border: 1px solid var(--surface-1); + border-radius: 16px; + padding: 1.25rem 1.4rem 1.5rem; + text-align: left; +} + +.waka-steps { + margin: 0.9rem 0 1.2rem; + padding-left: 1.2rem; + display: flex; + flex-direction: column; + gap: 0.5rem; + font-size: 0.85rem; + line-height: 1.45; + color: var(--text); +} + +.waka-steps code { + background: var(--surface-1); + padding: 0.05rem 0.35rem; + border-radius: 6px; + font-size: 0.8rem; +} + +.waka-steps a, +.waka-empty a, +.waka-credit a { + color: rgb(var(--accent-rgb)); + text-decoration: none; +} + +.waka-steps a:hover, +.waka-empty a:hover, +.waka-credit a:hover { + text-decoration: underline; +} + +.waka-setup-btn { + display: inline-block; + padding: 0.45rem 1rem; + border-radius: 999px; + background: rgb(var(--accent-rgb)); + color: var(--crust); + font-size: 0.82rem; + font-weight: 600; + text-decoration: none; + transition: transform 0.15s ease, filter 0.15s ease; +} + +.waka-setup-btn:hover { + transform: translateY(-1px); + filter: brightness(1.05); +} + +.waka-credit { + text-align: center; + font-size: 0.72rem; + color: var(--subtext-0); + margin: 1.4rem 0 0; +} + +/* ---- collapsible dropdown sections (details/summary) ---- */ +details.waka-section { + /* keep the card padding tight when collapsed; expands via [open] below */ + padding-bottom: 0.85rem; + transition: padding-bottom 0.15s ease; +} + +details.waka-section[open] { + padding-bottom: 1.15rem; +} + +/* The clickable header row */ +summary.section-title { + display: flex; + align-items: center; + justify-content: space-between; + gap: 0.5rem; + cursor: url('../assets/cursor/pointer_0.png'), pointer; + list-style: none; + user-select: none; + margin-bottom: 0; + transition: margin-bottom 0.15s ease, color 0.15s ease; +} + +/* Hide the native disclosure triangle (both engines) */ +summary.section-title::-webkit-details-marker { + display: none; +} + +summary.section-title::marker { + content: ""; +} + +summary.section-title:hover { + color: rgb(var(--accent-rgb)); +} + +summary.section-title:focus-visible { + outline: 2px solid rgb(var(--accent-rgb)); + outline-offset: 3px; + border-radius: 6px; +} + +/* Custom chevron that flips when the section is open */ +summary.section-title::after { + content: ""; + flex: none; + width: 0.5rem; + height: 0.5rem; + margin-right: 0.15rem; + border-right: 2px solid currentColor; + border-bottom: 2px solid currentColor; + transform: rotate(45deg); + transition: transform 0.2s ease; +} + +details.waka-section[open]>summary.section-title { + margin-bottom: 0.75rem; +} + +details.waka-section[open]>summary.section-title::after { + transform: rotate(-135deg); +} + +/* Tech-stack icons sit inside a collapsible card now: drop the big + page-bottom padding the standalone .dev-info block used. */ +.tech-stack .dev-info { + padding-bottom: 0; + justify-content: flex-start; +} + +/* ---- about / setup + badges section ---- */ +.about-badges { + display: flex; + flex-wrap: wrap; + gap: 0.5rem; + margin-bottom: 1rem; +} + +/* The .badge chips are reused here in normal page flow (the fixed-position + .badges container is gone); make sure they stay interactive + visible. */ +.about-badges .badge { + pointer-events: auto; +} + +.about-list { + margin-top: 0.25rem; +} + +/* hidden pokéball now lives inside the dev-info Setup section */ +.about-setup #pokeball-secret { + display: block; + margin: 0.9rem auto 0; +} + +/* ---- hardware spec list ---- */ +.hw-item { + text-decoration: none; + color: var(--text); +} + +.hw-intro { + margin: 0 0 0.9rem; + font-size: 0.8rem; + color: var(--subtext-0); +} + +.hw-list { + display: flex; + flex-direction: column; + gap: 0.55rem; + margin: 0; +} + +.hw-row { + display: grid; + grid-template-columns: 8rem 1fr; + gap: 0.7rem; + align-items: baseline; +} + +.hw-row dt { + font-size: 0.72rem; + text-transform: uppercase; + letter-spacing: 0.05em; + color: var(--subtext-0); +} + +.hw-row dd { + margin: 0; + font-size: 0.88rem; + color: var(--text); +} + +@media (max-width: 560px) { + .hw-row { + grid-template-columns: 6rem 1fr; + } +} + + diff --git a/css/pages/index.css b/css/pages/index.css new file mode 100644 index 0000000..27bca08 --- /dev/null +++ b/css/pages/index.css @@ -0,0 +1,567 @@ +/* ============================================================ + index.css — homepage only: the link hub grid (legacy, if + still used anywhere), the terminal widget, and the "currently + fronting" card beneath it. + ============================================================ */ + +/* ============================================================ + 3. LINK HUB (index page) + ============================================================ */ +.links { + display: grid; + grid-template-columns: repeat(auto-fit, 72px); + gap: 0.9rem; + justify-content: center; +} + +.link-card { + position: relative; + display: flex; + align-items: center; + justify-content: center; + width: 72px; + height: 72px; + border-radius: 16px; + background: var(--surface-0); + border: 1px solid var(--surface-1); + color: var(--text); + text-decoration: none; + transition: transform 0.15s ease, border-color 0.15s ease, + background 0.15s ease, box-shadow 0.15s ease; +} + +.link-card:hover { + transform: translateY(-3px); + background: var(--surface-1); + border-color: rgb(var(--accent-rgb)); + box-shadow: 0 6px 20px rgba(var(--accent-rgb), 0.22); +} + +.icon { + width: 30px; + height: 30px; + flex-shrink: 0; + filter: brightness(0) invert(1); + transition: filter 0.15s ease; +} + +.link-card:hover .icon { + filter: none; +} + +/* Tooltip revealed on hover */ +.link-text { + position: absolute; + bottom: calc(100% + 10px); + left: 50%; + transform: translateX(-50%) translateY(4px); + display: flex; + flex-direction: column; + align-items: center; + gap: 0.1rem; + padding: 0.5rem 0.75rem; + border-radius: 10px; + background: var(--crust); + border: 1px solid rgb(var(--accent-rgb)); + box-shadow: 0 6px 18px rgba(17, 17, 27, 0.55); + white-space: nowrap; + line-height: 1.3; + opacity: 0; + pointer-events: none; + transition: opacity 0.15s ease, transform 0.15s ease; + z-index: 10; +} + +.link-text::after { + content: ""; + position: absolute; + top: 100%; + left: 50%; + transform: translateX(-50%); + border: 6px solid transparent; + border-top-color: rgb(var(--accent-rgb)); +} + +.link-card:hover .link-text, +.link-card:focus-visible .link-text { + opacity: 1; + transform: translateX(-50%) translateY(0); +} + +.link-title { + font-weight: 500; + font-size: 0.95rem; + color: var(--text); +} + +.link-sub { + font-size: 0.78rem; + color: var(--subtext-0); +} + + +/* ============================================================ + 14. TERMINAL HOMEPAGE (+ 88x31 button wall) + ============================================================ */ +.terminal { + position: relative; + z-index: 1; + width: min(92vw, 600px); + /* locked height — the box must not resize between boot and ready, or as + command output is appended (the inner .t-output scrolls instead) */ + height: min(62vh, 460px); + display: flex; + flex-direction: column; + padding: 1rem 1.15rem 1.15rem; + background: var(--mantle); + border: 1px solid var(--surface-1); + border-radius: 14px; + box-shadow: 0 18px 50px -20px rgba(0, 0, 0, 0.7); + font-family: 'Comic Code', ui-monospace, 'JetBrains Mono', Menlo, monospace; + font-size: 0.86rem; + line-height: 1.5; + color: var(--text); + overflow: hidden; + /* lets .t-banner size itself off the terminal's width (cqw), not the + viewport, so the ascii always fits regardless of the loaded font */ + container-type: inline-size; +} + +body:has(.terminal) .hub { + max-width: min(92vw, 600px); + width: 100%; +} + +body:has(.terminal) .hub .terminal { + width: 100%; + margin: 0 auto; +} + +/* ---- boot log ---- */ +.t-boot { + margin: 0; + white-space: pre-wrap; + word-break: break-word; + font-size: 0.78rem; + color: var(--subtext-0); + max-height: 72vh; + overflow: hidden; +} + +.t-boot[hidden] { + display: none; +} + +.b-line { + display: block; +} + +.b-time { + color: var(--overlay-0); +} + +.b-info { + color: var(--blue); + font-weight: 700; +} + +.b-ok { + color: var(--green); + font-weight: 700; +} + +/* ---- main terminal ---- */ +.t-main { + display: flex; + flex-direction: column; + flex: 1; + /* fill the fixed-height terminal so .t-output scrolls */ + min-height: 0; +} + +.t-main[hidden] { + display: none; +} + +.t-banner { + margin: 0 0 0.5rem; + color: rgb(var(--accent-rgb)); + /* scale to the terminal's width (1cqw = 1% of it) so the 42-char banner + always fits; capped so it never gets oversized on a wide terminal */ + font-size: min(0.78rem, 1.9cqw); + line-height: 1.04; + white-space: pre; + overflow: hidden; + text-shadow: 0 0 14px rgba(var(--accent-rgb), 0.35); +} + +.t-greet { + margin-bottom: 0.7rem; + color: var(--subtext-1); +} + +.t-greet b { + color: rgb(var(--accent-rgb)); +} + +.t-dim { + color: var(--subtext-0); +} + +.t-accent { + color: rgb(var(--accent-rgb)); +} + +.t-inputline { + display: flex; + align-items: center; + gap: 0.5rem; + padding-bottom: 0.55rem; + border-bottom: 1px solid var(--surface-0); +} + +.t-prompt { + color: var(--green); + white-space: nowrap; + font-weight: 700; +} + +.t-path { + color: var(--blue); + font-weight: 700; +} + +.t-input { + flex: 1; + min-width: 0; + background: transparent; + border: none; + outline: none; + color: var(--text); + font: inherit; + caret-color: rgb(var(--accent-rgb)); +} + +.t-output { + margin-top: 0.6rem; + min-height: 0; + flex: 1; + overflow-y: auto; + display: flex; + flex-direction: column; + gap: 0.6rem; +} + +.t-echo { + color: var(--subtext-0); +} + +.t-result { + white-space: pre-wrap; + word-break: break-word; + margin-top: 0.15rem; +} + +.t-entry.is-error .t-result { + color: var(--red); +} + +/* hyfetch trans-flag block */ +.hf-c1 { + color: #5bcefa; +} + +.hf-c2 { + color: #f5a9b8; +} + +.hf-c3 { + color: #ffffff; +} + +.hf-pad { + color: transparent; +} + + + +/* ---- terminal: socials list (svg icon + clickable link) ---- */ +.t-socials-hint { + margin-bottom: 0.4rem; +} + +.t-socials { + display: flex; + flex-direction: column; + gap: 0.1rem; +} + +.t-social { + display: grid; + grid-template-columns: 18px 6.5rem 6rem 1fr; + align-items: center; + gap: 0.55rem; + padding: 0.22rem 0.4rem; + border-radius: 6px; + text-decoration: none; + color: var(--text); + border: 1px solid transparent; +} + +.t-social:hover { + background: var(--surface-0); + border-color: rgba(var(--accent-rgb), 0.4); +} + +.t-social-ic { + width: 16px; + height: 16px; + object-fit: contain; +} + +.t-social-key { + color: rgb(var(--accent-rgb)); +} + +.t-social-label { + color: var(--text); +} + +.t-social-sub { + white-space: nowrap; + overflow: hidden; + text-overflow: ellipsis; +} + +/* the "Opening …" confirmation line */ +.t-social-open { + display: inline-flex; + align-items: center; + gap: 0.4rem; + grid-template-columns: none; + padding: 0; + border: none; +} + +.t-social-open:hover { + background: transparent; +} + + +/* ---- terminal: ls-style socials list + social card ---- */ +.t-ls { + display: grid; + grid-template-columns: repeat(auto-fill, minmax(7rem, 1fr)); + gap: 0.1rem 1.2rem; +} + +.t-ls-item { + color: rgb(var(--accent-rgb)); +} + +.t-ls-foot { + margin-top: 0.6rem; +} + +.t-ls-foot b { + color: var(--text); +} + +.t-social-card { + display: flex; + flex-direction: column; + gap: 0.35rem; +} + +.t-sc-head { + display: flex; + align-items: center; + gap: 0.45rem; +} + +.t-sc-head .t-social-ic { + width: 18px; + height: 18px; +} + +.t-sc-url { + color: var(--blue); + text-decoration: none; + word-break: break-all; +} + +.t-sc-url:hover { + text-decoration: underline; +} + +.t-sc-ask { + margin-top: 0.2rem; +} + +.t-sc-ask b { + color: var(--text); +} + +.t-social-open { + display: inline-flex; + align-items: center; + gap: 0.4rem; + color: var(--text); + text-decoration: none; +} + +.t-social-open .t-social-ic { + width: 16px; + height: 16px; +} + + +/* ---- hyfetch: arch logo + info, side by side ---- */ +.hf { + display: flex; + gap: 1.1rem; + align-items: flex-start; + flex-wrap: wrap; +} + +.hf-logo { + margin: 0; + white-space: pre; + line-height: 1.02; + font-size: 0.62rem; +} + +.hf-info { + margin: 0; + white-space: pre; +} + +/* ===================================================================== + * fronting.js — "currently fronting" box (sits below the terminal) + * ===================================================================== */ +.fronting-card { + position: relative; + z-index: 1; + width: 100%; + margin: 0.9rem auto 0; + padding: 0.85rem 1rem; + background: var(--mantle); + border: 1px solid var(--surface-1); + border-radius: 14px; + box-shadow: 0 18px 50px -22px rgba(0, 0, 0, 0.6); +} + +.fronting-card[hidden] { + display: none; +} + +.fr-head { + display: flex; + align-items: center; + gap: 0.45rem; + margin-bottom: 0.7rem; + font-size: 0.72rem; + font-weight: 600; + letter-spacing: 0.06em; + text-transform: uppercase; + color: var(--subtext-0); +} + +.fr-dot { + width: 8px; + height: 8px; + border-radius: 50%; + background: var(--green); + box-shadow: 0 0 0 0 rgba(166, 227, 161, 0.55); + animation: fr-pulse 2.4s ease-out infinite; +} + +@keyframes fr-pulse { + 0% { + box-shadow: 0 0 0 0 rgba(166, 227, 161, 0.5); + } + + 70% { + box-shadow: 0 0 0 7px rgba(166, 227, 161, 0); + } + + 100% { + box-shadow: 0 0 0 0 rgba(166, 227, 161, 0); + } +} + +@media (prefers-reduced-motion: reduce) { + .fr-dot { + animation: none; + } +} + +.fr-members { + display: flex; + flex-wrap: wrap; + gap: 0.6rem; +} + +.fr-member { + --fr-accent: var(--pink); + display: flex; + align-items: center; + gap: 0.6rem; + flex: 1 1 auto; + min-width: 0; + padding: 0.5rem 0.75rem 0.5rem 0.5rem; + border-radius: 12px; + background: var(--surface-0); + border: 1px solid var(--surface-1); + border-left: 3px solid var(--fr-accent); + color: var(--text); +} + +.fr-av { + width: 38px; + height: 38px; + border-radius: 50%; + object-fit: cover; + flex: 0 0 auto; + border: 2px solid var(--fr-accent); + background: var(--crust); +} + +.fr-av--empty { + display: inline-block; +} + +.fr-meta { + display: flex; + flex-direction: column; + min-width: 0; + line-height: 1.25; +} + +.fr-name { + font-weight: 600; + color: var(--text); + white-space: nowrap; + overflow: hidden; + text-overflow: ellipsis; +} + +.fr-pronouns { + font-size: 0.74rem; + color: var(--subtext-0); +} + +.fr-empty { + font-size: 0.82rem; + color: var(--subtext-0); + font-style: italic; +} + + + +@media (max-width: 640px) { + .terminal { + width: 94vw; + height: clamp(300px, 65dvh, 70vh); + } +} diff --git a/css/pages/music.css b/css/pages/music.css new file mode 100644 index 0000000..c9e1682 --- /dev/null +++ b/css/pages/music.css @@ -0,0 +1,611 @@ +/* ============================================================ + music.css — the /music page: now-playing hero, lyrics panel, recently played, and top artists. + ============================================================ */ + +/* ===================================================================== + * MUSIC PAGE (/music) — merged in from music.css. + * Hero classes are .mdc-* to avoid colliding with the .dc-* discord + * widget already defined above. Other classes (.lyrics, .rc-*, .sec-*, + * .top-*, .ly-*, .music-*) are unique to this page. + * ===================================================================== */ + +/* Let the music page scroll; the link hub stays locked (same pattern as + .dev-info above). Without this, html,body{overflow:hidden} + from the homepage layout traps the page. */ +html:has(.music-wrap), +body:has(.music-wrap) { + height: auto; + min-height: 100dvh; + overflow-y: auto; +} + +body:has(.music-wrap) { + align-items: flex-start; +} + +.music-wrap { + max-width: 880px; + margin: 0 auto; + padding: 2.6rem 1.25rem 5rem; + font-family: 'Comic Code', ui-monospace, monospace; +} + +.music-head { + margin: 0 0 1.6rem; +} + +.music-head h1 { + font-size: clamp(1.7rem, 5vw, 2.4rem); + margin: 0 0 0.2rem; + color: rgb(var(--accent-rgb)); + letter-spacing: -0.02em; + transition: color 0.5s ease; +} + +.music-head p { + margin: 0; + color: var(--subtext-0); + font-size: 0.95rem; +} + +/* ---- now playing hero -------------------------------------------------- */ +.mdc { + display: grid; + grid-template-columns: 132px 1fr; + gap: 1.1rem; + align-items: center; + background: var(--mantle); + border: 1px solid var(--surface-0); + border-radius: 18px; + padding: 1.1rem; + position: relative; + overflow: hidden; + text-decoration: none; +} + +/* a soft wash of the album accent behind the hero */ +.mdc::before { + content: ""; + position: absolute; + inset: 0; + background: radial-gradient(120% 140% at 0% 0%, + rgba(var(--accent-rgb), 0.18), transparent 60%); + opacity: 0; + transition: opacity 0.6s ease; + pointer-events: none; +} + +#music.is-live .mdc::before { + opacity: 1; +} + +.mdc-art { + width: 132px; + height: 132px; + border-radius: 12px; + object-fit: cover; + background: var(--surface-0); + box-shadow: 0 8px 24px rgba(0, 0, 0, 0.35); +} + +.mdc-art:not(.has-art) { + display: grid; +} + +.mdc-art:not(.has-art)::after { + content: "♪"; + color: var(--overlay-0); + font-size: 2.4rem; + display: grid; + place-items: center; + height: 100%; +} + +.mdc-meta { + min-width: 0; + position: relative; +} + +.mdc-state { + display: inline-flex; + align-items: center; + gap: 0.4rem; + font-size: 0.7rem; + text-transform: uppercase; + letter-spacing: 0.08em; + color: var(--subtext-0); + margin-bottom: 0.35rem; +} + +#music.is-live .mdc-state { + color: rgb(var(--accent-rgb)); +} + +.mdc-title { + display: block; + font-size: 1.3rem; + font-weight: 700; + color: var(--text); + margin: 0 0 0.15rem; + line-height: 1.2; + white-space: nowrap; + overflow: hidden; + text-overflow: ellipsis; +} + +.mdc-title:hover { + color: rgb(var(--accent-rgb)); +} + +.mdc-artist { + display: block; + color: var(--subtext-1); + font-size: 0.95rem; +} + +.mdc-album { + display: block; + color: var(--subtext-0); + font-size: 0.82rem; + margin-top: 0.1rem; +} + +.mdc-progress { + margin-top: 0.8rem; + display: flex; + align-items: center; + gap: 0.6rem; +} + +.mdc-bar { + flex: 1; + height: 6px; + border-radius: 999px; + background: var(--surface-0); + overflow: hidden; +} + +.mdc-fill { + display: block; + height: 100%; + width: 0%; + background: rgb(var(--accent-rgb)); + border-radius: 999px; + transition: width 0.4s linear; +} + +.mdc-time { + font-size: 0.72rem; + color: var(--subtext-0); + font-variant-numeric: tabular-nums; +} + +/* ---- lyrics (the centrepiece) ------------------------------------------ */ +.sec-title { + font-size: 0.78rem; + text-transform: uppercase; + letter-spacing: 0.07em; + color: var(--subtext-0); + margin: 2.4rem 0 0.7rem; + font-weight: 500; +} + +.sec-row { + display: flex; + align-items: baseline; + justify-content: space-between; + gap: 0.8rem; + margin: 2.4rem 0 0.7rem; +} + +.sec-row .sec-title { + margin: 0; +} + +.ly-lock { + font-family: inherit; + font-size: 0.72rem; + letter-spacing: 0.04em; + cursor: url('../assets/cursor/pointer_0.png'), pointer; + border-radius: 999px; + padding: 0.28rem 0.8rem 0.28rem 0.7rem; + background: var(--surface-0); + color: var(--subtext-1); + border: 1px solid transparent; + display: inline-flex; + align-items: center; + gap: 0.4rem; + transition: color 0.15s ease, border-color 0.15s ease, background 0.15s ease; +} + +/* Spotify-style equalizer bars (replaces the old status dot) */ +.ly-bars { + display: inline-flex; + align-items: flex-end; + gap: 2px; + width: 13px; + height: 11px; + flex-shrink: 0; +} + +.ly-bars i { + flex: 1; + height: 100%; + border-radius: 1px; + background: currentColor; + transform-origin: bottom; + transform: scaleY(0.4); + opacity: 0.55; +} + +.ly-lock.is-locked { + color: rgb(var(--accent-rgb)); + border-color: rgba(var(--accent-rgb), 0.4); + background: rgba(var(--accent-rgb), 0.1); +} + +.ly-lock.is-locked .ly-bars i { + opacity: 1; + animation: ly-eq 0.9s ease-in-out infinite; +} + +.ly-lock.is-locked .ly-bars i:nth-child(2) { + animation-delay: 0.15s; +} + +.ly-lock.is-locked .ly-bars i:nth-child(3) { + animation-delay: 0.3s; +} + +.ly-lock.is-locked .ly-bars i:nth-child(4) { + animation-delay: 0.45s; +} + +@keyframes ly-eq { + + 0%, + 100% { + transform: scaleY(0.3); + } + + 50% { + transform: scaleY(1); + } +} + +@media (prefers-reduced-motion: reduce) { + .ly-lock.is-locked .ly-bars i { + animation: none; + transform: scaleY(0.65); + } +} + +.ly-lock:not(.is-locked):hover { + color: var(--text); + border-color: var(--surface-1); +} + +.lyrics { + position: relative; + /* anchor offsetTop for the follow scroll */ + height: 340px; + overflow-y: auto; + scroll-behavior: smooth; + overscroll-behavior: contain; + border-radius: 16px; + background: var(--crust); + border: 1px solid var(--surface-0); + padding: 1.4rem 1.4rem; + scrollbar-width: thin; + scrollbar-color: var(--surface-1) transparent; + /* fade the top + bottom so lines drift in and out */ + -webkit-mask-image: linear-gradient(180deg, transparent, #000 14%, #000 86%, transparent); + mask-image: linear-gradient(180deg, transparent, #000 14%, #000 86%, transparent); +} + +.lyrics::-webkit-scrollbar { + width: 8px; +} + +.lyrics::-webkit-scrollbar-thumb { + background: var(--surface-1); + border-radius: 999px; +} + +.ly-line { + margin: 0; + padding: 0.32rem 0; + font-size: 1.18rem; + line-height: 1.4; + color: var(--overlay-0); + transition: color 0.3s ease, opacity 0.3s ease, transform 0.3s ease; +} + +.is-synced .ly-line { + opacity: 0.55; +} + +.is-synced .ly-line.is-active { + color: rgb(var(--accent-rgb)); + opacity: 1; + font-weight: 700; + transform: translateX(2px); +} + +.ly-static { + color: var(--subtext-1); + opacity: 1; + font-size: 1.05rem; +} + +.ly-note { + color: var(--subtext-0); + font-size: 0.95rem; + text-align: center; + margin: 0; + padding-top: 1rem; +} + +.lyrics.is-instrumental, +.lyrics.is-empty, +.lyrics.is-loading { + display: grid; + place-content: center; + height: 180px; + -webkit-mask-image: none; + mask-image: none; +} + +.lyrics.is-instrumental .ly-note { + color: rgb(var(--accent-rgb)); + font-size: 1.2rem; +} + +/* ---- recently played --------------------------------------------------- */ +.recent { + list-style: none; + margin: 0; + padding: 0; + display: grid; + gap: 0.35rem; +} + +.rc-item a { + display: grid; + grid-template-columns: 44px 1fr auto; + gap: 0.7rem; + align-items: center; + text-decoration: none; + padding: 0.45rem 0.55rem; + border-radius: 12px; + transition: background 0.15s ease; +} + +.rc-item a:hover { + background: var(--surface-0); +} + +.rc-art { + width: 44px; + height: 44px; + border-radius: 8px; + object-fit: cover; + background: var(--surface-0); +} + +.rc-art-blank { + display: grid; + place-items: center; + color: var(--overlay-0); + font-size: 1.1rem; +} + +.rc-text { + min-width: 0; +} + +.rc-name { + display: block; + color: var(--text); + font-size: 0.92rem; + white-space: nowrap; + overflow: hidden; + text-overflow: ellipsis; +} + +.rc-artist { + display: block; + color: var(--subtext-0); + font-size: 0.78rem; + white-space: nowrap; + overflow: hidden; + text-overflow: ellipsis; +} + +.rc-when, +.rc-now { + font-size: 0.72rem; + white-space: nowrap; +} + +.rc-when { + color: var(--subtext-0); +} + +.rc-now { + color: rgb(var(--accent-rgb)); + font-weight: 700; +} + +.is-now { + background: rgba(var(--accent-rgb), 0.08); + border-radius: 12px; +} + +.rc-note { + color: var(--subtext-0); + font-size: 0.86rem; + padding: 0.6rem 0.4rem; + line-height: 1.5; +} + +.rc-note code { + background: var(--surface-0); + color: var(--text); + padding: 0.1rem 0.35rem; + border-radius: 6px; + font-size: 0.9em; +} + +/* ---- top artists ------------------------------------------------------- */ +.top-chips { + list-style: none; + margin: 0; + padding: 0; + display: flex; + flex-wrap: wrap; + gap: 0.5rem; +} + +.top-chip a { + display: inline-flex; + align-items: baseline; + gap: 0.45rem; + background: var(--mantle); + border: 1px solid var(--surface-0); + border-radius: 999px; + padding: 0.35rem 0.8rem; + text-decoration: none; + transition: border-color 0.15s ease; +} + +.top-chip a:hover { + border-color: rgb(var(--accent-rgb)); +} + +.top-rank { + color: rgb(var(--accent-rgb)); + font-weight: 700; + font-size: 0.78rem; +} + +.top-name { + color: var(--text); + font-size: 0.85rem; +} + +.top-plays { + color: var(--subtext-0); + font-size: 0.72rem; +} + +.music-back { + display: inline-block; + margin-top: 2.6rem; + font-size: 0.85rem; + color: rgb(var(--accent-rgb)); +} + +/* ---- responsive -------------------------------------------------------- */ +@media (max-width: 560px) { + .mdc { + grid-template-columns: 96px 1fr; + gap: 0.85rem; + padding: 0.9rem; + } + + .mdc-art { + width: 96px; + height: 96px; + } + + .mdc-title { + font-size: 1.1rem; + } + + .lyrics { + height: 300px; + } + + .ly-line { + font-size: 1.05rem; + } +} + +@media (prefers-reduced-motion: reduce) { + .mdc-fill { + transition: none; + } + + .ly-line { + transition: color 0.15s ease; + } +} + +/* ============================================================ + 16. Top artists — artist avatar in each chip (Deezer images) + ============================================================ */ +.top-chip a { + align-items: center; +} + +.top-art { + width: 34px; + height: 34px; + border-radius: 50%; + object-fit: cover; + flex: none; + display: inline-flex; + align-items: center; + justify-content: center; + background: var(--surface-0); + color: var(--subtext-0); + font-size: 0.95rem; + overflow: hidden; +} + +.top-text { + display: inline-flex; + flex-direction: column; + line-height: 1.2; + min-width: 0; +} + + +/* connection brand logos (replaces the old text type label) */ +.pc-conn-ic { + width: 14px; + height: 14px; + display: block; + flex: none; +} + +.presence-card.is-mini .pc-conn-ic { + width: 13px; + height: 13px; +} + +.friends-disclaimer { + margin: 2.5rem auto 0; + max-width: 60ch; + text-align: center; + font-size: .8rem; + line-height: 1.5; + opacity: .6; +} + +.friends-disclaimer a { + color: inherit; + text-decoration: underline; +} + +.obsessions { + display: grid; + grid-template-columns: repeat(auto-fit, minmax(280px, 1fr)); + gap: 1rem; + margin-bottom: 2rem; +} + +.obsession-embed { + width: 100%; + border: none; diff --git a/css/pages/projects.css b/css/pages/projects.css new file mode 100644 index 0000000..2614fd6 --- /dev/null +++ b/css/pages/projects.css @@ -0,0 +1,154 @@ +/* ============================================================ + projects.css — the /projects page card grid. + ============================================================ */ + +/* ============================================================ + 11. Projects PAGE + ============================================================ */ +/* On the projects page the header sits closer to the sections */ +body:has(.project-grid) .hub-header { + position: relative; + z-index: 1; + margin-bottom: 0.25rem; +} + +/* FIX: project-grid and friend-grid pages need scrolling — was missing */ +html:has(.project-grid), +html:has(.friend-grid) { + height: auto; + min-height: 100dvh; + overflow-y: auto; + overflow-x: hidden; +} + +body:has(.project-grid), +body:has(.friend-grid) { + height: auto; + min-height: 100dvh; + align-items: flex-start; + overflow-x: hidden; + overflow-y: visible; +} + +.section { + position: relative; + z-index: 1; + display: flex; + flex-direction: column; + align-items: center; + gap: 1.5rem; + width: 100%; +} + +.section-title { + margin: 0; + font-size: 1.1rem; + font-weight: 500; + letter-spacing: 0.08em; + text-transform: uppercase; + color: var(--mauve); +} + +.section-subtitle { + margin: -1.1rem 0 0; + font-size: 1.1rem; + font-weight: 500; + letter-spacing: 0.08em; + text-transform: lowercase; + color: var(--surface-2); +} + +/* ---- Project cards (horizontal: avatar left, title + status + bio) ---- */ +.project-grid { + margin-bottom: 1.5rem; + display: grid; + grid-template-columns: repeat(auto-fill, minmax(280px, 1fr)); + gap: 1rem; + width: 100%; + max-width: 640px; +} + +.project-card { + display: flex; + align-items: flex-start; + gap: 0.9rem; + padding: 1rem; + border-radius: 16px; + background: var(--surface-0); + border: 1px solid var(--surface-1); + color: var(--text); + text-decoration: none; + transition: transform 0.15s ease, border-color 0.15s ease, + background 0.15s ease, box-shadow 0.15s ease; +} + +.project-card:hover, +.project-card:focus-visible { + transform: translateY(-3px); + background: var(--surface-1); + border-color: rgb(var(--accent-rgb)); + box-shadow: 0 6px 20px rgba(var(--accent-rgb), 0.22); +} + +.project-card-img { + width: 56px; + height: 56px; + flex-shrink: 0; + border-radius: 14px; + object-fit: cover; + border: 2px solid var(--yellow); + box-shadow: 0 4px 14px rgba(var(--accent-rgb), 0.22); +} + +.project-card-body { + display: flex; + flex-direction: column; + gap: 0.35rem; + min-width: 0; +} + +.project-card-head { + display: flex; + align-items: center; + gap: 0.5rem; + flex-wrap: wrap; +} + +.project-card-title { + font-weight: 600; + font-size: 1rem; + color: var(--text); +} + +.project-card-status { + font-size: 0.66rem; + font-weight: 600; + letter-spacing: 0.04em; + text-transform: uppercase; + padding: 0.15rem 0.55rem; + border-radius: 999px; + background: var(--crust); + border: 1px solid var(--green); + color: var(--green); + white-space: nowrap; +} + +.project-card-status.closed { + border-color: var(--red); + color: var(--red); +} + +.project-card-bio { + margin: 0; + font-size: 0.85rem; + line-height: 1.45; + color: var(--subtext-0); +} + +/* Italic + dimmed until you replace it with a real description */ +.project-card-bio.is-placeholder { + font-style: italic; + opacity: 0.65; +} + + diff --git a/css/pages/selfies.css b/css/pages/selfies.css new file mode 100644 index 0000000..295cdcd --- /dev/null +++ b/css/pages/selfies.css @@ -0,0 +1,254 @@ +/* ============================================================ + selfies.css — the /selfies page grid + lightbox. + ============================================================ */ + +/* ============================================================ + 14. Selfies page + ============================================================ */ + +/* Let the gallery scroll (the default layout locks the viewport). Keyed on + the wrapper class so it scrolls even before selfies.js injects the grid — + mirrors the .friends-wrap rule used by the cool-people page. */ +html:has(.selfies-wrap), +body:has(.selfies-wrap) { + height: auto; + min-height: 100dvh; + overflow-y: auto; +} + +body:has(.selfies-wrap) { + align-items: flex-start; +} + +body:has(.selfies-wrap) .hub { + max-width: 960px; +} + +body:has(.selfies-wrap) .hub-header { + position: relative; + z-index: 1; + margin-bottom: 2rem; +} + +.selfie-grid { + display: grid; + grid-template-columns: repeat(auto-fill, minmax(160px, 1fr)); + gap: 0.9rem; + width: 100%; + margin-bottom: 1.5rem; + padding-bottom: 4.5rem; +} + +.selfie-thumb { + margin: 0; + padding: 0; + border: 1px solid var(--surface-1); + border-radius: 14px; + overflow: hidden; + background: var(--surface-0); + aspect-ratio: 1 / 1; + display: block; + transition: transform 0.15s ease, border-color 0.15s ease, + box-shadow 0.15s ease; +} + +.selfie-thumb img { + width: 100%; + height: 100%; + object-fit: cover; + display: block; +} + +.selfie-thumb:hover, +.selfie-thumb:focus-visible { + transform: translateY(-3px); + border-color: rgb(var(--accent-rgb)); + box-shadow: 0 6px 20px rgba(var(--accent-rgb), 0.22); + outline: none; +} + +.selfie-empty { + grid-column: 1 / -1; + text-align: center; + color: var(--subtext-0); + font-style: italic; + padding: 3rem 1rem; +} + +/* ---- Lightbox ---- */ +.lightbox { + position: fixed; + inset: 0; + z-index: 9999; + display: flex; + align-items: center; + justify-content: center; + padding: 1.5rem; + background: color-mix(in srgb, var(--crust) 86%, transparent); + -webkit-backdrop-filter: blur(6px); + backdrop-filter: blur(6px); +} + +.lightbox[hidden] { + display: none; +} + +.lightbox.is-open { + animation: lightbox-fade 0.18s ease; +} + +@keyframes lightbox-fade { + from { + opacity: 0; + } + + to { + opacity: 1; + } +} + +.lightbox-img { + max-width: min(92vw, 1100px); + max-height: 86vh; + object-fit: contain; + border-radius: 12px; + border: 2px solid rgba(var(--accent-rgb), 0.55); + box-shadow: 0 12px 40px rgba(0, 0, 0, 0.5); +} + +.lightbox-close, +.lightbox-nav { + position: fixed; + display: flex; + align-items: center; + justify-content: center; + border: 1px solid var(--surface-1); + background: color-mix(in srgb, var(--surface-0) 85%, transparent); + color: var(--text); + border-radius: 999px; + line-height: 1; + transition: background 0.15s ease, border-color 0.15s ease, + transform 0.15s ease; +} + +.lightbox-close:hover, +.lightbox-nav:hover, +.lightbox-close:focus-visible, +.lightbox-nav:focus-visible { + background: var(--surface-1); + border-color: rgb(var(--accent-rgb)); + outline: none; +} + +.lightbox-close { + top: 1rem; + right: 1rem; + width: 2.6rem; + height: 2.6rem; + font-size: 1.8rem; +} + +.lightbox-nav { + top: 50%; + transform: translateY(-50%); + width: 3rem; + height: 3rem; + font-size: 2rem; +} + +.lightbox-nav:hover { + transform: translateY(-50%) scale(1.06); +} + +.lightbox-prev { + left: 1rem; +} + +.lightbox-next { + right: 1rem; +} + +.lightbox-nav[hidden] { + display: none; +} + +/* Freeze the page behind the lightbox while it's open */ +body.lightbox-open { + overflow: hidden; +} + +@media (prefers-reduced-motion: reduce) { + + .selfie-thumb, + .lightbox-close, + .lightbox-nav { + transition: none; + } + + .lightbox.is-open { + animation: none; + } + + .lightbox-nav:hover { + transform: translateY(-50%); + } +} + +@media (max-width: 560px) { + .selfie-grid { + grid-template-columns: repeat(auto-fill, minmax(110px, 1fr)); + gap: 0.6rem; + } + + .lightbox-nav { + width: 2.6rem; + height: 2.6rem; + font-size: 1.6rem; + } +} + +/* ---- Captions (thumbnails + lightbox) ---- */ +.selfie-item { + margin: 0; + display: flex; + flex-direction: column; + gap: 0.45rem; +} + +.selfie-caption { + text-align: center; + font-size: 0.8rem; + line-height: 1.35; + color: var(--subtext-0); + overflow-wrap: anywhere; +} + +.lightbox-figure { + margin: 0; + display: flex; + flex-direction: column; + align-items: center; + gap: 0.8rem; + max-width: min(92vw, 1100px); +} + +/* leave room beneath the image for the caption line */ +.lightbox-img { + max-height: 80vh; +} + +.lightbox-caption { + margin: 0; + text-align: center; + color: var(--text); + font-size: 0.95rem; + line-height: 1.4; + max-width: min(92vw, 1100px); + overflow-wrap: anywhere; +} + +.lightbox-caption[hidden] { + display: none; +} + + diff --git a/css/shared/badges.css b/css/shared/badges.css new file mode 100644 index 0000000..7c24f2c --- /dev/null +++ b/css/shared/badges.css @@ -0,0 +1,78 @@ +/* ============================================================ + badges.css — system badges (bottom-right pill stack) + the + hidden pokeball easter egg tucked inside them. + Shared across all pages. + ============================================================ */ + +/* ============================================================ + 6. SYSTEM BADGES (shared, pinned bottom-right) + ============================================================ */ +.badges { + position: fixed; + right: 1rem; + bottom: 1rem; + display: flex; + flex-direction: column; + align-items: flex-end; + gap: 0.4rem; + pointer-events: none; + z-index: 5; +} + +.badge { + display: inline-flex; + align-items: center; + gap: 0.4rem; + padding: 0.3rem 0.6rem; + border-radius: 999px; + background: var(--surface-0); + border: 1px solid rgba(var(--accent-rgb), 0.45); + color: var(--subtext-1); + font-size: 0.75rem; + white-space: nowrap; + transition: border-color 0.6s ease, box-shadow 0.6s ease; +} + +.badge:hover { + border-color: rgb(var(--accent-rgb)); + box-shadow: 0 4px 14px -6px rgba(var(--accent-rgb), 0.5); +} + +.badge-icon { + width: 15px; + height: 15px; + filter: invert(78%) sepia(36%) saturate(640%) hue-rotate(280deg) brightness(105%); +} + + +/* ============================================================ + 12. HIDDEN POKÉBALL (unlocks the Pokémon cats once clicked) + ============================================================ */ +/* Small, low-contrast and tucked among the badges so it has to be + hunted for. Still clickable — that's the whole point of finding it. */ +#pokeball-secret { + width: 14px; + height: 14px; + opacity: 0.18; + align-self: center; + cursor: url('../assets/cursor/default_0.png'), default; + pointer-events: auto; + /* parent .badges sets none — re-enable here */ + image-rendering: auto; + transition: opacity 0.2s ease, transform 0.2s ease; + -webkit-user-drag: none; + user-select: none; +} + +#pokeball-secret:hover { + opacity: 0.85; + transform: scale(1.15); +} + +#pokeball-secret.found { + opacity: 1; + cursor: url('../assets/cursor/default_0.png'), default; + filter: drop-shadow(0 0 4px var(--red)); +} + + diff --git a/css/shared/keyring.css b/css/shared/keyring.css new file mode 100644 index 0000000..b4b093f --- /dev/null +++ b/css/shared/keyring.css @@ -0,0 +1,82 @@ +/* ============================================================ + keyring.css — lanyard.cafe webring widget (#lc-embed) + re-theme. Bottom-left, shared across all pages. + ============================================================ */ + +/* ===================================================================== + * lanyard.cafe keyring (webring) — embed.js injects #lc-embed with all + * styles inline, so every override here needs !important. Re-themes the + * default cream/brown look to Catppuccin and the site font, keeping the + * widget floating in the bottom-left (which is otherwise empty chrome). + * ===================================================================== */ +#lc-embed { + font-family: 'Comic Code', 'Quicksand', system-ui, sans-serif !important; + left: 1rem !important; + bottom: 1rem !important; + z-index: 5 !important; +} + +#lc-embed>section { + margin-bottom: 0 !important; +} + +/* the card */ +#lc-embed>section>div { + background: var(--surface-0) !important; + border: 1px solid rgba(var(--accent-rgb), 0.45) !important; + border-radius: 14px !important; + box-shadow: 0 10px 26px -16px rgba(0, 0, 0, 0.7) !important; +} + +/* prev / random / next buttons */ +#lc-embed a { + background: var(--surface-1) !important; + border-radius: 10px !important; + font-weight: 600 !important; + transition: transform 0.12s ease, background 0.12s ease, color 0.12s ease !important; +} + +#lc-embed a:nth-child(1), +#lc-embed a:nth-child(3) { + color: rgb(var(--accent-rgb)) !important; +} + +#lc-embed a:nth-child(2) { + color: var(--lavender) !important; +} + +#lc-embed a:hover { + background: var(--surface-2) !important; + transform: translateY(-2px) !important; +} + +/* the "you are at " line */ +#lc-embed p { + color: var(--subtext-0) !important; +} + +#lc-embed p span { + color: rgb(var(--accent-rgb)) !important; +} + +/* On mobile the body is a single flex column and every other floating + widget (nav, badges, presence card) is reflowed into it. The keyring, + left fixed, floated over the nav pills when scrolled to the bottom — so + here we drop it into the column too, last and centered. */ +@media (max-width: 640px) { + #lc-embed { + position: static !important; + inset: auto !important; + order: 6 !important; + width: 100% !important; + margin: 0 !important; + z-index: auto !important; + display: flex !important; + justify-content: center !important; + } + + #lc-embed>section>div { + min-width: 0 !important; + } +} + diff --git a/css/shared/layout.css b/css/shared/layout.css new file mode 100644 index 0000000..f2d2508 --- /dev/null +++ b/css/shared/layout.css @@ -0,0 +1,54 @@ +/* ============================================================ + layout.css — shared .hub / .pfp / .hub-header chrome used at the top of most pages. + ============================================================ */ + +/* ============================================================ + 2. SHARED LAYOUT & HEADER (all pages) + ============================================================ */ +.hub { + position: relative; + z-index: 1; + width: 100%; + max-width: 460px; +} + +.pfp { + width: 96px; + height: 96px; + border-radius: 50%; + object-fit: cover; + border: 3px solid var(--yellow); + box-shadow: 0 4px 18px rgba(245, 194, 231, 0.25); + margin-bottom: 0.75rem; +} + +.hub-header { + text-align: center; + margin-bottom: 2.25rem; +} + +.hub-header h1 { + margin: 0; + font-size: 2rem; + font-weight: 700; + color: rgb(var(--accent-rgb)); + transition: color 0.6s ease; +} + +.tagline { + margin: 0.35rem 0 0; + color: var(--subtext-0); + font-size: 0.95rem; + letter-spacing: 0.04em; + text-transform: uppercase; +} + +.pronouns { + margin: 0.35rem 0 0; + color: var(--mauve); + font-size: 0.95rem; + letter-spacing: 0.04em; + text-transform: lowercase; +} + + diff --git a/css/shared/nav.css b/css/shared/nav.css new file mode 100644 index 0000000..ed62a7d --- /dev/null +++ b/css/shared/nav.css @@ -0,0 +1,88 @@ +/* ============================================================ + 5. PAGE NAV (shared, pinned top-left) + ============================================================ */ +.nav { + position: fixed; + left: 1rem; + top: 1rem; + z-index: 6; +} + +.nav-links { + display: flex; + flex-direction: column; + align-items: flex-start; + gap: 0.4rem; +} + +.nav-link { + position: relative; + display: inline-flex; + align-items: center; + padding: 0.3rem 0.7rem; + border-radius: 999px; + background: var(--surface-0); + border: 1px solid var(--surface-1); + color: var(--subtext-1); + font-size: 0.8rem; + text-decoration: none; + transition: transform 0.15s ease, border-color 0.15s ease, + background 0.15s ease, color 0.15s ease; +} + +.nav-link:hover { + border-color: rgb(var(--accent-rgb)); + color: var(--text); + transform: translateX(2px); +} + +.nav-link.selected { + background: rgb(var(--accent-rgb)); + border-color: rgb(var(--accent-rgb)); + color: var(--crust); + font-weight: 700; + margin-left: 14px; +} + +.nav-link.is-a-dev { + background: var(--surface-1); + border-color: var(--surface-2); + color: var(--text); +} + +.nav-link.is-a-dev:hover { + border-color: var(--saphire); + transform: translateX(2px); +} + +/* Triangle pointing at the selected item */ +.nav-link.selected::before { + content: ""; + position: absolute; + left: -14px; + top: 50%; + transform: translateY(-50%); + border: 6px solid transparent; + border-left-color: rgb(var(--accent-rgb)); +} + + + +/* ---- boot reveal of side chrome (set by terminal.js on the homepage, + but targets these shared .nav / .badges elements) ---- */ +.nav, +.badges { + transition: opacity 0.6s ease, transform 0.6s ease; +} + +body.term-booting .nav, +body.term-booting .badges { + opacity: 0; + transform: translateY(8px); +} + +body.term-chrome-in .nav, +body.term-chrome-in .badges { + opacity: 1; + transform: none; +} diff --git a/css/shared/presence-card.css b/css/shared/presence-card.css new file mode 100644 index 0000000..27ee23d --- /dev/null +++ b/css/shared/presence-card.css @@ -0,0 +1,1217 @@ +/* ============================================================ + presence-card.css — the shared Discord-style presence card used on /discord and (in mini form) /cool-people, plus the /discord page stage layout. + ============================================================ */ + +/* ============================================================ + 16. PRESENCE CARD + /discord + /api EMBED (merged from player.css) + ============================================================ */ +html[data-theme="mocha"] { + color-scheme: dark; + --rosewater: #f5e0dc; + --flamingo: #f2cdcd; + --pink: #f5c2e7; + --accent-rgb: 245, 194, 231; + --mauve: #cba6f7; + --red: #f38ba8; + --maroon: #eba0ac; + --peach: #fab387; + --yellow: #f9e2af; + --green: #a6e3a1; + --teal: #94e2d5; + --sky: #89dceb; + --saphire: #74c7ec; + --blue: #89b4fa; + --lavender: #b4befe; + --text: #cdd6f4; + --subtext-0: #a6adc8; + --subtext-1: #bac2de; + --overlay-0: #6c7086; + --overlay-1: #7f849c; + --overlay-2: #9399b2; + --surface-0: #313244; + --surface-1: #45475a; + --surface-2: #585b70; + --base: #1e1e2e; + --mantle: #181825; + --crust: #11111b; +} + +html[data-theme="macchiato"] { + color-scheme: dark; + --rosewater: #f4dbd6; + --flamingo: #f0c6c6; + --pink: #f5bde6; + --accent-rgb: 245, 189, 230; + --mauve: #c6a0f6; + --red: #ed8796; + --maroon: #ee99a0; + --peach: #f5a97f; + --yellow: #eed49f; + --green: #a6da95; + --teal: #8bd5ca; + --sky: #91d7e3; + --saphire: #7dc4e4; + --blue: #8aadf4; + --lavender: #b7bdf8; + --text: #cad3f5; + --subtext-0: #a5adcb; + --subtext-1: #b8c0e0; + --overlay-0: #6e738d; + --overlay-1: #8087a2; + --overlay-2: #939ab7; + --surface-0: #363a4f; + --surface-1: #494d64; + --surface-2: #5b6078; + --base: #24273a; + --mantle: #1e2030; + --crust: #181926; +} + +html[data-theme="frappe"] { + color-scheme: dark; + --rosewater: #f2d5cf; + --flamingo: #eebebe; + --pink: #f4b8e4; + --accent-rgb: 244, 184, 228; + --mauve: #ca9ee6; + --red: #e78284; + --maroon: #ea999c; + --peach: #ef9f76; + --yellow: #e5c890; + --green: #a6d189; + --teal: #81c8be; + --sky: #99d1db; + --saphire: #85c1dc; + --blue: #8caaee; + --lavender: #babbf1; + --text: #c6d0f5; + --subtext-0: #a5adce; + --subtext-1: #b5bfe2; + --overlay-0: #737994; + --overlay-1: #838ba7; + --overlay-2: #949cbb; + --surface-0: #414559; + --surface-1: #51576d; + --surface-2: #626880; + --base: #303446; + --mantle: #292c3c; + --crust: #232634; +} + +html[data-theme="latte"] { + color-scheme: light; + --rosewater: #dc8a78; + --flamingo: #dd7878; + --pink: #ea76cb; + --accent-rgb: 234, 118, 203; + --mauve: #8839ef; + --red: #d20f39; + --maroon: #e64553; + --peach: #fe640b; + --yellow: #df8e1d; + --green: #40a02b; + --teal: #179299; + --sky: #04a5e5; + --saphire: #209fb5; + --blue: #1e66f5; + --lavender: #7287fd; + --text: #4c4f69; + --subtext-0: #6c6f85; + --subtext-1: #5c5f77; + --overlay-0: #9ca0b0; + --overlay-1: #8c8fa1; + --overlay-2: #7c7f93; + --surface-0: #ccd0da; + --surface-1: #bcc0cc; + --surface-2: #acb0be; + --base: #eff1f5; + --mantle: #e6e9ef; + --crust: #dce0e8; +} + + +/* ===================================================================== + * 2. STANDALONE PAGE STAGE + * Only the dedicated /api pages use .api-stage; it centers a single + * card on a Catppuccin gradient. The homepage never sets data-theme + * or .api-stage, so its fixed top-left card is untouched. + * ===================================================================== */ +html[data-theme] body.api-body { + margin: 0; + min-height: 100vh; + font-family: 'Comic Code', ui-monospace, system-ui, sans-serif; + color: var(--text); + background: linear-gradient(135deg, var(--base) 0%, var(--mantle) 60%, var(--crust) 100%); +} + +.api-stage { + min-height: 100vh; + display: flex; + align-items: center; + justify-content: center; + padding: 1.5rem; +} + +/* On the stage, the card sits in flow & centered instead of fixed. */ +.api-stage .presence-card { + position: static; + margin: 0; + max-width: 320px; + width: 100%; +} + +.api-empty { + text-align: center; + color: var(--subtext-0); + font-size: 0.9rem; + max-width: 420px; + line-height: 1.5; +} + +.api-empty a { + color: rgb(var(--accent-rgb)); +} + + +/* ===================================================================== + * 3. PRESENCE CARD (unified Discord-style profile pill) + * Lifted verbatim from main.css §13 so the card is self-contained. + * ===================================================================== */ +.presence-card { + --dc-accent: 245, 194, 231; + position: fixed; + top: 1rem; + left: 1rem; + z-index: 6; + width: max-content; + max-width: 280px; + background: var(--surface-0); + border: 1px solid var(--surface-1); + border-radius: 16px; + box-shadow: 0 8px 26px -12px rgba(17, 17, 27, 0.7); + overflow: hidden; + transition: border-color 0.2s ease, box-shadow 0.2s ease; +} + +.presence-card[hidden] { + display: none; +} + +.presence-card.has-accent { + border-color: rgba(var(--dc-accent), 0.5); + box-shadow: 0 8px 26px -12px rgba(var(--dc-accent), 0.6); +} + +/* ---- header (always visible) ---- */ +.pc-head { + display: flex; + align-items: center; + gap: 0.6rem; + padding: 0.5rem 0.7rem; +} + +.pc-avatar { + position: relative; + width: 40px; + height: 40px; + flex-shrink: 0; +} + +.pc-av-img { + width: 40px; + height: 40px; + border-radius: 50%; + object-fit: cover; + display: block; + /* solid fill behind the avatar — many PFPs (incl. Clove's) are partly + transparent, and Discord shows a solid backdrop rather than the banner. */ + background: var(--crust); +} + +/* avatar decoration / frame overlay (Discord cosmetic) */ +.pc-av-deco { + position: absolute; + top: 50%; + left: 50%; + width: 54px; + height: 54px; + transform: translate(-50%, -50%); + pointer-events: none; +} + +.pc-av-deco[hidden] { + display: none; +} + +.pc-status { + position: absolute; + right: -1px; + bottom: -1px; + width: 12px; + height: 12px; + border-radius: 50%; + border: 2.5px solid var(--surface-0); + background: var(--overlay-0); +} + +.presence-card[data-status="online"] .pc-status { + background: var(--green); +} + +.presence-card[data-status="idle"] .pc-status { + background: var(--yellow); +} + +.presence-card[data-status="dnd"] .pc-status { + background: var(--red); +} + +.presence-card[data-status="offline"] .pc-status { + background: var(--overlay-0); +} + +.pc-id { + display: flex; + flex-direction: column; + gap: 0.05rem; + min-width: 0; +} + +.pc-name { + font-size: 0.92rem; + font-weight: 700; + color: rgb(var(--accent-rgb)); + white-space: nowrap; + overflow: hidden; + text-overflow: ellipsis; + transition: color 0.5s ease; +} + +.pc-user { + font-size: 0.7rem; + color: var(--subtext-0); + white-space: nowrap; +} + +.pc-user:empty { + display: none; +} + +/* status word (Online / Idle / Do Not Disturb / Offline) */ +.pc-status-text { + font-size: 0.7rem; + font-weight: 600; + white-space: nowrap; + color: var(--overlay-1); +} + +.pc-status-text:empty { + display: none; +} + +.pc-status-text::before { + content: ""; + display: inline-block; + width: 7px; + height: 7px; + border-radius: 50%; + margin-right: 0.3rem; + vertical-align: baseline; + background: var(--overlay-0); +} + +.presence-card[data-status="online"] .pc-status-text { + color: var(--green); +} + +.presence-card[data-status="online"] .pc-status-text::before { + background: var(--green); +} + +.presence-card[data-status="idle"] .pc-status-text { + color: var(--yellow); +} + +.presence-card[data-status="idle"] .pc-status-text::before { + background: var(--yellow); +} + +.presence-card[data-status="dnd"] .pc-status-text { + color: var(--red); +} + +.presence-card[data-status="dnd"] .pc-status-text::before { + background: var(--red); +} + +.presence-card[data-status="offline"] .pc-status-text { + color: var(--overlay-1); +} + +.presence-card[data-status="offline"] .pc-status-text::before { + background: var(--overlay-0); +} + +/* ---- expandable sections ---- */ +.pc-sections { + display: flex; + flex-direction: column; + gap: 0.4rem; + padding: 0 0.6rem 0.6rem; + transition: opacity 0.2s ease; +} + +.presence-card:not(.has-sections) .pc-sections { + display: none; +} + +.pc-row { + display: flex; + align-items: center; + gap: 0.55rem; + padding: 0.4rem 0.5rem; + border-radius: 10px; + background: var(--mantle); + border: 1px solid transparent; + color: var(--text); + text-decoration: none; + transition: border-color 0.15s ease, transform 0.15s ease; +} + +a.pc-row:hover, +.pc-row--stack:hover { + border-color: rgba(var(--dc-accent), 0.55); + transform: translateX(2px); +} + +.pc-row-text { + display: flex; + flex-direction: column; + gap: 0.04rem; + min-width: 0; +} + +.pc-row-kind { + font-size: 0.6rem; + text-transform: uppercase; + letter-spacing: 0.05em; + color: var(--subtext-0); +} + +.pc-row-title { + font-size: 0.8rem; + font-weight: 500; + white-space: nowrap; + overflow: hidden; + text-overflow: ellipsis; + max-width: 200px; +} + +.pc-row-sub { + font-size: 0.7rem; + color: var(--subtext-0); + white-space: nowrap; + overflow: hidden; + text-overflow: ellipsis; + max-width: 200px; +} + +.pc-row-title:empty, +.pc-row-sub:empty { + display: none; +} + +.pc-row-elapsed { + font-size: 0.62rem; + color: var(--subtext-0); + margin-top: 0.1rem; +} + +.pc-row-elapsed:empty { + display: none; +} + +/* artwork / icons */ +.pc-art, +.pc-row-ic-img { + width: 38px; + height: 38px; + border-radius: 7px; + object-fit: cover; + flex-shrink: 0; +} + +.pc-row-ic.pc-dot { + width: 9px; + height: 9px; + border-radius: 50%; + flex-shrink: 0; + margin: 0 0.5rem; + background: rgb(var(--accent-rgb)); +} + +.pc-dev .pc-row-ic.pc-dot { + background: var(--blue); + border-radius: 2px; +} + +.pc-game .pc-row-ic.pc-dot { + background: var(--green); +} + +.pc-stream .pc-row-ic.pc-dot { + background: var(--mauve); +} + +/* custom status */ +.pc-custom { + position: relative; + align-self: flex-start; + background: var(--surface-1); + border: none; + padding: 0.5rem 0.7rem; + gap: 0.4rem; + align-items: flex-start; + border-radius: 13px; + border-top-left-radius: 4px; + margin-top: 0.3rem; +} + +/* Discord-style thought-bubble tail */ +.pc-custom::before, +.pc-custom::after { + content: ""; + position: absolute; + background: var(--surface-1); + border-radius: 50%; + pointer-events: none; +} + +.pc-custom::before { + width: 9px; + height: 9px; + top: -5px; + left: 12px; +} + +.pc-custom::after { + width: 5px; + height: 5px; + top: -11px; + left: 9px; +} + +.pc-custom:hover { + transform: none; + border-color: transparent; +} + +.pc-emoji { + width: 18px; + height: 18px; + flex-shrink: 0; + margin-top: 0.05rem; +} + +.pc-custom-text { + font-size: 0.74rem; + color: var(--subtext-0); + max-width: 230px; + white-space: normal; + overflow-wrap: anywhere; + line-height: 1.35; +} + +/* spotify progress */ +.pc-spotify .pc-row-title { + color: var(--green); +} + +.pc-progress { + display: flex; + flex-direction: column; + gap: 0.15rem; + margin-top: 0.25rem; + width: 180px; +} + +.pc-bar { + height: 4px; + border-radius: 999px; + background: var(--surface-1); + overflow: hidden; +} + +.pc-fill { + display: block; + height: 100%; + width: 0; + border-radius: 999px; + background: rgb(var(--dc-accent)); +} + +.pc-times { + display: flex; + justify-content: space-between; + font-size: 0.58rem; + color: var(--subtext-0); + font-variant-numeric: tabular-nums; +} + +@media (max-width: 640px) { + .presence-card { + max-width: calc(100vw - 2rem); + } + + .api-stage .presence-card { + max-width: 100%; + } +} + +/* ---- extended Lanyard fields ---- */ +.pc-name-row { + display: flex; + align-items: center; + gap: 0.35rem; + min-width: 0; +} + +.pc-name-row .pc-name { + min-width: 0; +} + +/* gradient display name (display_name_styles) */ +.pc-name.is-gradient { + -webkit-background-clip: text; + background-clip: text; + color: transparent; + -webkit-text-fill-color: transparent; +} + +/* server tag chip (primary_guild) */ +.pc-tag { + display: inline-flex; + align-items: center; + gap: 0.2rem; + flex-shrink: 0; + padding: 0.05rem 0.35rem; + border-radius: 6px; + background: var(--surface-2); + font-size: 0.58rem; + font-weight: 700; + letter-spacing: 0.03em; + color: var(--text); +} + +.pc-tag[hidden] { + display: none; +} + +.pc-tag-badge { + width: 14px; + height: 14px; + display: block; +} + +/* username + active-platform indicators */ +.pc-sub-row { + display: flex; + align-items: center; + gap: 0.35rem; +} + +.pc-platforms { + display: inline-flex; + align-items: center; + gap: 0.2rem; + color: var(--subtext-0); +} + +.pc-plat { + width: 12px; + height: 12px; + display: inline-flex; +} + +.pc-plat svg { + width: 12px; + height: 12px; + display: block; +} + +/* KV meta line (location, etc.) */ +.pc-meta { + display: flex; + align-items: center; + gap: 0.25rem; + margin-top: 0.1rem; + font-size: 0.66rem; + color: var(--subtext-0); +} + +.pc-meta[hidden] { + display: none; +} + +.pc-pin { + font-size: 0.7rem; + line-height: 1; +} + +/* stacked rows (activity rows that carry buttons) */ +.pc-row--stack { + flex-direction: column; + align-items: stretch; + gap: 0.4rem; +} + +.pc-row-link { + display: flex; + align-items: center; + gap: 0.55rem; + min-width: 0; + color: var(--text); + text-decoration: none; +} + +/* activity icon with small corner badge (assets.small_image) */ +.pc-ic-wrap { + position: relative; + flex-shrink: 0; + width: 38px; + height: 38px; +} + +.pc-ic-wrap .pc-row-ic-img { + width: 38px; + height: 38px; +} + +.pc-ic-badge { + position: absolute; + right: -3px; + bottom: -3px; + width: 16px; + height: 16px; + border-radius: 50%; + border: 2px solid var(--mantle); + object-fit: cover; +} + +/* activity buttons (labels from presence) */ +.pc-buttons { + display: flex; + flex-wrap: wrap; + gap: 0.35rem; +} + +.pc-btn { + font-size: 0.66rem; + padding: 0.22rem 0.55rem; + border-radius: 6px; + background: var(--surface-1); + color: var(--text); + text-decoration: none; + border: 1px solid transparent; + transition: border-color 0.15s ease, background 0.15s ease; +} + +.pc-btn:hover { + border-color: rgb(var(--dc-accent)); + background: var(--surface-2); +} + +/* profile badges */ +.pc-badges { + display: inline-flex; + align-items: center; + gap: 0.2rem; + flex-wrap: wrap; + margin-top: 0.15rem; +} + +.pc-badges:empty { + display: none; +} + +.pc-badge { + width: 16px; + height: 16px; + display: block; +} + +.pc-badge-link { + display: inline-flex; + line-height: 0; +} + +/* wishlist star + panel */ +.pc-star { + margin-left: auto; + align-self: flex-start; + background: none; + border: none; + cursor: url('../assets/cursor/pointer_0.png'), pointer; + font-size: 0.95rem; + line-height: 1; + color: var(--subtext-0); + padding: 0.1rem 0.15rem; + transition: color 0.15s ease, transform 0.15s ease; +} + +.pc-star:hover { + color: rgb(var(--accent-rgb)); + transform: scale(1.12); +} + +.pc-star.on { + color: var(--yellow); +} + +.pc-wishlist { + display: none; +} + +.presence-card.show-wishlist .pc-wishlist { + display: block; + border-top: 1px solid var(--surface-1); + margin: 0 0.6rem; + padding: 0.6rem 0 0.7rem; +} + +.pc-wishlist-title { + font-size: 0.62rem; + text-transform: uppercase; + letter-spacing: 0.05em; + color: var(--subtext-0); + margin-bottom: 0.45rem; +} + +.pc-wl-item { + display: flex; + align-items: center; + gap: 0.45rem; + padding: 0.25rem 0.4rem; + border-radius: 8px; + text-decoration: none; + color: var(--text); +} + +a.pc-wl-item:hover { + background: var(--mantle); +} + +.pc-wl-ic { + width: 22px; + height: 22px; + border-radius: 5px; + object-fit: cover; +} + +.pc-wl-text { + display: flex; + flex-direction: column; + line-height: 1.2; + min-width: 0; +} + +.pc-wl-name { + font-size: 0.8rem; +} + +.pc-wl-type { + font-size: 0.6rem; + text-transform: uppercase; + letter-spacing: 0.04em; + color: var(--subtext-0); +} + +.pc-wl-price { + margin-left: auto; + padding-left: 0.5rem; + font-size: 0.72rem; + color: var(--subtext-1); + white-space: nowrap; +} + +.pc-wl-item.is-owned { + opacity: 0.5; +} + +.pc-wl-empty { + font-size: 0.78rem; + color: var(--subtext-0); + margin: 0; +} + +/* Discord profile gradient (Catppuccin is the fallback) */ +.presence-card.has-profile-grad { + background: linear-gradient(180deg, rgb(var(--pc-grad-1-rgb)) 0%, rgb(var(--pc-grad-2-rgb)) 100%); +} + +.presence-card.has-profile-grad:not(.has-accent) { + border-color: rgba(var(--pc-grad-1-rgb), 0.6); +} + +.presence-card.has-profile-grad .pc-row { + background: rgba(17, 17, 27, 0.55); +} + + +/* ===================================================================== + * 4. EXTRAS (banner, bio, connected accounts — used on the /discord page) + * ===================================================================== */ +.pc-banner { + display: block; + width: 100%; + height: 96px; + object-fit: cover; + margin: 0; +} + +.pc-banner[hidden] { + display: none; +} + +/* solid/accent banner fallback when there's no Nitro banner image */ +.presence-card.has-banner-color::before { + content: ""; + display: block; + height: 64px; + background: var(--pc-banner-color, var(--surface-1)); +} + +/* when a banner is present, lift the avatar up over it */ +.presence-card.has-banner .pc-head, +.presence-card.has-banner-color .pc-head { + margin-top: -22px; +} + +.presence-card.has-banner .pc-avatar, +.presence-card.has-banner-color .pc-avatar { + width: 56px; + height: 56px; +} + +.presence-card.has-banner .pc-av-img, +.presence-card.has-banner-color .pc-av-img { + width: 56px; + height: 56px; + border: 3px solid var(--surface-0); +} + +.presence-card.has-banner .pc-av-deco, +.presence-card.has-banner-color .pc-av-deco { + width: 72px; + height: 72px; +} + +.pc-bio { + margin: 0 0.7rem 0.5rem; + padding: 0.5rem 0.6rem; + border-radius: 10px; + background: var(--mantle); + font-size: 0.74rem; + line-height: 1.4; + color: var(--subtext-1); + white-space: pre-wrap; + overflow-wrap: anywhere; +} + +.pc-bio[hidden] { + display: none; +} + +.pc-connections { + display: flex; + flex-wrap: wrap; + gap: 0.35rem; + margin: 0 0.7rem 0.6rem; +} + +.pc-connections[hidden] { + display: none; +} + +.pc-conn { + display: inline-flex; + align-items: center; + gap: 0.3rem; + padding: 0.2rem 0.5rem; + border-radius: 999px; + background: var(--surface-1); + border: 1px solid transparent; + color: var(--text); + font-size: 0.66rem; + text-decoration: none; + transition: border-color 0.15s ease, background 0.15s ease; +} + +a.pc-conn:hover { + border-color: rgb(var(--accent-rgb)); + background: var(--surface-2); +} + +.pc-conn-type { + text-transform: uppercase; + letter-spacing: 0.04em; + font-size: 0.56rem; + color: var(--subtext-0); +} + +.pc-conn-check { + color: var(--green); + font-weight: 700; +} + + +/* ===================================================================== + * 5. /discord PAGE STAGE (centered, slightly wider card) + * ===================================================================== */ +html:has(.presence-stage), +body:has(.presence-stage) { + height: auto; + min-height: 100dvh; + overflow-y: auto; +} + +body:has(.presence-stage) { + padding: 0; +} + +.presence-stage { + min-height: 100dvh; + display: flex; + flex-direction: column; + align-items: center; + justify-content: center; + padding: 1.5rem; +} + +.presence-intro { + text-align: center; + margin: 0 0 1.25rem; +} + +.presence-intro h1 { + margin: 0; + font-size: 1.8rem; + color: rgb(var(--accent-rgb)); +} + +.presence-intro p { + margin: 0.3rem 0 0; + font-size: 0.9rem; + color: var(--subtext-0); +} + +/* pronouns chip (shown on the card sub-row) */ +.pc-pronouns { + padding: 0.05rem 0.4rem; + border-radius: 6px; + background: var(--surface-2); + font-size: 0.6rem; + font-weight: 600; + color: var(--subtext-1); + white-space: nowrap; +} + +.pc-pronouns[hidden] { + display: none; +} + + +/* ===================================================================== + * 6. /discord PAGE — big "fills the page" presence card + * ===================================================================== */ +.presence-stage .presence-card { + position: static; + margin: 0; + width: 100%; + max-width: 680px; + border-radius: 20px; +} + +/* tall Nitro banner */ +.presence-stage .pc-banner { + height: 220px; +} + +.presence-stage .presence-card.has-banner-color::before { + height: 150px; +} + +/* header — roomier, big overlapping avatar */ +.presence-stage .pc-head { + gap: 1rem; + padding: 0.9rem 1.4rem; + align-items: flex-end; +} + +/* keep the identity column bottom-aligned to the avatar's visible lower + half, whether or not a custom-status bubble is present */ +.presence-stage .presence-card.has-custom .pc-head { + align-items: flex-end; +} + +/* only the avatar pokes up into the banner; the name/identity block stays + in the solid area below it */ +.presence-stage .presence-card.has-banner .pc-head, +.presence-stage .presence-card.has-banner-color .pc-head { + margin-top: 0; +} + +.presence-stage .presence-card.has-banner .pc-avatar, +.presence-stage .presence-card.has-banner-color .pc-avatar { + margin-top: -60px; +} + +.presence-stage .pc-avatar, +.presence-stage .presence-card.has-banner .pc-avatar, +.presence-stage .presence-card.has-banner-color .pc-avatar { + width: 120px; + height: 120px; +} + +.presence-stage .pc-av-img, +.presence-stage .presence-card.has-banner .pc-av-img, +.presence-stage .presence-card.has-banner-color .pc-av-img { + width: 120px; + height: 120px; + /* solid dark plate + ring so the banner sits clearly BEHIND the avatar + (the PFP itself is partly transparent) */ + background: var(--crust); + border: 6px solid var(--crust); +} + +.presence-stage .pc-av-deco, +.presence-stage .presence-card.has-banner .pc-av-deco, +.presence-stage .presence-card.has-banner-color .pc-av-deco { + width: 152px; + height: 152px; +} + +.presence-stage .pc-status { + width: 24px; + height: 24px; + border-width: 5px; +} + +/* identity block — bigger type */ +.presence-stage .pc-name { + font-size: 1.5rem; +} + +.presence-stage .pc-user { + font-size: 0.9rem; +} + +.presence-stage .pc-badges { + margin-top: 0.3rem; +} + +.presence-stage .pc-badge { + width: 22px; + height: 22px; +} + +/* bio + connections — wider, padded to match */ +.presence-stage .pc-bio { + margin: 0 1.4rem 0.8rem; + padding: 0.7rem 0.9rem; + font-size: 0.88rem; +} + +.presence-stage .pc-connections { + margin: 0 1.4rem 0.9rem; + gap: 0.5rem; +} + +.presence-stage .pc-conn { + font-size: 0.74rem; + padding: 0.3rem 0.65rem; +} + +/* activity rows — larger artwork + text */ +.presence-stage .pc-sections { + gap: 0.6rem; + padding: 0 1.4rem 1.1rem; +} + +.presence-stage .pc-row { + padding: 0.7rem 0.8rem; + border-radius: 14px; +} + +.presence-stage .pc-art, +.presence-stage .pc-row-ic-img, +.presence-stage .pc-ic-wrap, +.presence-stage .pc-ic-wrap .pc-row-ic-img { + width: 56px; + height: 56px; +} + +.presence-stage .pc-row-title { + font-size: 0.95rem; + max-width: none; +} + +.presence-stage .pc-row-sub { + font-size: 0.82rem; + max-width: none; +} + +.presence-stage .pc-progress { + width: 100%; +} + +.presence-stage .pc-custom-text { + font-size: 0.86rem; + max-width: none; +} + +/* wishlist + star scale up a touch */ +.presence-stage .pc-star { + font-size: 1.2rem; +} + +@media (max-width: 720px) { + .presence-stage .presence-card { + max-width: 100%; + } +} + +@media (max-width: 480px) { + .presence-stage .pc-banner { + height: 150px; + } + + .presence-stage .pc-avatar, + .presence-stage .presence-card.has-banner .pc-avatar, + .presence-stage .presence-card.has-banner-color .pc-avatar { + width: 92px; + height: 92px; + } + + .presence-stage .pc-av-img, + .presence-stage .presence-card.has-banner .pc-av-img, + .presence-stage .presence-card.has-banner-color .pc-av-img { + width: 92px; + height: 92px; + } + + .presence-stage .presence-card.has-banner .pc-head, + .presence-stage .presence-card.has-banner-color .pc-head { + margin-top: 0; + } + + .presence-stage .presence-card.has-banner .pc-avatar, + .presence-stage .presence-card.has-banner-color .pc-avatar { + margin-top: -46px; + } + + .presence-stage .pc-name { + font-size: 1.25rem; + } +} + diff --git a/css/shared/responsive.css b/css/shared/responsive.css new file mode 100644 index 0000000..4e5ed66 --- /dev/null +++ b/css/shared/responsive.css @@ -0,0 +1,209 @@ +/* ============================================================ + responsive.css — cross-page responsive overrides (mobile layout reflow, narrow-screen tweaks). + ============================================================ */ + +/* ============================================================ + 12. RESPONSIVE OVERRIDES + ============================================================ */ + +/* Shrink to fit narrow / short screens so the hub never scrolls */ +@media (max-width: 420px), +(max-height: 640px) { + .hub-header { + margin-bottom: 1.25rem; + } + + .hub-header h1 { + font-size: 1.6rem; + } + + .pfp { + width: 72px; + height: 72px; + margin-bottom: 0.5rem; + } + + .links { + grid-template-columns: repeat(auto-fit, 60px); + gap: 0.6rem; + } + + .link-card { + width: 60px; + height: 60px; + border-radius: 13px; + } + + .icon { + width: 26px; + height: 26px; + } +} + +/* Cat picker: 2 columns on very narrow screens */ +@media (max-width: 420px) { + .cat-grid { + grid-template-columns: repeat(2, 1fr); + } +} + +/* Mobile layout — single vertical scroll, stacked widgets */ +@media (max-width: 640px) { + + html { + height: auto; + /* Single vertical scroll root on mobile; clip horizontal overflow + so the absolutely-positioned link tooltips can't pan the page. */ + overflow-x: hidden; + overflow-y: auto; + } + + body, + body:has(.dev-info), + body:has(.project-grid), + body:has(.friend-grid) { + flex-direction: column; + justify-content: flex-start; + align-items: center; + gap: 1rem; + height: auto; + min-height: 100dvh; + overflow-x: hidden; + overflow-y: visible; + padding: 1.25rem 1rem 2rem; + } + + /* 1 — Top bar: the two single-item widgets, side by side */ + .topbar { + order: 1; + display: flex; + flex-direction: row; + flex-wrap: wrap; + align-items: center; + justify-content: center; + gap: 0.6rem; + width: 100%; + } + + /* FIX: the presence card injected by discord.js replaces #discord + with .presence-card (position:fixed by default in api.css). Inside + .topbar on mobile it must flow normally. */ + .topbar .presence-card, + .topbar .beta-bar { + position: static; + inset: auto; + } + + /* FIX: presence-card max-width so it doesn't overflow narrow screens */ + .topbar .presence-card { + max-width: min(100%, 320px); + width: 100%; + } + + /* 2 — Main content */ + .hub, + body:has(.dev-info) .hub, + body:has(.project-grid) .hub, + body:has(.friend-grid) .hub { + order: 2; + width: 100%; + max-width: 100%; + } + + /* 3 — Page nav as a centered group */ + .nav { + order: 3; + position: static; + inset: auto; + width: 100%; + } + + .nav-links { + flex-direction: row; + flex-wrap: wrap; + justify-content: center; + gap: 0.5rem; + } + + /* The selected-item pointer triangle / offset only makes sense in + the vertical desktop nav — drop it on mobile */ + .nav-link.selected { + margin-left: 0; + } + + .nav-link.selected::before { + display: none; + } + + /* 4 — System badges, centered and wrapping */ + .badges { + order: 4; + position: static; + inset: auto; + width: 100%; + flex-direction: row; + flex-wrap: wrap; + align-items: center; + justify-content: center; + /* FIX: restore pointer-events on mobile so pokéball and badges are tappable */ + pointer-events: auto; + } + + /* FIX: hide tooltips on touch (they'd stick on tap) */ + .link-card:hover .link-text { + opacity: 0; + pointer-events: none; + } + + .hub-header { + margin-bottom: 1.5rem; + } + + /* Keep the dev-info / projects / friends content from butting up + against the nav below it */ + .dev-info, + .project-grid, + .friend-grid { + padding-bottom: 1rem; + } + + /* FIX: bot sections need a bit of breathing room */ + .section+.section { + margin-top: 1.5rem; + } + + /* FIX: narrow waka bar label column so bars aren't crushed */ + .waka-bar-row { + grid-template-columns: 5rem 1fr auto; + } + + /* FIX: terminal height — respect short landscape viewports */ + .terminal { + width: 94vw; + height: clamp(300px, 65dvh, 70vh); + } +} + +/* Very narrow phones — squeeze waka bar name column further */ +@media (max-width: 380px) { + .waka-bar-row { + grid-template-columns: 4rem 1fr auto; + gap: 0.4rem; + } + + .waka-bar-val { + font-size: 0.66rem; + } + + /* Single column + slightly smaller avatars on very small screens */ + .project-grid { + grid-template-columns: 1fr; + } + + .project-card-img { + width: 48px; + height: 48px; + } +} + + diff --git a/css/shared/theme-switcher.css b/css/shared/theme-switcher.css new file mode 100644 index 0000000..8930859 --- /dev/null +++ b/css/shared/theme-switcher.css @@ -0,0 +1,211 @@ +/* ============================================================ + theme-switcher.css — top-right theme switcher button + the + secret cat-mode picker modal it can open. + Shared across all pages. + ============================================================ */ + +/* ============================================================ + 7. THEME SWITCHER (shared, icon button top-right) + ============================================================ */ +.beta-bar { + position: fixed; + top: 1rem; + right: 1rem; + z-index: 7; + display: flex; + align-items: center; + gap: 0.5rem; +} + +/* cat-collection button icon: the classic oneko idle frame, scaled down + from the 256x128 sprite sheet (idle frame lives at -96px,-96px) */ +.beta-cat-icon { + width: 22px; + height: 22px; + display: block; + background-image: url('/assets/oneko/classics/classic.png'); + background-repeat: no-repeat; + background-size: 176px 88px; + background-position: -66px -66px; + image-rendering: pixelated; +} + +.beta-btn { + display: inline-flex; + align-items: center; + justify-content: center; + padding: 0.35rem; + border-radius: 999px; + background: var(--surface-0); + border: 1px solid var(--surface-1); + cursor: url('../assets/cursor/pointer_0.png'), pointer; + transition: border-color 0.15s ease, transform 0.15s ease; +} + +.beta-btn:hover { + border-color: var(--pink); + transform: translateY(2px); +} + +.beta-icon { + width: 22px; + height: 22px; + display: block; +} + + +/* ============================================================ + 10. SECRET CAT MODES (toast + picker modal) + ============================================================ */ +.cat-toast { + position: fixed; + left: 50%; + bottom: 4.5rem; + transform: translateX(-50%) translateY(8px); + z-index: 2147483647; + padding: 0.4rem 0.9rem; + border-radius: 999px; + background: var(--crust); + border: 1px solid var(--pink); + color: var(--text); + font-size: 0.8rem; + white-space: nowrap; + opacity: 0; + pointer-events: none; + transition: opacity 0.2s ease, transform 0.2s ease; +} + +.cat-toast.show { + opacity: 1; + transform: translateX(-50%) translateY(0); +} + +.cat-picker { + position: fixed; + inset: 0; + z-index: 2147483646; + display: flex; + align-items: center; + justify-content: center; + padding: 1rem; + background: rgba(17, 17, 27, 0.65); + backdrop-filter: blur(2px); +} + +.cat-picker[hidden] { + display: none; +} + +.cat-picker-panel { + width: min(94vw, 430px); + max-height: 82vh; + overflow-y: auto; + background: var(--base); + border: 1px solid var(--surface-1); + border-radius: 16px; + padding: 1rem; + box-shadow: 0 16px 48px rgba(0, 0, 0, 0.55); +} + +.cat-picker-head { + display: flex; + align-items: center; + justify-content: space-between; + margin-bottom: 0.85rem; + font-weight: 700; + color: var(--pink); +} + +.cat-picker-close { + background: none; + border: none; + color: var(--subtext-0); + font-size: 1.35rem; + line-height: 1; + cursor: url('../assets/cursor/pointer_0.png'), pointer; + padding: 0 0.25rem; +} + +.cat-picker-close:hover { + color: var(--text); +} + +.cat-grid { + display: flex; + flex-direction: column; + gap: 1rem; +} + +.cat-section-title { + margin: 0 0 0.55rem; + font-size: 0.72rem; + font-weight: 700; + letter-spacing: 0.04em; + text-transform: uppercase; + color: var(--mauve); + border-bottom: 1px solid var(--surface-1); + padding-bottom: 0.3rem; +} + +.cat-section-items { + display: grid; + grid-template-columns: repeat(3, 1fr); + gap: 0.6rem; +} + +.cat-option { + display: flex; + flex-direction: column; + align-items: center; + gap: 0.3rem; + padding: 0.75rem 0.4rem 0.6rem; + border-radius: 12px; + background: var(--surface-0); + border: 1px solid var(--surface-1); + color: var(--text); + font-family: inherit; + font-size: 0.74rem; + text-align: center; + cursor: url('../assets/cursor/pointer_0.png'), pointer; + transition: transform 0.15s ease, border-color 0.15s ease; +} + +.cat-option:hover:not(.locked) { + transform: translateY(-2px); + border-color: var(--pink); +} + +.cat-option.current { + border-color: var(--pink); + box-shadow: inset 0 0 0 1px var(--pink); +} + +.cat-option.locked { + cursor: url('../assets/cursor/default_0.png'), default; + opacity: 0.75; +} + +.cat-preview { + /* 30px window + the -97px,-97px position = the idle frame inset 1px on + every side, so no preview can catch pixels from neighbouring frames */ + width: 30px; + height: 30px; + margin: 7px 1px 11px; + background-repeat: no-repeat; + image-rendering: pixelated; + transform: scale(1.7); + transform-origin: center; +} + +.cat-name { + font-weight: 500; +} + +.cat-hint { + margin: 0.85rem 0 0; + font-size: 0.68rem; + color: var(--subtext-0); + text-align: center; +} + + diff --git a/css/shared/visitor-counter.css b/css/shared/visitor-counter.css new file mode 100644 index 0000000..f6def84 --- /dev/null +++ b/css/shared/visitor-counter.css @@ -0,0 +1,57 @@ +/* ============================================================ + visitor-counter.css — #visitor-counter widget, top-right. + Shared across all pages. + ============================================================ */ + +/* ============================================================ + 15. VISITOR COUNTER (#visitor-counter) + Fixed to top-right, below .beta-bar (theme + cat buttons). + ============================================================ */ +#visitor-counter { + position: fixed; + top: 4rem; + /* clears the ~48px beta-bar + gap */ + right: 1rem; + z-index: 6; + display: flex; + flex-direction: column; + align-items: center; + gap: 4px; +} + +#visitor-counter .vc-label { + font-size: 0.65rem; + letter-spacing: 0.06em; + text-transform: lowercase; + color: var(--subtext-0); + font-family: 'Comic Code', ui-monospace, monospace; +} + +/* Boot reveal: fade in with the rest of the chrome */ +#visitor-counter { + transition: opacity 0.6s ease, transform 0.6s ease; +} + +body.term-booting #visitor-counter { + opacity: 0; + transform: translateY(8px); +} + +body.term-chrome-in #visitor-counter { + opacity: 1; + transform: none; +} + +/* Mobile: static in topbar flow */ +@media (max-width: 640px) { + #visitor-counter { + position: static; + margin: 0 auto; + } + + .topbar #visitor-counter { + order: 2; + } +} + + diff --git a/dev-info/index.html b/dev-info/index.html index 0744992..3d4db59 100644 --- a/dev-info/index.html +++ b/dev-info/index.html @@ -72,6 +72,7 @@ Music 88x31 Guestbook + ASCII diff --git a/discord/index.html b/discord/index.html index cd2b6f0..1527825 100644 --- a/discord/index.html +++ b/discord/index.html @@ -70,6 +70,7 @@ Music 88x31 Guestbook + ASCII diff --git a/guestbook/index.html b/guestbook/index.html index d516e39..717666d 100644 --- a/guestbook/index.html +++ b/guestbook/index.html @@ -68,6 +68,7 @@ Music 88x31 Guestbook + ASCII diff --git a/humans.txt b/humans.txt new file mode 100644 index 0000000..1b40a01 --- /dev/null +++ b/humans.txt @@ -0,0 +1,110 @@ +/* TEAM */ +Owner and Developer: Clove Twilight, AKA Doughmination + +/* SITE */ +Built with: HTML, CSS, JS +Hosted at: c.stupid.cat +Language: English + +/* THANKS */ +Ari for helping with some CSS (@AriTheStupidCat on GitHub) +git.gay for hosting the repo + + + +/* SITE ASCII */ +MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMWK00KNWMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMWXOxl:,.....cXMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM +MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMNk:'..',:ox0XWMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMNKxl:'...........oNMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM +MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMNo...........,:okKNMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMWKkl;................'kWMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM +MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMWd.................;lxKNMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMN0d:'....................:XMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM +MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMO,.....................;okXWMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMNOo;.............',,;clc:,'.'xWMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM +MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMNl....''''''....... .......':d0NWMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMN0o;..............',,;ldxoodl;'.cKMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM +MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMO;.',;:llolc;''...... .........;lkXWMMMMMMMMMMMMMMMMMMMMMMMMMMMMMWXx:............. ...,;;cdxc,;oxc,',kWMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM +MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMNd',,:oxxdoxkd:,'....... ..........'cxKWMWWNNXXXXXKKKKKKK00KKKXNX0o,............. ....,;;cxxl;cdd:,'.lNMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM +MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMKc';:okd:''cxko;''....... ...........':lodddollc:;,,''.......'''. .......... ......',;:ldxxxdc,'..;KMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM +MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMWO:,;:okd:,:okxl;,'......... ...........'';:cc:,'... .............. ... .......',;::cllc;,'...'kMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM +MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMWx,,;;cdkkxkkxo:;,'.......... ..,:lodxkOO00O00OOOOkdl;.................... ......';:lodddoc;'.....oWMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM +MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMNo.',;:cloooooolc:,'.......';cdk0KKK0OO000OkkkOOOOO00Ox:............... . ...;oxkkkkkkko;'....cNMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM +MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMXc..',;:ccodxkkkkxl;'..,:oxOO0KKK00OkO00OkkkkkkxxxxkkOOx,. ............ ..:odlcclxkko,....;KMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM +MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMK;...',:ldkkxolldxdl:lxOOOOkOO00K0OOKXXK00000000OOOkxxkk:. ... ....................';okkd:'...,0MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM +MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMK;...';cxkko;...,ldxOOOkkxxk0KXNXKKXNNK0000000KKKKK0Oxxx:. .. ......... .............. .'okkd;....'OMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM +MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM0,..',:dkkl'...,okOOkkxxxk0XNNNXKKXNNK00000000KKKKKKKOxc.. ..';;:cclllc:,'.. ............ .:xxc'.....kMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM +MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM0,..',lxkx:...:xOkkkxxkO0KNNNNXKKNWNXK000000000KKKKK0d;... 'ooooooooooooool:,..... ............',.......xWMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM +MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMO,..',cxkxl'.:xkkkxkOO00KNNNNXKXNWWXKKKKKKKK00KKK0Od;..... 'odooooooooooooooolc::::;,............ ......dWMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM +MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMWWNXXXNNWWMMMM0,...';lxkkl;okkxxO0000KNNNNXKXWWNXKKKKKKKKKK0Odoc,....... 'cooooooooooooooooooolcclol:'.......... .....xMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM +MMMMMMMMMMMMMMMMMMMMMMMMMMMMMWX0OxxddddddxkkO0Xk,....',coxo;cxxxO0000KNNNNXKXWWNXKKKKKKK0Oxl;'...........;llcccloooooooooooooooooolclooc,......... ....kMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM +MMMMMMMMMMMMMMMMMMMMMMMMMMMMMXOkkkkxolcclllooodl........,;;..;ok0000KNNNNXKXWWNXKKK0Okdl:'..............:oooo:,;coooooooooooooooooolccoool;........ . .oNMMMWNXK0OOkkkOO0KNWMMMMMMMMMMMMMMMMM +MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMWX0Okxollllllooooc. .......... ..,:loxO0KK0O0K0Oxolc:;'.................,looooool:;looooooooooooooooool:cooool;....... .:x0OkxdooooollooooodkKWMMMMMMMMMMMMMMM +MMMMMMMMMMMMMMMMMMMMMMMMMMMNKOxdoooooooooodooodl. .......... .......'''''..........................,coooooooooolccloodoooooooooooooooccldoool;..... .;:clooooollcccldxO0KXNWMMMMMMMMMMMMMMM +MMMMMMMMMMMMMMMMMMMMMMMMWKOxooooooooooooooddoool' .......... .............................. ..;loddolooooooooolccloooooooooooooooooccooooooc. .. ..;l:;coooooooooooooodkOKNMMMMMMMMMMMMMMM +MMMMMMMMMMMMMMMMMMMMMMN0xooooooooooooooooodooool'.......... . ................... .........'cooooooollooooooooolcclooooooooodoooodl:cooooooc. .:oooo::loooooooooooooooooxkKNMMMMMMMMMMMM +MMMMMMMMMMMMMMMMMMMMWKxoooooooooooooooooodoooool;......... .. .... ... .............',;:cc::looooooolloooooooooolccloodooooddoooooc:oooooooc'':oooooo::loooooooooodooooooooxOXWMMMMMMMMM +MMMMMMMMMMMMMMMMMMWKxooooooooooooooooooooooodollc. ...... .. ......,:ccc:;;;;;;::c:;:clloooolc::looooooolloooooooodoolcclooooooooooool:looodooooooooooooo::ooooooooooooooooooooodOXWMMMMMMM +MMMMMMMMMMMMMMMMMNOdooooooooooooooooooooooooollol' ..... .. ....':ooooooodoooooooo:cooooolcldx0kllodooooolloooooooooooooccclooodoooool:ldoodoooooooooooool:coooooooooooooooooooooodONMMMMMM +MMMMMMMMMMMMMMMWKxooooooooooooooooooooooooooolloo,...... .. ..'coooooooooooooooooc:looolclkXWWWNkllooooooolllooooooooooooolccloooooool;cooooooooooooooooooc:loooooooooooooooooooooood0WMMMM +MMMMMMMMMMMMMMW0doooooooooooooooooooooooooooolooo:...... ... ,ldooooooooooooooool:loolc:cOWWWWWWNOlloooooooolloooooooooooooolccclooool;;loooooooooooooooooo::oooooooooooooooooooooooookXMMM +MMMMMMMMMMMMMNkoooooooooooooooooooooooooodoolloool'......''. .'coooooooooooooooodoccooclxokNWWWWWWWW0oloooooooooloooooooooooooooolccclolcccooooooooooooooooooc:loooooooooooooooooooooooooxKWM +MMMMMMMMMMMMNkoooooooooooooooooooooooooooollcloodo:..'',;:c;..,cooooooooooooooooooc:llcd0kdKWWWWWWWWWWXxllooooooooooooooooooooooooooolcc:oxcloooooooooooooooooo:cooooooooooooooooooooooooood0W +MMMMMMMMMMMNkoooooooooooooooooooooooooooolllloddddl,.',:lodlclcloooooooooooooooool::::odo;cx0KXXNWWWWWWNOolooooooooooooooooooooooooooooolll::oooooooooooooooooo::ooooooooooooooooooooooooooooO +MMMMMMMMMMWOoooooooooooooooooooooooooooollllloddol:;,;;:cclloccooooooooooooooolc:,..'','.......',:lx0XWWWXxlloooooodooolooooooooooooooooooolcccclooooodooooooooc;coooooooooooooooooooooooooooo +MMMMMMMMMW0oooooooooooooooooooooooooodollllllc:;cloolc:::::::;coooooooooooooolc:;,ck0Okxolodolc::,...'cxKWWKxlloooooodolcclooooooooooooooooooollcccclooooooooool;:looooooooooooooooooooooodooo +MMMMMMMMMXdooooooooooooooooooooooodoooolllc:'..';:lodddlc:;;,,coooooooooooooooooclO0000xdOXXNNNNNX0kl,. .cONN0xllooooooool:;:clloooooooooddooooooollcccclloooool::lloooooooooooooooooooooooooo +MMMMMMMMNkoooooooooooooooooooooooooodollc,......'',;:ldxdlc;,,cooooooooooooooooddk0XNWNddNWWWWWWWWWWWN0d:;oXWWNKxolooooooooc:;:cc:::::clooooolllllllllc::;;:looo::lllooooooooooooooooooooooooo +MMMMMMMW0ooooooooooooooooooooooooooooooc. .........',;:cdxdl:;cooooodoooooooodxdxKWWWWKokWNNXXXXXXNWWWWWNXK0KNWWWXxccloooodol;'.......'oxc,;clollccccccllllloooo:;cllooooooooooooooooooooooooo +MMMMMMMKdoolloooooooooooooooooooooooool' ............',;:ldxdccooooooooooooddxdldNWWWNOlONNNNXXXKK00O0XWWWNK00XWWWOccccclll:'..''',:;cONXkl,.,cdxxxdooddoooooooo::cloooooooooooooooooooooooooo +MMMMMWKdolccooooooooooooooooooooodoodo,................',;coxocoooolloooooodxdoclxoc:;..',,;:ldxkKNNKOxkKWWWX0OXWNklollxOxolccloolc:ckNWWWWx::::ldxxddoooooooodo::lloooooooooooooooooooooooooo +MMMMW0dllollodooooooooooooooooooooooo:...................,;:llcooooclooooodxdo:. .,lkKXkONWWWXO0XXdclo0NKOxllcccccccclxKWWWxcodooodddxddooooooooc:lllooooooooooooooooooooooooo +MMMXxlld0Kdlooooooooooooooooooooooool'....................';:::loooccoooodxxdo; ............;clc. .cxKNWWWNKkK0lcxXN0OKOlldool:codoox0XXd:ooodoooodxxdoloooooc:lllooooooooooooooooooooooooo +MNOddOXWMXolooooooooooooooooooooodooc......................';:;:oooccoooodxdool. ...... ...lKNNKoc;. .c0NNNNKOO0kONX0OKNKoldolld0XXKKKKKKo:ooodooooodxxoloooool:cllooooooooooooooooooooooooo +MWNNWMMMMXdloooooooooooooooooooooooo;.......................,;:;cooc:looodxdool:'...... ...,ldl,'xKkl..oXNNNXOOKNNX0k0NNKdcoc'';:::cloxO0ocooooooodoodxoclooooo::clooooooooooooooooooooooooo +MMMMMMMMMWxloooooooooooooooooooooooo,.......................',:;:loc;:ooodxdoollo;..... ...';c;.,0WWN0ooKXXXKOOKNXKkOXNXkc:;. ...'cooooooooooddlclooooc;:looooooooooooooooooooooooo +MMMMMMMMMM0olooooooooooooooooooooooo,........................,;:;:ll,,coodxxdoocxx,...............oNMMMMXOKXXX0kOKXX0k0X0o..... ..,dkl;c;'. .:oddooooodxdc:coodo:;looooooooooooooooooooooooo +MMMMMMMMMMNxlooooooooooooooooooooooo,........................';:cccc;',codxxdoocoOxc,''..........oXMMMWNXKKKK0OkOO00Ok0Kkcc;... .;od:oXXKx'.'cooooooooodxoc::lool::ooooooooooooooooooooooooo +MMMMMMMMMMMXdloooooooooooooooooooooo;........................',:cooc;''';ldxxdolcxOOkxd:;ccc:;;;lkO0XXK000000OkOOOOOOkOKO0K:... .:l',OMWKc,:ooooooooolcdxllolc:cll::cooooooooooooooooooooooo +MMMMMMMMMMMM0olooooooooooooooooooood:.........................,:cokd:'...':oxkxoclkkkkkolxOOOOOOOkkOOO00000OOkO00000OkO00XXl..........oNXx;,loooooooooo:lxdllooooc:::;,;cooodooooooooooooooooo +MMMMMMMMMMMMWOllooooooooooooooooooool' .......................,;cokxc,'...'cldkxocokkkkdcoxkkkkOOOOOOOO00OOkkO0000000OkO00Kx:,''.....,xxcc::oooooooodo::dxolloooollollcccooooooooooooooodooooc +MMMMMMMMMMMMMWklooooooooooooooooooooo;.......................',:cdkxc,'...;kxllddooxxxxdlcdxkkkkkOOOOOOOOkOO000000000kkOO000Okkxddocccloxxccooooooooo::dxdoloooolloooooooooooooooooooooooooolo +MMMMMMMMMMMMMMNklooooooooooooooooooodl'......................';:lxkd:,'...cO0OxollodxxxxdlokkkkkkkkkkkkkkO0000000OO0OddOOO000000000000000d:ldoodoool:cdxooolodooloooooooodoooooooooooooooooloK +MMMMMMMMMMMMMMMNxlooooooooooooooooooooc......................,;cokxl;,...'oO00OOkdoloxxxxddxkkkkkkkkkkOO000000000O0K0dok0OOO000000O0OOO0kl:odooodolclddooollodolloooooooooooooooooooooooooll0W +MMMMMMMMMMMMMMMMXdloooooooooooooooooooo:....................,;:lxko:,'...cok0000OOOkkkkkkkddkkkkkkOOO00000KKKKKKKKKKKklx00OOOOOO00O0OOOOd:loooooooodddoooolloollooooooooooooooooooooooooollOWM +MMMMMMMMMMMMMMMMMKolooooooooooooooooooooc'.................,;:ldkdc;'..'coox0KKK00000OOOOOkkOO00000000KKKKKKKKKKKKKKOkk0KK00OOkkkOOOOOOklcodddddxddddooooollooooooooooooooooooooooooooooolkWMM +MMMMMMMMMMMMMMMMMW0lloooooooooooooooodoool,..............',;:lxkdc;'..;looodOXKKKKKKKKKKKKKKKKKKKKKKKXXXXXXXXXXXXXXKKKXKKKKKK00OOOkkkkkxodxdoooooooooooooolloooooooooooooooooooooooooooolxNMMM +MMMMMMMMMMMMMMMMMMWkloooooooooooooooooooolll,.. .......',;:coxxo:,'.,cooooookXXXXXXXXXXXXXXXXXXXXXNNNNNNNNNNNNNNNNNNNNXXXXXXKKKKK0000Oocllc:cllloooooooooolcloooooooooooooooooooooodoooldXMMMM +MMMMMMMMMMMMMMMMMMMXdloooooooooooooooooolloool;.. ....',:loddoc;,;;,cooolooloKNNNNXXXNXNNNNNNNNNNNNXNWWWWWWWWWWWWWWWNNNNNNNXXXXXXKKK0x:;;:loooolooooooooooocloooooooooooooooooooooodooloKMMMMM +MMMMMMMMMMMMMMMMMMMWOloooooooooooooooooolooooodoc:;,,,;:lllc:;,',cc':ooc;lolcxKNNNNNNNNNNNNNNNWWWWN00K0KKKKKXNWWWWWWWWWNNNNNNNNXXXXXKOo::cooccolloooooooooollooooooooooooooooooooooodolOWMMMMM +MMMMMMMMMMMMMMWMMMMMKoloooooooooodoodoolooooooooodddooddoc;;;,'.,:,.;::;.;lccdOKNWWWWWWWWWWWWWWWWWWX0OKXXKKK0KXNWWWNXK00KNWWNNNNNNNNXkc::cooc,:llooooooooooolooooooooooooooooooooooooldXMMMMMM +MMMMMMMMMMMWKk0WMMMMKoloooooooooooodooloodollloodoodddoc;,''....';'.'....':,;dOO0XWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWNXXNNWWWWWWWNNNN0dc::;:lc:''::looooooooooolooooooooooooooooooooodolkWMMMMMM +MMMMMMMMMMNkcdNMMMMM0llooooooooooooolloooolcccllooool:,..,'.................'d0000KNWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWNKxl::::'':c;'.,,;ooooooooooooloooooooooooooooooooooolOMMMMWXK +MMMMMMMMMNxcckWMMMMNdlooooooooooooollooooooccllolcc:;,';cc;..................dXK0000XXNWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWXOdc:;;:::,..,'.....:ooooooooooooloooooooooooooooooodoolOWMMMMNx +MMMMMMMMMOllloOXWWKdlooooooooooooollooooooolclooooooooooooc,...,;............dNWX00000KKXNWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWX0Okl:::,',;;,.........;loooooooooooolooooooooooooooooooooldNMMMMMK +MMMMMMMMWkloooloddoloooooooooooolloooooooodolccllllllllooo:..';c;...........'xWWWNK0000000KXWWWWWWWWWWWWWWWWWWWWWWWWWWNXK0OkkO0o',;,...''.........:llooooooooooooloooooooooooooooooooolxNMMMWk +MMMMMMMMMKolooooooooooodooooooolooooodooooooolcc:::cclooo:..,coc'.'...'.....,kWWWWNXK00000OO0KXNWWWWWWWWWWWWWWWWWWNK0OOOO00K000d,.................,loloooooooooooolloooooooooooooooooooldkOkdl +MMMMMMMMW0l:loooooooooooooooollooooooddooooooooolcloooooc;:cooo;,c:'';,.....:0WWWWWWNK0000000OOO0KXWWWWWWWWWWWNK00OkOO0KKXXKK00Oc...............,,,cooolloooodoooooollooooooooooooooooooollloo +MMMMMMMMMXklloooooooodooooolloooooooooooooooooollodooooolooooooloolcc:....,,oXWWWWWWWWXK000000000OkO0XNWWWNX0kllxO00000KKKXKKK00x,............'',cllollollloolllloooolcloooooooooooooooooooooo +MMMMMMMMMMWXOxollooooooollooooooooooooodoodoooclooooooooooooooooodooc'',',;:xNWWWWWWWWWNXK000000000OkOO00OOkOd'..',:cldk0KKXXKKK0o'...''...''..;:loooolloooolloooooooolccloooooooooooooooooooo +MMMMMMMMMMMMMWNKOkxdlllooooollooooooooooooool;:oooooooooooooooooooooc:c:;::oONWWWWWWWWWWWNXK0000000000000000Kd. ........,;:clodxkkc..';:,..':;',loooooolooooooooooooodoolcclloooooooooooooooll +MMMMMMMMMMMMMMMWXKOxoooodddooooooooooooooooc,;lllooolcooooooooooooooool:::lOXNWWWWWWWWWWWWWWNXK0000000000000Kx..................'''..';cc;,,:llclooooooolloooooodooooooooollodollllllllllodxOK +O0KKXXNNXXKK0Okxdoooodxkkxdoooooooooooooooc''::,;lc,';looooooooooodoool::ckNNNWWWWWWWWWWWWWWWWNNNXKK00000000Kx. .....................,::cc:::looooooooooolooooooooooollooooodxO00OOOOOO0KXWMMM +0kxdddddddooooooodxk0KKOdooodooooooooooooc'.',..,'..':loollooolccllool::;c0WWWWWWWWWWWWWWWWWWWWWWWWNNNXXXXXNN0l'.....................';:clc::codooo:;loooooddooooooooolllooooodx0XWMMMMMMMMMMM +MWNXK0OOkkkkOOO0KXNWN0xooooddoooooooooool,...........'cl:,:ccc,',;loc::;'.;dKWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWX0Ol.....................';cl:,;clooll;.:oo:;lxOOxooooooooooodxdoooodk0XNWMMMMMMM +MMMMMMMMWWWMMMMMMMN0xooooooooooooooooooo:............';,..'','...;:;;;;.....'lkXWWWWWWWWWWWWWWWWWWWWWWWWWWWWWNKXXc'l;..................';:,.';:coc;,.,ll,.,lkXKkddoooooooodxOOkxdooodxO0KXXNNW +MMMMMMMMMMMMMMMMN0xoooooooooooooodoooooc'........................''',,.. .....,cx0NWWWWWWWWWWWWWWWWWWWWWWWWWWXXWx:OXc...................'...'',c:'...''...,o0XKOxdooooooooodOXNX0OkxxddddxkOO +MMMMMMMMMMMMMMN0xooodoooooooooooooooood:....'..'...................''.... ........;oOXWWWWWWWWWWWWWWWWWWWWWWWWWWO:kWKc............. .......................;xKXXKOxdooooooooodONMMMWNNXXXXNNW +MMMMMMMMMMMMWKxooooodooooooooooooooodkkc...,,';;..'..''.''..,'............ ..........;o0NWWWWWWWWWWWWWWWWWWWWWWWOcxWWK:.......... .........................oKXXXXKOxdooooooooox0NMMMMMMMMMMM +MMMMMMMMMMWKkdooooooooooooooooooodxk0KO:...;ccl;';,.'::;:,,cc'............ ............:kXWWWWWWWWWWWWWWWWWWWWWO:kWWW0;......... ..........................oKXXXXXXKkddoooooooooxKWMMMMMMMMM +MMMMMMMMWXkdoooooooodoooooooooodk0KKKKO:..'looo:;c,.:lclc:ll;............... ............:ONWWWWWWWWWWWWWWWWWWWx:OWWWWO,....... .....,;,.................'dKXXXXXXXX0kddoooooododkXWMMMMMMM +MMMMMMWXOdooooooooooooooooooodk0KXXXKK0l.':oooolll,,llcloll:'................. .... .........oXWWWWWWWWWWWWWWWWWNocKWWWWWx'...... ....';::;'.,,.....''..'..':kXXXXXXXXXXX0xdooooooooodONMMMMMM +MMMMMN0xooooodoooooooooooodxO0KKKKKKK0x:,;loodoodo:clc:lool,................... .... ........lOXWWWWWWWWWWWWWWW0cdWWWWNXKo...... ....'',:lllo:,;;''c:,:c,';,lKXXXXXXXXXXXKOxdoooooooooxKWMMMM +MMMWKkooooodooooooooooodxk0KKKKKKKKOo;..,cooooooooool::looc'..................... .... ........lXWWWWWWWWWWWWWNocKWWNXXXNXl..... .....':ooodollol:coooooc:;''dKXXXXXXXXXXXXKkxddooooooodkXWMM +MMNOdoooooooooodoooodxk0KXXKKKKK0xc'....'cooooooooool::clol,....................... .......... .dNWWWWWWWWWWWWk:kWWXKNWWWWK:... .....:ooooodoooooooodooo:''.;OXXXXXXXXXXXXXXKkdododooooox0WM +WKxooooooooooooooodxk0XNNNXXXKOo;........,cooooooooolc:::clc;'........................ ..........'kWWWWWWWWWWWkcxNWWNWWWWWWW0,.. ....;lolloolcloolodoooc;.....oKXXXXXXXXXXXXXXX0xoodoooooodON +Odoooooooooooooodxk0KXXXNNXKxc'...........,coooooooooc::,'';::;,........................ ......cXWWWWWWWWNkcxNWWWWWWWWNX0d' . ....;:,,:oc,;c:,;loc;'.......,kXXXXXXXXXXXXXXNN0xoooooooooox +oodoooooooooooddk0KXXXXXNXk:...............':oooooooolc:;.................................. ......kWWWWWWWXdckNWWNKOxdllcccclc. ........;,..''.'::,...........cKXXXXXXXXXXXXXNNX0doooodooooo +oooooooooodoodxOKXXXXXX0d;......''''''''''..':loodoooolc:,................................... .lXWWNX0d,'coooooollodxO0KKKO; ..............................,xXXXNNNNXXXXXXXXXXOoooooooooo +oooooooooooodkKXXXXXXXk:..........''''''.....',coooodoolc:,....................................... .,:::;;'..;oxk0KKKKKKKKK0kl;;;clc,'..''',.....................:0XXNNNNXXXXXXXXXXKxooooooooo +oooooooooodx0NNNXXXXXKc............''''.........,clodooool:;'..................................... .:oc;dOko:o0KKKKXK0OOkx:'ck0KKKOo:,:lclc;;;'... .............'dXNXXXXXNNNXXXXXXX0xoooooooo +ooooooooodxKNWWNXXXXNXc...........................';clooooolc;'................................... .cOd:;:oxxc'c00OOkkkkOOl'oNWWWWWNOolooooooc,..... .............;OXXXXXXXNNXXXXNNNN0dooooooo +oooooooodkKXXNNXXXXXXXo..............................',;:clooolc:;,'.............................. 'l:cd::ol:''dkkO0KKKKO,.ldddddddlcodoodo:'...... .............cKXXXXNNNXXNNNNNNNXkooooood +ooooooodOKXXNNNXXXXXXXx'..................................'''',,,,''.............................. .;;okl,;od:;kKK00OOOOd'.,;,,,,,,,;:looo:......... .............'dXXXNNNNXNNNNNNNNN0doooooo +oooooodOXXXXXNNNNNXXXXO;.......................................................................... .';,,,,cc;lkOOOOOOO0O:............':ll' ......... .............,kXNNNNNNNNNNNNNNNXkoooooo +ooddookKXXXXXNNNNNXXXXKc........................................................................... ,ldd:. ,d0KKKKKKKKKKk' ...........;c'.......... .............cKNNNNNNNNNNNNNNNXkoooooo \ No newline at end of file diff --git a/index.html b/index.html index 9c62b28..635f2df 100644 --- a/index.html +++ b/index.html @@ -88,6 +88,7 @@ Music 88x31 Guestbook + ASCII diff --git a/music/index.html b/music/index.html index 4d359f0..bd19590 100644 --- a/music/index.html +++ b/music/index.html @@ -74,6 +74,7 @@ Music 88x31 Guestbook + ASCII diff --git a/projects/index.html b/projects/index.html index 5923db4..d858a24 100644 --- a/projects/index.html +++ b/projects/index.html @@ -64,6 +64,7 @@ Music 88x31 Guestbook + ASCII