From 735b245871d94cb6ace8913cd1370b02b5aeb28b Mon Sep 17 00:00:00 2001 From: Leonardo Santiago Date: Sat, 1 Jun 2024 15:25:15 -0300 Subject: remove old theme, use bearblog theme instead --- .envrc | 1 + .gitmodules | 3 + .hugo_build.lock | 0 archetypes/default.md | 5 - blog.org | 102 +- config/_default/hugo.toml | 66 - config/_default/languages.en.toml | 28 - config/_default/markup.toml | 13 - config/_default/menus.en.toml | 67 - config/_default/module.toml | 3 - config/_default/params.toml | 146 -- content/_index.md | 10 + content/about.md | 19 + content/about/index.md | 15 - content/blog/rust-is-not-about-memory-safety.md | 93 + content/index.md | 10 - content/posts/.#correctness-is-all-you-need.md | 1 - content/posts/correctness-is-all-you-need.md | 32 - curriculum/answer.org | 101 - curriculum/cv.aux | 14 - curriculum/cv.bcf | 2393 -------------------- curriculum/cv.out | 4 - curriculum/cv.run.xml | 85 - hugo.toml | 52 + layouts/partials/custom_head.html | 17 + layouts/partials/footer.html | 1 + layouts/partials/nav.html | 7 + public/404.html | 706 ++---- public/about/index.html | 1062 +++------ public/android-chrome-192x192.png | Bin 17874 -> 0 bytes public/android-chrome-512x512.png | Bin 37648 -> 0 bytes public/apple-touch-icon.png | Bin 16152 -> 0 bytes public/authors/index.html | 549 ----- public/authors/index.xml | 12 - public/blog/correctness/index.html | 273 +++ public/blog/correctness/index.xml | 19 + public/blog/index.html | 277 +++ public/blog/index.xml | 19 + public/blog/rust/index.html | 273 +++ public/blog/rust/index.xml | 19 + public/categories/index.html | 549 ----- public/categories/index.xml | 12 - ...24b8e99386757d81f1bf8c4452c6220cf4c63970408.css | 1 - public/cv.pdf | Bin 0 -> 127017 bytes public/favicon-16x16.png | Bin 151 -> 0 bytes public/favicon-32x32.png | Bin 223 -> 0 bytes public/favicon.ico | Bin 4439 -> 0 bytes public/index.html | 710 ++---- public/index.json | 2 - public/index.xml | 26 +- ...b0c7e12cd161caace1dd794ac3d34d40937cbcc9ee12.js | 1 - ...ac0b74967e251c9a566d94d469dd28b8787fed4f46f5.js | 15 - ...8474b20b96fa38f7d85b405f165ff72b7b163c5ad11b.js | 1 - ...789bd5ce67c1d2a215b9fb258c3496a7cd25e7cb5fdf.js | 1 - public/js/zoom.min.js | 2 - public/lib/jquery/jquery.slim.min.js | 2 - public/page/1/index.html | 10 - .../posts/correctness-is-all-you-need/index.html | 750 ------ public/posts/index.html | 691 ------ public/posts/index.xml | 22 - public/posts/page/1/index.html | 10 - public/posts/software-correctness/index.html | 821 ------- public/robots.txt | 3 +- public/rust-is-not-about-memory-safety/index.html | 337 +++ public/series/index.html | 549 ----- public/series/index.xml | 12 - public/shin.ico | Bin 4439 -> 0 bytes public/shin.png | Bin 9754 -> 0 bytes public/site.webmanifest | 1 - public/sitemap.xml | 20 +- public/tags/coq/index.html | 689 ------ public/tags/coq/index.xml | 22 - public/tags/coq/page/1/index.html | 10 - public/tags/index.html | 549 ----- public/tags/index.xml | 12 - public/tags/rust/index.html | 689 ------ public/tags/rust/index.xml | 22 - public/tags/rust/page/1/index.html | 10 - ...in.css_83735de7ca999e9c17f3419b41b93fdb.content | 1 - .../main.css_83735de7ca999e9c17f3419b41b93fdb.json | 1 - ...e.scss_511aa33e99371f93fbf403479ebfd32e.content | 1 - ...mode.scss_511aa33e99371f93fbf403479ebfd32e.json | 1 - static/cv.pdf | Bin 0 -> 127017 bytes static/favicon-16x16.png | Bin 151 -> 0 bytes static/favicon-32x32.png | Bin 223 -> 0 bytes static/favicon.ico | Bin 4439 -> 0 bytes static/shin.png | Bin 9754 -> 0 bytes themes/blowfish | 1 - themes/hugo-bearblog | 1 + 89 files changed, 2233 insertions(+), 10821 deletions(-) create mode 100644 .envrc create mode 100644 .gitmodules create mode 100644 .hugo_build.lock delete mode 100644 archetypes/default.md delete mode 100644 config/_default/hugo.toml delete mode 100644 config/_default/languages.en.toml delete mode 100644 config/_default/markup.toml delete mode 100644 config/_default/menus.en.toml delete mode 100644 config/_default/module.toml delete mode 100644 config/_default/params.toml create mode 100644 content/_index.md create mode 100644 content/about.md delete mode 100644 content/about/index.md create mode 100644 content/blog/rust-is-not-about-memory-safety.md delete mode 100644 content/index.md delete mode 120000 content/posts/.#correctness-is-all-you-need.md delete mode 100644 content/posts/correctness-is-all-you-need.md delete mode 100644 curriculum/answer.org delete mode 100644 curriculum/cv.aux delete mode 100644 curriculum/cv.bcf delete mode 100644 curriculum/cv.out delete mode 100644 curriculum/cv.run.xml create mode 100644 hugo.toml create mode 100644 layouts/partials/custom_head.html create mode 100644 layouts/partials/footer.html create mode 100644 layouts/partials/nav.html delete mode 100644 public/android-chrome-192x192.png delete mode 100644 public/android-chrome-512x512.png delete mode 100644 public/apple-touch-icon.png delete mode 100644 public/authors/index.html delete mode 100644 public/authors/index.xml create mode 100644 public/blog/correctness/index.html create mode 100644 public/blog/correctness/index.xml create mode 100644 public/blog/index.html create mode 100644 public/blog/index.xml create mode 100644 public/blog/rust/index.html create mode 100644 public/blog/rust/index.xml delete mode 100644 public/categories/index.html delete mode 100644 public/categories/index.xml delete mode 100644 public/css/main.bundle.min.81c7ce66608dd0b86aa3e571076f8794993d50f0d4a5b153013edfc28642a93c4104edfdc604558908c3624b8e99386757d81f1bf8c4452c6220cf4c63970408.css create mode 100644 public/cv.pdf delete mode 100644 public/favicon-16x16.png delete mode 100644 public/favicon-32x32.png delete mode 100644 public/favicon.ico delete mode 100644 public/index.json delete mode 100644 public/js/appearance.min.516a16745bea5a9bd011138d254cc0fd3973cd55ce6e15f3dec763e7c7c2c7448f8fe7b54cca811cb821b0c7e12cd161caace1dd794ac3d34d40937cbcc9ee12.js delete mode 100644 public/js/main.bundle.min.b36dda9ec4ec11e967fd341e7d57b8c484ac7a39f8f329f7bcf7ce4812569de8607db866a086d4789956ac0b74967e251c9a566d94d469dd28b8787fed4f46f5.js delete mode 100644 public/js/page.min.b06a29d42a4ed16787978e2eee1e8c797b7698db2bc14ccee78f5c80ac566fc996190a73ad80a5e987558474b20b96fa38f7d85b405f165ff72b7b163c5ad11b.js delete mode 100644 public/js/process.min.62060bb247f4de2b6dde45903668fefb68d792f365587605177b1227c0cf43588701edaca0cb40e2c8e2789bd5ce67c1d2a215b9fb258c3496a7cd25e7cb5fdf.js delete mode 100644 public/js/zoom.min.js delete mode 100644 public/lib/jquery/jquery.slim.min.js delete mode 100644 public/page/1/index.html delete mode 100644 public/posts/correctness-is-all-you-need/index.html delete mode 100644 public/posts/index.html delete mode 100644 public/posts/index.xml delete mode 100644 public/posts/page/1/index.html delete mode 100644 public/posts/software-correctness/index.html create mode 100644 public/rust-is-not-about-memory-safety/index.html delete mode 100644 public/series/index.html delete mode 100644 public/series/index.xml delete mode 100644 public/shin.ico delete mode 100644 public/shin.png delete mode 100644 public/site.webmanifest delete mode 100644 public/tags/coq/index.html delete mode 100644 public/tags/coq/index.xml delete mode 100644 public/tags/coq/page/1/index.html delete mode 100644 public/tags/index.html delete mode 100644 public/tags/index.xml delete mode 100644 public/tags/rust/index.html delete mode 100644 public/tags/rust/index.xml delete mode 100644 public/tags/rust/page/1/index.html delete mode 100644 resources/_gen/assets/ananke/css/main.css_83735de7ca999e9c17f3419b41b93fdb.content delete mode 100644 resources/_gen/assets/ananke/css/main.css_83735de7ca999e9c17f3419b41b93fdb.json delete mode 100644 resources/_gen/assets/scss/dark-mode.scss_511aa33e99371f93fbf403479ebfd32e.content delete mode 100644 resources/_gen/assets/scss/dark-mode.scss_511aa33e99371f93fbf403479ebfd32e.json create mode 100644 static/cv.pdf delete mode 100644 static/favicon-16x16.png delete mode 100644 static/favicon-32x32.png delete mode 100644 static/favicon.ico delete mode 100644 static/shin.png delete mode 160000 themes/blowfish create mode 160000 themes/hugo-bearblog diff --git a/.envrc b/.envrc new file mode 100644 index 0000000..3550a30 --- /dev/null +++ b/.envrc @@ -0,0 +1 @@ +use flake diff --git a/.gitmodules b/.gitmodules new file mode 100644 index 0000000..c53b474 --- /dev/null +++ b/.gitmodules @@ -0,0 +1,3 @@ +[submodule "themes/hugo-bearblog"] + path = themes/hugo-bearblog + url = https://github.com/janraasch/hugo-bearblog.git diff --git a/.hugo_build.lock b/.hugo_build.lock new file mode 100644 index 0000000..e69de29 diff --git a/archetypes/default.md b/archetypes/default.md deleted file mode 100644 index c6f3fce..0000000 --- a/archetypes/default.md +++ /dev/null @@ -1,5 +0,0 @@ -+++ -title = '{{ replace .File.ContentBaseName "-" " " | title }}' -date = {{ .Date }} -draft = true -+++ diff --git a/blog.org b/blog.org index 3d55df4..2916438 100644 --- a/blog.org +++ b/blog.org @@ -6,38 +6,114 @@ * lowest case :PROPERTIES: :EXPORT_HUGO_SECTION: / -:EXPORT_FILE_NAME: index +:EXPORT_FILE_NAME: _index :END: a lower case only blog, purely for aesthetics. -here I talk about discrete mathematics (mostly computer science), including compilers, language theory, type theory, computability theory, software correctness, formal verification, and any other (entirely theoretical almost non-applicable) nerd topic you can think of. - +here I talk about discrete mathematics (mostly computer science), including compilers, language theory, type theory, computability theory, software correctness, formal verification, and any other (entirely theoretical, almost non-applicable) nerd topic you can think of. * about :PROPERTIES: -:EXPORT_HUGO_SECTION: /about -:EXPORT_FILE_NAME: index +:EXPORT_HUGO_SECTION: / +:EXPORT_FILE_NAME: about +:EXPORT_HUGO_CUSTOM_FRONT_MATTER: :menu main :END: -i'm leonardo santiago, a software engineer based in brazil. my interests are in compiler design, programming tools (emacs) and functional programming, usually dabbliing in related topics too. i'm most confortable in nix and rust, but i know a fair share of other languages. +i'm leonardo santiago, a software engineer based in brazil. my interests are in compiler design, programming tools (emacs), functional programming, and proof languages. i'm most confortable in nix and rust, but i know a fair share of other languages. -currently, software engineer @ [[https://mixrank.com][Mixrank]]. +currently, i work as a software engineer @ [[https://mixrank.com][Mixrank]], and you can find my curriculum [[./static/cv.pdf][here]]. -this blog was built using [[https://github.com/gohugoio/hugo][hugo]], and it's source code is openly available here: -@@hugo:{{< github repo="o-santi/nixos" >}}@@ +if you feel like smugly responding to any of my posts (or just want to kindly send me a message), these are my socials: +- [[mailto:leonardo.ribeiro.santiago@gmail.com][email]] +- [[https://www.linkedin.com/in/leonardo-ribeiro-santiago/][linkedin]] +- [[https://github.com/o-santi][github]] -you can find me at: @@hugo:[{{< icon "email" >}}](mailto:leonardo.ribeiro.santiago@gmail.com)@@ @@hugo:[{{< icon "linkedin" >}}](https://www.linkedin.com/in/leonardo-ribeiro-santiago/)@@ @@hugo:[{{< icon "github" >}}](https://github.com/o-santi)@@ @@hugo:[{{< icon "telegram" >}}](https://t.me/osanti4)@@ @@hugo:[{{< icon "twitter" >}}](https://twitter.com/o_santi_)@@ +this blog was built using emacs' excelent org-mode and [[https://github.com/gohugoio/hugo][hugo]] (with the [[https://github.com/janraasch/hugo-bearblog][bearblog theme]]). * blog :PROPERTIES: -:EXPORT_HUGO_SECTION: /posts +:EXPORT_HUGO_SECTION: /blog :END: -** rust is not about memory safety :coq:rust: +** rust is not about memory safety :rust:correctness: :PROPERTIES: -:EXPORT_FILE_NAME: correctness-is-all-you-need +:EXPORT_FILE_NAME: rust-is-not-about-memory-safety :END: +most of rust discussions nowadays revolve about memory safety, and how it is safer than C / C++ / zig / go / whatever language is being trashed on twitter that day. while yes, that is true - not that the bar for most of these is particularly high - what I think is the main point of the language is always glossed over: correctness. when one tries to criticize any of the aforementioned languages, one is answered with the following argument: +#+begin_quote +your program segfaults? skill issue +#+end_quote +but i'd like to make the counter-argument that, no, this has nothing to do with skill issue. + +*** formal language theory +the first thing one learns when they're studying formal languages (the field that studies grammars, state automata, etc) is that the rules that describe a certain grammar must match *exactly* the ones that you want to include in your language. this means that there's a bidirectional relationship between the grammar you describe (which directly define the automata that parses that language) and the words[fn:: formally they are defined as a sequence of tokens in certain alphabet that the automata closures over. normally we think of "words" as the whole program that we're parsing.] that it parses (which are related to the semantics of the program, how it executes). + +from it, it can be inferred that the grammar *must not* allow in the language any words that does not have defined semantics, and in the opposite direction, that the language should not specify semantics to any program that cannot be parsed by the rules of the grammar. both of these are required in order to make study of this grammar <-> language partnership fun, pleasing, and most importantly sound. + +going beyond, formal language theory also gives you the knowledge that the execution of any program can be given as a set of grammar rules in an abstract machine (the most famous one being a turing machine). in the same way you can define a set of grammar rules to parse parenthesized arithmetic expressions using a stack automaton, you can define a set of grammar rules to model the execution of a C program, and, albeit super complex, can be modeled as a turing machine. this usually gets the name of C abstract machine, and is the basis for formal specification of behavior in the language. + +and no, i'm not talking about modeling a C parser as a state machine (which probably is easier than most languages, if you ignore pre-processor stuff). i'm talking about modeling C *execution* as a language being parsed. drawing a parallel, when parsing parenthesized expressions, you pop things in and out of the stack to represent "balancedness", and in the same way, when "parsecuting" C code, you must write to memory, represent side effects, represent type casts and pointer conversions and everything *as part of the language*. + +in the same way that you'd hope that a parenthesized arithmetic expression parser would recognize that ~(1 + 2) + 3)~ is an invalid expression, you'd expect that the C compiler would correctly verify that the following series of tokens is not a /well behaved/ program: +#+begin_src c +int foo(int * myptr) { + *myptr = 5; +} +foo(NULL); +#+end_src + +i say /well behaved/ because i can't say /invalid/. it is in fact defined by the spec that when you dereference a ~NULL~ pointer the result is [[http://blog.llvm.org/2011/05/what-every-c-programmer-should-know.html][/undefined behavior/]]. and this is C's achilles heel: instead of outright banning programs like the one above (which i'd argue is the correct approach), it will happily compile and give you garbage output. + +framing it this way really exposes the fragility of C, because undefined behavior has to always be taken into account. and, by the nature of it, there is no way to represent it other than as a black box, such that, if your code ever encounters it, then literally all you can say is that *the whole result of the program* is undefined - that is, it can be anything. you cannot show properties, nor say what will happen once your program enters this state, as the C specification literally does not define it. it may come to a halt, write garbage to the screen or completely delete half of the files of your program, and there's no way to predict what will come out of it, by definition. in the lucky case, it will segfault while executing and you'll be extremely pissed off, but that is not at all guaranteed. this is akin to having a float expression with some deep term being ~NaN~, in that it eventually must evaluate to ~NaN~ and you can't draw any conclusions about the result of the expression (other that it isn't a number). + +language designers are by no means dumb, and yes, they know much, much more than me about these problems. undefined behavior exists exactly because there must be parts of your code that your compiler *must* assume that aren't possible, so that it can correctly compile. for example, let's say that you inadvertently try to dereference a pointer that you have no knowledge about. the C compiler simply does not have enough information to know if it is ~NULL~, if it is still pointing to valid memory, or if the memory has been initialized, so what it's approach is simply emit code *as if* it was a valid, initialized, non-null pointer. + +it is essential to realize that this is an *assumption*, and in almost most cases, it simply does not care whether or not it actually was actually still valid, so writing to it may have a myriad of effects of different effects (none of which are the compiler's concerns). sometimes, your system might correctly intercept a read/write from invalid/null memory and raise you a signal, but that is not guaranteed. + +and there are a huge number of tools to aid in finding undefined behavior, it's just that 1. they are not by any means standards of C development (not in spec and not in standard compilers) and 2 they are fallible and will always let some undefined programs slip by. + +*** runtime exceptions are not the solution + +most languages try to handle this by introducing some sort of runtime exception system, which i think is a terrible idea. while this is much, much safer than what C does, it still makes reasoning about the code extremely hard by completely obliterating locality of reason. your indexing operation may still be out of bounds, and while this now has defined outcomes, it is one of the possible outcomes of your program (whether you like it or not), and you must handle it. and, of course, no one handles all of them, for it is humanely impossible to do it in most languages because: + +1. it is hard to know when an operation can raise an exception, and under which conditions. +2. even if documented, it is never enforced that all exceptions must be gracefully handled, so some random function in a dependency of a dependency may raise an error from an unexpected corner case and you must deal with it. + +this is a symptom of virtually all modern languages, and none of them have any good answers to it. java mandates that you report in your function type signature the errors that it may raise (which is a rare java W), but it does let you write code with [[https://docs.oracle.com/javase/tutorial/essential/exceptions/runtime.html][unchecked exceptions]] that won't signal a compile error if ignored, which eventually will crash your minecraft game. python, ruby, php and most other languages (even [[https://www.tweag.io/blog/2020-04-16-exceptions-in-haskell/][haskell]] made this mistake) do not even attempt to signal when a function might raise an exception. javascript somehow manages to be even worse, by having horrible implicit-by-default type casts, having undefined AND null, using strings as UTF-16, using floats as standard numbers, implicitly inserting semicolons, and honestly the list could go on forever. + +the root of all these problems is, quite literally, the same: that your compiler (or interpreter) lets into your program execution states that you didn't anticipate for. one of the best of examples of the opposite, surprisingly enough, is regex matchers. while i concede that their syntax can be extremely confusing, they have the best property of software: if they compile, they work exactly as intended - which i henceforth will call *correctness*. this is because regular languages' properties and their state automata have been studied to extreme depths, and it is entirely possible to write a regex implementation that is *correct* (in the same way as above), going as far as providing formal verifications of that [fn::the excellent software foundations book [[https://softwarefoundations.cis.upenn.edu/lf-current/IndProp.html][explains thoroughly]] how one might formally write one possible regex matcher, and prove that the implementation is correct]. + +from this definition of *correctness* we can also derive a semantically useful definition for the word bug: an unexpected outcome for the program, that shouldn't be allowed in the language. of course java behavior might be defined for all inputs (for the most part, i'm sure there are might be problems here and there) but just because one possible outcome of program is ~NullPointerException~ doesn't mean that it is *expected*, making it, by my definition, a bug. + +*** make invalid states unrepresentable +what the regex example makes clear is that the key to correctness is to make your language tight enough to have defined and *desired* output for all possible inputs. this is not to say that it won't raise errors; much to the contrary, it must have parser errors saying that some strings aren't valid regexes. instead, it means that all errors are *predictable*, and *well defined* (in some sense). + +you, as the programmer, is then in charge of ensuring that the resulting regex program actually solves the problem you have at hands. want to match 3 words of 2 digit numbers followed by a capital letter? great, they can do that. want to match balanced parenthesized expressions? sadly, regex is incapable of ever solving that, because that language [[https://en.wikipedia.org/wiki/Pumping_lemma_for_regular_languages#Use_of_the_lemma_to_prove_non-regularity][is not regular]], so no matter how hard you try it will never solve it. + +in a way, there's a beauty in how C sidesteps this: it defines one of the possible program outputs as being /undefined/, and it is on the programmers behalf to tightly ensure that the program has 0 paths to /undefined behavior/. in fact, it is probably one of the most [[https://www.open-std.org/jtc1/sc22/wg14/www/docs/n1256.pdf][well specified languages]], which is what makes it suitable for writing formally verifiable programs [fn::through the use of external tools like Coq's [[https://vst.cs.princeton.edu/veric/][verifiable C series]]]. + +the main strength of rust, and where it differs from all mainstream languages, is that it has a very clear focus on program *correctness*. the raison d'être of the borrow checker is statically assuring that all references are pointing to valid memory, such that it is literally impossible for any borrow be null or to point to some freed memory (modulus [[https://github.com/Speykious/cve-rs][implementation errors of course]]). this completely rules out this possibility of bugs from the language we're trying to "parse". remember the C excerpt from above, where i said that the compiler should rule out the program as invalid? well, it is literally impossible to write that sort of program in rust, because one cannot construct a ~NULL~ reference. + +not only that, but rust languages features makes it so, so much easier to write *correct* software: sum types (tagged unions), ~Option~ instead of ~NULL~ (which in and of itself is amazing), ~Result~ for errors (making obligatory to handle all possible branches your program can take), a strong and powerful static type system, and ditching inheritance and classes in favor of traits. + +note that i never ever talked about memory safety. even in a world where C wasn't in fact full of memory vulnerabilities, rust would still be miles better, because it statically assures you that the *meaning of your program is tightly reproduced by the code you've written*. it is, by design, more correct than C, and the only way a problem can possibly happen is by side stepping rust static checks by using ~unsafe~. + +it is just a happy coincidence that this leads to a language that isn't garbage collected, that is relatively lean, fast, easy to embed, has good ergonomics and that enables you to write asynchronous and multi-threaded programs. these properties are awesome to boost rust to a very well regarded status between developers, but aren't at all related to languages that enable you to build reliable, correct software. out of curiosity, i'd happily defend the case that [[https://coq.inria.fr/][coq]] is also one of these languages, and it absolutely does not hold any of these any of those. + +*** software engineering as a craft + +finally, i think this relates to how i personally model the software development job as a whole. it starts by having some problem you think you can use computers to solve, and then follow 3 clearly stratified steps: + +1. define how one might solve the problem. this usually means splitting it into several possible cases and treating each and every one of them separately. +2. define an abstract machine that executes the very same steps, *and making sure that it tightly adheres to your plan* +3. implement the very same machine in a language, *making sure that your implementation adheres tightly to your abstract machine* + +the part that programmers usually get paid millions of dollars for is the step *1 -> 2*, which is by far the hardest and that requires the most creativity and craftsmanship. what usually makes people say that [[https://www.youtube.com/watch?v=FeAMiBKi_EM][software is in decline]] is that we don't learn the value of executing step *3* properly. this leads to sloppy, half baked software that crashes when X Y Z happens, and we've just come to terms with software being so brittle. + +it is not by chance that Yang et al. could only find measly 9 bugs after 6 CPU years of fuzzing in [[https://compcert.org/man/manual001.html][compcert]], a formally verified c compiler (written in coq), where as in gcc and clang, they [[https://users.cs.utah.edu/~regehr/papers/pldi11-preprint.pdf#subsection.3.2][found and reported more than 300]]. all these 9 bugs where in the unverified front end of the compiler (the parser), and there were literally 0 middle end (compiler passes and AST translations) bugs found, which is unheard of. this is not by chance, they've spent many years writing proofs that all of their passes are correct, safe, and preserve the meaning of the original program. + +i really think software developers should strive for that kind of resilience, which i believe can only be achieved through properly valuing *correctness* . i don't think it is reasonable to expect that all software be built using coq and proving every little bit of it (due to business constraints) but i think that rust is a good enough language to start taking things more seriously. * COMMENT Local Variables :ARCHIVE: diff --git a/config/_default/hugo.toml b/config/_default/hugo.toml deleted file mode 100644 index 41a40d6..0000000 --- a/config/_default/hugo.toml +++ /dev/null @@ -1,66 +0,0 @@ -# -- Site Configuration -- -# Refer to the theme docs for more details about each of these parameters. -# https://blowfish.page/docs/getting-started/ - -theme = "blowfish" -baseURL = "https://o-santi.github.io" -defaultContentLanguage = "en" - -enableRobotsTXT = true -paginate = 10 -summaryLength = 0 - -capitalizeListTitles = false -pluralizeListTitles = false - -buildDrafts = false -buildFuture = false - -# googleAnalytics = "G-XXXXXXXXX" - -[imaging] - anchor = 'Center' - -[taxonomies] - tag = "tags" - category = "categories" - author = "authors" - series = "series" - -[sitemap] - changefreq = 'daily' - filename = 'sitemap.xml' - priority = 0.5 - -[outputs] - home = ["HTML", "RSS", "JSON"] - -[related] - threshold = 0 - toLower = false - - [[related.indices]] - name = "tags" - weight = 100 - - [[related.indices]] - name = "categories" - weight = 100 - - [[related.indices]] - name = "series" - weight = 50 - - [[related.indices]] - name = "authors" - weight = 20 - - [[related.indices]] - name = "date" - weight = 10 - - [[related.indices]] - applyFilter = false - name = 'fragmentrefs' - type = 'fragments' - weight = 10 diff --git a/config/_default/languages.en.toml b/config/_default/languages.en.toml deleted file mode 100644 index 949dc35..0000000 --- a/config/_default/languages.en.toml +++ /dev/null @@ -1,28 +0,0 @@ -languageCode = "en" -languageName = "English" -weight = 1 -title = "lowest case" - -[params] - displayName = "EN" - isoCode = "en" - rtl = false - dateFormat = "2 January 2006" - # logo = "static/shin.png" - # secondaryLogo = "img/secondary-logo.png" - # description = "My awesome website" - # copyright = "Copy, _right?_ :thinking_face:" - -[author] - name = "leonardo santiago" -# image = "img/blowfish_logo.png" -# headline = "I'm only human" -# bio = "A little bit about you" - links = [ - { email = "mailto:leonardo.ribeiro.santiago@gmail.com" }, - { github = "https://github.com/o-santi" }, - { gitlab = "https://gitlab.com/o-santi" }, - { linkedin = "https://www.linkedin.com/in/leonardo-ribeiro-santiago/" }, - { telegram = "https://t.me/osanti4" }, - { twitter = "https://twitter.com/o-santi" }, - ] diff --git a/config/_default/markup.toml b/config/_default/markup.toml deleted file mode 100644 index c5449fc..0000000 --- a/config/_default/markup.toml +++ /dev/null @@ -1,13 +0,0 @@ -# -- Markup -- -# These settings are required for the theme to function. - -[goldmark] -[goldmark.renderer] - unsafe = true - -[highlight] - noClasses = false - -[tableOfContents] - startLevel = 2 - endLevel = 4 diff --git a/config/_default/menus.en.toml b/config/_default/menus.en.toml deleted file mode 100644 index 65abe45..0000000 --- a/config/_default/menus.en.toml +++ /dev/null @@ -1,67 +0,0 @@ -# -- Main Menu -- -# The main menu is displayed in the header at the top of the page. -# Acceptable parameters are name, pageRef, page, url, title, weight. -# -# The simplest menu configuration is to provide: -# name = The name to be displayed for this menu link -# pageRef = The identifier of the page or section to link to -# -# By default the menu is ordered alphabetically. This can be -# overridden by providing a weight value. The menu will then be -# ordered by weight from lowest to highest. - -[[main]] - name = "blog" - pageRef = "posts" - -[[main]] - name = "about" - pageRef = "/about" - -[[main]] - name = "tags" - pageRef = "/tags" - - -#[[main]] -# name = "example sub-menu 1" -# parent = "Parent" -# pageRef = "posts" -# weight = 20 - -#[[main]] -# name = "example sub-menu 2" -# parent = "Parent" -# pageRef = "posts" -# weight = 20 - -#[[subnavigation]] -# name = "An interesting topic" -# pageRef = "tags/interesting-topic" -# weight = 10 - -#[[subnavigation]] -# name = "My Awesome Category" -# pre = "github" -# pageRef = "categories/awesome" -# weight = 20 - -#[[main]] -# name = "Categories" -# pageRef = "categories" -# weight = 20 - -# -- Footer Menu -- -# The footer menu is displayed at the bottom of the page, just before -# the copyright notice. Configure as per the main menu above. - - -# [[footer]] -# name = "github" -# pre = "github" -# url = "https://github.com/o-santi" - -# [[footer]] -# name = "Categories" -# pageRef = "categories" -# weight = 20 diff --git a/config/_default/module.toml b/config/_default/module.toml deleted file mode 100644 index 74f7727..0000000 --- a/config/_default/module.toml +++ /dev/null @@ -1,3 +0,0 @@ -[hugoVersion] - extended = false - min = "0.87.0" diff --git a/config/_default/params.toml b/config/_default/params.toml deleted file mode 100644 index 2c5dab2..0000000 --- a/config/_default/params.toml +++ /dev/null @@ -1,146 +0,0 @@ -# -- Theme Options -- -# These options control how the theme functions and allow you to -# customise the display of your website. -# -# Refer to the theme docs for more details about each of these parameters. -# https://blowfish.page/docs/configuration/#theme-parameters - -colorScheme = "fire" -defaultAppearance = "dark" # valid options: light or dark -autoSwitchAppearance = true - -enableSearch = true -enableCodeCopy = false - -mainSections = ["posts"] - -disableImageOptimization = false -disableTextInHeader = false - -# defaultBackgroundImage = "IMAGE.jpg" # used as default for background images -# defaultFeaturedImage = "IMAGE.jpg" # used as default for featured images in all articles - -highlightCurrentMenuArea = true -# smartTOC = true -# smartTOCHideUnfocusedChildren = true - -[header] - layout = "basic" # valid options: basic, fixed, fixed-fill, fixed-gradient, fixed-fill-blur - -[footer] - showMenu = true - showCopyright = true - showThemeAttribution = true - showAppearanceSwitcher = true - showScrollToTop = true - -[homepage] - layout = "page" # valid options: page, profile, hero, card, background, custom - #homepageImage = "IMAGE.jpg" # used in: hero, and card - showRecent = true - showRecentItems = 5 - showMoreLink = true - showMoreLinkDest = "/posts" - cardView = false - cardViewScreenWidth = false - layoutBackgroundBlur = false # only used when layout equals background - -[article] - showDate = true - showViews = false - showLikes = false - showDateOnlyInArticle = false - showDateUpdated = false - showAuthor = false - # showAuthorBottom = false - showHero = false - # heroStyle = "basic" # valid options: basic, big, background, thumbAndBackground - layoutBackgroundBlur = true # only used when heroStyle equals background or thumbAndBackground - layoutBackgroundHeaderSpace = true # only used when heroStyle equals background - showBreadcrumbs = true - showDraftLabel = true - showEdit = false - # editURL = "https://github.com/username/repo/" - editAppendPath = true - seriesOpened = false - showHeadingAnchors = true - showPagination = true - invertPagination = false - showReadingTime = true - showTableOfContents = true - # showRelatedContent = false - # relatedContentLimit = 3 - showTaxonomies = true - showAuthorsBadges = false - showWordCount = false - showZenMode = false - -[list] - showHero = false - # heroStyle = "background" # valid options: basic, big, background, thumbAndBackground - layoutBackgroundBlur = true # only used when heroStyle equals background or thumbAndBackground - layoutBackgroundHeaderSpace = true # only used when heroStyle equals background - showBreadcrumbs = false - showSummary = false - showViews = false - showLikes = false - showTableOfContents = false - showCards = false - groupByYear = true - cardView = false - cardViewScreenWidth = false - constrainItemsWidth = false - -[sitemap] - excludedKinds = ["taxonomy", "term"] - -[taxonomy] - showTermCount = false - showHero = false - # heroStyle = "background" # valid options: basic, big, background, thumbAndBackground - showBreadcrumbs = false - showViews = false - showLikes = false - showTableOfContents = false - cardView = false - -[term] - showHero = false - # heroStyle = "background" # valid options: basic, big, background, thumbAndBackground - showBreadcrumbs = false - showViews = false - showLikes = false - showTableOfContents = true - groupByYear = false - cardView = false - cardViewScreenWidth = false - -[firebase] - # apiKey = "XXXXXX" - # authDomain = "XXXXXX" - # projectId = "XXXXXX" - # storageBucket = "XXXXXX" - # messagingSenderId = "XXXXXX" - # appId = "XXXXXX" - # measurementId = "XXXXXX" - -[fathomAnalytics] - # site = "ABC12345" - # domain = "llama.yoursite.com" - -[umamiAnalytics] - # websiteid = "ABC12345" - # domain = "llama.yoursite.com" - -[buymeacoffee] - # identifier = "" - # globalWidget = true - # globalWidgetMessage = "Hello" - # globalWidgetColor = "#FFDD00" - # globalWidgetPosition = "Right" - -[verification] - # google = "" - # bing = "" - # pinterest = "" - # yandex = "" diff --git a/content/_index.md b/content/_index.md new file mode 100644 index 0000000..db8eace --- /dev/null +++ b/content/_index.md @@ -0,0 +1,10 @@ ++++ +title = "lowest case" +author = ["santi"] +lastmod = 2024-06-01T10:31:58-03:00 +draft = false ++++ + +a lower case only blog, purely for aesthetics. + +here I talk about discrete mathematics (mostly computer science), including compilers, language theory, type theory, computability theory, software correctness, formal verification, and any other (entirely theoretical, almost non-applicable) nerd topic you can think of. diff --git a/content/about.md b/content/about.md new file mode 100644 index 0000000..6f59209 --- /dev/null +++ b/content/about.md @@ -0,0 +1,19 @@ ++++ +title = "about" +author = ["santi"] +lastmod = 2024-06-01T12:12:47-03:00 +draft = false +menu = "main" ++++ + +i'm leonardo santiago, a software engineer based in brazil. my interests are in compiler design, programming tools (emacs), functional programming, and proof languages. i'm most confortable in nix and rust, but i know a fair share of other languages. + +currently, i work as a software engineer @ [Mixrank](https://mixrank.com), and you can find my curriculum [here](/cv.pdf). + +if you feel like smugly responding to any of my posts (or just want to kindly send me a message), these are my socials: + +- [email](mailto:leonardo.ribeiro.santiago@gmail.com) +- [linkedin](https://www.linkedin.com/in/leonardo-ribeiro-santiago/) +- [github](https://github.com/o-santi) + +this blog was built using emacs' excelent org-mode and [hugo](https://github.com/gohugoio/hugo) (with the [bearblog theme](https://github.com/janraasch/hugo-bearblog)). diff --git a/content/about/index.md b/content/about/index.md deleted file mode 100644 index 831e9ec..0000000 --- a/content/about/index.md +++ /dev/null @@ -1,15 +0,0 @@ -+++ -title = "about" -author = ["santi"] -lastmod = 2024-05-01T11:53:23-03:00 -draft = false -+++ - -i'm leonardo santiago, a software engineer based in brazil. my interests are in compiler design, programming tools (emacs) and functional programming, usually dabbliing in related topics too. i'm most confortable in nix and rust, but i know a fair share of other languages. - -currently, software engineer @ [Mixrank](https://mixrank.com). - -this blog was built using [hugo](https://github.com/gohugoio/hugo), and it's source code is openly available here: -{{< github repo="o-santi/nixos" >}} - -you can find me at: [{{< icon "email" >}}](mailto:leonardo.ribeiro.santiago@gmail.com) [{{< icon "linkedin" >}}](https://www.linkedin.com/in/leonardo-ribeiro-santiago/) [{{< icon "github" >}}](https://github.com/o-santi) [{{< icon "telegram" >}}](https://t.me/osanti4) [{{< icon "twitter" >}}](https://twitter.com/o_santi_) diff --git a/content/blog/rust-is-not-about-memory-safety.md b/content/blog/rust-is-not-about-memory-safety.md new file mode 100644 index 0000000..b060f3c --- /dev/null +++ b/content/blog/rust-is-not-about-memory-safety.md @@ -0,0 +1,93 @@ ++++ +title = "rust is not about memory safety" +author = ["santi"] +lastmod = 2024-06-01T15:21:30-03:00 +tags = ["rust", "correctness"] +draft = false ++++ + +most of rust discussions nowadays revolve about memory safety, and how it is safer than C / C++ / zig / go / whatever language is being trashed on twitter that day. while yes, that is true - not that the bar for most of these is particularly high - what I think is the main point of the language is always glossed over: correctness. when one tries to criticize any of the aforementioned languages, one is answered with the following argument: + +> your program segfaults? skill issue + +but i'd like to make the counter-argument that, no, this has nothing to do with skill issue. + + +## formal language theory {#formal-language-theory} + +the first thing one learns when they're studying formal languages (the field that studies grammars, state automata, etc) is that the rules that describe a certain grammar must match **exactly** the ones that you want to include in your language. this means that there's a bidirectional relationship between the grammar you describe (which directly define the automata that parses that language) and the words[^fn:1] that it parses (which are related to the semantics of the program, how it executes). + +from it, it can be inferred that the grammar **must not** allow in the language any words that does not have defined semantics, and in the opposite direction, that the language should not specify semantics to any program that cannot be parsed by the rules of the grammar. both of these are required in order to make study of this grammar <-> language partnership fun, pleasing, and most importantly sound. + +going beyond, formal language theory also gives you the knowledge that the execution of any program can be given as a set of grammar rules in an abstract machine (the most famous one being a turing machine). in the same way you can define a set of grammar rules to parse parenthesized arithmetic expressions using a stack automaton, you can define a set of grammar rules to model the execution of a C program, and, albeit super complex, can be modeled as a turing machine. this usually gets the name of C abstract machine, and is the basis for formal specification of behavior in the language. + +and no, i'm not talking about modeling a C parser as a state machine (which probably is easier than most languages, if you ignore pre-processor stuff). i'm talking about modeling C **execution** as a language being parsed. drawing a parallel, when parsing parenthesized expressions, you pop things in and out of the stack to represent "balancedness", and in the same way, when "parsecuting" C code, you must write to memory, represent side effects, represent type casts and pointer conversions and everything **as part of the language**. + +in the same way that you'd hope that a parenthesized arithmetic expression parser would recognize that `(1 + 2) + 3)` is an invalid expression, you'd expect that the C compiler would correctly verify that the following series of tokens is not a _well behaved_ program: + +```c +int foo(int * myptr) { + *myptr = 5; +} +foo(NULL); +``` + +i say _well behaved_ because i can't say _invalid_. it is in fact defined by the spec that when you dereference a `NULL` pointer the result is [_undefined behavior_](http://blog.llvm.org/2011/05/what-every-c-programmer-should-know.html). and this is C's achilles heel: instead of outright banning programs like the one above (which i'd argue is the correct approach), it will happily compile and give you garbage output. + +framing it this way really exposes the fragility of C, because undefined behavior has to always be taken into account. and, by the nature of it, there is no way to represent it other than as a black box, such that, if your code ever encounters it, then literally all you can say is that **the whole result of the program** is undefined - that is, it can be anything. you cannot show properties, nor say what will happen once your program enters this state, as the C specification literally does not define it. it may come to a halt, write garbage to the screen or completely delete half of the files of your program, and there's no way to predict what will come out of it, by definition. in the lucky case, it will segfault while executing and you'll be extremely pissed off, but that is not at all guaranteed. this is akin to having a float expression with some deep term being `NaN`, in that it eventually must evaluate to `NaN` and you can't draw any conclusions about the result of the expression (other that it isn't a number). + +language designers are by no means dumb, and yes, they know much, much more than me about these problems. undefined behavior exists exactly because there must be parts of your code that your compiler **must** assume that aren't possible, so that it can correctly compile. for example, let's say that you inadvertently try to dereference a pointer that you have no knowledge about. the C compiler simply does not have enough information to know if it is `NULL`, if it is still pointing to valid memory, or if the memory has been initialized, so what it's approach is simply emit code **as if** it was a valid, initialized, non-null pointer. + +it is essential to realize that this is an **assumption**, and in almost most cases, it simply does not care whether or not it actually was actually still valid, so writing to it may have a myriad of effects of different effects (none of which are the compiler's concerns). sometimes, your system might correctly intercept a read/write from invalid/null memory and raise you a signal, but that is not guaranteed. + +and there are a huge number of tools to aid in finding undefined behavior, it's just that 1. they are not by any means standards of C development (not in spec and not in standard compilers) and 2 they are fallible and will always let some undefined programs slip by. + + +## runtime exceptions are not the solution {#runtime-exceptions-are-not-the-solution} + +most languages try to handle this by introducing some sort of runtime exception system, which i think is a terrible idea. while this is much, much safer than what C does, it still makes reasoning about the code extremely hard by completely obliterating locality of reason. your indexing operation may still be out of bounds, and while this now has defined outcomes, it is one of the possible outcomes of your program (whether you like it or not), and you must handle it. and, of course, no one handles all of them, for it is humanely impossible to do it in most languages because: + +1. it is hard to know when an operation can raise an exception, and under which conditions. +2. even if documented, it is never enforced that all exceptions must be gracefully handled, so some random function in a dependency of a dependency may raise an error from an unexpected corner case and you must deal with it. + +this is a symptom of virtually all modern languages, and none of them have any good answers to it. java mandates that you report in your function type signature the errors that it may raise (which is a rare java W), but it does let you write code with [unchecked exceptions](https://docs.oracle.com/javase/tutorial/essential/exceptions/runtime.html) that won't signal a compile error if ignored, which eventually will crash your minecraft game. python, ruby, php and most other languages (even [haskell](https://www.tweag.io/blog/2020-04-16-exceptions-in-haskell/) made this mistake) do not even attempt to signal when a function might raise an exception. javascript somehow manages to be even worse, by having horrible implicit-by-default type casts, having undefined AND null, using strings as UTF-16, using floats as standard numbers, implicitly inserting semicolons, and honestly the list could go on forever. + +the root of all these problems is, quite literally, the same: that your compiler (or interpreter) lets into your program execution states that you didn't anticipate for. one of the best of examples of the opposite, surprisingly enough, is regex matchers. while i concede that their syntax can be extremely confusing, they have the best property of software: if they compile, they work exactly as intended - which i henceforth will call **correctness**. this is because regular languages' properties and their state automata have been studied to extreme depths, and it is entirely possible to write a regex implementation that is **correct** (in the same way as above), going as far as providing formal verifications of that [^fn:2]. + +from this definition of **correctness** we can also derive a semantically useful definition for the word bug: an unexpected outcome for the program, that shouldn't be allowed in the language. of course java behavior might be defined for all inputs (for the most part, i'm sure there are might be problems here and there) but just because one possible outcome of program is `NullPointerException` doesn't mean that it is **expected**, making it, by my definition, a bug. + + +## make invalid states unrepresentable {#make-invalid-states-unrepresentable} + +what the regex example makes clear is that the key to correctness is to make your language tight enough to have defined and **desired** output for all possible inputs. this is not to say that it won't raise errors; much to the contrary, it must have parser errors saying that some strings aren't valid regexes. instead, it means that all errors are **predictable**, and **well defined** (in some sense). + +you, as the programmer, is then in charge of ensuring that the resulting regex program actually solves the problem you have at hands. want to match 3 words of 2 digit numbers followed by a capital letter? great, they can do that. want to match balanced parenthesized expressions? sadly, regex is incapable of ever solving that, because that language [is not regular](https://en.wikipedia.org/wiki/Pumping_lemma_for_regular_languages#Use_of_the_lemma_to_prove_non-regularity), so no matter how hard you try it will never solve it. + +in a way, there's a beauty in how C sidesteps this: it defines one of the possible program outputs as being _undefined_, and it is on the programmers behalf to tightly ensure that the program has 0 paths to _undefined behavior_. in fact, it is probably one of the most [well specified languages](https://www.open-std.org/jtc1/sc22/wg14/www/docs/n1256.pdf), which is what makes it suitable for writing formally verifiable programs [^fn:3]. + +the main strength of rust, and where it differs from all mainstream languages, is that it has a very clear focus on program **correctness**. the raison d'être of the borrow checker is statically assuring that all references are pointing to valid memory, such that it is literally impossible for any borrow be null or to point to some freed memory (modulus [implementation errors of course](https://github.com/Speykious/cve-rs)). this completely rules out this possibility of bugs from the language we're trying to "parse". remember the C excerpt from above, where i said that the compiler should rule out the program as invalid? well, it is literally impossible to write that sort of program in rust, because one cannot construct a `NULL` reference. + +not only that, but rust languages features makes it so, so much easier to write **correct** software: sum types (tagged unions), `Option` instead of `NULL` (which in and of itself is amazing), `Result` for errors (making obligatory to handle all possible branches your program can take), a strong and powerful static type system, and ditching inheritance and classes in favor of traits. + +note that i never ever talked about memory safety. even in a world where C wasn't in fact full of memory vulnerabilities, rust would still be miles better, because it statically assures you that the **meaning of your program is tightly reproduced by the code you've written**. it is, by design, more correct than C, and the only way a problem can possibly happen is by side stepping rust static checks by using `unsafe`. + +it is just a happy coincidence that this leads to a language that isn't garbage collected, that is relatively lean, fast, easy to embed, has good ergonomics and that enables you to write asynchronous and multi-threaded programs. these properties are awesome to boost rust to a very well regarded status between developers, but aren't at all related to languages that enable you to build reliable, correct software. out of curiosity, i'd happily defend the case that [coq](https://coq.inria.fr/) is also one of these languages, and it absolutely does not hold any of these any of those. + + +## software engineering as a craft {#software-engineering-as-a-craft} + +finally, i think this relates to how i personally model the software development job as a whole. it starts by having some problem you think you can use computers to solve, and then follow 3 clearly stratified steps: + +1. define how one might solve the problem. this usually means splitting it into several possible cases and treating each and every one of them separately. +2. define an abstract machine that executes the very same steps, **and making sure that it tightly adheres to your plan** +3. implement the very same machine in a language, **making sure that your implementation adheres tightly to your abstract machine** + +the part that programmers usually get paid millions of dollars for is the step **1 -> 2**, which is by far the hardest and that requires the most creativity and craftsmanship. what usually makes people say that [software is in decline](https://www.youtube.com/watch?v=FeAMiBKi_EM) is that we don't learn the value of executing step **3** properly. this leads to sloppy, half baked software that crashes when X Y Z happens, and we've just come to terms with software being so brittle. + +it is not by chance that Yang et al. could only find measly 9 bugs after 6 CPU years of fuzzing in [compcert](https://compcert.org/man/manual001.html), a formally verified c compiler (written in coq), where as in gcc and clang, they [found and reported more than 300](https://users.cs.utah.edu/~regehr/papers/pldi11-preprint.pdf#subsection.3.2). all these 9 bugs where in the unverified front end of the compiler (the parser), and there were literally 0 middle end (compiler passes and AST translations) bugs found, which is unheard of. this is not by chance, they've spent many years writing proofs that all of their passes are correct, safe, and preserve the meaning of the original program. + +i really think software developers should strive for that kind of resilience, which i believe can only be achieved through properly valuing **correctness** . i don't think it is reasonable to expect that all software be built using coq and proving every little bit of it (due to business constraints) but i think that rust is a good enough language to start taking things more seriously. + +[^fn:1]: formally they are defined as a sequence of tokens in certain alphabet that the automata closures over. normally we think of "words" as the whole program that we're parsing. +[^fn:2]: the excellent software foundations book [explains thoroughly](https://softwarefoundations.cis.upenn.edu/lf-current/IndProp.html) how one might formally write one possible regex matcher, and prove that the implementation is correct +[^fn:3]: through the use of external tools like Coq's [verifiable C series](https://vst.cs.princeton.edu/veric/) diff --git a/content/index.md b/content/index.md deleted file mode 100644 index 9e4122e..0000000 --- a/content/index.md +++ /dev/null @@ -1,10 +0,0 @@ -+++ -title = "lowest case" -author = ["santi"] -lastmod = 2024-05-01T11:53:23-03:00 -draft = false -+++ - -a lower case only blog, purely for aesthetics. - -here I talk about discrete mathematics (mostly computer science), including compilers, language theory, type theory, computability theory, software correctness, formal verification, and any other (entirely theoretical almost non-applicable) nerd topic you can think of. diff --git a/content/posts/.#correctness-is-all-you-need.md b/content/posts/.#correctness-is-all-you-need.md deleted file mode 120000 index 0aea4a6..0000000 --- a/content/posts/.#correctness-is-all-you-need.md +++ /dev/null @@ -1 +0,0 @@ -leonardo@kunagisa.300940:1715192908 \ No newline at end of file diff --git a/content/posts/correctness-is-all-you-need.md b/content/posts/correctness-is-all-you-need.md deleted file mode 100644 index 20ded9a..0000000 --- a/content/posts/correctness-is-all-you-need.md +++ /dev/null @@ -1,32 +0,0 @@ -+++ -title = "correctness is all you need" -author = ["santi"] -lastmod = 2024-05-09T23:35:32-03:00 -tags = ["coq", "rust"] -draft = false -+++ - -```python ->>> 0.1 + 0.2 -0.30000000000000004 -``` - -which of course is an annoying encounter for the unitiated in floats, but there's a much bigger problem, that usually isn't noticed at all until much later, that float addition itself isn't even associative: - -```python ->>> (0.1 + 0.2) + 0.3 -0.6000000000000001 ->>> 0.1 + (0.2 + 0.3) -0.6 ->>> 0.1 + (0.2 + 0.3) == (0.1 + 0.2) + 0.3 -False ->>> -``` - -and this is a problem, because associativity is a big underlying assumption that we commonly have for numbers, when, for example, summing a list in reverse. other common pitfalls include: - -- not all numbers have an additive inverse, ie. for some number `n`, `n + (-n) != n`. -- not all numbers different than 0 have a multiplicative inverse, ie. for some number `n`, `n / n != 1`. -- addition is not commutative, ie. for numbers `a` `b`, `a + b != b + a`. - -and the list goes you on, you get the idea. this usually isn't thought of the main problems in diff --git a/curriculum/answer.org b/curriculum/answer.org deleted file mode 100644 index 84bf413..0000000 --- a/curriculum/answer.org +++ /dev/null @@ -1,101 +0,0 @@ -#+TITLE: Rust Engineering Lead -#+AUTHOR: Leonardo Ribeiro Santiago (120036072) -#+OPTIONS: toc:nil date:nil -#+LATEX_HEADER: \usepackage[portuguese]{babel} - -* Engineering experience -** Describe a skill or knowledge you acquired recently that has been impactful for you. Why did you make this investment? What has the outcome been? -I've been investing the last year to learning NixOS, and nix systems (especially flakes) in general, and it honestly has paid off so much. As everyone says, it's a technology with a very steep learning curve, as the documentation is sparse and most of the times outdated, and to get up to date info you almost always need to look at the source code. - -Still, nixpgks is amazing and been able to provide me with never breaking software and fearless upgrades, so that I can confidently keep my machines up to date. Nowadays I use it both in my main machine and in my laptop, using different configs derived from the same flake (sharing almost everything). - -** What new skill would you like to learn? Why do you think this is important or timely or interesting? Why do you think you will be good at it? - -NixOS got me very interested in the DevOps field, as I find it very good at managing multiple computers' configurations and setups. I also think I'm a good fit for that side of programming, as it usually requires a very rich understanding of linux, as well as integration between different systems. - -** What kinds of software projects have you worked on before? Which operating systems, development environments, languages, databases? - -Professionally, I daily deal with Python, Rust, PostgreSQL and Nix (and NixOS). In the past I've also worked in other languages, such as Haskell, a fair bit of Javascript, LaTex and XML, and C. For some smaller projects I've interacted with OCaml (built my old blog generator from scratch on it), Coq and Lean (proof assistants), common-lisp (for the NES emulator) and emacs lisp (daily). As far as operating systems go, I've started on WSL, then quickly hopped on Ubuntu, had some graphics card drivers issues, hopped to Arch linux, also had driver issues, hopped on to Manjaro, suffered from the same issues, then back to windows for a while where my laptop worked. Last year I decided to go full time on NixOS, and I've been happily using it ever since. - -** Why Rust? What is your history with this language? - -My history in Rust is very tangled with my history with functional languages in general. I have a very non-standard history, in that I learned functional programming through a friend, while trying to implement a more powerful parser at my first (junior) job. He explained to me about parser combinators and introduced me to the language he was working on, called Kind. I loved programming in Kind, as it's syntax was very much javascript like (on purpose) but it was dependently typed (used a very simple non-standard theory called self-types). I tried writing a parser to fit for my needs at the time, but I was clearly not knowledgeable enough (and looking back what I was trying to acchieve wasn't even possible). - -Curiously enough, two years later I went to the same company that my friend was working on, and they were using Rust (to build a functional runtime). I had heard it about it by then, and certainly knew a thing or two, but had no experience in it professionally so getting to work with it gave me the same feeling as I had with Kind. It was a very powerful language, with very high performance (which Kind didn't have), and a strict compiler that does not take a whole minute to verify? Neat! I loved it, and started quickly munching through every piece of rust info I could find on the internet: blogs, conference talks (I love seeing those), tutorials, etc. I then learned about how the borrow checker works, why it works, and got even more in love with it, and still to this day I try writing everything I can on it. - -The thing that always makes me motivated to work around Rust is the fact that it makes it possible to make invalid states unrepresentable (which is the whole point of correctness). The prime example to this is the way errors are handled in Go: you return a tuple, with a good value and an error value, and you *must* only set only one of them, while the other is null. This begs for the obvious question: what happens when you set both of them? Most of the time, this leads to undefined behaviour, because often it will rely on the assumption that only one of them is set in the code, but Go *has no way of ensuring that*. Rust on the other hand handles this gracefully by using type variants, so that instead of a tuple containing both, it can be statically asserted that it always returns one of the kind. - -** Would you describe yourself as a high quality coder? Why? - -I think the main quality any serious developer should value the most is correctness, in so far as accurately describing your problem, then accurately describing your algorithm (and how it *always* solve your problem, not /mostly/ or /generally/, *always*), then finally making sure that the code you write implements the algorithm faithfully (possibly making use of proof assistants to verify certain key pro. If code is done this way, thoroughly and paying due diligence, then the resulting product will always be of the highest quality, without a doubt. And I'm a programmer who always strive for doing this process, which makes me a high quality coder. - -Of course, it isn't possible to always strictly adhere to this schedule, be it because of tight business schedules, or maybe your project's ambitions are just too broad to accurately describe every facet in a humans' life span, but I still think that following as much as you can will still get you to a high quality product in the end. - -** Outline your thoughts on open source software development. What is important to get right in open source projects? What open source projects have you worked on? Have you been an open source maintainer, on which projects, and what was your role? - -I value very much open source software, and I try as much as possible to keep my personal projects open source. My NixOS config is the best example, where I openly strived to make it open source, even though I had to keep personal secrets in it. Due to this, I went through a lengthy span of time searching for possible solutions and finally arrived at the current one I use (agenix, where the secrets are encrypted with my systems public ssh keys, and having one private key is enough to decrypt them), and I will always happily share it with everyone, as open source is probably the main reason I know everything that I know today. - -The main thing to get correctly right in open source projects is to have a clear, specified goal that it tries to solve, in order to make it possible to probe whether or not it is in the right direction (which incidentally aligns very well with the Unix philosophy). I believe this to be necessary because projects with very broad ambitions tend to either get everything done in a half baked way or simply to ditch some parts in favor of others, or just to be abandoned altogether due to the sheer complexity. This is further supported by the fact that there are very few everlasting monolythical open source projects, with emacs and the linux kernel being the only ones that come to mind (and both of them have very clear flaws, though I'm much more knowledgeable in emacs). Most successful projects tend then to be done in layers developed separately with different goals, with the best example being the very-common-in-linux hierarchy: kernel -> OS -> window servers -> window managers -> applications, and still composing is a common source of problems (X11 vs wayland). - -Personally, I have contributed to a few open source projects that are not my own, with the biggest one that comes to mind being [[https://github.com/o-santi/nocargo][nocargo]], a rust build tool intended to supersede cargo inside nix, written entirely in nix. It has solves some very clear problems that cargo can't really tackle (while being a rust build tool), like crate level caching (which is the best you can do with rustc, as crates are it's unit of compilation) that are globally shared through different projects, and probably the most important one being clearly expressing dependencies on non-rust software. My role was mostly to extend it's features, because it remained unmantained for almost 2 years, in order to support new cargo features that were breaking compatibility otherwise. Though I got it to a good state (where I use it daily with no problems), I haven't had time to properly merge it to the main branch (neither has oxalica) so it remains an open [[https://github.com/oxalica/nocargo/pull/17][pull request]] to this day. I still intend to finish it once I have more free time. - -** Describe your experience building large systems with many services - web front ends, REST APIs, data stores, event processing and other kinds of integration between components. What are the key things to think about in regard to architecture, maintainability, and reliability in these large systems? - -Working with large systems with many services is my main job at Mixrank. We have a lot of public API's, dozens of databases, client deliveries schemes and most importantly, in-house tooling to dealing with all of the requirements (some of which are open source). - -I believe there are three key facets to think about when building this kind of software, which are clear structure, static checkers (be it compiler, linter or other kind of tools) and good documentation. They are needed to solve the most common source of problems in big systems: the overwhelmingly big context you need to hold in your mind in order to make any simple change. -- Good project structure makes it so that all of your changes are local (they won't break other parts elsewhere) and that you don't need to keep track of multiple places to update (eg. having to update the same address in 7 separate parts of the codebase). -- Static checkers give you confidence to structure code in a way such that preventable mistakes (such as type errors or forgetable edge cases) can be seen before they get to production. -- Good documentation makes information accessible to newcomers and introduces them to the codebase, while also keeping clear what the semantics of certain parts of the code is assumed to be (eg. what does it mean when this field is null in this API call?). - -** How comprehensive would you say your knowledge of a Linux distribution is, from the kernel up? How familiar are you with low-level system architecture, runtimes and Linux distro packaging? How have you gained this knowledge? - -I'd say I'm not that confident at the kernel, since I don't have much experience working with. Though, I have built some low-level systems and runtimes (both my at my previous company and my current one), that give me confidence when interacting with the kernel. In distro packaging, I have a lot of experience in packaging software to NixOS, both because of using it daily to solve my own problems, and to solve needs for my current job. It also gives me a lot of insights into other distros packaging system too (how to do it correctly). - -** Outline your thoughts on quality in software development. What practices are most effective to drive improvements in quality? - -First we must define what quality is: for me, it boils down to two predicates: -1. Predictability, in so far as always doing the same thing with the same input, and having specifiable outputs on different inputs. -2. Reliability, as in it won't break because of unexpected inputs, or strange edge cases that aren't handled well. - -This kind of software quality must strictly come from strict adherence to correctness, as I've answered before. The more you formally specify semantics around your code, the more reliable and predictable it will become, and thus higher the quality. Ideally you'd like your whole software to be a single state machine, which clearly defined transitions for each state; though this isn't always feasible, mostly due to scale. Small scale software can and should be state machines with clear state trasitions - think of rust builder patterns, regexes, parsers and http requests - and composing them simply and correctly is the best way to ensure highest software quality. - -** Outline your thoughts on documentation in large software projects. What practices should teams follow? What are great examples of open source docs? - -I think source code will always be the best documentation. People tend to forget to update documentation (especially in lesser important parts of the project) and it can't be expected to always be updated. Since there's no way to verify that the semantics in the comments will always match the one in the code (and the code being the actual thing that we can verify), we shouldn't realy on it being up to date. - -A good practice is to make documentation automatically generated from source code (and automatically updated by CI), especialely when it can then be indexed later by a searching tool, with the best examples that come to mind being [[https://hoogle.haskell.org/][hoogle]] and rust docs themselves, which optionally let you include comments for functions and type definitions. - -** Outline your thoughts on user experience, usability and design in software. How do you lead teams to deliver outstanding user experience? - -Outstanding user experience always comes from reliability, and making sure that outcomes are clearly defined. Does you software expect a filepath as an input? Then, it must gracefully handle the case where the input is *not* a file path, clearly explaining to the user how to correctly use the software. - -You must also have consistent behavior around your codebase: you either accept relative paths or you don't, throughout your commands/subcommands/inputs, that is, you can't tell the user you expect a certain pattern in input A and then have that same pattern fail in input B. - -** Outline your thoughts on performance in software engineering. How do you ensure that your product is fast? - -Performance always come from good design. There's no such thing as "implement first, optmize later" as it always lead to huge software refactors whenever performance isn't satisfactory enough. One must always predict how certain algorithms can be implemented *correctly* through the designing phase, to then try to predict whether or not the expected performance is going to be satisfactory. - -Sometimes the only way to correctly handle all the inputs is through a slow and memory heavy O(n^5) algorithm. A good engineer should then consider: why is this algorithm so slow? Can I expect it to be faster? Are most cases actually O(n) and only edge cases perform worse? Maybe you can consider limiting your input to only good performing algorithms, and explain to the user that in the edge cases it won't perform so well - or maybe you can outright prohibit the user of inputting these edge cases. - -** Outline your thoughts on security in software engineering. How do you lead your engineers to improve their security posture and awareness? - -To increase security and awareness is to increase understanding around the codebase, mainly around the semantics. Most security mistakes comes from not handling *correctly* (the word I always mention) edge cases in your software be them: -1. unexpected inputs are not correctly handled. -2. null pointer dereference - when you assume some pointer points to valid memory when it really doesn't. -3. out of bounds memory access - when you incorrectly assert the size of the array you're reading from, most common when there are complicated loop relationships in indexes. -4. unexpected semantics in language design - think of mutable default arguments in python, that are a common source of headaches (when someone expects them to be reset every call, but in fact they're shared through multiple calls). -5. wrong ownership semantics - assuming it's fine to modify some non-local variable inside a function (that should not modify it). - -A generally safe language will solve *1*, *2* and *3*, through static types, ~Option~, ~Result~, and bounds checking. A well designed language can also solve *4*. But only Rust can solve *5*, through the complicated analysis of the borrow checker. When using a language that does not solve any of these problems, we then force the programmer to keep these complicated relationships in their head, *at all times*, and it is not reasonable to assume that people won't make mistakes - even the most experienced programmer will spew out a few problems per week. Then, Rust's job on software security is clear: empower people to write correct software, and allow them to focus on actually delivering value (instead of fighting a data race condition). - -Also, I don't think unit testing (or any kind of testing) significantly improve security. Of course, in dynamic languages, where static analyzers are hard to get, they are important in assuring that you are not forgeting anything, but I absolutely do not think that adding one thousand tests will solve issues. Issues happen exactly because you did not think of them and instead of adding a test to handle a specific edge case, you're much better off ensuring that your program handles *all* classes of edge cases. Ideally, you'd like to formally specify your software - with the prime example being [[https://compcert.org/man/manual001.html][CompCert]], where reportedly Csmith (a C code fuzzy tester) couldn't find any bugs in the well-verified and checked middle-end (compiler optimizations passes) that other major compilers (gcc, llvm) were infested (300+); the only bugs found in the compiler where in the non-verified front end (the C parser), measly 9 bugs. - -** Outline your thoughts on DevOps and DevSecOps. Which practices are effective, and which are overrated? - -Mostly I think what really makes DevOps efective is being able to *completely* reason about your system before sending them off to the production servers. Being able to describe the exact end state of the software in your system beforehand lets you ensure key properties (eg. user X must always have ssh key Y when condition Z happens). - -This is exactly why I like NixOS: it's whole idea is to separate build from recipe. That is, you're able to describe and instantiate a complete recipe for a system, ranging from installed programs, to users configurations, to installed fonts, to services that must run on startup and their configurations as well, all while using a powerful turing complete language - which is great for structuring your code and making it readable and sharable. - -Then, you are also able to, before installing the whole spec in the machine, inspect the end state of it inside a common repl. For example, lets say you have a list of users with roles and ssh keys, and you'd like to give each user permissions to machines based on their roles. In NixOS, this is as simple as importing the users, doing a common loop (in functional programming, a fold) and then assingning the correct value to each field of the configuration. To ensure you are correct, you're also able to instantiate, and see exactly which users have access to that machine *before installing*, and NixOS ensures you that those are the exact ones that will have access to it. - diff --git a/curriculum/cv.aux b/curriculum/cv.aux deleted file mode 100644 index d94a749..0000000 --- a/curriculum/cv.aux +++ /dev/null @@ -1,14 +0,0 @@ -\relax -\providecommand\babel@aux[2]{} -\@nameuse{bbl@beforestart} -\abx@aux@refcontext{ynt/global//global/global} -\providecommand\hyper@newdestlabel[2]{} -\providecommand\HyField@AuxAddToFields[1]{} -\providecommand\HyField@AuxAddToCoFields[2]{} -\babel@aux{english}{} -\@writefile{toc}{\contentsline {section}{\numberline {1}Work Experience}{1}{section.1}\protected@file@percent } -\@writefile{toc}{\contentsline {section}{\numberline {2}Projects}{1}{section.2}\protected@file@percent } -\@writefile{toc}{\contentsline {section}{\numberline {3}Education}{2}{section.3}\protected@file@percent } -\@writefile{toc}{\contentsline {section}{\numberline {4}Skills}{2}{section.4}\protected@file@percent } -\abx@aux@read@bbl@mdfivesum{nobblfile} -\gdef \@abspage@last{2} diff --git a/curriculum/cv.bcf b/curriculum/cv.bcf deleted file mode 100644 index 694199d..0000000 --- a/curriculum/cv.bcf +++ /dev/null @@ -1,2393 +0,0 @@ - - - - - - output_encoding - utf8 - - - input_encoding - utf8 - - - debug - 0 - - - mincrossrefs - 2 - - - minxrefs - 2 - - - sortcase - 1 - - - sortupper - 1 - - - - - - - alphaothers - + - - - extradatecontext - labelname - labeltitle - - - labelalpha - 0 - - - labelnamespec - shortauthor - author - shorteditor - editor - translator - - - labeltitle - 0 - - - labeltitlespec - shorttitle - title - maintitle - - - labeltitleyear - 0 - - - labeldateparts - 1 - - - labeldatespec - date - year - eventdate - origdate - urldate - nodate - - - julian - 0 - - - gregorianstart - 1582-10-15 - - - maxalphanames - 3 - - - maxbibnames - 2 - - - maxcitenames - 3 - - - maxsortnames - 2 - - - maxitems - 3 - - - minalphanames - 1 - - - minbibnames - 1 - - - mincitenames - 1 - - - minsortnames - 1 - - - minitems - 1 - - - nohashothers - 0 - - - noroman - 0 - - - nosortothers - 0 - - - pluralothers - 0 - - - singletitle - 0 - - - skipbib - 0 - - - skipbiblist - 0 - - - skiplab - 0 - - - sortalphaothers - + - - - sortlocale - english - - - sortingtemplatename - ynt - - - sortsets - 0 - - - uniquelist - true - - - uniquename - full - - - uniqueprimaryauthor - 0 - - - uniquetitle - 0 - - - uniquebaretitle - 0 - - - uniquework - 0 - - - useprefix - 0 - - - useafterword - 1 - - - useannotator - 1 - - - useauthor - 1 - - - usebookauthor - 1 - - - usecommentator - 1 - - - useeditor - 1 - - - useeditora - 1 - - - useeditorb - 1 - - - useeditorc - 1 - - - useforeword - 1 - - - useholder - 1 - - - useintroduction - 1 - - - usenamea - 1 - - - usenameb - 1 - - - usenamec - 1 - - - usetranslator - 0 - - - useshortauthor - 1 - - - useshorteditor - 1 - - - - - - extradatecontext - labelname - labeltitle - - - labelalpha - 0 - - - labelnamespec - shortauthor - author - shorteditor - editor - translator - - - labeltitle - 0 - - - labeltitlespec - shorttitle - title - maintitle - - - labeltitleyear - 0 - - - labeldateparts - 1 - - - labeldatespec - date - year - eventdate - origdate - urldate - nodate - - - maxalphanames - 3 - - - maxbibnames - 2 - - - maxcitenames - 3 - - - maxsortnames - 2 - - - maxitems - 3 - - - minalphanames - 1 - - - minbibnames - 1 - - - mincitenames - 1 - - - minsortnames - 1 - - - minitems - 1 - - - nohashothers - 0 - - - noroman - 0 - - - nosortothers - 0 - - - singletitle - 0 - - - skipbib - 0 - - - skipbiblist - 0 - - - skiplab - 0 - - - uniquelist - true - - - uniquename - full - - - uniqueprimaryauthor - 0 - - - uniquetitle - 0 - - - uniquebaretitle - 0 - - - uniquework - 0 - - - useprefix - 0 - - - useafterword - 1 - - - useannotator - 1 - - - useauthor - 1 - - - usebookauthor - 1 - - - usecommentator - 1 - - - useeditor - 1 - - - useeditora - 1 - - - useeditorb - 1 - - - useeditorc - 1 - - - useforeword - 1 - - - useholder - 1 - - - useintroduction - 1 - - - usenamea - 1 - - - usenameb - 1 - - - usenamec - 1 - - - usetranslator - 0 - - - useshortauthor - 1 - - - useshorteditor - 1 - - - - - datamodel - labelalphanametemplate - labelalphatemplate - inheritance - translit - uniquenametemplate - sortingnamekeytemplate - sortingtemplate - extradatespec - extradatecontext - labelnamespec - labeltitlespec - labeldatespec - controlversion - alphaothers - sortalphaothers - presort - texencoding - bibencoding - sortingtemplatename - sortlocale - language - autolang - langhook - indexing - hyperref - backrefsetstyle - block - pagetracker - citecounter - citetracker - ibidtracker - idemtracker - opcittracker - loccittracker - labeldate - labeltime - dateera - date - time - eventdate - eventtime - origdate - origtime - urldate - urltime - alldatesusetime - alldates - alltimes - gregorianstart - autocite - notetype - uniquelist - uniquename - refsection - refsegment - citereset - sortlos - babel - datelabel - backrefstyle - arxiv - familyinits - giveninits - prefixinits - suffixinits - useafterword - useannotator - useauthor - usebookauthor - usecommentator - useeditor - useeditora - useeditorb - useeditorc - useforeword - useholder - useintroduction - usenamea - usenameb - usenamec - usetranslator - useshortauthor - useshorteditor - debug - loadfiles - safeinputenc - sortcase - sortupper - terseinits - abbreviate - dateabbrev - clearlang - sortcites - sortsets - backref - backreffloats - trackfloats - parentracker - labeldateusetime - datecirca - dateuncertain - dateusetime - eventdateusetime - origdateusetime - urldateusetime - julian - datezeros - timezeros - timezones - seconds - autopunct - punctfont - labelnumber - labelalpha - labeltitle - labeltitleyear - labeldateparts - pluralothers - nohashothers - nosortothers - noroman - singletitle - uniquetitle - uniquebaretitle - uniquework - uniqueprimaryauthor - defernumbers - locallabelwidth - bibwarn - useprefix - skipbib - skipbiblist - skiplab - dataonly - defernums - firstinits - sortfirstinits - sortgiveninits - labelyear - isbn - url - doi - eprint - related - dashed - mergedate - bibtexcaseprotection - mincrossrefs - minxrefs - maxnames - minnames - maxbibnames - minbibnames - maxcitenames - mincitenames - maxsortnames - minsortnames - maxitems - minitems - maxalphanames - minalphanames - maxparens - dateeraauto - - - alphaothers - sortalphaothers - presort - indexing - citetracker - ibidtracker - idemtracker - opcittracker - loccittracker - uniquelist - uniquename - familyinits - giveninits - prefixinits - suffixinits - useafterword - useannotator - useauthor - usebookauthor - usecommentator - useeditor - useeditora - useeditorb - useeditorc - useforeword - useholder - useintroduction - usenamea - usenameb - usenamec - usetranslator - useshortauthor - useshorteditor - terseinits - abbreviate - dateabbrev - clearlang - labelnumber - labelalpha - labeltitle - labeltitleyear - labeldateparts - nohashothers - nosortothers - noroman - singletitle - uniquetitle - uniquebaretitle - uniquework - uniqueprimaryauthor - useprefix - skipbib - skipbiblist - skiplab - dataonly - skiplos - labelyear - isbn - url - doi - eprint - related - mergedate - bibtexcaseprotection - labelalphatemplate - translit - sortexclusion - sortinclusion - extradatecontext - labelnamespec - labeltitlespec - labeldatespec - maxnames - minnames - maxbibnames - minbibnames - maxcitenames - mincitenames - maxsortnames - minsortnames - maxitems - minitems - maxalphanames - minalphanames - - - noinherit - nametemplates - labelalphanametemplatename - uniquenametemplatename - sortingnamekeytemplatename - presort - indexing - citetracker - ibidtracker - idemtracker - opcittracker - loccittracker - uniquelist - uniquename - familyinits - giveninits - prefixinits - suffixinits - useafterword - useannotator - useauthor - usebookauthor - usecommentator - useeditor - useeditora - useeditorb - useeditorc - useforeword - useholder - useintroduction - usenamea - usenameb - usenamec - usetranslator - useshortauthor - useshorteditor - terseinits - abbreviate - dateabbrev - clearlang - labelnumber - labelalpha - labeltitle - labeltitleyear - labeldateparts - nohashothers - nosortothers - noroman - singletitle - uniquetitle - uniquebaretitle - uniquework - uniqueprimaryauthor - useprefix - skipbib - skipbiblist - skiplab - dataonly - skiplos - isbn - url - doi - eprint - related - mergedate - bibtexcaseprotection - maxnames - minnames - maxbibnames - minbibnames - maxcitenames - mincitenames - maxsortnames - minsortnames - maxitems - minitems - maxalphanames - minalphanames - - - nametemplates - labelalphanametemplatename - uniquenametemplatename - sortingnamekeytemplatename - uniquelist - uniquename - familyinits - giveninits - prefixinits - suffixinits - terseinits - nohashothers - nosortothers - useprefix - - - nametemplates - labelalphanametemplatename - uniquenametemplatename - sortingnamekeytemplatename - uniquename - familyinits - giveninits - prefixinits - suffixinits - terseinits - useprefix - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - prefix - family - - - - - shorthand - label - labelname - labelname - - - year - - - - - - labelyear - year - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - prefix - family - given - - - - - prefix - family - - - given - - - suffix - - - prefix - - - mm - - - - sf,sm,sn,pf,pm,pn,pp - family,given,prefix,suffix - boolean,integer,string,xml - default,transliteration,transcription,translation - - - article - artwork - audio - bibnote - book - bookinbook - booklet - collection - commentary - customa - customb - customc - customd - custome - customf - dataset - inbook - incollection - inproceedings - inreference - image - jurisdiction - legal - legislation - letter - manual - misc - movie - music - mvcollection - mvreference - mvproceedings - mvbook - online - patent - performance - periodical - proceedings - reference - report - review - set - software - standard - suppbook - suppcollection - suppperiodical - thesis - unpublished - video - xdata - - - sortyear - volume - volumes - abstract - addendum - annotation - booksubtitle - booktitle - booktitleaddon - chapter - edition - eid - entrysubtype - eprintclass - eprinttype - eventtitle - eventtitleaddon - gender - howpublished - indexsorttitle - indextitle - isan - isbn - ismn - isrn - issn - issue - issuesubtitle - issuetitle - issuetitleaddon - iswc - journalsubtitle - journaltitle - journaltitleaddon - label - langid - langidopts - library - mainsubtitle - maintitle - maintitleaddon - nameaddon - note - number - origtitle - pagetotal - part - relatedstring - relatedtype - reprinttitle - series - shorthandintro - subtitle - title - titleaddon - usera - userb - userc - userd - usere - userf - venue - version - shorthand - shortjournal - shortseries - shorttitle - sorttitle - sortshorthand - sortkey - presort - institution - lista - listb - listc - listd - liste - listf - location - organization - origlocation - origpublisher - publisher - afterword - annotator - author - bookauthor - commentator - editor - editora - editorb - editorc - foreword - holder - introduction - namea - nameb - namec - translator - shortauthor - shorteditor - sortname - authortype - editoratype - editorbtype - editorctype - editortype - bookpagination - nameatype - namebtype - namectype - pagination - pubstate - type - language - origlanguage - crossref - xref - date - endyear - year - month - day - hour - minute - second - timezone - yeardivision - endmonth - endday - endhour - endminute - endsecond - endtimezone - endyeardivision - eventdate - eventendyear - eventyear - eventmonth - eventday - eventhour - eventminute - eventsecond - eventtimezone - eventyeardivision - eventendmonth - eventendday - eventendhour - eventendminute - eventendsecond - eventendtimezone - eventendyeardivision - origdate - origendyear - origyear - origmonth - origday - orighour - origminute - origsecond - origtimezone - origyeardivision - origendmonth - origendday - origendhour - origendminute - origendsecond - origendtimezone - origendyeardivision - urldate - urlendyear - urlyear - urlmonth - urlday - urlhour - urlminute - urlsecond - urltimezone - urlyeardivision - urlendmonth - urlendday - urlendhour - urlendminute - urlendsecond - urlendtimezone - urlendyeardivision - doi - eprint - file - verba - verbb - verbc - url - xdata - ids - entryset - related - keywords - options - relatedoptions - pages - execute - - - abstract - annotation - authortype - bookpagination - crossref - day - doi - eprint - eprintclass - eprinttype - endday - endhour - endminute - endmonth - endsecond - endtimezone - endyear - endyeardivision - entryset - entrysubtype - execute - file - gender - hour - ids - indextitle - indexsorttitle - isan - ismn - iswc - keywords - label - langid - langidopts - library - lista - listb - listc - listd - liste - listf - minute - month - namea - nameb - namec - nameatype - namebtype - namectype - nameaddon - options - origday - origendday - origendhour - origendminute - origendmonth - origendsecond - origendtimezone - origendyear - origendyeardivision - orighour - origminute - origmonth - origsecond - origtimezone - origyear - origyeardivision - origlocation - origpublisher - origtitle - pagination - presort - related - relatedoptions - relatedstring - relatedtype - second - shortauthor - shorteditor - shorthand - shorthandintro - shortjournal - shortseries - shorttitle - sortkey - sortname - sortshorthand - sorttitle - sortyear - timezone - url - urlday - urlendday - urlendhour - urlendminute - urlendmonth - urlendsecond - urlendtimezone - urlendyear - urlhour - urlminute - urlmonth - urlsecond - urltimezone - urlyear - usera - userb - userc - userd - usere - userf - verba - verbb - verbc - xdata - xref - year - yeardivision - - - set - entryset - - - article - addendum - annotator - author - commentator - editor - editora - editorb - editorc - editortype - editoratype - editorbtype - editorctype - eid - issn - issue - issuetitle - issuesubtitle - issuetitleaddon - journalsubtitle - journaltitle - journaltitleaddon - language - note - number - origlanguage - pages - pubstate - series - subtitle - title - titleaddon - translator - version - volume - - - bibnote - note - - - book - author - addendum - afterword - annotator - chapter - commentator - edition - editor - editora - editorb - editorc - editortype - editoratype - editorbtype - editorctype - eid - foreword - introduction - isbn - language - location - maintitle - maintitleaddon - mainsubtitle - note - number - origlanguage - pages - pagetotal - part - publisher - pubstate - series - subtitle - title - titleaddon - translator - volume - volumes - - - mvbook - addendum - afterword - annotator - author - commentator - edition - editor - editora - editorb - editorc - editortype - editoratype - editorbtype - editorctype - foreword - introduction - isbn - language - location - note - number - origlanguage - pagetotal - publisher - pubstate - series - subtitle - title - titleaddon - translator - volume - volumes - - - inbook - bookinbook - suppbook - addendum - afterword - annotator - author - booktitle - bookauthor - booksubtitle - booktitleaddon - chapter - commentator - edition - editor - editora - editorb - editorc - editortype - editoratype - editorbtype - editorctype - eid - foreword - introduction - isbn - language - location - mainsubtitle - maintitle - maintitleaddon - note - number - origlanguage - part - publisher - pages - pubstate - series - subtitle - title - titleaddon - translator - volume - volumes - - - booklet - addendum - author - chapter - editor - editortype - eid - howpublished - language - location - note - pages - pagetotal - pubstate - subtitle - title - titleaddon - type - - - collection - reference - addendum - afterword - annotator - chapter - commentator - edition - editor - editora - editorb - editorc - editortype - editoratype - editorbtype - editorctype - eid - foreword - introduction - isbn - language - location - mainsubtitle - maintitle - maintitleaddon - note - number - origlanguage - pages - pagetotal - part - publisher - pubstate - series - subtitle - title - titleaddon - translator - volume - volumes - - - mvcollection - mvreference - addendum - afterword - annotator - author - commentator - edition - editor - editora - editorb - editorc - editortype - editoratype - editorbtype - editorctype - foreword - introduction - isbn - language - location - note - number - origlanguage - publisher - pubstate - subtitle - title - titleaddon - translator - volume - volumes - - - incollection - suppcollection - inreference - addendum - afterword - annotator - author - booksubtitle - booktitle - booktitleaddon - chapter - commentator - edition - editor - editora - editorb - editorc - editortype - editoratype - editorbtype - editorctype - eid - foreword - introduction - isbn - language - location - mainsubtitle - maintitle - maintitleaddon - note - number - origlanguage - pages - part - publisher - pubstate - series - subtitle - title - titleaddon - translator - volume - volumes - - - dataset - addendum - author - edition - editor - editortype - language - location - note - number - organization - publisher - pubstate - series - subtitle - title - titleaddon - type - version - - - manual - addendum - author - chapter - edition - editor - editortype - eid - isbn - language - location - note - number - organization - pages - pagetotal - publisher - pubstate - series - subtitle - title - titleaddon - type - version - - - misc - software - addendum - author - editor - editortype - howpublished - language - location - note - organization - pubstate - subtitle - title - titleaddon - type - version - - - online - addendum - author - editor - editortype - language - note - organization - pubstate - subtitle - title - titleaddon - version - - - patent - addendum - author - holder - location - note - number - pubstate - subtitle - title - titleaddon - type - version - - - periodical - addendum - editor - editora - editorb - editorc - editortype - editoratype - editorbtype - editorctype - issn - issue - issuesubtitle - issuetitle - issuetitleaddon - language - note - number - pubstate - series - subtitle - title - titleaddon - volume - yeardivision - - - mvproceedings - addendum - editor - editortype - eventday - eventendday - eventendhour - eventendminute - eventendmonth - eventendsecond - eventendtimezone - eventendyear - eventendyeardivision - eventhour - eventminute - eventmonth - eventsecond - eventtimezone - eventyear - eventyeardivision - eventtitle - eventtitleaddon - isbn - language - location - note - number - organization - pagetotal - publisher - pubstate - series - subtitle - title - titleaddon - venue - volumes - - - proceedings - addendum - chapter - editor - editortype - eid - eventday - eventendday - eventendhour - eventendminute - eventendmonth - eventendsecond - eventendtimezone - eventendyear - eventendyeardivision - eventhour - eventminute - eventmonth - eventsecond - eventtimezone - eventyear - eventyeardivision - eventtitle - eventtitleaddon - isbn - language - location - mainsubtitle - maintitle - maintitleaddon - note - number - organization - pages - pagetotal - part - publisher - pubstate - series - subtitle - title - titleaddon - venue - volume - volumes - - - inproceedings - addendum - author - booksubtitle - booktitle - booktitleaddon - chapter - editor - editortype - eid - eventday - eventendday - eventendhour - eventendminute - eventendmonth - eventendsecond - eventendtimezone - eventendyear - eventendyeardivision - eventhour - eventminute - eventmonth - eventsecond - eventtimezone - eventyear - eventyeardivision - eventtitle - eventtitleaddon - isbn - language - location - mainsubtitle - maintitle - maintitleaddon - note - number - organization - pages - part - publisher - pubstate - series - subtitle - title - titleaddon - venue - volume - volumes - - - report - addendum - author - chapter - eid - institution - isrn - language - location - note - number - pages - pagetotal - pubstate - subtitle - title - titleaddon - type - version - - - thesis - addendum - author - chapter - eid - institution - language - location - note - pages - pagetotal - pubstate - subtitle - title - titleaddon - type - - - unpublished - addendum - author - eventday - eventendday - eventendhour - eventendminute - eventendmonth - eventendsecond - eventendtimezone - eventendyear - eventendyeardivision - eventhour - eventminute - eventmonth - eventsecond - eventtimezone - eventyear - eventyeardivision - eventtitle - eventtitleaddon - howpublished - language - location - note - pubstate - subtitle - title - titleaddon - type - venue - - - abstract - addendum - afterword - annotator - author - bookauthor - booksubtitle - booktitle - booktitleaddon - chapter - commentator - editor - editora - editorb - editorc - foreword - holder - institution - introduction - issuesubtitle - issuetitle - issuetitleaddon - journalsubtitle - journaltitle - journaltitleaddon - location - mainsubtitle - maintitle - maintitleaddon - nameaddon - note - organization - origlanguage - origlocation - origpublisher - origtitle - part - publisher - relatedstring - series - shortauthor - shorteditor - shorthand - shortjournal - shortseries - shorttitle - sortname - sortshorthand - sorttitle - subtitle - title - titleaddon - translator - venue - - - article - book - inbook - bookinbook - suppbook - booklet - collection - incollection - suppcollection - manual - misc - mvbook - mvcollection - online - patent - periodical - suppperiodical - proceedings - inproceedings - reference - inreference - report - set - thesis - unpublished - - - date - year - - - - - set - - entryset - - - - article - - author - journaltitle - title - - - - book - mvbook - - author - title - - - - inbook - bookinbook - suppbook - - author - title - booktitle - - - - booklet - - - author - editor - - title - - - - collection - reference - mvcollection - mvreference - - editor - title - - - - incollection - suppcollection - inreference - - author - editor - title - booktitle - - - - dataset - - title - - - - manual - - title - - - - misc - software - - title - - - - online - - title - - url - doi - eprint - - - - - patent - - author - title - number - - - - periodical - - editor - title - - - - proceedings - mvproceedings - - title - - - - inproceedings - - author - title - booktitle - - - - report - - author - title - type - institution - - - - thesis - - author - title - type - institution - - - - unpublished - - author - title - - - - - isbn - - - issn - - - ismn - - - gender - - - - - - - citations.bib - - - - - - - presort - - - sortkey - - - sortyear - year - 9999 - - - sortname - author - editor - translator - sorttitle - title - - - sorttitle - title - - - - diff --git a/curriculum/cv.out b/curriculum/cv.out deleted file mode 100644 index da78e19..0000000 --- a/curriculum/cv.out +++ /dev/null @@ -1,4 +0,0 @@ -\BOOKMARK [1][-]{section.1}{\376\377\000W\000o\000r\000k\000\040\000E\000x\000p\000e\000r\000i\000e\000n\000c\000e}{}% 1 -\BOOKMARK [1][-]{section.2}{\376\377\000P\000r\000o\000j\000e\000c\000t\000s}{}% 2 -\BOOKMARK [1][-]{section.3}{\376\377\000E\000d\000u\000c\000a\000t\000i\000o\000n}{}% 3 -\BOOKMARK [1][-]{section.4}{\376\377\000S\000k\000i\000l\000l\000s}{}% 4 diff --git a/curriculum/cv.run.xml b/curriculum/cv.run.xml deleted file mode 100644 index 5c64f7c..0000000 --- a/curriculum/cv.run.xml +++ /dev/null @@ -1,85 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - -]> - - - latex - - cv.bcf - - - cv.bbl - - - blx-dm.def - blx-compat.def - biblatex.def - standard.bbx - authoryear.bbx - authoryear.cbx - biblatex.cfg - english.lbx - - - - biber - - biber - cv - - - cv.bcf - - - cv.bbl - - - cv.bbl - - - cv.bcf - - - citations.bib - - - diff --git a/hugo.toml b/hugo.toml new file mode 100644 index 0000000..d56797d --- /dev/null +++ b/hugo.toml @@ -0,0 +1,52 @@ +# Base URL used when generating links to your pages +# Set to the URL for your site +baseURL = "https://o-santi.github.com" + +# The name of this wonderful theme ;-). +theme = 'hugo-bearblog' + +# Basic metadata configuration for your blog. +title = "lowestcase" +author = "leonardo santiago" +languageCode = "en-US" + +# Generate a nice robots.txt for SEO +enableRobotsTXT = true +staticDir = [ "static" ] + +# Generate "Bearblog"-like URLs !only!, see https://bearblog.dev/. +disableKinds = ["taxonomy"] +ignoreErrors = ["error-disable-taxonomy"] +[permalinks] + blog = "/:slug/" + tags = "/blog/:slug" + +[params] + # The "description" of your website. This is used in the meta data of your generated html. + description = "a lowercase only blog" + + # The path to your "favicon". This should be a square (at least 32px x 32px) png-file. + # Hint: It's good practise to also put a "favicon.ico"-file into your "static"-folder. + # favicon = "images/favicon.png" + + # These "images" are used for the structured data templates. This will show up, when + # services like Twitter or Slack want to generate a preview of a link to your site. + # See https://gohugo.io/templates/internal#twitter-cards and + # https://gohugo.io/templates/internal#open-graph. + # images = ["images/share.png"] + + # Another "title" :-). This one is used as the site_name on the Hugo's internal + # opengraph structured data template. + # See https://ogp.me/ and https://gohugo.io/templates/internal#open-graph. + title = "lowestcase" + + # This theme will, by default, inject a made-with-line at the bottom of the page. + # You can turn it off, but we would really appreciate if you don’t :-). + hideMadeWithLine = true + + # By default, this theme displays dates with a format like "02 Jan, 2006", but + # you can customize it by setting the `dateFormat` param in your site's config + # file. See [Hugo's Format function docs](https://gohugo.io/functions/format/) + # for details. An example TOML config that uses [ISO + # 8601](https://en.wikipedia.org/wiki/ISO_8601) format: + dateFormat = "02-01-2006" diff --git a/layouts/partials/custom_head.html b/layouts/partials/custom_head.html new file mode 100644 index 0000000..71cbf20 --- /dev/null +++ b/layouts/partials/custom_head.html @@ -0,0 +1,17 @@ + diff --git a/layouts/partials/footer.html b/layouts/partials/footer.html new file mode 100644 index 0000000..a102ffa --- /dev/null +++ b/layouts/partials/footer.html @@ -0,0 +1 @@ +leonardo santiago | diff --git a/layouts/partials/nav.html b/layouts/partials/nav.html new file mode 100644 index 0000000..909fc98 --- /dev/null +++ b/layouts/partials/nav.html @@ -0,0 +1,7 @@ +home +{{ range .Site.Menus.main }} +{{ .Name }} +{{ end }} +{{ with .Site.GetPage "/blog" }} +blog +{{ end }} diff --git a/public/404.html b/public/404.html index 4d56ada..12d4704 100644 --- a/public/404.html +++ b/public/404.html @@ -1,497 +1,249 @@ - - - - - - - - - 404 Page not found · lowest case - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + +404 + + + + + + + + + - - - - - - - + + + + + + + + + + + + - -
- skip to main content -
- - - -
- - -
- - - - - - - - - -
-
- -

page not found 😕

-

- error 404 -

-
-

it seems that the page you've requested does not exist.

-
- - -
- - - - -
- - - -

- © - 2024 - leonardo santiago -

- - - - -

- - - powered by Hugo & Blowfish -

- - -
- - - - - - -
- -
diff --git a/public/about/index.html b/public/about/index.html index 0483f54..494ed57 100644 --- a/public/about/index.html +++ b/public/about/index.html @@ -1,827 +1,277 @@ - - - - - + + + + + - - - about · lowest case - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +about | lowestcase + + + + + + + - - + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + - -
- skip to main content -
- - - - - - - - - - - -
-
- - - -
- - -
- -
    - - - - - - - - - -
- - - -

- about -

-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- - - ·1 min - - - - -
- - - - - -
+ +

- - - - - - - - - - - - -

- - +

-
- - - - - - +
+
leonardo santiago | +
- - - - - - - - - - - - - -
- - - - - - - - - - - - - - - - - - -
-
- - - - - - -
- - - -
- - - - -
- - - -

- © - 2024 - leonardo santiago -

- - - - -

- - - powered by Hugo & Blowfish -

- - -
- - - - - - -
- -
diff --git a/public/android-chrome-192x192.png b/public/android-chrome-192x192.png deleted file mode 100644 index b63c037..0000000 Binary files a/public/android-chrome-192x192.png and /dev/null differ diff --git a/public/android-chrome-512x512.png b/public/android-chrome-512x512.png deleted file mode 100644 index da0f767..0000000 Binary files a/public/android-chrome-512x512.png and /dev/null differ diff --git a/public/apple-touch-icon.png b/public/apple-touch-icon.png deleted file mode 100644 index a011953..0000000 Binary files a/public/apple-touch-icon.png and /dev/null differ diff --git a/public/authors/index.html b/public/authors/index.html deleted file mode 100644 index f6abbc8..0000000 --- a/public/authors/index.html +++ /dev/null @@ -1,549 +0,0 @@ - - - - - - - - - - authors · lowest case - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- skip to main content -
- - - - - - - - - - - -
-
- - - - - -
- -

authors

-
- - - - - - - - - - - - - - - - - - - - - - -
- - -
- - -
-
- - - - - - - - - -
- -
- - - - - - -
- - - - -
- - - -

- © - 2024 - leonardo santiago -

- - - - -

- - - powered by Hugo & Blowfish -

- - -
- - - - - - -
- -
- - - diff --git a/public/authors/index.xml b/public/authors/index.xml deleted file mode 100644 index 1724adb..0000000 --- a/public/authors/index.xml +++ /dev/null @@ -1,12 +0,0 @@ - - - - authors on lowest case - http://localhost:1313/authors/ - Recent content in authors on lowest case - Hugo -- gohugo.io - en - © 2024 leonardo santiago - - - diff --git a/public/blog/correctness/index.html b/public/blog/correctness/index.html new file mode 100644 index 0000000..9c57d5a --- /dev/null +++ b/public/blog/correctness/index.html @@ -0,0 +1,273 @@ + + + + + + + +Correctness | lowestcase + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+

lowestcase

+
+ +
+
+ + +

Filtering for "Correctness"

+ + Remove filter + + + + + +
+ +
+ + + + + + diff --git a/public/blog/correctness/index.xml b/public/blog/correctness/index.xml new file mode 100644 index 0000000..9b91eed --- /dev/null +++ b/public/blog/correctness/index.xml @@ -0,0 +1,19 @@ + + + + Correctness on lowestcase + http://localhost:1313/blog/correctness/ + Recent content in Correctness on lowestcase + Hugo + en-US + Sat, 01 Jun 2024 15:21:30 -0300 + + + rust is not about memory safety + http://localhost:1313/rust-is-not-about-memory-safety/ + Sat, 01 Jun 2024 15:21:30 -0300 + http://localhost:1313/rust-is-not-about-memory-safety/ + most of rust discussions nowadays revolve about memory safety, and how it is safer than C / C++ / zig / go / whatever language is being trashed on twitter that day. while yes, that is true - not that the bar for most of these is particularly high - what I think is the main point of the language is always glossed over: correctness. when one tries to criticize any of the aforementioned languages, one is answered with the following argument: + + + diff --git a/public/blog/index.html b/public/blog/index.html new file mode 100644 index 0000000..cfe0206 --- /dev/null +++ b/public/blog/index.html @@ -0,0 +1,277 @@ + + + + + + + +Blogs | lowestcase + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+

lowestcase

+
+ +
+
+ + + + + +
+ + #Correctness  + + #Rust  + +
+
+ +
+ +
+ + + + + + diff --git a/public/blog/index.xml b/public/blog/index.xml new file mode 100644 index 0000000..bdbd344 --- /dev/null +++ b/public/blog/index.xml @@ -0,0 +1,19 @@ + + + + Blogs on lowestcase + http://localhost:1313/blog/ + Recent content in Blogs on lowestcase + Hugo + en-US + Sat, 01 Jun 2024 15:21:30 -0300 + + + rust is not about memory safety + http://localhost:1313/rust-is-not-about-memory-safety/ + Sat, 01 Jun 2024 15:21:30 -0300 + http://localhost:1313/rust-is-not-about-memory-safety/ + most of rust discussions nowadays revolve about memory safety, and how it is safer than C / C++ / zig / go / whatever language is being trashed on twitter that day. while yes, that is true - not that the bar for most of these is particularly high - what I think is the main point of the language is always glossed over: correctness. when one tries to criticize any of the aforementioned languages, one is answered with the following argument: + + + diff --git a/public/blog/rust/index.html b/public/blog/rust/index.html new file mode 100644 index 0000000..d61a2ab --- /dev/null +++ b/public/blog/rust/index.html @@ -0,0 +1,273 @@ + + + + + + + +Rust | lowestcase + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+

lowestcase

+
+ +
+
+ + +

Filtering for "Rust"

+ + Remove filter + + + + + +
+ +
+ + + + + + diff --git a/public/blog/rust/index.xml b/public/blog/rust/index.xml new file mode 100644 index 0000000..8714ca6 --- /dev/null +++ b/public/blog/rust/index.xml @@ -0,0 +1,19 @@ + + + + Rust on lowestcase + http://localhost:1313/blog/rust/ + Recent content in Rust on lowestcase + Hugo + en-US + Sat, 01 Jun 2024 15:21:30 -0300 + + + rust is not about memory safety + http://localhost:1313/rust-is-not-about-memory-safety/ + Sat, 01 Jun 2024 15:21:30 -0300 + http://localhost:1313/rust-is-not-about-memory-safety/ + most of rust discussions nowadays revolve about memory safety, and how it is safer than C / C++ / zig / go / whatever language is being trashed on twitter that day. while yes, that is true - not that the bar for most of these is particularly high - what I think is the main point of the language is always glossed over: correctness. when one tries to criticize any of the aforementioned languages, one is answered with the following argument: + + + diff --git a/public/categories/index.html b/public/categories/index.html deleted file mode 100644 index 00d2b67..0000000 --- a/public/categories/index.html +++ /dev/null @@ -1,549 +0,0 @@ - - - - - - - - - - categories · lowest case - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- skip to main content -
- - - - - - - - - - - -
-
- - - - - -
- -

categories

-
- - - - - - - - - - - - - - - - - - - - - - -
- - -
- - -
-
- - - - - - - - - -
- -
- - - - - - -
- - - - -
- - - -

- © - 2024 - leonardo santiago -

- - - - -

- - - powered by Hugo & Blowfish -

- - -
- - - - - - -
- -
- - - diff --git a/public/categories/index.xml b/public/categories/index.xml deleted file mode 100644 index cc900a4..0000000 --- a/public/categories/index.xml +++ /dev/null @@ -1,12 +0,0 @@ - - - - categories on lowest case - http://localhost:1313/categories/ - Recent content in categories on lowest case - Hugo -- gohugo.io - en - © 2024 leonardo santiago - - - diff --git a/public/css/main.bundle.min.81c7ce66608dd0b86aa3e571076f8794993d50f0d4a5b153013edfc28642a93c4104edfdc604558908c3624b8e99386757d81f1bf8c4452c6220cf4c63970408.css b/public/css/main.bundle.min.81c7ce66608dd0b86aa3e571076f8794993d50f0d4a5b153013edfc28642a93c4104edfdc604558908c3624b8e99386757d81f1bf8c4452c6220cf4c63970408.css deleted file mode 100644 index c6df25a..0000000 --- a/public/css/main.bundle.min.81c7ce66608dd0b86aa3e571076f8794993d50f0d4a5b153013edfc28642a93c4104edfdc604558908c3624b8e99386757d81f1bf8c4452c6220cf4c63970408.css +++ /dev/null @@ -1 +0,0 @@ -:root{--color-neutral:255, 255, 255;--color-neutral-50:250, 250, 249;--color-neutral-100:245, 245, 244;--color-neutral-200:231, 229, 228;--color-neutral-300:214, 211, 209;--color-neutral-400:168, 162, 158;--color-neutral-500:120, 113, 108;--color-neutral-600:87, 83, 78;--color-neutral-700:68, 64, 60;--color-neutral-800:41, 37, 36;--color-neutral-900:28, 25, 23;--color-primary-50:255, 247, 237;--color-primary-100:255, 237, 213;--color-primary-200:254, 215, 170;--color-primary-300:253, 186, 116;--color-primary-400:251, 146, 60;--color-primary-500:249, 115, 22;--color-primary-600:234, 88, 12;--color-primary-700:194, 65, 12;--color-primary-800:154, 52, 18;--color-primary-900:124, 45, 18;--color-secondary-50:255, 241, 242;--color-secondary-100:255, 228, 230;--color-secondary-200:254, 205, 211;--color-secondary-300:253, 164, 175;--color-secondary-400:251, 113, 133;--color-secondary-500:244, 63, 94;--color-secondary-600:225, 29, 72;--color-secondary-700:190, 18, 60;--color-secondary-800:159, 18, 57;--color-secondary-900:136, 19, 55}/*!Blowfish | MIT License | https://github.com/nunocoracao/blowfish*/#zen-mode-button{cursor:pointer}.zen-mode{position:relative}body.zen-mode-enable{ #bmc-wbtn, .author { display:none !important; }}/*!tailwindcss v3.4.3 | MIT License | https://tailwindcss.com*/*,::before,::after{box-sizing:border-box;border-width:0;border-style:solid;border-color:initial}::before,::after{--tw-content:''}html,:host{line-height:1.5;-webkit-text-size-adjust:100%;-moz-tab-size:4;-o-tab-size:4;tab-size:4;font-family:ui-sans-serif,system-ui,sans-serif,apple color emoji,segoe ui emoji,segoe ui symbol,noto color emoji;font-feature-settings:normal;font-variation-settings:normal;-webkit-tap-highlight-color:transparent}body{margin:0;line-height:inherit}hr{height:0;color:inherit;border-top-width:1px}abbr:where([title]){-webkit-text-decoration:underline dotted;text-decoration:underline dotted}h1,h2,h3,h4,h5,h6{font-size:inherit;font-weight:inherit}a{color:inherit;text-decoration:inherit}b,strong{font-weight:bolder}code,kbd,samp,pre{font-family:ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,liberation mono,courier new,monospace;font-feature-settings:normal;font-variation-settings:normal;font-size:1em}small{font-size:80%}sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline}sub{bottom:-.25em}sup{top:-.5em}table{text-indent:0;border-color:inherit;border-collapse:collapse}button,input,optgroup,select,textarea{font-family:inherit;font-feature-settings:inherit;font-variation-settings:inherit;font-size:100%;font-weight:inherit;line-height:inherit;letter-spacing:inherit;color:inherit;margin:0;padding:0}button,select{text-transform:none}button,input:where([type=button]),input:where([type=reset]),input:where([type=submit]){-webkit-appearance:button;background-color:transparent;background-image:none}:-moz-focusring{outline:auto}:-moz-ui-invalid{box-shadow:none}progress{vertical-align:baseline}::-webkit-inner-spin-button,::-webkit-outer-spin-button{height:auto}[type=search]{-webkit-appearance:textfield;outline-offset:-2px}::-webkit-search-decoration{-webkit-appearance:none}::-webkit-file-upload-button{-webkit-appearance:button;font:inherit}summary{display:list-item}blockquote,dl,dd,h1,h2,h3,h4,h5,h6,hr,figure,p,pre{margin:0}fieldset{margin:0;padding:0}legend{padding:0}ol,ul,menu{list-style:none;margin:0;padding:0}dialog{padding:0}textarea{resize:vertical}input::-moz-placeholder,textarea::-moz-placeholder{opacity:1;color:#9ca3af}input::placeholder,textarea::placeholder{opacity:1;color:#9ca3af}button,[role=button]{cursor:pointer}:disabled{cursor:default}img,svg,video,canvas,audio,iframe,embed,object{display:block;vertical-align:middle}img,video{max-width:100%;height:auto}[hidden]{display:none}[type=text],input:where(:not([type])),[type=email],[type=url],[type=password],[type=number],[type=date],[type=datetime-local],[type=month],[type=search],[type=tel],[type=time],[type=week],[multiple],textarea,select{-webkit-appearance:none;-moz-appearance:none;appearance:none;background-color:#fff;border-color:#6b7280;border-width:1px;border-radius:0;padding-top:.5rem;padding-right:.75rem;padding-bottom:.5rem;padding-left:.75rem;font-size:1rem;line-height:1.5rem;--tw-shadow:0 0 #0000}[type=text]:focus,input:where(:not([type])):focus,[type=email]:focus,[type=url]:focus,[type=password]:focus,[type=number]:focus,[type=date]:focus,[type=datetime-local]:focus,[type=month]:focus,[type=search]:focus,[type=tel]:focus,[type=time]:focus,[type=week]:focus,[multiple]:focus,textarea:focus,select:focus{outline:2px solid transparent;outline-offset:2px;--tw-ring-inset:var(--tw-empty,/*!*/ /*!*/);--tw-ring-offset-width:0px;--tw-ring-offset-color:#fff;--tw-ring-color:#2563eb;--tw-ring-offset-shadow:var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);--tw-ring-shadow:var(--tw-ring-inset) 0 0 0 calc(1px + var(--tw-ring-offset-width)) var(--tw-ring-color);box-shadow:var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow);border-color:#2563eb}input::-moz-placeholder,textarea::-moz-placeholder{color:#6b7280;opacity:1}input::placeholder,textarea::placeholder{color:#6b7280;opacity:1}::-webkit-datetime-edit-fields-wrapper{padding:0}::-webkit-date-and-time-value{min-height:1.5em;text-align:inherit}::-webkit-datetime-edit{display:inline-flex}::-webkit-datetime-edit,::-webkit-datetime-edit-year-field,::-webkit-datetime-edit-month-field,::-webkit-datetime-edit-day-field,::-webkit-datetime-edit-hour-field,::-webkit-datetime-edit-minute-field,::-webkit-datetime-edit-second-field,::-webkit-datetime-edit-millisecond-field,::-webkit-datetime-edit-meridiem-field{padding-top:0;padding-bottom:0}select{background-image:url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' fill='none' viewBox='0 0 20 20'%3e%3cpath stroke='%236b7280' stroke-linecap='round' stroke-linejoin='round' stroke-width='1.5' d='M6 8l4 4 4-4'/%3e%3c/svg%3e");background-position:right .5rem center;background-repeat:no-repeat;background-size:1.5em 1.5em;padding-right:2.5rem;-webkit-print-color-adjust:exact;print-color-adjust:exact}[multiple],[size]:where(select:not([size="1"])){background-image:initial;background-position:initial;background-repeat:unset;background-size:initial;padding-right:.75rem;-webkit-print-color-adjust:unset;print-color-adjust:unset}[type=checkbox],[type=radio]{-webkit-appearance:none;-moz-appearance:none;appearance:none;padding:0;-webkit-print-color-adjust:exact;print-color-adjust:exact;display:inline-block;vertical-align:middle;background-origin:border-box;-webkit-user-select:none;-moz-user-select:none;user-select:none;flex-shrink:0;height:1rem;width:1rem;color:#2563eb;background-color:#fff;border-color:#6b7280;border-width:1px;--tw-shadow:0 0 #0000}[type=checkbox]{border-radius:0}[type=radio]{border-radius:100%}[type=checkbox]:focus,[type=radio]:focus{outline:2px solid transparent;outline-offset:2px;--tw-ring-inset:var(--tw-empty,/*!*/ /*!*/);--tw-ring-offset-width:2px;--tw-ring-offset-color:#fff;--tw-ring-color:#2563eb;--tw-ring-offset-shadow:var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);--tw-ring-shadow:var(--tw-ring-inset) 0 0 0 calc(2px + var(--tw-ring-offset-width)) var(--tw-ring-color);box-shadow:var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow)}[type=checkbox]:checked,[type=radio]:checked{border-color:transparent;background-color:currentColor;background-size:100% 100%;background-position:50%;background-repeat:no-repeat}[type=checkbox]:checked{background-image:url("data:image/svg+xml,%3csvg viewBox='0 0 16 16' fill='white' xmlns='http://www.w3.org/2000/svg'%3e%3cpath d='M12.207 4.793a1 1 0 010 1.414l-5 5a1 1 0 01-1.414 0l-2-2a1 1 0 011.414-1.414L6.5 9.086l4.293-4.293a1 1 0 011.414 0z'/%3e%3c/svg%3e")}@media(forced-colors:active){[type=checkbox]:checked{-webkit-appearance:auto;-moz-appearance:auto;appearance:auto}}[type=radio]:checked{background-image:url("data:image/svg+xml,%3csvg viewBox='0 0 16 16' fill='white' xmlns='http://www.w3.org/2000/svg'%3e%3ccircle cx='8' cy='8' r='3'/%3e%3c/svg%3e")}@media(forced-colors:active){[type=radio]:checked{-webkit-appearance:auto;-moz-appearance:auto;appearance:auto}}[type=checkbox]:checked:hover,[type=checkbox]:checked:focus,[type=radio]:checked:hover,[type=radio]:checked:focus{border-color:transparent;background-color:currentColor}[type=checkbox]:indeterminate{background-image:url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' fill='none' viewBox='0 0 16 16'%3e%3cpath stroke='white' stroke-linecap='round' stroke-linejoin='round' stroke-width='2' d='M4 8h8'/%3e%3c/svg%3e");border-color:transparent;background-color:currentColor;background-size:100% 100%;background-position:50%;background-repeat:no-repeat}@media(forced-colors:active){[type=checkbox]:indeterminate{-webkit-appearance:auto;-moz-appearance:auto;appearance:auto}}[type=checkbox]:indeterminate:hover,[type=checkbox]:indeterminate:focus{border-color:transparent;background-color:currentColor}[type=file]{background:unset;border-color:inherit;border-width:0;border-radius:0;padding:0;font-size:unset;line-height:inherit}[type=file]:focus{outline:1px solid ButtonText;outline:1px auto -webkit-focus-ring-color}*,::before,::after{--tw-border-spacing-x:0;--tw-border-spacing-y:0;--tw-translate-x:0;--tw-translate-y:0;--tw-rotate:0;--tw-skew-x:0;--tw-skew-y:0;--tw-scale-x:1;--tw-scale-y:1;--tw-pan-x: ;--tw-pan-y: ;--tw-pinch-zoom: ;--tw-scroll-snap-strictness:proximity;--tw-gradient-from-position: ;--tw-gradient-via-position: ;--tw-gradient-to-position: ;--tw-ordinal: ;--tw-slashed-zero: ;--tw-numeric-figure: ;--tw-numeric-spacing: ;--tw-numeric-fraction: ;--tw-ring-inset: ;--tw-ring-offset-width:0px;--tw-ring-offset-color:#fff;--tw-ring-color:rgb(59 130 246 / 0.5);--tw-ring-offset-shadow:0 0 #0000;--tw-ring-shadow:0 0 #0000;--tw-shadow:0 0 #0000;--tw-shadow-colored:0 0 #0000;--tw-blur: ;--tw-brightness: ;--tw-contrast: ;--tw-grayscale: ;--tw-hue-rotate: ;--tw-invert: ;--tw-saturate: ;--tw-sepia: ;--tw-drop-shadow: ;--tw-backdrop-blur: ;--tw-backdrop-brightness: ;--tw-backdrop-contrast: ;--tw-backdrop-grayscale: ;--tw-backdrop-hue-rotate: ;--tw-backdrop-invert: ;--tw-backdrop-opacity: ;--tw-backdrop-saturate: ;--tw-backdrop-sepia: ;--tw-contain-size: ;--tw-contain-layout: ;--tw-contain-paint: ;--tw-contain-style: }::backdrop{--tw-border-spacing-x:0;--tw-border-spacing-y:0;--tw-translate-x:0;--tw-translate-y:0;--tw-rotate:0;--tw-skew-x:0;--tw-skew-y:0;--tw-scale-x:1;--tw-scale-y:1;--tw-pan-x: ;--tw-pan-y: ;--tw-pinch-zoom: ;--tw-scroll-snap-strictness:proximity;--tw-gradient-from-position: ;--tw-gradient-via-position: ;--tw-gradient-to-position: ;--tw-ordinal: ;--tw-slashed-zero: ;--tw-numeric-figure: ;--tw-numeric-spacing: ;--tw-numeric-fraction: ;--tw-ring-inset: ;--tw-ring-offset-width:0px;--tw-ring-offset-color:#fff;--tw-ring-color:rgb(59 130 246 / 0.5);--tw-ring-offset-shadow:0 0 #0000;--tw-ring-shadow:0 0 #0000;--tw-shadow:0 0 #0000;--tw-shadow-colored:0 0 #0000;--tw-blur: ;--tw-brightness: ;--tw-contrast: ;--tw-grayscale: ;--tw-hue-rotate: ;--tw-invert: ;--tw-saturate: ;--tw-sepia: ;--tw-drop-shadow: ;--tw-backdrop-blur: ;--tw-backdrop-brightness: ;--tw-backdrop-contrast: ;--tw-backdrop-grayscale: ;--tw-backdrop-hue-rotate: ;--tw-backdrop-invert: ;--tw-backdrop-opacity: ;--tw-backdrop-saturate: ;--tw-backdrop-sepia: ;--tw-contain-size: ;--tw-contain-layout: ;--tw-contain-paint: ;--tw-contain-style: }.container{width:100%}@media(min-width:640px){.container{max-width:640px}}@media(min-width:853px){.container{max-width:853px}}@media(min-width:1024px){.container{max-width:1024px}}@media(min-width:1280px){.container{max-width:1280px}}@media(min-width:1536px){.container{max-width:1536px}}.prose{color:var(--tw-prose-body);max-width:65ch}.prose :where(p):not(:where([class~=not-prose],[class~=not-prose] *)){margin-top:1.25em;margin-bottom:1.25em}.prose :where([class~=lead]):not(:where([class~=not-prose],[class~=not-prose] *)){color:var(--tw-prose-lead);font-size:1.25em;line-height:1.6;margin-top:1.2em;margin-bottom:1.2em}.prose :where(a):not(:where([class~=not-prose],[class~=not-prose] *)){color:var(--tw-prose-links);text-decoration:none;font-weight:500;text-decoration-color:rgba(var(--color-primary-300),1)}.prose :where(a):not(:where([class~=not-prose],[class~=not-prose] *)):hover{color:rgba(var(--color-primary-600),1);text-decoration:none;border-radius:.09rem}.prose :where(strong):not(:where([class~=not-prose],[class~=not-prose] *)){color:var(--tw-prose-bold);font-weight:600}.prose :where(a strong):not(:where([class~=not-prose],[class~=not-prose] *)){color:inherit}.prose :where(blockquote strong):not(:where([class~=not-prose],[class~=not-prose] *)){color:inherit}.prose :where(thead th strong):not(:where([class~=not-prose],[class~=not-prose] *)){color:inherit}.prose :where(ol):not(:where([class~=not-prose],[class~=not-prose] *)){list-style-type:decimal;margin-top:1.25em;margin-bottom:1.25em;padding-inline-start:1.625em}.prose :where(ol[type=A]):not(:where([class~=not-prose],[class~=not-prose] *)){list-style-type:upper-alpha}.prose :where(ol[type=a]):not(:where([class~=not-prose],[class~=not-prose] *)){list-style-type:lower-alpha}.prose :where(ol[type=As]):not(:where([class~=not-prose],[class~=not-prose] *)){list-style-type:upper-alpha}.prose :where(ol[type=as]):not(:where([class~=not-prose],[class~=not-prose] *)){list-style-type:lower-alpha}.prose :where(ol[type=I]):not(:where([class~=not-prose],[class~=not-prose] *)){list-style-type:upper-roman}.prose :where(ol[type=i]):not(:where([class~=not-prose],[class~=not-prose] *)){list-style-type:lower-roman}.prose :where(ol[type=Is]):not(:where([class~=not-prose],[class~=not-prose] *)){list-style-type:upper-roman}.prose :where(ol[type=is]):not(:where([class~=not-prose],[class~=not-prose] *)){list-style-type:lower-roman}.prose :where(ol[type="1"]):not(:where([class~=not-prose],[class~=not-prose] *)){list-style-type:decimal}.prose :where(ul):not(:where([class~=not-prose],[class~=not-prose] *)){list-style-type:disc;margin-top:1.25em;margin-bottom:1.25em;padding-inline-start:1.625em}.prose :where(ol>li):not(:where([class~=not-prose],[class~=not-prose] *))::marker{font-weight:400;color:var(--tw-prose-counters)}.prose :where(ul>li):not(:where([class~=not-prose],[class~=not-prose] *))::marker{color:var(--tw-prose-bullets)}.prose :where(dt):not(:where([class~=not-prose],[class~=not-prose] *)){color:var(--tw-prose-headings);font-weight:600;margin-top:1.25em}.prose :where(hr):not(:where([class~=not-prose],[class~=not-prose] *)){border-color:var(--tw-prose-hr);border-top-width:1px;margin-top:3em;margin-bottom:3em}.prose :where(blockquote):not(:where([class~=not-prose],[class~=not-prose] *)){font-weight:500;font-style:italic;color:var(--tw-prose-quotes);border-inline-start-width:.25rem;border-inline-start-color:var(--tw-prose-quote-borders);quotes:"\201C""\201D""\2018""\2019";margin-top:1.6em;margin-bottom:1.6em;padding-inline-start:1em}.prose :where(blockquote p:first-of-type):not(:where([class~=not-prose],[class~=not-prose] *))::before{content:open-quote}.prose :where(blockquote p:last-of-type):not(:where([class~=not-prose],[class~=not-prose] *))::after{content:close-quote}.prose :where(h1):not(:where([class~=not-prose],[class~=not-prose] *)){color:var(--tw-prose-headings);font-weight:800;font-size:2.25em;margin-top:0;margin-bottom:.8888889em;line-height:1.1111111}.prose :where(h1 strong):not(:where([class~=not-prose],[class~=not-prose] *)){font-weight:900;color:inherit}.prose :where(h2):not(:where([class~=not-prose],[class~=not-prose] *)){color:var(--tw-prose-headings);font-weight:700;font-size:1.5em;margin-top:2em;margin-bottom:1em;line-height:1.3333333}.prose :where(h2 strong):not(:where([class~=not-prose],[class~=not-prose] *)){font-weight:800;color:inherit}.prose :where(h3):not(:where([class~=not-prose],[class~=not-prose] *)){color:var(--tw-prose-headings);font-weight:600;font-size:1.25em;margin-top:1.6em;margin-bottom:.6em;line-height:1.6}.prose :where(h3 strong):not(:where([class~=not-prose],[class~=not-prose] *)){font-weight:700;color:inherit}.prose :where(h4):not(:where([class~=not-prose],[class~=not-prose] *)){color:var(--tw-prose-headings);font-weight:600;margin-top:1.5em;margin-bottom:.5em;line-height:1.5}.prose :where(h4 strong):not(:where([class~=not-prose],[class~=not-prose] *)){font-weight:700;color:inherit}.prose :where(img):not(:where([class~=not-prose],[class~=not-prose] *)){margin-top:2em;margin-bottom:2em}.prose :where(picture):not(:where([class~=not-prose],[class~=not-prose] *)){display:block;margin-top:2em;margin-bottom:2em}.prose :where(video):not(:where([class~=not-prose],[class~=not-prose] *)){margin-top:2em;margin-bottom:2em}.prose :where(kbd):not(:where([class~=not-prose],[class~=not-prose] *)){font-weight:600;font-family:inherit;color:var(--tw-prose-kbd);box-shadow:0 0 0 1px rgb(var(--tw-prose-kbd-shadows)/10%),0 3px rgb(var(--tw-prose-kbd-shadows)/10%);font-size:.9rem;border-radius:.25rem;padding-top:.1875em;padding-inline-end:.375em;padding-bottom:.1875em;padding-inline-start:.375em;background-color:rgba(var(--color-neutral-200),1);padding:.1rem .4rem}.prose :where(code):not(:where([class~=not-prose],[class~=not-prose] *)){color:var(--tw-prose-code);font-weight:600;font-size:.875em;background-color:rgba(var(--color-neutral-50),1);padding-top:3px;padding-bottom:3px;padding-left:5px;padding-right:5px;border-radius:.25rem}.prose :where(code):not(:where([class~=not-prose],[class~=not-prose] *))::before{content:"`";display:none}.prose :where(code):not(:where([class~=not-prose],[class~=not-prose] *))::after{content:"`";display:none}.prose :where(a code):not(:where([class~=not-prose],[class~=not-prose] *)){color:var(--tw-prose-code)}.prose :where(h1 code):not(:where([class~=not-prose],[class~=not-prose] *)){color:inherit}.prose :where(h2 code):not(:where([class~=not-prose],[class~=not-prose] *)){color:inherit;font-size:.875em}.prose :where(h3 code):not(:where([class~=not-prose],[class~=not-prose] *)){color:inherit;font-size:.9em}.prose :where(h4 code):not(:where([class~=not-prose],[class~=not-prose] *)){color:inherit}.prose :where(blockquote code):not(:where([class~=not-prose],[class~=not-prose] *)){color:inherit}.prose :where(thead th code):not(:where([class~=not-prose],[class~=not-prose] *)){color:inherit}.prose :where(pre):not(:where([class~=not-prose],[class~=not-prose] *)){color:var(--tw-prose-pre-code);background-color:var(--tw-prose-pre-bg);overflow-x:auto;font-weight:400;font-size:.875em;line-height:1.7142857;margin-top:1.7142857em;margin-bottom:1.7142857em;border-radius:.375rem;padding-top:.8571429em;padding-inline-end:1.1428571em;padding-bottom:.8571429em;padding-inline-start:1.1428571em}.prose :where(pre code):not(:where([class~=not-prose],[class~=not-prose] *)){background-color:transparent;border-width:0;border-radius:0;padding:0;font-weight:inherit;color:inherit;font-size:inherit;font-family:inherit;line-height:inherit}.prose :where(pre code):not(:where([class~=not-prose],[class~=not-prose] *))::before{content:none}.prose :where(pre code):not(:where([class~=not-prose],[class~=not-prose] *))::after{content:none}.prose :where(table):not(:where([class~=not-prose],[class~=not-prose] *)){width:100%;table-layout:auto;text-align:start;margin-top:2em;margin-bottom:2em;font-size:.875em;line-height:1.7142857}.prose :where(thead):not(:where([class~=not-prose],[class~=not-prose] *)){border-bottom-width:1px;border-bottom-color:var(--tw-prose-th-borders)}.prose :where(thead th):not(:where([class~=not-prose],[class~=not-prose] *)){color:var(--tw-prose-headings);font-weight:600;vertical-align:bottom;padding-inline-end:.5714286em;padding-bottom:.5714286em;padding-inline-start:.5714286em}.prose :where(tbody tr):not(:where([class~=not-prose],[class~=not-prose] *)){border-bottom-width:1px;border-bottom-color:var(--tw-prose-td-borders)}.prose :where(tbody tr:last-child):not(:where([class~=not-prose],[class~=not-prose] *)){border-bottom-width:0}.prose :where(tbody td):not(:where([class~=not-prose],[class~=not-prose] *)){vertical-align:baseline}.prose :where(tfoot):not(:where([class~=not-prose],[class~=not-prose] *)){border-top-width:1px;border-top-color:var(--tw-prose-th-borders)}.prose :where(tfoot td):not(:where([class~=not-prose],[class~=not-prose] *)){vertical-align:top}.prose :where(figure>*):not(:where([class~=not-prose],[class~=not-prose] *)){margin-top:0;margin-bottom:0}.prose :where(figcaption):not(:where([class~=not-prose],[class~=not-prose] *)){color:var(--tw-prose-captions);font-size:.875em;line-height:1.4285714;margin-top:.8571429em}.prose{--tw-prose-body:rgba(var(--color-neutral-700), 1);--tw-prose-headings:rgba(var(--color-neutral-800), 1);--tw-prose-lead:rgba(var(--color-neutral-500), 1);--tw-prose-links:rgba(var(--color-primary-600), 1);--tw-prose-bold:rgba(var(--color-neutral-900), 1);--tw-prose-counters:rgba(var(--color-neutral-800), 1);--tw-prose-bullets:rgba(var(--color-neutral-500), 1);--tw-prose-hr:rgba(var(--color-neutral-200), 1);--tw-prose-quotes:rgba(var(--color-neutral-700), 1);--tw-prose-quote-borders:rgba(var(--color-primary-200), 1);--tw-prose-captions:rgba(var(--color-neutral-500), 1);--tw-prose-kbd:#111827;--tw-prose-kbd-shadows:17 24 39;--tw-prose-code:rgba(var(--color-secondary-700), 1);--tw-prose-pre-code:rgba(var(--color-neutral-700), 1);--tw-prose-pre-bg:rgba(var(--color-neutral-50), 1);--tw-prose-th-borders:rgba(var(--color-neutral-500), 1);--tw-prose-td-borders:rgba(var(--color-neutral-300), 1);--tw-prose-invert-body:rgba(var(--color-neutral-300), 1);--tw-prose-invert-headings:rgba(var(--color-neutral-50), 1);--tw-prose-invert-lead:rgba(var(--color-neutral-500), 1);--tw-prose-invert-links:rgba(var(--color-primary-400), 1);--tw-prose-invert-bold:rgba(var(--color-neutral), 1);--tw-prose-invert-counters:rgba(var(--color-neutral-400), 1);--tw-prose-invert-bullets:rgba(var(--color-neutral-600), 1);--tw-prose-invert-hr:rgba(var(--color-neutral-500), 1);--tw-prose-invert-quotes:rgba(var(--color-neutral-200), 1);--tw-prose-invert-quote-borders:rgba(var(--color-primary-900), 1);--tw-prose-invert-captions:rgba(var(--color-neutral-400), 1);--tw-prose-invert-kbd:#fff;--tw-prose-invert-kbd-shadows:255 255 255;--tw-prose-invert-code:rgba(var(--color-secondary-400), 1);--tw-prose-invert-pre-code:rgba(var(--color-neutral-200), 1);--tw-prose-invert-pre-bg:rgba(var(--color-neutral-700), 1);--tw-prose-invert-th-borders:rgba(var(--color-neutral-500), 1);--tw-prose-invert-td-borders:rgba(var(--color-neutral-700), 1);font-size:1rem;line-height:1.75}.prose :where(picture>img):not(:where([class~=not-prose],[class~=not-prose] *)){margin-top:0;margin-bottom:0}.prose :where(li):not(:where([class~=not-prose],[class~=not-prose] *)){margin-top:.5em;margin-bottom:.5em}.prose :where(ol>li):not(:where([class~=not-prose],[class~=not-prose] *)){padding-inline-start:.375em}.prose :where(ul>li):not(:where([class~=not-prose],[class~=not-prose] *)){padding-inline-start:.375em}.prose :where(.prose>ul>li p):not(:where([class~=not-prose],[class~=not-prose] *)){margin-top:.75em;margin-bottom:.75em}.prose :where(.prose>ul>li>*:first-child):not(:where([class~=not-prose],[class~=not-prose] *)){margin-top:1.25em}.prose :where(.prose>ul>li>*:last-child):not(:where([class~=not-prose],[class~=not-prose] *)){margin-bottom:1.25em}.prose :where(.prose>ol>li>*:first-child):not(:where([class~=not-prose],[class~=not-prose] *)){margin-top:1.25em}.prose :where(.prose>ol>li>*:last-child):not(:where([class~=not-prose],[class~=not-prose] *)){margin-bottom:1.25em}.prose :where(ul ul,ul ol,ol ul,ol ol):not(:where([class~=not-prose],[class~=not-prose] *)){margin-top:.75em;margin-bottom:.75em}.prose :where(dl):not(:where([class~=not-prose],[class~=not-prose] *)){margin-top:1.25em;margin-bottom:1.25em}.prose :where(dd):not(:where([class~=not-prose],[class~=not-prose] *)){margin-top:.5em;padding-inline-start:1.625em}.prose :where(hr+*):not(:where([class~=not-prose],[class~=not-prose] *)){margin-top:0}.prose :where(h2+*):not(:where([class~=not-prose],[class~=not-prose] *)){margin-top:0}.prose :where(h3+*):not(:where([class~=not-prose],[class~=not-prose] *)){margin-top:0}.prose :where(h4+*):not(:where([class~=not-prose],[class~=not-prose] *)){margin-top:0}.prose :where(thead th:first-child):not(:where([class~=not-prose],[class~=not-prose] *)){padding-inline-start:0}.prose :where(thead th:last-child):not(:where([class~=not-prose],[class~=not-prose] *)){padding-inline-end:0}.prose :where(tbody td,tfoot td):not(:where([class~=not-prose],[class~=not-prose] *)){padding-top:.5714286em;padding-inline-end:.5714286em;padding-bottom:.5714286em;padding-inline-start:.5714286em}.prose :where(tbody td:first-child,tfoot td:first-child):not(:where([class~=not-prose],[class~=not-prose] *)){padding-inline-start:0}.prose :where(tbody td:last-child,tfoot td:last-child):not(:where([class~=not-prose],[class~=not-prose] *)){padding-inline-end:0}.prose :where(figure):not(:where([class~=not-prose],[class~=not-prose] *)){margin-top:2em;margin-bottom:2em}.prose :where(.prose>:first-child):not(:where([class~=not-prose],[class~=not-prose] *)){margin-top:0}.prose :where(.prose>:last-child):not(:where([class~=not-prose],[class~=not-prose] *)){margin-bottom:0}.prose :where(mark):not(:where([class~=not-prose],[class~=not-prose] *)){color:rgba(var(--color-neutral-800),1);background-color:rgba(var(--color-primary-600),1);padding:.1rem .2rem;border-radius:.25rem}.prose :where(p):not(:where([class~=not-prose],[class~=not-prose] *))::before{display:none}.prose :where(p):not(:where([class~=not-prose],[class~=not-prose] *))::after{display:none}.prose :where(a.active):not(:where([class~=not-prose],[class~=not-prose] *)){text-decoration-color:rgba(var(--color-primary-600),1)}.prose :where(p.active):not(:where([class~=not-prose],[class~=not-prose] *)){text-decoration-color:rgba(var(--color-primary-600),1)}.prose-invert{--tw-prose-body:var(--tw-prose-invert-body);--tw-prose-headings:var(--tw-prose-invert-headings);--tw-prose-lead:var(--tw-prose-invert-lead);--tw-prose-links:var(--tw-prose-invert-links);--tw-prose-bold:var(--tw-prose-invert-bold);--tw-prose-counters:var(--tw-prose-invert-counters);--tw-prose-bullets:var(--tw-prose-invert-bullets);--tw-prose-hr:var(--tw-prose-invert-hr);--tw-prose-quotes:var(--tw-prose-invert-quotes);--tw-prose-quote-borders:var(--tw-prose-invert-quote-borders);--tw-prose-captions:var(--tw-prose-invert-captions);--tw-prose-kbd:var(--tw-prose-invert-kbd);--tw-prose-kbd-shadows:var(--tw-prose-invert-kbd-shadows);--tw-prose-code:var(--tw-prose-invert-code);--tw-prose-pre-code:var(--tw-prose-invert-pre-code);--tw-prose-pre-bg:var(--tw-prose-invert-pre-bg);--tw-prose-th-borders:var(--tw-prose-invert-th-borders);--tw-prose-td-borders:var(--tw-prose-invert-td-borders)}.prose-invert :where(a):not(:where([class~=not-prose],[class~=not-prose] *)){text-decoration-color:rgba(var(--color-neutral-600),1)}.prose-invert :where(a):not(:where([class~=not-prose],[class~=not-prose] *)):hover{color:rgba(var(--color-primary-400),1)}.prose-invert :where(kbd):not(:where([class~=not-prose],[class~=not-prose] *)){color:rgba(var(--color-neutral-200),1);background-color:rgba(var(--color-neutral-700),1)}.prose-invert :where(mark):not(:where([class~=not-prose],[class~=not-prose] *)){background-color:rgba(var(--color-primary-400),1)}.prose-invert :where(code):not(:where([class~=not-prose],[class~=not-prose] *)){background-color:rgba(var(--color-neutral-700),1)}.prose-invert :where(a.active):not(:where([class~=not-prose],[class~=not-prose] *)){text-decoration-color:rgba(var(--color-primary-400),1)}.prose-invert :where(p.active):not(:where([class~=not-prose],[class~=not-prose] *)){text-decoration-color:rgba(var(--color-primary-400),1)}.sr-only{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0,0,0,0);white-space:nowrap;border-width:0}.pointer-events-none{pointer-events:none}.pointer-events-auto{pointer-events:auto}.\!visible{visibility:visible!important}.visible{visibility:visible}.invisible{visibility:hidden}.collapse{visibility:collapse}.static{position:static}.fixed{position:fixed}.\!absolute{position:absolute!important}.absolute{position:absolute}.relative{position:relative}.sticky{position:sticky}.inset-0{inset:0}.inset-x-0{left:0;right:0}.bottom-0{bottom:0}.left-0{left:0}.right-0{right:0}.top-0{top:0}.top-20{top:5rem}.top-\[110vh\]{top:110vh}.top-\[calc\(100vh-5\.5rem\)\]{top:calc(100vh - 5.5rem)}.z-10{z-index:10}.z-30{z-index:30}.z-\[1040\]{z-index:1040}.z-\[1070\]{z-index:1070}.z-\[1080\]{z-index:1080}.z-\[1\]{z-index:1}.z-\[2\]{z-index:2}.z-\[999\]{z-index:999}.order-first{order:-9999}.float-left{float:left}.\!-m-px{margin:-1px!important}.m-0{margin:0}.m-1{margin:.25rem}.m-2{margin:.5rem}.m-auto{margin:auto}.-mx-2{margin-left:-.5rem;margin-right:-.5rem}.-my-2{margin-top:-.5rem;margin-bottom:-.5rem}.mx-1{margin-left:.25rem;margin-right:.25rem}.mx-\[15\%\]{margin-left:15%;margin-right:15%}.mx-\[3px\]{margin-left:3px;margin-right:3px}.mx-auto{margin-left:auto;margin-right:auto}.my-0{margin-top:0;margin-bottom:0}.my-3{margin-top:.75rem;margin-bottom:.75rem}.\!mb-0{margin-bottom:0!important}.\!mb-9{margin-bottom:2.25rem!important}.\!mt-0{margin-top:0!important}.-mb-1{margin-bottom:-.25rem}.-ml-12{margin-left:-3rem}.-mr-2{margin-right:-.5rem}.-mr-48{margin-right:-12rem}.-mr-\[100\%\]{margin-right:-100%}.mb-0{margin-bottom:0}.mb-1{margin-bottom:.25rem}.mb-10{margin-bottom:2.5rem}.mb-12{margin-bottom:3rem}.mb-16{margin-bottom:4rem}.mb-2{margin-bottom:.5rem}.mb-20{margin-bottom:5rem}.mb-3{margin-bottom:.75rem}.mb-5{margin-bottom:1.25rem}.mb-6{margin-bottom:1.5rem}.mb-\[2px\]{margin-bottom:2px}.ml-2{margin-left:.5rem}.ml-3{margin-left:.75rem}.ml-6{margin-left:1.5rem}.ml-auto{margin-left:auto}.mr-1{margin-right:.25rem}.mr-2{margin-right:.5rem}.mr-3{margin-right:.75rem}.mr-5{margin-right:1.25rem}.mr-auto{margin-right:auto}.mt-0{margin-top:0}.mt-1{margin-top:.25rem}.mt-10{margin-top:2.5rem}.mt-12{margin-top:3rem}.mt-2{margin-top:.5rem}.mt-20{margin-top:5rem}.mt-3{margin-top:.75rem}.mt-4{margin-top:1rem}.mt-5{margin-top:1.25rem}.mt-6{margin-top:1.5rem}.mt-8{margin-top:2rem}.mt-\[-2px\]{margin-top:-2px}.mt-\[0\.1rem\]{margin-top:.1rem}.box-border{box-sizing:border-box}.box-content{box-sizing:content-box}.\!block{display:block!important}.block{display:block}.inline-block{display:inline-block}.inline{display:inline}.flex{display:flex}.table{display:table}.grid{display:grid}.hidden{display:none}.\!h-px{height:1px!important}.h-0{height:0}.h-1\/2{height:50%}.h-12{height:3rem}.h-24{height:6rem}.h-3{height:.75rem}.h-36{height:9rem}.h-48{height:12rem}.h-6{height:1.5rem}.h-8{height:2rem}.h-\[1000px\]{height:1000px}.h-\[150px\]{height:150px}.h-\[3px\]{height:3px}.h-\[800px\]{height:800px}.h-auto{height:auto}.h-full{height:100%}.h-screen{height:100vh}.max-h-3{max-height:.75rem}.max-h-\[5rem\]{max-height:5rem}.min-h-0{min-height:0}.min-h-\[130px\]{min-height:130px}.min-h-\[148px\]{min-height:148px}.min-h-full{min-height:100%}.\!w-px{width:1px!important}.w-0{width:0}.w-12{width:3rem}.w-2{width:.5rem}.w-24{width:6rem}.w-3{width:.75rem}.w-36{width:9rem}.w-6{width:1.5rem}.w-8{width:2rem}.w-\[15\%\]{width:15%}.w-\[30px\]{width:30px}.w-auto{width:auto}.w-full{width:100%}.w-screen{width:100vw}.min-w-0{min-width:0}.min-w-\[1\.8rem\]{min-width:1.8rem}.min-w-\[220px\]{min-width:220px}.min-w-\[30px\]{min-width:30px}.min-w-full{min-width:100%}.max-w-3xl{max-width:48rem}.max-w-7xl{max-width:80rem}.max-w-\[1600px\]{max-width:1600px}.max-w-\[200px\]{max-width:200px}.max-w-\[267px\]{max-width:267px}.max-w-\[5rem\]{max-width:5rem}.max-w-\[64rem\]{max-width:64rem}.max-w-\[calc\(100\%-1rem\)\]{max-width:calc(100% - 1rem)}.max-w-fit{max-width:-moz-fit-content;max-width:fit-content}.max-w-full{max-width:100%}.max-w-prose{max-width:65ch}.max-w-xl{max-width:36rem}.flex-1{flex:1}.flex-auto{flex:auto}.flex-initial{flex:initial}.flex-none{flex:none}.shrink-0{flex-shrink:0}.grow{flex-grow:1}.grow-0{flex-grow:0}.basis-auto{flex-basis:auto}.-translate-x-full{--tw-translate-x:-100%;transform:translate(var(--tw-translate-x),var(--tw-translate-y))rotate(var(--tw-rotate))skewX(var(--tw-skew-x))skewY(var(--tw-skew-y))scaleX(var(--tw-scale-x))scaleY(var(--tw-scale-y))}.-translate-y-8{--tw-translate-y:-2rem;transform:translate(var(--tw-translate-x),var(--tw-translate-y))rotate(var(--tw-rotate))skewX(var(--tw-skew-x))skewY(var(--tw-skew-y))scaleX(var(--tw-scale-x))scaleY(var(--tw-scale-y))}.translate-x-full{--tw-translate-x:100%;transform:translate(var(--tw-translate-x),var(--tw-translate-y))rotate(var(--tw-rotate))skewX(var(--tw-skew-x))skewY(var(--tw-skew-y))scaleX(var(--tw-scale-x))scaleY(var(--tw-scale-y))}.scale-0{--tw-scale-x:0;--tw-scale-y:0;transform:translate(var(--tw-translate-x),var(--tw-translate-y))rotate(var(--tw-rotate))skewX(var(--tw-skew-x))skewY(var(--tw-skew-y))scaleX(var(--tw-scale-x))scaleY(var(--tw-scale-y))}.scale-100{--tw-scale-x:1;--tw-scale-y:1;transform:translate(var(--tw-translate-x),var(--tw-translate-y))rotate(var(--tw-rotate))skewX(var(--tw-skew-x))skewY(var(--tw-skew-y))scaleX(var(--tw-scale-x))scaleY(var(--tw-scale-y))}.scale-\[1\.02\]{--tw-scale-x:1.02;--tw-scale-y:1.02;transform:translate(var(--tw-translate-x),var(--tw-translate-y))rotate(var(--tw-rotate))skewX(var(--tw-skew-x))skewY(var(--tw-skew-y))scaleX(var(--tw-scale-x))scaleY(var(--tw-scale-y))}.transform{transform:translate(var(--tw-translate-x),var(--tw-translate-y))rotate(var(--tw-rotate))skewX(var(--tw-skew-x))skewY(var(--tw-skew-y))scaleX(var(--tw-scale-x))scaleY(var(--tw-scale-y))}.transform-none{transform:none}@keyframes pulse{50%{opacity:.5}}.animate-pulse{animation:pulse 2s cubic-bezier(.4,0,.6,1)infinite}.cursor-default{cursor:default}.cursor-pointer{cursor:pointer}.touch-none{touch-action:none}.touch-pan-y{--tw-pan-y:pan-y;touch-action:var(--tw-pan-x)var(--tw-pan-y)var(--tw-pinch-zoom)}.resize{resize:both}.list-none{list-style-type:none}.appearance-none{-webkit-appearance:none;-moz-appearance:none;appearance:none}.flex-row{flex-direction:row}.flex-col{flex-direction:column}.flex-wrap{flex-wrap:wrap}.items-end{align-items:flex-end}.items-center{align-items:center}.justify-center{justify-content:center}.justify-between{justify-content:space-between}.gap-4{gap:1rem}.space-x-2>:not([hidden])~:not([hidden]){--tw-space-x-reverse:0;margin-right:calc(.5rem * var(--tw-space-x-reverse));margin-left:calc(.5rem * calc(1 - var(--tw-space-x-reverse)))}.space-x-3>:not([hidden])~:not([hidden]){--tw-space-x-reverse:0;margin-right:calc(.75rem * var(--tw-space-x-reverse));margin-left:calc(.75rem * calc(1 - var(--tw-space-x-reverse)))}.space-x-5>:not([hidden])~:not([hidden]){--tw-space-x-reverse:0;margin-right:calc(1.25rem * var(--tw-space-x-reverse));margin-left:calc(1.25rem * calc(1 - var(--tw-space-x-reverse)))}.space-y-10>:not([hidden])~:not([hidden]){--tw-space-y-reverse:0;margin-top:calc(2.5rem * calc(1 - var(--tw-space-y-reverse)));margin-bottom:calc(2.5rem * var(--tw-space-y-reverse))}.space-y-2>:not([hidden])~:not([hidden]){--tw-space-y-reverse:0;margin-top:calc(.5rem * calc(1 - var(--tw-space-y-reverse)));margin-bottom:calc(.5rem * var(--tw-space-y-reverse))}.space-y-3>:not([hidden])~:not([hidden]){--tw-space-y-reverse:0;margin-top:calc(.75rem * calc(1 - var(--tw-space-y-reverse)));margin-bottom:calc(.75rem * var(--tw-space-y-reverse))}.place-self-center{place-self:center}.self-center{align-self:center}.overflow-auto{overflow:auto}.\!overflow-hidden{overflow:hidden!important}.overflow-hidden{overflow:hidden}.overflow-visible{overflow:visible}.scroll-smooth{scroll-behavior:smooth}.whitespace-normal{white-space:normal}.\!whitespace-nowrap{white-space:nowrap!important}.break-normal{overflow-wrap:normal;word-break:normal}.break-words{overflow-wrap:break-word}.\!rounded-md{border-radius:.375rem!important}.rounded{border-radius:.25rem}.rounded-2xl{border-radius:1rem}.rounded-\[50\%\]{border-radius:50%}.rounded-full{border-radius:9999px}.rounded-lg{border-radius:.5rem}.rounded-md{border-radius:.375rem}.rounded-xl{border-radius:.75rem}.rounded-b-lg{border-bottom-right-radius:.5rem;border-bottom-left-radius:.5rem}.rounded-e-\[0\.25rem\]{border-start-end-radius:.25rem;border-end-end-radius:.25rem}.rounded-s-\[0\.25rem\]{border-start-start-radius:.25rem;border-end-start-radius:.25rem}.rounded-t-lg{border-top-left-radius:.5rem;border-top-right-radius:.5rem}.\!border-0{border-width:0!important}.border{border-width:1px}.border-0{border-width:0}.border-2{border-width:2px}.border-y-\[10px\]{border-top-width:10px;border-bottom-width:10px}.border-b-2{border-bottom-width:2px}.border-e-0{border-inline-end-width:0}.border-l-2{border-left-width:2px}.border-s-0{border-inline-start-width:0}.border-s-\[0\.125rem\]{border-inline-start-width:.125rem}.border-t{border-top-width:1px}.border-solid{border-style:solid}.border-dotted{border-style:dotted}.border-neutral-100{--tw-border-opacity:1;border-color:rgba(var(--color-neutral-100),var(--tw-border-opacity))}.border-neutral-200{--tw-border-opacity:1;border-color:rgba(var(--color-neutral-200),var(--tw-border-opacity))}.border-neutral-300{--tw-border-opacity:1;border-color:rgba(var(--color-neutral-300),var(--tw-border-opacity))}.border-primary-400{--tw-border-opacity:1;border-color:rgba(var(--color-primary-400),var(--tw-border-opacity))}.border-primary-500{--tw-border-opacity:1;border-color:rgba(var(--color-primary-500),var(--tw-border-opacity))}.border-secondary-500{--tw-border-opacity:1;border-color:rgba(var(--color-secondary-500),var(--tw-border-opacity))}.border-transparent{border-color:transparent}.border-t-transparent{border-top-color:transparent}.bg-\[\#6d6d6d\]{--tw-bg-opacity:1;background-color:rgb(109 109 109/var(--tw-bg-opacity))}.bg-neutral{--tw-bg-opacity:1;background-color:rgba(var(--color-neutral),var(--tw-bg-opacity))}.bg-neutral-100{--tw-bg-opacity:1;background-color:rgba(var(--color-neutral-100),var(--tw-bg-opacity))}.bg-neutral-100\/50{background-color:rgba(var(--color-neutral-100),.5)}.bg-neutral-300{--tw-bg-opacity:1;background-color:rgba(var(--color-neutral-300),var(--tw-bg-opacity))}.bg-neutral-500\/50{background-color:rgba(var(--color-neutral-500),.5)}.bg-neutral\/50{background-color:rgba(var(--color-neutral),.5)}.bg-primary-100{--tw-bg-opacity:1;background-color:rgba(var(--color-primary-100),var(--tw-bg-opacity))}.bg-primary-200{--tw-bg-opacity:1;background-color:rgba(var(--color-primary-200),var(--tw-bg-opacity))}.bg-primary-500{--tw-bg-opacity:1;background-color:rgba(var(--color-primary-500),var(--tw-bg-opacity))}.bg-primary-600{--tw-bg-opacity:1;background-color:rgba(var(--color-primary-600),var(--tw-bg-opacity))}.bg-transparent{background-color:transparent}.bg-gradient-to-b{background-image:linear-gradient(to bottom,var(--tw-gradient-stops))}.bg-gradient-to-r{background-image:linear-gradient(to right,var(--tw-gradient-stops))}.bg-gradient-to-t{background-image:linear-gradient(to top,var(--tw-gradient-stops))}.bg-none{background-image:none}.from-neutral{--tw-gradient-from:rgba(var(--color-neutral), 1) var(--tw-gradient-from-position);--tw-gradient-to:rgba(var(--color-neutral), 0) var(--tw-gradient-to-position);--tw-gradient-stops:var(--tw-gradient-from), var(--tw-gradient-to)}.from-primary-500{--tw-gradient-from:rgba(var(--color-primary-500), 1) var(--tw-gradient-from-position);--tw-gradient-to:rgba(var(--color-primary-500), 0) var(--tw-gradient-to-position);--tw-gradient-stops:var(--tw-gradient-from), var(--tw-gradient-to)}.from-60\%{--tw-gradient-from-position:60%}.to-neutral{--tw-gradient-to:rgba(var(--color-neutral), 1) var(--tw-gradient-to-position)}.to-neutral-100{--tw-gradient-to:rgba(var(--color-neutral-100), 1) var(--tw-gradient-to-position)}.to-secondary-600{--tw-gradient-to:rgba(var(--color-secondary-600), 1) var(--tw-gradient-to-position)}.to-transparent{--tw-gradient-to:transparent var(--tw-gradient-to-position)}.bg-clip-padding{background-clip:padding-box}.object-cover{-o-object-fit:cover;object-fit:cover}.object-scale-down{-o-object-fit:scale-down;object-fit:scale-down}.object-left{-o-object-position:left;object-position:left}.\!p-0{padding:0!important}.p-0{padding:0}.p-1{padding:.25rem}.p-1\.5{padding:.375rem}.p-4{padding:1rem}.p-5{padding:1.25rem}.p-6{padding:1.5rem}.px-0{padding-left:0;padding-right:0}.px-1{padding-left:.25rem;padding-right:.25rem}.px-1\.5{padding-left:.375rem;padding-right:.375rem}.px-2{padding-left:.5rem;padding-right:.5rem}.px-3{padding-left:.75rem;padding-right:.75rem}.px-4{padding-left:1rem;padding-right:1rem}.px-6{padding-left:1.5rem;padding-right:1.5rem}.px-\[0\.4rem\]{padding-left:.4rem;padding-right:.4rem}.px-\[30px\]{padding-left:30px;padding-right:30px}.py-1{padding-top:.25rem;padding-bottom:.25rem}.py-1\.5{padding-top:.375rem;padding-bottom:.375rem}.py-10{padding-top:2.5rem;padding-bottom:2.5rem}.py-16{padding-top:4rem;padding-bottom:4rem}.py-2{padding-top:.5rem;padding-bottom:.5rem}.py-3{padding-top:.75rem;padding-bottom:.75rem}.py-4{padding-top:1rem;padding-bottom:1rem}.py-6{padding-top:1.5rem;padding-bottom:1.5rem}.py-8{padding-top:2rem;padding-bottom:2rem}.py-\[0\.4rem\]{padding-top:.4rem;padding-bottom:.4rem}.py-\[1px\]{padding-top:1px;padding-bottom:1px}.pb-2{padding-bottom:.5rem}.pb-3{padding-bottom:.75rem}.pb-32{padding-bottom:8rem}.pb-4{padding-bottom:1rem}.pl-2{padding-left:.5rem}.pl-\[24px\]{padding-left:24px}.pr-\[24px\]{padding-right:24px}.pt-16{padding-top:4rem}.pt-2{padding-top:.5rem}.pt-3{padding-top:.75rem}.pt-4{padding-top:1rem}.pt-8{padding-top:2rem}.text-left{text-align:left}.text-center{text-align:center}.text-right{text-align:right}.-indent-\[999px\]{text-indent:-999px}.align-top{vertical-align:top}.align-middle{vertical-align:middle}.align-bottom{vertical-align:bottom}.align-text-bottom{vertical-align:text-bottom}.text-2xl{font-size:1.5rem;line-height:2rem}.text-4xl{font-size:2.25rem;line-height:2.5rem}.text-\[0\.6rem\]{font-size:.6rem}.text-base{font-size:1rem;line-height:1.5rem}.text-lg{font-size:1.125rem;line-height:1.75rem}.text-sm{font-size:.875rem;line-height:1.25rem}.text-xl{font-size:1.25rem;line-height:1.75rem}.text-xs{font-size:.75rem;line-height:1rem}.font-bold{font-weight:700}.font-extrabold{font-weight:800}.font-light{font-weight:300}.font-medium{font-weight:500}.font-normal{font-weight:400}.font-semibold{font-weight:600}.uppercase{text-transform:uppercase}.normal-case{text-transform:none}.italic{font-style:italic}.not-italic{font-style:normal}.leading-3{line-height:.75rem}.leading-6{line-height:1.5rem}.leading-7{line-height:1.75rem}.leading-\[1\.6\]{line-height:1.6}.tracking-normal{letter-spacing:0}.\!text-neutral{--tw-text-opacity:1 !important;color:rgba(var(--color-neutral),var(--tw-text-opacity))!important}.text-neutral-200{--tw-text-opacity:1;color:rgba(var(--color-neutral-200),var(--tw-text-opacity))}.text-neutral-300{--tw-text-opacity:1;color:rgba(var(--color-neutral-300),var(--tw-text-opacity))}.text-neutral-400{--tw-text-opacity:1;color:rgba(var(--color-neutral-400),var(--tw-text-opacity))}.text-neutral-50{--tw-text-opacity:1;color:rgba(var(--color-neutral-50),var(--tw-text-opacity))}.text-neutral-500{--tw-text-opacity:1;color:rgba(var(--color-neutral-500),var(--tw-text-opacity))}.text-neutral-700{--tw-text-opacity:1;color:rgba(var(--color-neutral-700),var(--tw-text-opacity))}.text-neutral-800{--tw-text-opacity:1;color:rgba(var(--color-neutral-800),var(--tw-text-opacity))}.text-neutral-900{--tw-text-opacity:1;color:rgba(var(--color-neutral-900),var(--tw-text-opacity))}.text-primary-100{--tw-text-opacity:1;color:rgba(var(--color-primary-100),var(--tw-text-opacity))}.text-primary-300{--tw-text-opacity:1;color:rgba(var(--color-primary-300),var(--tw-text-opacity))}.text-primary-400{--tw-text-opacity:1;color:rgba(var(--color-primary-400),var(--tw-text-opacity))}.text-primary-500{--tw-text-opacity:1;color:rgba(var(--color-primary-500),var(--tw-text-opacity))}.text-primary-600{--tw-text-opacity:1;color:rgba(var(--color-primary-600),var(--tw-text-opacity))}.text-primary-700{--tw-text-opacity:1;color:rgba(var(--color-primary-700),var(--tw-text-opacity))}.text-primary-800{--tw-text-opacity:1;color:rgba(var(--color-primary-800),var(--tw-text-opacity))}.text-transparent{color:transparent}.\!no-underline{text-decoration-line:none!important}.no-underline{text-decoration-line:none}.decoration-neutral-300{text-decoration-color:rgba(var(--color-neutral-300),1)}.decoration-primary-500{text-decoration-color:rgba(var(--color-primary-500),1)}.underline-offset-auto{text-underline-offset:auto}.\!opacity-0{opacity:0!important}.\!opacity-100{opacity:1!important}.opacity-0{opacity:0}.opacity-100{opacity:1}.opacity-30{opacity:.3}.opacity-50{opacity:.5}.opacity-60{opacity:.6}.opacity-65{opacity:.65}.mix-blend-normal{mix-blend-mode:normal}.mix-blend-multiply{mix-blend-mode:multiply}.shadow{--tw-shadow:0 1px 3px 0 rgb(0 0 0 / 0.1), 0 1px 2px -1px rgb(0 0 0 / 0.1);--tw-shadow-colored:0 1px 3px 0 var(--tw-shadow-color), 0 1px 2px -1px var(--tw-shadow-color);box-shadow:var(--tw-ring-offset-shadow,0 0 #0000),var(--tw-ring-shadow,0 0 #0000),var(--tw-shadow)}.shadow-2xl{--tw-shadow:0 25px 50px -12px rgb(0 0 0 / 0.25);--tw-shadow-colored:0 25px 50px -12px var(--tw-shadow-color);box-shadow:var(--tw-ring-offset-shadow,0 0 #0000),var(--tw-ring-shadow,0 0 #0000),var(--tw-shadow)}.shadow-lg{--tw-shadow:0 10px 15px -3px rgb(0 0 0 / 0.1), 0 4px 6px -4px rgb(0 0 0 / 0.1);--tw-shadow-colored:0 10px 15px -3px var(--tw-shadow-color), 0 4px 6px -4px var(--tw-shadow-color);box-shadow:var(--tw-ring-offset-shadow,0 0 #0000),var(--tw-ring-shadow,0 0 #0000),var(--tw-shadow)}.shadow-xl{--tw-shadow:0 20px 25px -5px rgb(0 0 0 / 0.1), 0 8px 10px -6px rgb(0 0 0 / 0.1);--tw-shadow-colored:0 20px 25px -5px var(--tw-shadow-color), 0 8px 10px -6px var(--tw-shadow-color);box-shadow:var(--tw-ring-offset-shadow,0 0 #0000),var(--tw-ring-shadow,0 0 #0000),var(--tw-shadow)}.blur{--tw-blur:blur(8px);filter:var(--tw-blur)var(--tw-brightness)var(--tw-contrast)var(--tw-grayscale)var(--tw-hue-rotate)var(--tw-invert)var(--tw-saturate)var(--tw-sepia)var(--tw-drop-shadow)}.filter{filter:var(--tw-blur)var(--tw-brightness)var(--tw-contrast)var(--tw-grayscale)var(--tw-hue-rotate)var(--tw-invert)var(--tw-saturate)var(--tw-sepia)var(--tw-drop-shadow)}.backdrop-blur{--tw-backdrop-blur:blur(8px);-webkit-backdrop-filter:var(--tw-backdrop-blur)var(--tw-backdrop-brightness)var(--tw-backdrop-contrast)var(--tw-backdrop-grayscale)var(--tw-backdrop-hue-rotate)var(--tw-backdrop-invert)var(--tw-backdrop-opacity)var(--tw-backdrop-saturate)var(--tw-backdrop-sepia);backdrop-filter:var(--tw-backdrop-blur)var(--tw-backdrop-brightness)var(--tw-backdrop-contrast)var(--tw-backdrop-grayscale)var(--tw-backdrop-hue-rotate)var(--tw-backdrop-invert)var(--tw-backdrop-opacity)var(--tw-backdrop-saturate)var(--tw-backdrop-sepia)}.backdrop-blur-2xl{--tw-backdrop-blur:blur(40px);-webkit-backdrop-filter:var(--tw-backdrop-blur)var(--tw-backdrop-brightness)var(--tw-backdrop-contrast)var(--tw-backdrop-grayscale)var(--tw-backdrop-hue-rotate)var(--tw-backdrop-invert)var(--tw-backdrop-opacity)var(--tw-backdrop-saturate)var(--tw-backdrop-sepia);backdrop-filter:var(--tw-backdrop-blur)var(--tw-backdrop-brightness)var(--tw-backdrop-contrast)var(--tw-backdrop-grayscale)var(--tw-backdrop-hue-rotate)var(--tw-backdrop-invert)var(--tw-backdrop-opacity)var(--tw-backdrop-saturate)var(--tw-backdrop-sepia)}.backdrop-blur-sm{--tw-backdrop-blur:blur(4px);-webkit-backdrop-filter:var(--tw-backdrop-blur)var(--tw-backdrop-brightness)var(--tw-backdrop-contrast)var(--tw-backdrop-grayscale)var(--tw-backdrop-hue-rotate)var(--tw-backdrop-invert)var(--tw-backdrop-opacity)var(--tw-backdrop-saturate)var(--tw-backdrop-sepia);backdrop-filter:var(--tw-backdrop-blur)var(--tw-backdrop-brightness)var(--tw-backdrop-contrast)var(--tw-backdrop-grayscale)var(--tw-backdrop-hue-rotate)var(--tw-backdrop-invert)var(--tw-backdrop-opacity)var(--tw-backdrop-saturate)var(--tw-backdrop-sepia)}.transition-\[height\]{transition-property:height;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:150ms}.transition-\[transform\2c _opacity\]{transition-property:transform,opacity;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:150ms}.transition-\[width\]{transition-property:width;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:150ms}.transition-all{transition-property:all;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:150ms}.transition-opacity{transition-property:opacity;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:150ms}.transition-transform{transition-property:transform;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:150ms}.duration-150{transition-duration:150ms}.duration-200{transition-duration:200ms}.duration-300{transition-duration:300ms}.duration-\[350ms\]{transition-duration:350ms}.duration-\[600ms\]{transition-duration:600ms}.ease-\[cubic-bezier\(0\2c 0\2c 0\.15\2c 1\)\2c _cubic-bezier\(0\2c 0\2c 0\.15\2c 1\)\]{transition-timing-function:cubic-bezier(0,0,.15,1),cubic-bezier(0,0,.15,1)}.ease-\[cubic-bezier\(0\.25\2c 0\.1\2c 0\.25\2c 1\.0\)\]{transition-timing-function:cubic-bezier(.25,.1,.25,1)}.ease-in-out{transition-timing-function:cubic-bezier(.4,0,.2,1)}.ease-linear{transition-timing-function:linear}.\!\[clip\:rect\(0\2c 0\2c 0\2c 0\)\]{clip:rect(0,0,0,0)!important}body a,body button{transition-property:color,background-color,border-color,text-decoration-color,fill,stroke;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:150ms}.icon svg{height:1em;width:1em}#search-query::-webkit-search-cancel-button,#search-query::-webkit-search-decoration,#search-query::-webkit-search-results-button,#search-query::-webkit-search-results-decoration{display:none}body:has(#menu-controller:checked){overflow-y:hidden}#menu-button:has(#menu-controller:checked){visibility:hidden}#menu-controller:checked~#menu-wrapper{visibility:visible;opacity:1}.prose blockquote:where([dir=rtl],[dir=rtl] *){border-left-width:0;border-right-width:4px;padding-right:1rem}.prose ul>li:where([dir=rtl],[dir=rtl] *),.prose ol>li:where([dir=rtl],[dir=rtl] *){margin-right:1.75rem;padding-left:0;padding-right:.5rem}.prose ol>li:where([dir=rtl],[dir=rtl] *):before,.prose ul>li:where([dir=rtl],[dir=rtl] *):before{left:auto;right:.25rem}.prose thead td:first-child:where([dir=rtl],[dir=rtl] *),.prose thead th:first-child:where([dir=rtl],[dir=rtl] *){padding-right:0}.prose thead td:last-child:where([dir=rtl],[dir=rtl] *),.prose thead th:last-child:where([dir=rtl],[dir=rtl] *){padding-left:0}.prose div.min-w-0.max-w-prose>*:first-child{margin-top:.75rem}.toc ul,.toc li{list-style-type:none;padding-left:0;padding-right:0;line-height:1.375}.toc ul ul:where([dir=ltr],[dir=ltr] *){padding-left:1rem}.toc ul ul:where([dir=rtl],[dir=rtl] *){padding-right:1rem}.toc a{font-weight:400;--tw-text-opacity:1;color:rgba(var(--color-neutral-700),var(--tw-text-opacity))}.toc a:is(.dark *){--tw-text-opacity:1;color:rgba(var(--color-neutral-400),var(--tw-text-opacity))}.toc ul>li:where([dir=rtl],[dir=rtl] *){margin-right:0}.highlight-wrapper{display:block}.highlight{position:relative;z-index:0}.highlight:hover>.copy-button{visibility:visible}.copy-button{visibility:hidden;position:absolute;top:0;right:0;z-index:10;width:5rem;cursor:pointer;white-space:nowrap;border-bottom-left-radius:.375rem;border-top-right-radius:.375rem;--tw-bg-opacity:1;background-color:rgba(var(--color-neutral-200),var(--tw-bg-opacity));padding-top:.25rem;padding-bottom:.25rem;font-family:ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,liberation mono,courier new,monospace;font-size:.875rem;line-height:1.25rem;--tw-text-opacity:1;color:rgba(var(--color-neutral-700),var(--tw-text-opacity));opacity:.9}.copy-button:is(.dark *){--tw-bg-opacity:1;background-color:rgba(var(--color-neutral-600),var(--tw-bg-opacity));--tw-text-opacity:1;color:rgba(var(--color-neutral-200),var(--tw-text-opacity))}.copy-button:hover,.copy-button:focus,.copy-button:active,.copy-button:active:hover{--tw-bg-opacity:1;background-color:rgba(var(--color-primary-100),var(--tw-bg-opacity))}.copy-button:hover:is(.dark *),.copy-button:focus:is(.dark *),.copy-button:active:is(.dark *),.copy-button:active:hover:is(.dark *){--tw-bg-opacity:1;background-color:rgba(var(--color-primary-600),var(--tw-bg-opacity))}.copy-textarea{position:absolute;z-index:-10;opacity:.05}.katex-display{overflow:auto hidden}table{display:block;overflow:auto}code{word-wrap:break-word;overflow-wrap:break-word}.prose .chroma{position:static;border-radius:.375rem;--tw-bg-opacity:1;background-color:rgba(var(--color-neutral-50),var(--tw-bg-opacity));--tw-text-opacity:1;color:rgba(var(--color-neutral-700),var(--tw-text-opacity))}.prose .chroma:is(.dark *){--tw-bg-opacity:1;background-color:rgba(var(--color-neutral-700),var(--tw-bg-opacity));--tw-text-opacity:1;color:rgba(var(--color-neutral-200),var(--tw-text-opacity))}.chroma .lntd,.chroma .lntd pre{margin:0;border-style:none;padding:0;vertical-align:top}.chroma .lntable{display:block;width:auto;overflow:hidden;padding-left:1rem;padding-right:1rem;padding-top:.75rem;padding-bottom:.75rem;font-size:1rem;line-height:1.5rem;border-spacing:0}.chroma .hl{margin-left:-1rem;margin-right:-1rem;display:block;width:auto;--tw-bg-opacity:1;background-color:rgba(var(--color-primary-100),var(--tw-bg-opacity));padding-left:1rem;padding-right:1rem}.chroma .hl:is(.dark *){--tw-bg-opacity:1;background-color:rgba(var(--color-primary-900),var(--tw-bg-opacity))}.chroma .lntd .hl{margin:0;padding:0}.chroma .lnt,.chroma .ln{margin-right:.4em;padding-left:.4em;padding-right:.4em;padding-top:0;padding-bottom:0;--tw-text-opacity:1;color:rgba(var(--color-neutral-600),var(--tw-text-opacity))}.chroma .lnt:is(.dark *),.chroma .ln:is(.dark *){--tw-text-opacity:1;color:rgba(var(--color-neutral-300),var(--tw-text-opacity))}.chroma .k,.chroma .kd,.chroma .kn,.chroma .kp,.chroma .kr,.chroma .nc,.chroma .fm,.chroma .nn,.chroma .vc,.chroma .o{--tw-text-opacity:1;color:rgba(var(--color-primary-600),var(--tw-text-opacity))}.chroma .k:is(.dark *),.chroma .kd:is(.dark *),.chroma .kn:is(.dark *),.chroma .kp:is(.dark *),.chroma .kr:is(.dark *),.chroma .nc:is(.dark *),.chroma .fm:is(.dark *),.chroma .nn:is(.dark *),.chroma .vc:is(.dark *),.chroma .o:is(.dark *){--tw-text-opacity:1;color:rgba(var(--color-primary-300),var(--tw-text-opacity))}.chroma .kc{font-weight:600;--tw-text-opacity:1;color:rgba(var(--color-secondary-400),var(--tw-text-opacity))}.chroma .kc:is(.dark *){--tw-text-opacity:1;color:rgba(var(--color-secondary-500),var(--tw-text-opacity))}.chroma .kt,.chroma .nv,.chroma .vi,.chroma .vm,.chroma .m,.chroma .mb,.chroma .mf,.chroma .mh,.chroma .mi,.chroma .il,.chroma .mo{--tw-text-opacity:1;color:rgba(var(--color-secondary-400),var(--tw-text-opacity))}.chroma .kt:is(.dark *),.chroma .nv:is(.dark *),.chroma .vi:is(.dark *),.chroma .vm:is(.dark *),.chroma .m:is(.dark *),.chroma .mb:is(.dark *),.chroma .mf:is(.dark *),.chroma .mh:is(.dark *),.chroma .mi:is(.dark *),.chroma .il:is(.dark *),.chroma .mo:is(.dark *){--tw-text-opacity:1;color:rgba(var(--color-secondary-600),var(--tw-text-opacity))}.chroma .n,.chroma .nd,.chroma .ni,.chroma .nl{--tw-text-opacity:1;color:rgba(var(--color-secondary-900),var(--tw-text-opacity))}.chroma .n:is(.dark *),.chroma .nd:is(.dark *),.chroma .ni:is(.dark *),.chroma .nl:is(.dark *){--tw-text-opacity:1;color:rgba(var(--color-secondary-200),var(--tw-text-opacity))}.chroma .na,.chroma .nb,.chroma .bp,.chroma .nx,.chroma .py,.chroma .nt{--tw-text-opacity:1;color:rgba(var(--color-secondary-800),var(--tw-text-opacity))}.chroma .na:is(.dark *),.chroma .nb:is(.dark *),.chroma .bp:is(.dark *),.chroma .nx:is(.dark *),.chroma .py:is(.dark *),.chroma .nt:is(.dark *){--tw-text-opacity:1;color:rgba(var(--color-secondary-300),var(--tw-text-opacity))}.chroma .no,.chroma .ne,.chroma .vg{font-weight:600;--tw-text-opacity:1;color:rgba(var(--color-secondary-400),var(--tw-text-opacity))}.chroma .no:is(.dark *),.chroma .ne:is(.dark *),.chroma .vg:is(.dark *){--tw-text-opacity:1;color:rgba(var(--color-secondary-500),var(--tw-text-opacity))}.chroma .nf{--tw-text-opacity:1;color:rgba(var(--color-secondary-600),var(--tw-text-opacity))}.chroma .nf:is(.dark *){--tw-text-opacity:1;color:rgba(var(--color-secondary-500),var(--tw-text-opacity))}.chroma .l,.chroma .ld,.chroma .s,.chroma .sa,.chroma .sb,.chroma .sc,.chroma .dl,.chroma .sd,.chroma .s2,.chroma .sh,.chroma .si,.chroma .sx,.chroma .s1,.chroma .gi,.chroma .go,.chroma .gp{--tw-text-opacity:1;color:rgba(var(--color-primary-800),var(--tw-text-opacity))}.chroma .l:is(.dark *),.chroma .ld:is(.dark *),.chroma .s:is(.dark *),.chroma .sa:is(.dark *),.chroma .sb:is(.dark *),.chroma .sc:is(.dark *),.chroma .dl:is(.dark *),.chroma .sd:is(.dark *),.chroma .s2:is(.dark *),.chroma .sh:is(.dark *),.chroma .si:is(.dark *),.chroma .sx:is(.dark *),.chroma .s1:is(.dark *),.chroma .gi:is(.dark *),.chroma .go:is(.dark *),.chroma .gp:is(.dark *){--tw-text-opacity:1;color:rgba(var(--color-primary-400),var(--tw-text-opacity))}.chroma .se{font-weight:600;--tw-text-opacity:1;color:rgba(var(--color-secondary-400),var(--tw-text-opacity))}.chroma .se:is(.dark *){--tw-text-opacity:1;color:rgba(var(--color-secondary-500),var(--tw-text-opacity))}.chroma .sr,.chroma .ss{font-weight:600;--tw-text-opacity:1;color:rgba(var(--color-primary-800),var(--tw-text-opacity))}.chroma .sr:is(.dark *),.chroma .ss:is(.dark *){--tw-text-opacity:1;color:rgba(var(--color-primary-400),var(--tw-text-opacity))}.chroma .ow{font-weight:600;--tw-text-opacity:1;color:rgba(var(--color-primary-400),var(--tw-text-opacity))}.chroma .ow:is(.dark *){--tw-text-opacity:1;color:rgba(var(--color-primary-600),var(--tw-text-opacity))}.chroma .c,.chroma .cm,.chroma .c1,.chroma .cs,.chroma .cp,.chroma .cpf{font-style:italic;--tw-text-opacity:1;color:rgba(var(--color-neutral-500),var(--tw-text-opacity))}.chroma .c:is(.dark *),.chroma .cm:is(.dark *),.chroma .c1:is(.dark *),.chroma .cs:is(.dark *),.chroma .cp:is(.dark *),.chroma .cpf:is(.dark *){--tw-text-opacity:1;color:rgba(var(--color-neutral-400),var(--tw-text-opacity))}.chroma .ch{font-weight:600;font-style:italic;--tw-text-opacity:1;color:rgba(var(--color-neutral-500),var(--tw-text-opacity))}.chroma .ch:is(.dark *){--tw-text-opacity:1;color:rgba(var(--color-neutral-400),var(--tw-text-opacity))}.chroma .ge{font-style:italic}.chroma .gh{font-weight:600;--tw-text-opacity:1;color:rgba(var(--color-neutral-500),var(--tw-text-opacity))}.chroma .gs{font-weight:600}.chroma .gu,.chroma .gt{--tw-text-opacity:1;color:rgba(var(--color-neutral-500),var(--tw-text-opacity))}.chroma .gl{text-decoration-line:underline}pre{text-align:left}.thumbnail{min-width:300px;height:180px;background-repeat:no-repeat;background-size:cover;background-position:50%}.thumbnail_card{height:200px;background-repeat:no-repeat;background-size:cover;background-position:50%}.thumbnail_card_related{height:150px;background-repeat:no-repeat;background-size:cover;background-position:50%}.thumbnail_card_term{height:150px;background-repeat:no-repeat;background-size:cover;background-position:50%}.single_hero_basic{background-repeat:no-repeat;background-size:cover;background-position:50%}.single_hero_round{max-height:50vh;-o-object-fit:cover;object-fit:cover}.single_hero_background{background-repeat:no-repeat;background-size:cover;background-position:50%;width:calc(100% + 40px);z-index:-10;margin-left:-20px}.hero_gradient{width:100%;height:100%}.thumbnailshadow{box-shadow:5px 5px 20px 1px rgba(0,0,0,.3)}.anchor{display:block;position:relative;top:-150px;height:0;visibility:hidden}@media(min-width:640px){.thumbnail{min-width:100%;height:180px}.article{flex-wrap:wrap}}@media(min-width:853px){.thumbnail{min-width:300px;min-height:180px;height:auto}.article{flex-wrap:nowrap}}.medium-zoom-image--opened{z-index:100}.nested-menu:hover+.menuhide{visibility:visible;opacity:1;transition:visibility .3s,opacity .3s ease-in-out}.menuhide:hover{visibility:visible;opacity:1;transition:visibility .3s,opacity .3s ease-in-out}.menuhide{visibility:hidden;opacity:0;transition:visibility .3s,opacity .3s ease-in-out;z-index:1000}.active{text-decoration-line:underline;text-decoration-thickness:3px;text-underline-offset:4px}.grid-w10{width:calc(10% - 5px);margin:0!important}.grid-w15{width:calc(15% - 5px);margin:0!important}.grid-w20{width:calc(20% - 5px);margin:0!important}.grid-w25{width:calc(25% - 5px);margin:0!important}.grid-w30{width:calc(30% - 5px);margin:0!important}.grid-w33{width:calc(33% - 5px);margin:0!important}.grid-w35{width:calc(35% - 5px);margin:0!important}.grid-w40{width:calc(40% - 5px);margin:0!important}.grid-w45{width:calc(45% - 5px);margin:0!important}.grid-w50{width:calc(50% - 5px);margin:0!important}.grid-w55{width:calc(55% - 5px);margin:0!important}.grid-w60{width:calc(60% - 5px);margin:0!important}.grid-w65{width:calc(65% - 5px);margin:0!important}.grid-w66{width:calc(66% - 5px);margin:0!important}.grid-w70{width:calc(70% - 5px);margin:0!important}.grid-w75{width:calc(75% - 5px);margin:0!important}.grid-w80{width:calc(80% - 5px);margin:0!important}.grid-w85{width:calc(85% - 5px);margin:0!important}.grid-w90{width:calc(90% - 5px);margin:0!important}.grid-w95{width:calc(95% - 5px);margin:0!important}.grid-w100{width:calc(100% - 5px);margin:0!important}@media(min-width:640px){.sm\:grid-w10{width:calc(10% - 5px);margin:0!important}.sm\:grid-w15{width:calc(15% - 5px);margin:0!important}.sm\:grid-w20{width:calc(20% - 5px);margin:0!important}.sm\:grid-w25{width:calc(25% - 5px);margin:0!important}.sm\:grid-w30{width:calc(30% - 5px);margin:0!important}.sm\:grid-w33{width:calc(33% - 5px);margin:0!important}.sm\:grid-w35{width:calc(35% - 5px);margin:0!important}.sm\:grid-w40{width:calc(40% - 5px);margin:0!important}.sm\:grid-w45{width:calc(45% - 5px);margin:0!important}.sm\:grid-w50{width:calc(50% - 5px);margin:0!important}.sm\:grid-w55{width:calc(55% - 5px);margin:0!important}.sm\:grid-w60{width:calc(60% - 5px);margin:0!important}.sm\:grid-w65{width:calc(65% - 5px);margin:0!important}.sm\:grid-w66{width:calc(66% - 5px);margin:0!important}.sm\:grid-w70{width:calc(70% - 5px);margin:0!important}.sm\:grid-w75{width:calc(75% - 5px);margin:0!important}.sm\:grid-w80{width:calc(80% - 5px);margin:0!important}.sm\:grid-w85{width:calc(85% - 5px);margin:0!important}.sm\:grid-w90{width:calc(90% - 5px);margin:0!important}.sm\:grid-w95{width:calc(95% - 5px);margin:0!important}.sm\:grid-w100{width:calc(100% - 5px);margin:0!important}}@media(min-width:853px){.md\:grid-w10{width:calc(10% - 5px);margin:0!important}.md\:grid-w15{width:calc(15% - 5px);margin:0!important}.md\:grid-w20{width:calc(20% - 5px);margin:0!important}.md\:grid-w25{width:calc(25% - 5px);margin:0!important}.md\:grid-w30{width:calc(30% - 5px);margin:0!important}.md\:grid-w33{width:calc(33% - 5px);margin:0!important}.md\:grid-w35{width:calc(35% - 5px);margin:0!important}.md\:grid-w40{width:calc(40% - 5px);margin:0!important}.md\:grid-w45{width:calc(45% - 5px);margin:0!important}.md\:grid-w50{width:calc(50% - 5px);margin:0!important}.md\:grid-w55{width:calc(55% - 5px);margin:0!important}.md\:grid-w60{width:calc(60% - 5px);margin:0!important}.md\:grid-w65{width:calc(65% - 5px);margin:0!important}.md\:grid-w66{width:calc(66% - 5px);margin:0!important}.md\:grid-w70{width:calc(70% - 5px);margin:0!important}.md\:grid-w75{width:calc(75% - 5px);margin:0!important}.md\:grid-w80{width:calc(80% - 5px);margin:0!important}.md\:grid-w85{width:calc(85% - 5px);margin:0!important}.md\:grid-w90{width:calc(90% - 5px);margin:0!important}.md\:grid-w95{width:calc(95% - 5px);margin:0!important}.md\:grid-w100{width:calc(100% - 5px);margin:0!important}}@media(min-width:1024px){.lg\:grid-w10{width:calc(10% - 5px);margin:0!important}.lg\:grid-w15{width:calc(15% - 5px);margin:0!important}.lg\:grid-w20{width:calc(20% - 5px);margin:0!important}.lg\:grid-w25{width:calc(25% - 5px);margin:0!important}.lg\:grid-w30{width:calc(30% - 5px);margin:0!important}.lg\:grid-w33{width:calc(33% - 5px);margin:0!important}.lg\:grid-w35{width:calc(35% - 5px);margin:0!important}.lg\:grid-w40{width:calc(40% - 5px);margin:0!important}.lg\:grid-w45{width:calc(45% - 5px);margin:0!important}.lg\:grid-w50{width:calc(50% - 5px);margin:0!important}.lg\:grid-w55{width:calc(55% - 5px);margin:0!important}.lg\:grid-w60{width:calc(60% - 5px);margin:0!important}.lg\:grid-w65{width:calc(65% - 5px);margin:0!important}.lg\:grid-w66{width:calc(66% - 5px);margin:0!important}.lg\:grid-w70{width:calc(70% - 5px);margin:0!important}.lg\:grid-w75{width:calc(75% - 5px);margin:0!important}.lg\:grid-w80{width:calc(80% - 5px);margin:0!important}.lg\:grid-w85{width:calc(85% - 5px);margin:0!important}.lg\:grid-w90{width:calc(90% - 5px);margin:0!important}.lg\:grid-w95{width:calc(95% - 5px);margin:0!important}.lg\:grid-w100{width:calc(100% - 5px);margin:0!important}}@media(min-width:1280px){.xl\:grid-w10{width:calc(10% - 5px);margin:0!important}.xl\:grid-w15{width:calc(15% - 5px);margin:0!important}.xl\:grid-w20{width:calc(20% - 5px);margin:0!important}.xl\:grid-w25{width:calc(25% - 5px);margin:0!important}.xl\:grid-w30{width:calc(30% - 5px);margin:0!important}.xl\:grid-w33{width:calc(33% - 5px);margin:0!important}.xl\:grid-w35{width:calc(35% - 5px);margin:0!important}.xl\:grid-w40{width:calc(40% - 5px);margin:0!important}.xl\:grid-w45{width:calc(45% - 5px);margin:0!important}.xl\:grid-w50{width:calc(50% - 5px);margin:0!important}.xl\:grid-w55{width:calc(55% - 5px);margin:0!important}.xl\:grid-w60{width:calc(60% - 5px);margin:0!important}.xl\:grid-w65{width:calc(65% - 5px);margin:0!important}.xl\:grid-w66{width:calc(66% - 5px);margin:0!important}.xl\:grid-w70{width:calc(70% - 5px);margin:0!important}.xl\:grid-w75{width:calc(75% - 5px);margin:0!important}.xl\:grid-w80{width:calc(80% - 5px);margin:0!important}.xl\:grid-w85{width:calc(85% - 5px);margin:0!important}.xl\:grid-w90{width:calc(90% - 5px);margin:0!important}.xl\:grid-w95{width:calc(95% - 5px);margin:0!important}.xl\:grid-w100{width:calc(100% - 5px);margin:0!important}}@media(min-width:1536px){.2xl\:grid-w10{width:calc(10% - 5px);margin:0!important}.2xl\:grid-w15{width:calc(15% - 5px);margin:0!important}.2xl\:grid-w20{width:calc(20% - 5px);margin:0!important}.2xl\:grid-w25{width:calc(25% - 5px);margin:0!important}.2xl\:grid-w30{width:calc(30% - 5px);margin:0!important}.2xl\:grid-w33{width:calc(33% - 5px);margin:0!important}.2xl\:grid-w35{width:calc(35% - 5px);margin:0!important}.2xl\:grid-w40{width:calc(40% - 5px);margin:0!important}.2xl\:grid-w45{width:calc(45% - 5px);margin:0!important}.2xl\:grid-w50{width:calc(50% - 5px);margin:0!important}.2xl\:grid-w55{width:calc(55% - 5px);margin:0!important}.2xl\:grid-w60{width:calc(60% - 5px);margin:0!important}.2xl\:grid-w65{width:calc(65% - 5px);margin:0!important}.2xl\:grid-w66{width:calc(66% - 5px);margin:0!important}.2xl\:grid-w70{width:calc(70% - 5px);margin:0!important}.2xl\:grid-w75{width:calc(75% - 5px);margin:0!important}.2xl\:grid-w80{width:calc(80% - 5px);margin:0!important}.2xl\:grid-w85{width:calc(85% - 5px);margin:0!important}.2xl\:grid-w90{width:calc(90% - 5px);margin:0!important}.2xl\:grid-w95{width:calc(95% - 5px);margin:0!important}.2xl\:grid-w100{width:calc(100% - 5px);margin:0!important}}.ratio-16-9{padding-top:56.25%}.ratio-21-9{padding-top:42.85%}.ratio-32-9{padding-top:28.125%}@media(min-width:640px){.sm\:ratio-16-9{padding-top:56.25%}.sm\:ratio-21-9{padding-top:42.85%}.sm\:ratio-32-9{padding-top:28.125%}}@media(min-width:853px){.md\:ratio-16-9{padding-top:56.25%}.md\:ratio-21-9{padding-top:42.85%}.md\:ratio-32-9{padding-top:28.125%}}@media(min-width:1024px){.lg\:ratio-16-9{padding-top:56.25%}.lg\:ratio-21-9{padding-top:42.85%}.lg\:ratio-32-9{padding-top:28.125%}}@media(min-width:1280px){.xl\:ratio-16-9{padding-top:56.25%}.xl\:ratio-21-9{padding-top:42.85%}.xl\:ratio-32-9{padding-top:28.125%}}@media(min-width:1536px){.2xl\:ratio-16-9{padding-top:56.25%}.2xl\:ratio-21-9{padding-top:42.85%}.2xl\:ratio-32-9{padding-top:28.125%}}.dark\:prose-invert:is(.dark *){--tw-prose-body:var(--tw-prose-invert-body);--tw-prose-headings:var(--tw-prose-invert-headings);--tw-prose-lead:var(--tw-prose-invert-lead);--tw-prose-links:var(--tw-prose-invert-links);--tw-prose-bold:var(--tw-prose-invert-bold);--tw-prose-counters:var(--tw-prose-invert-counters);--tw-prose-bullets:var(--tw-prose-invert-bullets);--tw-prose-hr:var(--tw-prose-invert-hr);--tw-prose-quotes:var(--tw-prose-invert-quotes);--tw-prose-quote-borders:var(--tw-prose-invert-quote-borders);--tw-prose-captions:var(--tw-prose-invert-captions);--tw-prose-kbd:var(--tw-prose-invert-kbd);--tw-prose-kbd-shadows:var(--tw-prose-invert-kbd-shadows);--tw-prose-code:var(--tw-prose-invert-code);--tw-prose-pre-code:var(--tw-prose-invert-pre-code);--tw-prose-pre-bg:var(--tw-prose-invert-pre-bg);--tw-prose-th-borders:var(--tw-prose-invert-th-borders);--tw-prose-td-borders:var(--tw-prose-invert-td-borders)}.dark\:prose-invert:is(.dark *) :where(a):not(:where([class~=not-prose],[class~=not-prose] *)){text-decoration-color:rgba(var(--color-neutral-600),1)}.dark\:prose-invert:is(.dark *) :where(a):not(:where([class~=not-prose],[class~=not-prose] *)):hover{color:rgba(var(--color-primary-400),1)}.dark\:prose-invert:is(.dark *) :where(kbd):not(:where([class~=not-prose],[class~=not-prose] *)){color:rgba(var(--color-neutral-200),1);background-color:rgba(var(--color-neutral-700),1)}.dark\:prose-invert:is(.dark *) :where(mark):not(:where([class~=not-prose],[class~=not-prose] *)){background-color:rgba(var(--color-primary-400),1)}.dark\:prose-invert:is(.dark *) :where(code):not(:where([class~=not-prose],[class~=not-prose] *)){background-color:rgba(var(--color-neutral-700),1)}.dark\:prose-invert:is(.dark *) :where(a.active):not(:where([class~=not-prose],[class~=not-prose] *)){text-decoration-color:rgba(var(--color-primary-400),1)}.dark\:prose-invert:is(.dark *) :where(p.active):not(:where([class~=not-prose],[class~=not-prose] *)){text-decoration-color:rgba(var(--color-primary-400),1)}.after\:clear-both::after{content:var(--tw-content);clear:both}.after\:block::after{content:var(--tw-content);display:block}.after\:content-\[\'\'\]::after{--tw-content:'';content:var(--tw-content)}.first\:mt-8:first-child{margin-top:2rem}.empty\:hidden:empty{display:none}.hover\:border-transparent:hover{border-color:transparent}.hover\:\!bg-primary-500:hover{--tw-bg-opacity:1 !important;background-color:rgba(var(--color-primary-500),var(--tw-bg-opacity))!important}.hover\:bg-primary-100:hover{--tw-bg-opacity:1;background-color:rgba(var(--color-primary-100),var(--tw-bg-opacity))}.hover\:bg-primary-500:hover{--tw-bg-opacity:1;background-color:rgba(var(--color-primary-500),var(--tw-bg-opacity))}.hover\:bg-primary-600:hover{--tw-bg-opacity:1;background-color:rgba(var(--color-primary-600),var(--tw-bg-opacity))}.hover\:text-neutral:hover{--tw-text-opacity:1;color:rgba(var(--color-neutral),var(--tw-text-opacity))}.hover\:text-primary-400:hover{--tw-text-opacity:1;color:rgba(var(--color-primary-400),var(--tw-text-opacity))}.hover\:text-primary-500:hover{--tw-text-opacity:1;color:rgba(var(--color-primary-500),var(--tw-text-opacity))}.hover\:text-primary-600:hover{--tw-text-opacity:1;color:rgba(var(--color-primary-600),var(--tw-text-opacity))}.hover\:text-primary-700:hover{--tw-text-opacity:1;color:rgba(var(--color-primary-700),var(--tw-text-opacity))}.hover\:underline:hover{text-decoration-line:underline}.hover\:no-underline:hover{text-decoration-line:none}.hover\:decoration-primary-400:hover{text-decoration-color:rgba(var(--color-primary-400),1)}.hover\:decoration-2:hover{text-decoration-thickness:2px}.hover\:underline-offset-2:hover{text-underline-offset:2px}.hover\:opacity-90:hover{opacity:.9}.hover\:outline-none:hover{outline:2px solid transparent;outline-offset:2px}.focus\:translate-y-0:focus{--tw-translate-y:0px;transform:translate(var(--tw-translate-x),var(--tw-translate-y))rotate(var(--tw-rotate))skewX(var(--tw-skew-x))skewY(var(--tw-skew-y))scaleX(var(--tw-scale-x))scaleY(var(--tw-scale-y))}.focus\:bg-primary-100:focus{--tw-bg-opacity:1;background-color:rgba(var(--color-primary-100),var(--tw-bg-opacity))}.focus\:no-underline:focus{text-decoration-line:none}.focus\:opacity-90:focus{opacity:.9}.focus\:outline-none:focus{outline:2px solid transparent;outline-offset:2px}.focus\:outline-dotted:focus{outline-style:dotted}.focus\:outline-2:focus{outline-width:2px}.focus\:outline-transparent:focus{outline-color:transparent}.group:hover .group-hover\:text-primary-300{--tw-text-opacity:1;color:rgba(var(--color-primary-300),var(--tw-text-opacity))}.group:hover .group-hover\:text-primary-600{--tw-text-opacity:1;color:rgba(var(--color-primary-600),var(--tw-text-opacity))}.group:hover .group-hover\:underline{text-decoration-line:underline}.group:hover .group-hover\:decoration-primary-500{text-decoration-color:rgba(var(--color-primary-500),1)}.group:hover .group-hover\:opacity-100{opacity:1}.data-\[twe-carousel-fade\]\:z-0[data-twe-carousel-fade]{z-index:0}.data-\[twe-carousel-fade\]\:z-\[1\][data-twe-carousel-fade]{z-index:1}.data-\[popper-reference-hidden\]\:hidden[data-popper-reference-hidden]{display:none}.data-\[twe-carousel-fade\]\:opacity-0[data-twe-carousel-fade]{opacity:0}.data-\[twe-carousel-fade\]\:opacity-100[data-twe-carousel-fade]{opacity:1}.data-\[twe-carousel-fade\]\:duration-\[600ms\][data-twe-carousel-fade]{transition-duration:600ms}.group[data-twe-input-focused] .group-data-\[twe-input-focused\]\:border-x-0{border-left-width:0;border-right-width:0}.group[data-twe-input-state-active] .group-data-\[twe-input-state-active\]\:border-x-0{border-left-width:0;border-right-width:0}.group[data-twe-input-focused] .group-data-\[twe-input-focused\]\:border-e-0{border-inline-end-width:0}.group[data-twe-input-focused] .group-data-\[twe-input-focused\]\:border-s-0{border-inline-start-width:0}.group[data-twe-input-focused] .group-data-\[twe-input-focused\]\:border-t{border-top-width:1px}.group[data-twe-input-state-active] .group-data-\[twe-input-state-active\]\:border-e-0{border-inline-end-width:0}.group[data-twe-input-state-active] .group-data-\[twe-input-state-active\]\:border-s-0{border-inline-start-width:0}.group[data-twe-input-state-active] .group-data-\[twe-input-state-active\]\:border-t{border-top-width:1px}.group[data-twe-input-focused] .group-data-\[twe-input-focused\]\:border-solid{border-style:solid}.group[data-twe-input-state-active] .group-data-\[twe-input-state-active\]\:border-solid{border-style:solid}.group[data-twe-input-focused] .group-data-\[twe-input-focused\]\:border-t-transparent{border-top-color:transparent}.group[data-twe-input-state-active] .group-data-\[twe-input-state-active\]\:border-t-transparent{border-top-color:transparent}@media(prefers-reduced-motion:reduce){.motion-reduce\:transition-none{transition-property:none}}.dark\:flex:is(.dark *){display:flex}.dark\:hidden:is(.dark *){display:none}.dark\:border-neutral-400:is(.dark *){--tw-border-opacity:1;border-color:rgba(var(--color-neutral-400),var(--tw-border-opacity))}.dark\:border-neutral-600:is(.dark *){--tw-border-opacity:1;border-color:rgba(var(--color-neutral-600),var(--tw-border-opacity))}.dark\:border-neutral-700:is(.dark *){--tw-border-opacity:1;border-color:rgba(var(--color-neutral-700),var(--tw-border-opacity))}.dark\:border-primary-300:is(.dark *){--tw-border-opacity:1;border-color:rgba(var(--color-primary-300),var(--tw-border-opacity))}.dark\:border-primary-600:is(.dark *){--tw-border-opacity:1;border-color:rgba(var(--color-primary-600),var(--tw-border-opacity))}.dark\:bg-neutral-400:is(.dark *){--tw-bg-opacity:1;background-color:rgba(var(--color-neutral-400),var(--tw-bg-opacity))}.dark\:bg-neutral-600:is(.dark *){--tw-bg-opacity:1;background-color:rgba(var(--color-neutral-600),var(--tw-bg-opacity))}.dark\:bg-neutral-700:is(.dark *){--tw-bg-opacity:1;background-color:rgba(var(--color-neutral-700),var(--tw-bg-opacity))}.dark\:bg-neutral-800:is(.dark *){--tw-bg-opacity:1;background-color:rgba(var(--color-neutral-800),var(--tw-bg-opacity))}.dark\:bg-neutral-800\/50:is(.dark *){background-color:rgba(var(--color-neutral-800),.5)}.dark\:bg-neutral-900\/50:is(.dark *){background-color:rgba(var(--color-neutral-900),.5)}.dark\:bg-primary-300:is(.dark *){--tw-bg-opacity:1;background-color:rgba(var(--color-primary-300),var(--tw-bg-opacity))}.dark\:bg-primary-400:is(.dark *){--tw-bg-opacity:1;background-color:rgba(var(--color-primary-400),var(--tw-bg-opacity))}.dark\:bg-primary-800:is(.dark *){--tw-bg-opacity:1;background-color:rgba(var(--color-primary-800),var(--tw-bg-opacity))}.dark\:bg-primary-900:is(.dark *){--tw-bg-opacity:1;background-color:rgba(var(--color-primary-900),var(--tw-bg-opacity))}.dark\:from-neutral-800:is(.dark *){--tw-gradient-from:rgba(var(--color-neutral-800), 1) var(--tw-gradient-from-position);--tw-gradient-to:rgba(var(--color-neutral-800), 0) var(--tw-gradient-to-position);--tw-gradient-stops:var(--tw-gradient-from), var(--tw-gradient-to)}.dark\:from-primary-600:is(.dark *){--tw-gradient-from:rgba(var(--color-primary-600), 1) var(--tw-gradient-from-position);--tw-gradient-to:rgba(var(--color-primary-600), 0) var(--tw-gradient-to-position);--tw-gradient-stops:var(--tw-gradient-from), var(--tw-gradient-to)}.dark\:to-neutral-800:is(.dark *){--tw-gradient-to:rgba(var(--color-neutral-800), 1) var(--tw-gradient-to-position)}.dark\:to-secondary-800:is(.dark *){--tw-gradient-to:rgba(var(--color-secondary-800), 1) var(--tw-gradient-to-position)}.dark\:text-neutral:is(.dark *){--tw-text-opacity:1;color:rgba(var(--color-neutral),var(--tw-text-opacity))}.dark\:text-neutral-100:is(.dark *){--tw-text-opacity:1;color:rgba(var(--color-neutral-100),var(--tw-text-opacity))}.dark\:text-neutral-200:is(.dark *){--tw-text-opacity:1;color:rgba(var(--color-neutral-200),var(--tw-text-opacity))}.dark\:text-neutral-300:is(.dark *){--tw-text-opacity:1;color:rgba(var(--color-neutral-300),var(--tw-text-opacity))}.dark\:text-neutral-400:is(.dark *){--tw-text-opacity:1;color:rgba(var(--color-neutral-400),var(--tw-text-opacity))}.dark\:text-neutral-500:is(.dark *){--tw-text-opacity:1;color:rgba(var(--color-neutral-500),var(--tw-text-opacity))}.dark\:text-neutral-700:is(.dark *){--tw-text-opacity:1;color:rgba(var(--color-neutral-700),var(--tw-text-opacity))}.dark\:text-neutral-800:is(.dark *){--tw-text-opacity:1;color:rgba(var(--color-neutral-800),var(--tw-text-opacity))}.dark\:text-primary-200:is(.dark *){--tw-text-opacity:1;color:rgba(var(--color-primary-200),var(--tw-text-opacity))}.dark\:text-primary-400:is(.dark *){--tw-text-opacity:1;color:rgba(var(--color-primary-400),var(--tw-text-opacity))}.dark\:opacity-60:is(.dark *){opacity:.6}.dark\:hover\:\!bg-primary-700:hover:is(.dark *){--tw-bg-opacity:1 !important;background-color:rgba(var(--color-primary-700),var(--tw-bg-opacity))!important}.dark\:hover\:bg-primary-400:hover:is(.dark *){--tw-bg-opacity:1;background-color:rgba(var(--color-primary-400),var(--tw-bg-opacity))}.dark\:hover\:bg-primary-900:hover:is(.dark *){--tw-bg-opacity:1;background-color:rgba(var(--color-primary-900),var(--tw-bg-opacity))}.dark\:hover\:text-neutral-800:hover:is(.dark *){--tw-text-opacity:1;color:rgba(var(--color-neutral-800),var(--tw-text-opacity))}.dark\:hover\:text-primary-400:hover:is(.dark *){--tw-text-opacity:1;color:rgba(var(--color-primary-400),var(--tw-text-opacity))}.dark\:focus\:bg-primary-900:focus:is(.dark *){--tw-bg-opacity:1;background-color:rgba(var(--color-primary-900),var(--tw-bg-opacity))}.group:hover .dark\:group-hover\:text-neutral-700:is(.dark *){--tw-text-opacity:1;color:rgba(var(--color-neutral-700),var(--tw-text-opacity))}.group:hover .dark\:group-hover\:text-primary-400:is(.dark *){--tw-text-opacity:1;color:rgba(var(--color-primary-400),var(--tw-text-opacity))}@media(min-width:640px){.sm\:mb-0{margin-bottom:0}.sm\:mt-16{margin-top:4rem}.sm\:w-1\/2{width:50%}.sm\:grid-cols-2{grid-template-columns:repeat(2,minmax(0,1fr))}.sm\:flex-row{flex-direction:row}.sm\:overflow-hidden{overflow:hidden}.sm\:p-6{padding:1.5rem}.sm\:px-14{padding-left:3.5rem;padding-right:3.5rem}.sm\:px-6{padding-left:1.5rem;padding-right:1.5rem}.sm\:py-24{padding-top:6rem;padding-bottom:6rem}.sm\:text-lg{font-size:1.125rem;line-height:1.75rem}}@media(min-width:853px){.md\:-mr-16{margin-right:-4rem}.md\:ml-12{margin-left:3rem}.md\:mr-7{margin-right:1.75rem}.md\:mt-0{margin-top:0}.md\:flex{display:flex}.md\:hidden{display:none}.md\:h-56{height:14rem}.md\:h-\[200px\]{height:200px}.md\:w-1\/3{width:33.333333%}.md\:w-auto{width:auto}.md\:grid-cols-3{grid-template-columns:repeat(3,minmax(0,1fr))}.md\:justify-start{justify-content:flex-start}.md\:p-\[10vh\]{padding:10vh}.md\:px-24{padding-left:6rem;padding-right:6rem}}@media(min-width:1024px){.lg\:absolute{position:absolute}.lg\:relative{position:relative}.lg\:sticky{position:sticky}.lg\:left-0{left:0}.lg\:top-10{top:2.5rem}.lg\:top-\[140px\]{top:140px}.lg\:order-last{order:9999}.lg\:m-0{margin:0}.lg\:mx-0{margin-left:0;margin-right:0}.lg\:mx-auto{margin-left:auto;margin-right:auto}.lg\:ml-auto{margin-left:auto}.lg\:mt-0{margin-top:0}.lg\:block{display:block}.lg\:grid{display:grid}.lg\:hidden{display:none}.lg\:h-72{height:18rem}.lg\:h-full{height:100%}.lg\:w-1\/4{width:25%}.lg\:w-auto{width:auto}.lg\:max-w-7xl{max-width:80rem}.lg\:max-w-none{max-width:none}.lg\:max-w-xs{max-width:20rem}.lg\:grid-flow-col-dense{grid-auto-flow:column dense}.lg\:grid-cols-2{grid-template-columns:repeat(2,minmax(0,1fr))}.lg\:flex-row{flex-direction:row}.lg\:gap-24{gap:6rem}.lg\:p-\[12vh\]{padding:12vh}.lg\:px-0{padding-left:0;padding-right:0}.lg\:px-32{padding-left:8rem;padding-right:8rem}.lg\:px-8{padding-left:2rem;padding-right:2rem}.lg\:py-16{padding-top:4rem;padding-bottom:4rem}.lg\:py-32{padding-top:8rem;padding-bottom:8rem}}@media(min-width:1280px){.xl\:w-1\/4{width:25%}.xl\:grid-cols-4{grid-template-columns:repeat(4,minmax(0,1fr))}}@media(min-width:1536px){.\32xl\:grid-cols-5{grid-template-columns:repeat(5,minmax(0,1fr))}}.ltr\:-left-6:where([dir=ltr],[dir=ltr] *){left:-1.5rem}.ltr\:right-0:where([dir=ltr],[dir=ltr] *){right:0}.ltr\:-ml-5:where([dir=ltr],[dir=ltr] *){margin-left:-1.25rem}.ltr\:ml-2:where([dir=ltr],[dir=ltr] *){margin-left:.5rem}.ltr\:mr-14:where([dir=ltr],[dir=ltr] *){margin-right:3.5rem}.ltr\:mr-4:where([dir=ltr],[dir=ltr] *){margin-right:1rem}.ltr\:block:where([dir=ltr],[dir=ltr] *){display:block}.ltr\:inline:where([dir=ltr],[dir=ltr] *){display:inline}.ltr\:hidden:where([dir=ltr],[dir=ltr] *){display:none}.ltr\:border-l:where([dir=ltr],[dir=ltr] *){border-left-width:1px}.ltr\:pl-5:where([dir=ltr],[dir=ltr] *){padding-left:1.25rem}.ltr\:pr-2:where([dir=ltr],[dir=ltr] *){padding-right:.5rem}.ltr\:pr-3:where([dir=ltr],[dir=ltr] *){padding-right:.75rem}.ltr\:text-right:where([dir=ltr],[dir=ltr] *){text-align:right}@media(min-width:640px){.ltr\:sm\:mr-7:where([dir=ltr],[dir=ltr] *){margin-right:1.75rem}.ltr\:sm\:last\:mr-0:last-child:where([dir=ltr],[dir=ltr] *){margin-right:0}}@media(min-width:1024px){.ltr\:lg\:pl-8:where([dir=ltr],[dir=ltr] *){padding-left:2rem}}.rtl\:-right-6:where([dir=rtl],[dir=rtl] *){right:-1.5rem}.rtl\:left-0:where([dir=rtl],[dir=rtl] *){left:0}.rtl\:-mr-5:where([dir=rtl],[dir=rtl] *){margin-right:-1.25rem}.rtl\:ml-14:where([dir=rtl],[dir=rtl] *){margin-left:3.5rem}.rtl\:ml-4:where([dir=rtl],[dir=rtl] *){margin-left:1rem}.rtl\:mr-2:where([dir=rtl],[dir=rtl] *){margin-right:.5rem}.rtl\:block:where([dir=rtl],[dir=rtl] *){display:block}.rtl\:inline:where([dir=rtl],[dir=rtl] *){display:inline}.rtl\:hidden:where([dir=rtl],[dir=rtl] *){display:none}.rtl\:border-r:where([dir=rtl],[dir=rtl] *){border-right-width:1px}.rtl\:pl-2:where([dir=rtl],[dir=rtl] *){padding-left:.5rem}.rtl\:pl-3:where([dir=rtl],[dir=rtl] *){padding-left:.75rem}.rtl\:pr-5:where([dir=rtl],[dir=rtl] *){padding-right:1.25rem}.rtl\:text-left:where([dir=rtl],[dir=rtl] *){text-align:left}@media(min-width:640px){.rtl\:sm\:ml-7:where([dir=rtl],[dir=rtl] *){margin-left:1.75rem}.rtl\:sm\:last\:ml-0:last-child:where([dir=rtl],[dir=rtl] *){margin-left:0}}@media(min-width:1024px){.rtl\:lg\:pr-8:where([dir=rtl],[dir=rtl] *){padding-right:2rem}}@media print{.print\:hidden{display:none}} \ No newline at end of file diff --git a/public/cv.pdf b/public/cv.pdf new file mode 100644 index 0000000..bf46a5e Binary files /dev/null and b/public/cv.pdf differ diff --git a/public/favicon-16x16.png b/public/favicon-16x16.png deleted file mode 100644 index 9c2c206..0000000 Binary files a/public/favicon-16x16.png and /dev/null differ diff --git a/public/favicon-32x32.png b/public/favicon-32x32.png deleted file mode 100644 index d7f7417..0000000 Binary files a/public/favicon-32x32.png and /dev/null differ diff --git a/public/favicon.ico b/public/favicon.ico deleted file mode 100644 index e953b1f..0000000 Binary files a/public/favicon.ico and /dev/null differ diff --git a/public/index.html b/public/index.html index 46d256e..30dd6c4 100644 --- a/public/index.html +++ b/public/index.html @@ -1,565 +1,257 @@ - + + + - - - - + + - - - lowest case - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- skip to main content -
- - -