diff --git a/.markdownlint.json b/.markdownlint.json new file mode 100644 index 0000000..2b5d85d --- /dev/null +++ b/.markdownlint.json @@ -0,0 +1,8 @@ +{ + "MD033": { + "allowed_elements": [ + "div", + "sup" + ] + } +} \ No newline at end of file diff --git a/_config.yml b/_config.yml index 1fda1f1..74ca7e8 100644 --- a/_config.yml +++ b/_config.yml @@ -1,8 +1,8 @@ # SITE CONFIGURATION title: Donjon # your site title -author: CharlesLedger +author: CharlesLedger description: > # Meta description of Homepage - The whispers from the Donjon of Ledger. The latest news about security research at Ledger. + The whispers from the Donjon of Ledger. The latest news about security research at Ledger. baseurl: "" # the subpath of your site, e.g. /blog url: "https://donjon.ledger.com" @@ -15,28 +15,30 @@ social: # THEME SETTINGS navigation: # Navigation links - - {name: 'Bounty', link: '/bounty'} - - {name: 'Security Bulletins', link: '/lsb'} - - {name: 'Threat Model', link: '/threat-model'} - - {name: 'About', link: '/about'} - - {name: 'Contact', link: '/contact'} + - { name: "Bounty", link: "/bounty" } + - { name: "Security Bulletins", link: "/lsb" } + - { name: "Threat Model", link: "/threat-model" } + - { name: "Tools Suite", link: "/tools-suite" } + - { name: "About", link: "/about" } + - { name: "Contact", link: "/contact" } tagline: > - The security research at Ledger + The security research at Ledger collections: lsb: output: true threat-model: output: true + tools-suite: + output: true hero_img: posts/sleek_lg.jpg # Main background image: use the path from /assets/img/ => This will output /assets/img/posts/sleek_lg.jpg email: donjon@ledger.fr # email for form submission -twitter_username: donjonledger -github_username: ledger-donjon - +x_username: donjonledger +github_username: ledger-donjon # google_tag_manager: GTM-XXXXXXX # Uncomment to enable GTM. Replace GTM-XXXXXXX with your GTM container ID @@ -59,7 +61,7 @@ exclude: - gulpfile.js - sleek.jpg -include: ['_pages'] +include: ["_pages"] permalink: /:title/ compress_html: diff --git a/_includes/critical.css b/_includes/critical.css index b93f0e8..2f09f96 100644 --- a/_includes/critical.css +++ b/_includes/critical.css @@ -1 +1,549 @@ -h1{color:#313237;margin-top:0;margin-bottom:.5rem}.dark-bg{background-color:#313237}@media only screen and (min-width:48em){.post-card{width:48.4375%;margin-right:3.125%}.post-card:last-of-type,.post-card:nth-child(2n+2){margin-right:0}}html{line-height:1.15;-ms-text-size-adjust:100%;-webkit-text-size-adjust:100%}body{margin:0}header,nav,section{display:block}h1{font-size:2em;margin:.67em 0}figure,main{display:block}figure{margin:1em 40px}a{background-color:transparent;-webkit-text-decoration-skip:objects}img{border-style:none}svg:not(:root){overflow:hidden}::-webkit-file-upload-button{-webkit-appearance:button;font:inherit}html{-webkit-box-sizing:border-box;box-sizing:border-box}body{-webkit-overflow-scrolling:touch}*,::after,::before{-webkit-box-sizing:inherit;box-sizing:inherit}.site{display:-webkit-box;display:-ms-flexbox;display:flex;min-height:100vh;-webkit-box-orient:vertical;-webkit-box-direction:normal;-ms-flex-direction:column;flex-direction:column}.site__content{-webkit-box-flex:1;-ms-flex:1;flex:1}img{max-width:100%;height:auto;width:auto;vertical-align:middle}figure{margin:0}body{background-color:#fff;font-family:-apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,"Helvetica Neue",Arial,"Hiragino Sans GB","Microsoft YaHei","WenQuanYi Micro Hei",sans-serif;font-size:1rem;line-height:1.5;color:#343851;-webkit-font-smoothing:antialiased;-webkit-text-size-adjust:100%}p{margin-top:0;margin-bottom:1.25rem}h1,h2{color:#313237;margin-top:0;margin-bottom:.5rem}a{color:#277cea;text-decoration:none;border-bottom:1px dashed #277cea}.blur{background:#fff;filter:url('data:image/svg+xml;charset=utf-8,#filter');-webkit-filter:blur(1rem);filter:blur(1rem)}.container{padding:0 20px;max-width:100%;margin:0 auto}@media only screen and (min-width:36em){.container{max-width:540px;margin:0 auto}}@media only screen and (min-width:48em){.container{max-width:720px;margin:0 auto}}@media only screen and (min-width:62em){.container{max-width:960px;margin:0 auto}}@media only screen and (min-width:75em){.container{max-width:1170px;margin:0 auto}}.header{background-color:#fff;color:#343851;position:absolute;z-index:4;width:100%;top:0;left:0;will-change:transform;-webkit-transform:translateY(0);transform:translateY(0)}.header a{display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-align:center;-ms-flex-align:center;align-items:center;border-bottom:0}.header__logo{display:-webkit-box;display:-ms-flexbox;display:flex;height:100%;overflow:hidden;padding:19px 0;margin-right:1.25rem;outline:0;border-bottom:0;color:#313237}.header__logo .header__logo--container{width:38px}.header__logo .header__logo--container .logo{fill:currentColor}.header__inner{display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-align:center;-ms-flex-align:center;align-items:center;height:3.75em;-webkit-box-pack:justify;-ms-flex-pack:justify;justify-content:space-between}.header__links{padding-bottom:.5rem;display:none;position:absolute;top:3.75em;left:0;width:100%;height:auto;background:#fff}.header__link{color:#343851;padding:.938rem 0;border-top:1px solid #ededed}.header__toggle{display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-orient:vertical;-webkit-box-direction:normal;-ms-flex-direction:column;flex-direction:column;-webkit-box-pack:center;-ms-flex-pack:center;justify-content:center;width:44px;height:100%;background-color:transparent;padding-left:1.25rem}.header__toggle span{display:block;position:relative;margin-top:4px;background-color:#343851;width:100%;height:2px;border-radius:1px}.header__toggle span:first-child{margin-top:0}@media (min-width:62em){.header__toggle{display:none;visibility:hidden}.header__links{position:static;padding:0;display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-orient:vertical;-webkit-box-direction:normal;-ms-flex-direction:column;flex-direction:column;visibility:visible;width:auto;height:100%}.header__links-wrapper{display:-webkit-box;display:-ms-flexbox;display:flex;height:100%;padding:0}.header__link{position:relative;padding:.938rem 1rem;border:0;height:100%}.header__link::after{content:"";display:block;position:absolute;left:0;bottom:0;height:3px;width:100%;-webkit-transform:scaleX(0);transform:scaleX(0);background:#277cea}}.post-card{display:block;position:relative;width:100%;min-height:250px;border-radius:4px;overflow:hidden;background-color:#fff;-webkit-box-shadow:0 1px 3px rgba(0,0,0,.08);box-shadow:0 1px 3px rgba(0,0,0,.08);margin-bottom:2.25rem;border-bottom:0}@media only screen and (min-width:48em){.post-card{width:48.4375%;margin-right:3.125%}.post-card:nth-child(2n+2){margin-right:0}}@media only screen and (min-width:75em){.post-card{width:31.25%;margin-right:3.125%}.post-card:nth-child(2n+2){margin-right:3.125%}}.post-card__label{position:absolute;top:1.5rem;left:1.5rem;z-index:2}.post-card__inner{display:block;position:relative;padding:1.875rem 1.25rem .625rem;width:100%;color:#838c8d;border-bottom:0}.post-card__header{margin-bottom:.75rem}.post-card__meta{font-size:.875rem}.post-card__thumb{margin:0;background:#fff;position:relative;overflow:hidden}.post-card__thumb::after{content:"";display:block;height:0;width:100%;padding-bottom:56.25%}.post-card__thumb>*{position:absolute;top:0;left:0;width:100%;height:100%;display:block}.label{padding:0 10px;margin-bottom:1rem;display:inline-block;line-height:20px;font-size:.75rem;text-transform:uppercase;letter-spacing:1px;color:rgba(255,255,255,.8);border:2px solid rgba(255,255,255,.5);border-radius:100px}.hero{margin:3.75rem auto 0;min-height:16.25rem;width:100%;position:relative;background-color:#dde5ea;background-repeat:no-repeat;background-position:50%;background-size:cover}@media only screen and (min-width:62em){.hero{margin:0 auto;height:36em}}.hero::before{position:absolute;display:block;content:"";top:0;left:0;width:100%;height:100%;background:rgba(52,56,81,.8)}.hero__wrap{position:absolute;margin:auto;top:50%;left:50%;-webkit-transform:translate(-50%,-50%);transform:translate(-50%,-50%);text-align:center;color:rgba(255,255,255,.8);width:100%;max-width:90%;z-index:1}.hero__wrap .hero__title{font-size:1.8em;color:#fff}.blog{background-color:#f9f9f9}.post-list{padding-top:2.5em;display:-webkit-box;display:-ms-flexbox;display:flex;-ms-flex-wrap:wrap;flex-wrap:wrap;-webkit-box-flex:1;-ms-flex:1 0 auto;flex:1 0 auto}@media only screen and (min-width:48em){.hero__wrap{max-width:40em}.hero__wrap .hero__title{padding:1rem 0;font-size:2.625em;line-height:3.125rem}.post-list{padding-top:5em}} +h1 { + color: #313237; + margin-top: 0; + margin-bottom: .5rem +} + +.dark-bg { + background-color: #313237 +} + +@media only screen and (min-width:48em) { + .post-card { + width: 48.4375%; + margin-right: 3.125% + } + + .post-card:last-of-type, + .post-card:nth-child(2n+2) { + margin-right: 0 + } +} + +html { + line-height: 1.15; + -ms-text-size-adjust: 100%; + -webkit-text-size-adjust: 100% +} + +body { + margin: 0 +} + +header, +nav, +section { + display: block +} + +h1 { + font-size: 2em; + margin: .67em 0 +} + +figure, +main { + display: block +} + +figure { + margin: 1em 40px +} + +a { + background-color: transparent; + -webkit-text-decoration-skip: objects +} + +img { + border-style: none +} + +svg:not(:root) { + overflow: hidden +} + +::-webkit-file-upload-button { + -webkit-appearance: button; + font: inherit +} + +html { + -webkit-box-sizing: border-box; + box-sizing: border-box +} + +body { + -webkit-overflow-scrolling: touch +} + +*, +::after, +::before { + -webkit-box-sizing: inherit; + box-sizing: inherit +} + +.site { + display: -webkit-box; + display: -ms-flexbox; + display: flex; + min-height: 100vh; + -webkit-box-orient: vertical; + -webkit-box-direction: normal; + -ms-flex-direction: column; + flex-direction: column +} + +.site__content { + -webkit-box-flex: 1; + -ms-flex: 1; + flex: 1 +} + +img { + max-width: 100%; + height: auto; + width: auto; + vertical-align: middle +} + +figure { + margin: 0 +} + +body { + background-color: #fff; + font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, "Hiragino Sans GB", "Microsoft YaHei", "WenQuanYi Micro Hei", sans-serif; + font-size: 1rem; + line-height: 1.5; + color: #343851; + -webkit-font-smoothing: antialiased; + -webkit-text-size-adjust: 100% +} + +p { + margin-top: 0; + margin-bottom: 1.25rem +} + +h1, +h2 { + color: #313237; + margin-top: 0; + text-decoration: none; + margin-bottom: .5rem +} + +a { + color: #ff5300; + text-decoration: none; + border-bottom: 1px dashed #ff5300 +} + +a:active, +a:focus { + outline: 0; +} + +a:hover, +a:focus { + color: #ff7533; + border-bottom: 1px solid #ff7533; +} + + +.blur { + background: #fff; + filter: url('data:image/svg+xml;charset=utf-8,#filter'); + -webkit-filter: blur(1rem); + filter: blur(1rem) +} + +.container { + padding: 0 20px; + max-width: 100%; + margin: 0 auto +} + +@media only screen and (min-width:36em) { + .container { + max-width: 540px; + margin: 0 auto + } +} + +@media only screen and (min-width:48em) { + .container { + max-width: 720px; + margin: 0 auto + } +} + +@media only screen and (min-width:62em) { + .container { + max-width: 960px; + margin: 0 auto + } +} + +@media only screen and (min-width:75em) { + .container { + max-width: 1170px; + margin: 0 auto + } +} + +.header { + background-color: #fff; + color: #343851; + position: absolute; + z-index: 4; + width: 100%; + top: 0; + left: 0; + will-change: transform; + -webkit-transform: translateY(0); + transform: translateY(0) +} + +.header a { + display: -webkit-box; + display: -ms-flexbox; + display: flex; + -webkit-box-align: center; + -ms-flex-align: center; + align-items: center; + border-bottom: 0 +} + +.header__logo { + display: -webkit-box; + display: -ms-flexbox; + display: flex; + height: 100%; + overflow: hidden; + padding: 19px 0; + margin-right: 1.25rem; + outline: 0; + border-bottom: 0; + color: #313237 +} + +.header__logo .header__logo--container { + height: 40px; + width: 184px; +} + +.header__logo .header__logo--container .logo { + fill: currentColor +} + +.header__inner { + display: -webkit-box; + display: -ms-flexbox; + display: flex; + -webkit-box-align: center; + -ms-flex-align: center; + align-items: center; + height: 3.75em; + -webkit-box-pack: justify; + -ms-flex-pack: justify; + justify-content: space-between +} + +.header__links { + padding-bottom: .5rem; + display: none; + position: absolute; + top: 3.75em; + left: 0; + width: 100%; + height: auto; + background: #fff +} + +.header__link { + color: #343851; + padding: .938rem 0; + border-top: 1px solid #ededed +} + +.header__toggle { + display: -webkit-box; + display: -ms-flexbox; + display: flex; + -webkit-box-orient: vertical; + -webkit-box-direction: normal; + -ms-flex-direction: column; + flex-direction: column; + -webkit-box-pack: center; + -ms-flex-pack: center; + justify-content: center; + width: 44px; + height: 100%; + background-color: transparent; + padding-left: 1.25rem +} + +.header__toggle span { + display: block; + position: relative; + margin-top: 4px; + background-color: #343851; + width: 100%; + height: 2px; + border-radius: 1px +} + +.header__toggle span:first-child { + margin-top: 0 +} + +@media (min-width:62em) { + .header__toggle { + display: none; + visibility: hidden + } + + .header__links { + position: static; + padding: 0; + display: -webkit-box; + display: -ms-flexbox; + display: flex; + -webkit-box-orient: vertical; + -webkit-box-direction: normal; + -ms-flex-direction: column; + flex-direction: column; + visibility: visible; + width: auto; + height: 100% + } + + .header__links-wrapper { + display: -webkit-box; + display: -ms-flexbox; + display: flex; + height: 100%; + padding: 0 + } + + .header__link { + position: relative; + padding: .938rem 1rem; + border: 0; + height: 100% + } + + .header__link::after { + content: ""; + display: block; + position: absolute; + left: 0; + bottom: 0; + height: 3px; + width: 100%; + -webkit-transform: scaleX(0); + transform: scaleX(0); + background: #ff5300 + } +} + +.post-card { + display: block; + position: relative; + width: 100%; + min-height: 250px; + border-radius: 4px; + overflow: hidden; + background-color: #fff; + -webkit-box-shadow: 0 1px 3px rgba(0, 0, 0, .08); + box-shadow: 0 1px 3px rgba(0, 0, 0, .08); + margin-bottom: 2.25rem; + border-bottom: 0 +} + +@media only screen and (min-width:48em) { + .post-card { + width: 48.4375%; + margin-right: 3.125% + } + + .post-card:nth-child(2n+2) { + margin-right: 0 + } +} + +@media only screen and (min-width:75em) { + .post-card { + width: 31.25%; + margin-right: 3.125% + } + + .post-card:nth-child(2n+2) { + margin-right: 3.125% + } +} + +.post-card__label { + position: absolute; + top: 1.5rem; + left: 1.5rem; + z-index: 2 +} + +.post-card__inner { + display: block; + position: relative; + padding: 1.875rem 1.25rem .625rem; + width: 100%; + color: #838c8d; + border-bottom: 0 +} + +.post-card__header { + margin-bottom: .75rem +} + +.post-card__meta { + font-size: .875rem +} + +.post-card__thumb { + margin: 0; + background: #fff; + position: relative; + overflow: hidden +} + +.post-card__thumb::after { + content: ""; + display: block; + height: 0; + width: 100%; + padding-bottom: 56.25% +} + +.post-card__thumb>* { + position: absolute; + top: 0; + left: 0; + width: 100%; + height: 100%; + display: block +} + +.label { + padding: 0 10px; + margin-bottom: 1rem; + display: inline-block; + line-height: 20px; + font-size: .75rem; + text-transform: uppercase; + letter-spacing: 1px; + color: rgba(255, 255, 255, .8); + border: 2px solid rgba(255, 255, 255, .5); + border-radius: 100px +} + +.hero { + margin: 3.75rem auto 0; + min-height: 16.25rem; + width: 100%; + position: relative; + background-color: #dde5ea; + background-repeat: no-repeat; + background-position: 50%; + background-size: cover +} + +@media only screen and (min-width:62em) { + .hero { + margin: 0 auto; + height: 36em + } +} + +.hero::before { + position: absolute; + display: block; + content: ""; + top: 0; + left: 0; + width: 100%; + height: 100%; + background: rgba(52, 56, 81, .8) +} + +.hero__wrap { + position: absolute; + margin: auto; + top: 50%; + left: 50%; + -webkit-transform: translate(-50%, -50%); + transform: translate(-50%, -50%); + text-align: center; + color: rgba(255, 255, 255, .8); + width: 100%; + max-width: 90%; + z-index: 1 +} + +.hero__wrap .hero__title { + font-size: 1.8em; + color: #fff +} + +.blog { + background-color: #f9f9f9 +} + +.post-list { + padding-top: 2.5em; + display: -webkit-box; + display: -ms-flexbox; + display: flex; + -ms-flex-wrap: wrap; + flex-wrap: wrap; + -webkit-box-flex: 1; + -ms-flex: 1 0 auto; + flex: 1 0 auto +} + +@media only screen and (min-width:48em) { + .hero__wrap { + max-width: 40em + } + + .hero__wrap .hero__title { + padding: 1rem 0; + font-size: 2.625em; + line-height: 3.125rem + } + + .post-list { + padding-top: 5em + } +} + + +table { + font-size: 14.5px; +} + +.social__link:not(:last-child) { + margin-right: 1.5rem; +} + +.header__link_out { + border-top: 1px solid #ededed; + padding: 1rem; + background: #ff7533; + color: white; + border: none; + border-radius: 4px; + margin: auto; + margin-left: 20px; + height: 40px; +} \ No newline at end of file diff --git a/_includes/footer.html b/_includes/footer.html index 2f5dc25..cf2eee8 100644 --- a/_includes/footer.html +++ b/_includes/footer.html @@ -2,34 +2,48 @@
© {{ site.time | date: '%Y' }} {{ site.title | escape }}. All rights reserved.
- + {% if site.service_worker %} -{% endif %} +{% endif %} \ No newline at end of file diff --git a/_includes/head.html b/_includes/head.html index cbb46d2..acbd767 100644 --- a/_includes/head.html +++ b/_includes/head.html @@ -5,11 +5,15 @@ {% seo %} - - - + + + - + @@ -21,43 +25,48 @@ - + {% if page.title %} - + {% else %} - + {% endif %} {% if page.url %} - + {% endif %} {% if page.summary %} - + {% else %} - + {% endif %} {% if page.featured-img %} - + {% else %} - + {% endif %} {% if site.google_tag_manager %} - {% include gtm.html %} + {% include gtm.html %} {% endif %} {% feed_meta %} - + + + - + - + \ No newline at end of file diff --git a/_includes/header.html b/_includes/header.html index fad7024..59fc3bf 100644 --- a/_includes/header.html +++ b/_includes/header.html @@ -3,23 +3,23 @@
- + \ No newline at end of file diff --git a/_sass/abstracts/_variables.scss b/_sass/abstracts/_variables.scss index 57465b8..4fd1e8b 100755 --- a/_sass/abstracts/_variables.scss +++ b/_sass/abstracts/_variables.scss @@ -3,13 +3,13 @@ src: url("/assets/fonts/MuseoSans_300.otf"); } -$primary: #ef7f24 !default; -$secondary: #ff6161 !default; +$primary: #ff5300 !default; +$secondary: #ff4000 !default; $border: #ededed !default; -$primary-light: #f1a668; +$primary-light: #ff641a; $reverse: #413e3c !default; $success: #8fd896 !default; -$error: #ff6161 !default; +$error: #ff4000 !default; $bg-color: #fff !default; $light-bg-color: #f9f9f9; @@ -35,4 +35,4 @@ $code-bg-color: #faf8f6 !default; $code-text-color: #2e2925 !default; // Borders -$border-color: #fee5dc !default; +$border-color: #fee5dc !default; \ No newline at end of file diff --git a/_sass/layout/_nav.scss b/_sass/layout/_nav.scss index e071a74..73f2d6b 100755 --- a/_sass/layout/_nav.scss +++ b/_sass/layout/_nav.scss @@ -44,14 +44,15 @@ color: $heading-color; border-bottom: 0; } +} - .header__logo--container { - width: 40px; +.header__logo--container { + height: 40px; + width: 184px; +} - .logo { - fill: currentColor; - } - } +.logo { + fill: currentColor; } .header__inner { @@ -129,7 +130,7 @@ width: 0; height: 0; opacity: 0; - background-color: rgba(0, 0 , 0, .75); + background-color: rgba(0, 0, 0, .75); z-index: 2; transition: opacity 1s ease 0.1s; @@ -193,4 +194,4 @@ transition: transform .2s ease-in-out; } } -} +} \ No newline at end of file diff --git a/about.md b/about.md index 661bf19..e55322a 100644 --- a/about.md +++ b/about.md @@ -13,11 +13,11 @@ From time to time, the team also works on improving the security of the ecosyste Punctually, the Donjon runs external security audit/consultancy. The Donjon fields of expertise are quite wide: + - Software security - Hardware security - Cryptography -The Donjon also believes in open-source. It open-sources most of its internal attack tools. +The Donjon also believes in open-source. It open-sources most of its internal attack tools. [GitHub Donjon](https://github.com/ledger-donjon) Pull requests are welcome. - diff --git a/assets/css/main.css b/assets/css/main.css index 4aa84d2..a8fdc98 100755 --- a/assets/css/main.css +++ b/assets/css/main.css @@ -1,6 +1,8 @@ @font-face { font-family: "MuseoSans_300"; - src: url("/assets/fonts/MuseoSans_300.otf"); } + src: url("/assets/fonts/MuseoSans_300.otf"); +} + /* * Recommended to use import if you're building the site through gulp. * @import "node_modules/normalize.css/normalize"; @@ -20,7 +22,8 @@ html { -ms-text-size-adjust: 100%; /* 2 */ -webkit-text-size-adjust: 100%; - /* 2 */ } + /* 2 */ +} /* Sections ========================================================================== */ @@ -28,7 +31,8 @@ html { * Remove the margin in all browsers (opinionated). */ body { - margin: 0; } + margin: 0; +} /** * Add the correct display in IE 9-. @@ -39,7 +43,8 @@ footer, header, nav, section { - display: block; } + display: block; +} /** * Correct the font size and margin on `h1` elements within `section` and @@ -47,7 +52,8 @@ section { */ h1 { font-size: 2em; - margin: 0.67em 0; } + margin: 0.67em 0; +} /* Grouping content ========================================================================== */ @@ -59,13 +65,15 @@ figcaption, figure, main { /* 1 */ - display: block; } + display: block; +} /** * Add the correct margin in IE 8. */ figure { - margin: 1em 40px; } + margin: 1em 40px; +} /** * 1. Add the correct box sizing in Firefox. @@ -77,7 +85,8 @@ hr { height: 0; /* 1 */ overflow: visible; - /* 2 */ } + /* 2 */ +} /** * 1. Correct the inheritance and scaling of font size in all browsers. @@ -87,7 +96,8 @@ pre { font-family: monospace, monospace; /* 1 */ font-size: 1em; - /* 2 */ } + /* 2 */ +} /* Text-level semantics ========================================================================== */ @@ -99,7 +109,8 @@ a { background-color: transparent; /* 1 */ -webkit-text-decoration-skip: objects; - /* 2 */ } + /* 2 */ +} /** * 1. Remove the bottom border in Chrome 57- and Firefox 39-. @@ -111,21 +122,24 @@ abbr[title] { text-decoration: underline; /* 2 */ text-decoration: underline dotted; - /* 2 */ } + /* 2 */ +} /** * Prevent the duplicate application of `bolder` by the next rule in Safari 6. */ b, strong { - font-weight: inherit; } + font-weight: inherit; +} /** * Add the correct font weight in Chrome, Edge, and Safari. */ b, strong { - font-weight: bolder; } + font-weight: bolder; +} /** * 1. Correct the inheritance and scaling of font size in all browsers. @@ -137,26 +151,30 @@ samp { font-family: monospace, monospace; /* 1 */ font-size: 1em; - /* 2 */ } + /* 2 */ +} /** * Add the correct font style in Android 4.3-. */ dfn { - font-style: italic; } + font-style: italic; +} /** * Add the correct background and color in IE 9-. */ mark { background-color: #ff0; - color: #000; } + color: #000; +} /** * Add the correct font size in all browsers. */ small { - font-size: 80%; } + font-size: 80%; +} /** * Prevent `sub` and `sup` elements from affecting the line height in @@ -167,13 +185,16 @@ sup { font-size: 75%; line-height: 0; position: relative; - vertical-align: baseline; } + vertical-align: baseline; +} sub { - bottom: -0.25em; } + bottom: -0.25em; +} sup { - top: -0.5em; } + top: -0.5em; +} /* Embedded content ========================================================================== */ @@ -182,26 +203,30 @@ sup { */ audio, video { - display: inline-block; } + display: inline-block; +} /** * Add the correct display in iOS 4-7. */ audio:not([controls]) { display: none; - height: 0; } + height: 0; +} /** * Remove the border on images inside links in IE 10-. */ img { - border-style: none; } + border-style: none; +} /** * Hide the overflow in IE. */ svg:not(:root) { - overflow: hidden; } + overflow: hidden; +} /* Forms ========================================================================== */ @@ -221,7 +246,8 @@ textarea { line-height: 1.15; /* 1 */ margin: 0; - /* 2 */ } + /* 2 */ +} /** * Show the overflow in IE. @@ -230,7 +256,8 @@ textarea { button, input { /* 1 */ - overflow: visible; } + overflow: visible; +} /** * Remove the inheritance of text transform in Edge, Firefox, and IE. @@ -239,7 +266,8 @@ input { button, select { /* 1 */ - text-transform: none; } + text-transform: none; +} /** * 1. Prevent a WebKit bug where (2) destroys native `audio` and `video` @@ -251,7 +279,8 @@ html [type="button"], [type="reset"], [type="submit"] { -webkit-appearance: button; - /* 2 */ } + /* 2 */ +} /** * Remove the inner border and padding in Firefox. @@ -261,7 +290,8 @@ button::-moz-focus-inner, [type="reset"]::-moz-focus-inner, [type="submit"]::-moz-focus-inner { border-style: none; - padding: 0; } + padding: 0; +} /** * Restore the focus styles unset by the previous rule. @@ -270,13 +300,15 @@ button:-moz-focusring, [type="button"]:-moz-focusring, [type="reset"]:-moz-focusring, [type="submit"]:-moz-focusring { - outline: 1px dotted ButtonText; } + outline: 1px dotted ButtonText; +} /** * Correct the padding in Firefox. */ fieldset { - padding: 0.35em 0.75em 0.625em; } + padding: 0.35em 0.75em 0.625em; +} /** * 1. Correct the text wrapping in Edge and IE. @@ -296,7 +328,8 @@ legend { padding: 0; /* 3 */ white-space: normal; - /* 1 */ } + /* 1 */ +} /** * 1. Add the correct display in IE 9-. @@ -306,13 +339,15 @@ progress { display: inline-block; /* 1 */ vertical-align: baseline; - /* 2 */ } + /* 2 */ +} /** * Remove the default vertical scrollbar in IE. */ textarea { - overflow: auto; } + overflow: auto; +} /** * 1. Add the correct box sizing in IE 10-. @@ -323,14 +358,16 @@ textarea { box-sizing: border-box; /* 1 */ padding: 0; - /* 2 */ } + /* 2 */ +} /** * Correct the cursor style of increment and decrement buttons in Chrome. */ [type="number"]::-webkit-inner-spin-button, [type="number"]::-webkit-outer-spin-button { - height: auto; } + height: auto; +} /** * 1. Correct the odd appearance in Chrome and Safari. @@ -340,14 +377,16 @@ textarea { -webkit-appearance: textfield; /* 1 */ outline-offset: -2px; - /* 2 */ } + /* 2 */ +} /** * Remove the inner padding and cancel buttons in Chrome and Safari on macOS. */ [type="search"]::-webkit-search-cancel-button, [type="search"]::-webkit-search-decoration { - -webkit-appearance: none; } + -webkit-appearance: none; +} /** * 1. Correct the inability to style clickable types in iOS and Safari. @@ -357,7 +396,8 @@ textarea { -webkit-appearance: button; /* 1 */ font: inherit; - /* 2 */ } + /* 2 */ +} /* Interactive ========================================================================== */ @@ -367,13 +407,15 @@ textarea { */ details, menu { - display: block; } + display: block; +} /* * Add the correct display in all browsers. */ summary { - display: list-item; } + display: list-item; +} /* Scripting ========================================================================== */ @@ -381,13 +423,15 @@ summary { * Add the correct display in IE 9-. */ canvas { - display: inline-block; } + display: inline-block; +} /** * Add the correct display in IE. */ template { - display: none; } + display: none; +} /* Hidden ========================================================================== */ @@ -395,38 +439,47 @@ template { * Add the correct display in IE 10-. */ [hidden] { - display: none; } + display: none; +} html { - box-sizing: border-box; } + box-sizing: border-box; +} body { - -webkit-overflow-scrolling: touch; } + -webkit-overflow-scrolling: touch; +} *, *::before, *::after { - box-sizing: inherit; } + box-sizing: inherit; +} .site { display: flex; min-height: 100vh; - flex-direction: column; } + flex-direction: column; +} .site__content { - flex: 1; } + flex: 1; +} img { max-width: 100%; height: auto; width: auto; - vertical-align: middle; } + vertical-align: middle; +} img::selection { - background: transparent; } + background: transparent; +} figure { - margin: 0; } + margin: 0; +} body { background-color: #fff; @@ -435,15 +488,18 @@ body { line-height: 1.5; color: #514134; -webkit-font-smoothing: antialiased; - -webkit-text-size-adjust: 100%; } + -webkit-text-size-adjust: 100%; +} ::selection { color: #fff; - background-color: #413e3c; } + background-color: #413e3c; +} p { margin-top: 0; - margin-bottom: 1.25rem; } + margin-bottom: 1.25rem; +} h1, h2, @@ -453,33 +509,45 @@ h5, h6 { color: #373431; margin-top: 0; - margin-bottom: .5rem; } + margin-bottom: .5rem; +} a { - color: #ef7f24; + color: #ff5300; text-decoration: none; transition: all .2s linear; - border-bottom: 1px dashed #ef7f24; } - a:active, a:focus { - outline: 0; } - a:hover, a:focus { - color: #f1a668; - border-bottom: 1px solid #f1a668; } + border-bottom: 1px dashed #ff5300; +} + +a:active, +a:focus { + outline: 0; +} + +a:hover, +a:focus { + color: #ff7533; + border-bottom: 1px solid #ff7533; +} hr { height: 1px; background: #ededed; - border: 0; } + border: 0; +} em { - font-style: italic; } + font-style: italic; +} abbr[title] { - text-decoration: none; } + text-decoration: none; +} mark { background: #ff0; - color: #373431; } + color: #373431; +} code { padding: 0.2em 0.4em; @@ -487,7 +555,8 @@ code { font-size: 0.9rem; color: #2e2925; background-color: #faf8f6; - border-radius: 3px; } + border-radius: 3px; +} pre { padding: 0.8rem; @@ -499,54 +568,75 @@ pre { word-wrap: normal; background-color: #faf8f6; border: solid 1px #fee5dc; - border-radius: 0.3rem; } - pre > code { - padding: 0; - margin: 0; - font-size: 0.9rem; - color: #2e2925; - word-break: normal; - white-space: pre; - background: transparent; - border: 0; } + border-radius: 0.3rem; +} + +pre>code { + padding: 0; + margin: 0; + font-size: 0.9rem; + color: #2e2925; + word-break: normal; + white-space: pre; + background: transparent; + border: 0; +} .blur { background: #fff; filter: url('data:image/svg+xml;charset=utf-8,#filter'); -webkit-filter: blur(1rem); filter: blur(1rem); - transition: filter 400ms, -webkit-filter 400ms; } - .blur.lazyloaded { - -webkit-filter: blur(0); - filter: blur(0); } + transition: filter 400ms, -webkit-filter 400ms; +} + +.blur.lazyloaded { + -webkit-filter: blur(0); + filter: blur(0); +} .dark-bg { - background-color: #373431; } + background-color: #373431; +} .hidden { display: none; - visibility: hidden; } + visibility: hidden; +} .container { padding: 0 20px; margin: 0 auto; - max-width: 100%; } - @media only screen and (min-width: 36em) { - .container { - margin: 0 auto; - max-width: 540px; } } - @media only screen and (min-width: 48em) { - .container { - margin: 0 auto; - max-width: 720px; } } - @media only screen and (min-width: 62em) { - .container { - margin: 0 auto; - max-width: 960px; } } - @media only screen and (min-width: 75em) { - .container { - margin: 0 auto; - max-width: 1170px; } } + max-width: 100%; +} + +@media only screen and (min-width: 36em) { + .container { + margin: 0 auto; + max-width: 540px; + } +} + +@media only screen and (min-width: 48em) { + .container { + margin: 0 auto; + max-width: 720px; + } +} + +@media only screen and (min-width: 62em) { + .container { + margin: 0 auto; + max-width: 960px; + } +} + +@media only screen and (min-width: 75em) { + .container { + margin: 0 auto; + max-width: 1170px; + } +} .header { background-color: #fff; @@ -558,19 +648,26 @@ pre { left: 0; will-change: transform; transition: transform .3s, background-color 0.5s ease; - transform: translateY(0%); } - .header a { - display: flex; - align-items: center; - border-bottom: 0; } - .header.fix-nav { - position: fixed; - background-color: #fff; - transition: transform .3s, background-color 0.5s ease; - z-index: 5; } - .header.hide-nav { - transform: translateY(-120%); - transition: transform .3s; } + transform: translateY(0%); +} + +.header a { + display: flex; + align-items: center; + border-bottom: 0; +} + +.header.fix-nav { + position: fixed; + background-color: #fff; + transition: transform .3s, background-color 0.5s ease; + z-index: 5; +} + +.header.hide-nav { + transform: translateY(-120%); + transition: transform .3s; +} .header__logo { display: flex; @@ -580,20 +677,29 @@ pre { margin-right: 1.25rem; outline: 0; border-bottom: 0; - color: #373431; } - .header__logo:hover { - color: #373431; - border-bottom: 0; } - .header__logo .header__logo--container { - width: 40px; } - .header__logo .header__logo--container .logo { - fill: currentColor; } + color: #373431; +} + +.header__logo:hover { + color: #373431; + border-bottom: 0; +} + +.header__logo .header__logo--container { + height: 40px; + width: 184px; +} + +.header__logo .header__logo--container .logo { + fill: currentColor; +} .header__inner { display: flex; align-items: center; height: 3.75em; - justify-content: space-between; } + justify-content: space-between; +} .header__links { padding-bottom: .5rem; @@ -603,30 +709,35 @@ pre { left: 0; width: 100%; height: auto; - background: #fff; } + background: #fff; +} .header__link { color: #514134; padding: .938rem 0; - border-top: 1px solid #ededed; } + border-top: 1px solid #ededed; +} .header__link_out { - padding: .938rem 0; - border-top: 1px solid #ededed; } + border-top: 1px solid #ededed; +} -.header__link_out, .header__link_out:focus { +.header__link_out, +.header__link_out:focus { padding: 1rem; - background: #f1a668; + background: #ff7533; color: white; border: none; border-radius: 4px; margin: auto; margin-left: 20px; - height: 40px; } + height: 40px; +} .header__link_out:hover { color: white; - background: #ef7f24; } + background: #ff5300; +} .header__toggle { display: flex; @@ -636,24 +747,35 @@ pre { height: 100%; background-color: transparent; padding-left: 1.25rem; - cursor: pointer; } - .header__toggle span { - display: block; - position: relative; - margin-top: 4px; - background-color: #514134; - width: 100%; - height: 2px; - border-radius: 1px; - transition: all 0.2s cubic-bezier(1, 0.13, 0.35, 1.09); } - .header__toggle span:first-child { - margin-top: 0; } - .header__toggle.--open span:first-child { - transform: rotate(45deg) translate(4px, 4px); } - .header__toggle.--open span:nth-child(2n) { - opacity: 0; } - .header__toggle.--open span:last-child { - transform: rotate(-45deg) translate(4px, -4px); } + cursor: pointer; +} + +.header__toggle span { + display: block; + position: relative; + margin-top: 4px; + background-color: #514134; + width: 100%; + height: 2px; + border-radius: 1px; + transition: all 0.2s cubic-bezier(1, 0.13, 0.35, 1.09); +} + +.header__toggle span:first-child { + margin-top: 0; +} + +.header__toggle.--open span:first-child { + transform: rotate(45deg) translate(4px, 4px); +} + +.header__toggle.--open span:nth-child(2n) { + opacity: 0; +} + +.header__toggle.--open span:last-child { + transform: rotate(-45deg) translate(4px, -4px); +} .header__overlay { position: fixed; @@ -664,16 +786,20 @@ pre { opacity: 0; background-color: rgba(0, 0, 0, 0.75); z-index: 2; - transition: opacity 1s ease 0.1s; } - .header__overlay.--open { - width: 100%; - height: 120%; - opacity: 1; } + transition: opacity 1s ease 0.1s; +} + +.header__overlay.--open { + width: 100%; + height: 120%; + opacity: 1; +} @media (min-width: 62em) { .header__toggle { display: none; - visibility: hidden; } + visibility: hidden; + } .header__links { position: static; @@ -682,64 +808,84 @@ pre { flex-direction: column; visibility: visible; width: auto; - height: 100%; } + height: 100%; + } .header__links-wrapper { display: flex; height: 100%; - padding: 0; } + padding: 0; + } .header__link { position: relative; padding: .938rem 1rem; border: 0; - height: 100%; } - .header__link::after { - content: ""; - display: block; - position: absolute; - left: 0; - bottom: 0; - height: 3px; - width: 100%; - transform: scaleX(0); - background: #ef7f24; - transition: color 0.2s ease-in-out, transform .2s ease-in-out; } - .header__link:hover { - color: #a14f0c; } - .header__link:hover::after, - .header__link :active::after, - .header__link :focus::after { - transform: scaleX(1); - color: #a14f0c; - transition: transform .2s ease-in-out; } } + height: 100%; + } + + .header__link::after { + content: ""; + display: block; + position: absolute; + left: 0; + bottom: 0; + height: 3px; + width: 100%; + transform: scaleX(0); + background: #ff5300; + transition: color 0.2s ease-in-out, transform .2s ease-in-out; + } + + .header__link:hover { + color: #ff5300; + } + + .header__link:hover::after, + .header__link:active::after, + .header__link:focus::after { + transform: scaleX(1); + color: #a14f0c; + transition: transform .2s ease-in-out; + } +} + footer { padding: 2.8125rem 0; border-top: 1px solid #f0f0f0; text-align: center; font-size: 0.875rem; - color: rgba(33, 33, 33, 0.6); } - footer a { - color: rgba(33, 33, 33, 0.6); - border-bottom: 0; } - footer a:hover, footer a:focus { - color: #ef7f24; - border-bottom: 0; } + color: rgba(33, 33, 33, 0.6); +} + +footer a { + color: rgba(33, 33, 33, 0.6); + border-bottom: 0; +} + +footer a:hover, +footer a:focus { + color: #ff5300; + border-bottom: 0; +} .social { display: flex; justify-content: center; align-items: center; max-width: 200px; - margin: 0 auto 25px; } + margin: 0 auto 25px; +} .social__link:not(:last-child) { - margin-right: 1.5rem; } + margin-right: 1.5rem; +} .social__icon { fill: currentColor; height: 1.5rem; - width: 1.5rem; } + width: 1.5rem; +} .btn, input[type="submit"], @@ -762,42 +908,54 @@ input[type="button"] { border: 0; border-radius: 0; transition: all 0.45s cubic-bezier(0.25, 1, 0.33, 1); - outline: 0; } - .btn::after, - input[type="submit"]::after, - input[type="reset"]::after, - input[type="button"]::after { - display: none; } - .btn:hover, - .btn :focus, - .btn :active, - input[type="submit"]:hover, - input[type="submit"] :focus, - input[type="submit"] :active, - input[type="reset"]:hover, - input[type="reset"] :focus, - input[type="reset"] :active, - input[type="button"]:hover, - input[type="button"] :focus, - input[type="button"] :active { - color: #fff; - background-color: #4a4644; - outline: 0; } - -.btn + .btn { - margin-top: 2em; } - @media only screen and (min-width: 350px) { - .btn + .btn { - margin-top: 0; - margin-left: 2em; } } + outline: 0; +} + +.btn::after, +input[type="submit"]::after, +input[type="reset"]::after, +input[type="button"]::after { + display: none; +} + +.btn:hover, +.btn :focus, +.btn :active, +input[type="submit"]:hover, +input[type="submit"] :focus, +input[type="submit"] :active, +input[type="reset"]:hover, +input[type="reset"] :focus, +input[type="reset"] :active, +input[type="button"]:hover, +input[type="button"] :focus, +input[type="button"] :active { + color: #fff; + background-color: #4a4644; + outline: 0; +} + +.btn+.btn { + margin-top: 2em; +} + +@media only screen and (min-width: 350px) { + .btn+.btn { + margin-top: 0; + margin-left: 2em; + } +} button:disabled { cursor: not-allowed; opacity: .65; - transition: background-color .2s ease; } - button:disabled:hover, - button:disabled :focus { - background-color: #252322; } + transition: background-color .2s ease; +} + +button:disabled:hover, +button:disabled :focus { + background-color: #252322; +} .post-card { display: block; @@ -810,62 +968,96 @@ button:disabled { box-shadow: 0 1px 3px rgba(0, 0, 0, 0.08); margin-bottom: 2.25rem; border-bottom: 0; - transition: box-shadow .25s ease; } - .post-card:hover, .post-card:focus { - border-bottom: 0; - box-shadow: 0 2px 40px 0 rgba(153, 155, 168, 0.3); } - @media only screen and (min-width: 48em) { - .post-card { - width: 48.4375%; - margin-right: 3.125%; } - .post-card:last-of-type, .post-card:nth-child(2n+2) { - margin-right: 0; } } - @media only screen and (min-width: 75em) { - .post-card { - width: 31.25%; - margin-right: 3.125%; } - .post-card:nth-child(2n+2) { - margin-right: 3.125%; } - .post-card:last-of-type, .post-card:nth-child(3n+3) { - margin-right: 0; } } - .post-card__label { - position: absolute; - top: 1.5rem; - left: 1.5rem; - z-index: 2; } - .post-card__inner { - display: block; - position: relative; - padding: 1.875rem 1.25rem 0.625rem; - width: 100%; - color: #8d8883; - border-bottom: 0; } - .post-card__inner:focus, .post-card__inner:hover { - color: #8d8883; - border-bottom: 0; } - .post-card__header { - margin-bottom: 0.75rem; } - .post-card__meta { - font-size: 0.875rem; } + transition: box-shadow .25s ease; +} + +.post-card:hover, +.post-card:focus { + border-bottom: 0; + box-shadow: 0 2px 40px 0 rgba(153, 155, 168, 0.3); +} + +@media only screen and (min-width: 48em) { + .post-card { + width: 48.4375%; + margin-right: 3.125%; + } + + .post-card:last-of-type, + .post-card:nth-child(2n+2) { + margin-right: 0; + } +} + +@media only screen and (min-width: 75em) { + .post-card { + width: 31.25%; + margin-right: 3.125%; + } + + .post-card:nth-child(2n+2) { + margin-right: 3.125%; + } + + .post-card:last-of-type, + .post-card:nth-child(3n+3) { + margin-right: 0; + } +} + +.post-card__label { + position: absolute; + top: 1.5rem; + left: 1.5rem; + z-index: 2; +} + +.post-card__inner { + display: block; + position: relative; + padding: 1.875rem 1.25rem 0.625rem; + width: 100%; + color: #8d8883; + border-bottom: 0; +} + +.post-card__inner:focus, +.post-card__inner:hover { + color: #8d8883; + border-bottom: 0; +} + +.post-card__header { + margin-bottom: 0.75rem; +} + +.post-card__meta { + font-size: 0.875rem; +} .post-card__thumb { margin: 0; background: #fff; position: relative; - overflow: hidden; } - .post-card__thumb::after { - content: ""; - display: block; - height: 0; - width: 100%; - padding-bottom: 56.25%; } - .post-card__thumb > * { - position: absolute; - top: 0; - left: 0; - width: 100%; - height: 100%; - display: block; } + overflow: hidden; +} + +.post-card__thumb::after { + content: ""; + display: block; + height: 0; + width: 100%; + padding-bottom: 56.25%; +} + +.post-card__thumb>* { + position: absolute; + top: 0; + left: 0; + width: 100%; + height: 100%; + display: block; +} .label { padding: 0px 10px; @@ -878,16 +1070,21 @@ button:disabled { color: rgba(255, 255, 255, 0.8); border: 2px solid rgba(255, 255, 255, 0.5); border-radius: 100px; - transition: all 0.2s ease; } - .label:focus, .label:hover { - color: #fff; - background-color: #ef7f24; - border: 2px solid #ef7f24; } + transition: all 0.2s ease; +} + +.label:focus, +.label:hover { + color: #fff; + background-color: #ff5300; + border: 2px solid #ff5300; +} .pagination { display: flex; justify-content: center; - margin: 1.25rem auto; } + margin: 1.25rem auto; +} input, textarea { @@ -898,66 +1095,86 @@ textarea { border-bottom: 2px solid #ededed; outline: none; font-family: "MuseoSans_300", -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, "Hiragino Sans GB", "Microsoft YaHei", "WenQuanYi Micro Hei", sans-serif; - background: transparent; } - input:focus, - textarea:focus { - border-color: #ef7f24; - transition: border-color .25s; } + background: transparent; +} + +input:focus, +textarea:focus { + border-color: #ff5300; + transition: border-color .25s; +} .form__input { position: relative; display: inline-block; width: 100%; - margin-bottom: 35px; } - .form__input::before { - content: ""; - position: absolute; - bottom: 0; - left: 0; - width: 0; - height: 2px; - background: #ef7f24; - z-index: 5; - transition: width 0.45s cubic-bezier(0.694, 0.048, 0.335, 1); - transition-delay: .1s; } - .form__input::after { - content: ""; - position: absolute; - bottom: 0; - left: 0; - width: 0; - height: 2px; - background: #ff6161; - z-index: 4; - transition: width 0.45s cubic-bezier(0.694, 0.048, 0.335, 1); } - .form__input:hover::after, - .form__input :focus::after, - .form__input :active::after { - width: 100%; } - .form__input:hover::before, - .form__input :focus::before, - .form__input :active::after { - width: 100%; } - .form__input.error:hover::after, - .form__input.error :focus::after, - .form__input.error :active::after { - width: 0%; } - .form__input.error:hover::before, - .form__input.error :focus::before, - .form__input.error :active::after { - width: 0%; } + margin-bottom: 35px; +} + +.form__input::before { + content: ""; + position: absolute; + bottom: 0; + left: 0; + width: 0; + height: 2px; + background: #ff5300; + z-index: 5; + transition: width 0.45s cubic-bezier(0.694, 0.048, 0.335, 1); + transition-delay: .1s; +} + +.form__input::after { + content: ""; + position: absolute; + bottom: 0; + left: 0; + width: 0; + height: 2px; + background: #ff4000; + z-index: 4; + transition: width 0.45s cubic-bezier(0.694, 0.048, 0.335, 1); +} + +.form__input:hover::after, +.form__input :focus::after, +.form__input :active::after { + width: 100%; +} + +.form__input:hover::before, +.form__input :focus::before, +.form__input :active::after { + width: 100%; +} + +.form__input.error:hover::after, +.form__input.error :focus::after, +.form__input.error :active::after { + width: 0%; +} + +.form__input.error:hover::before, +.form__input.error :focus::before, +.form__input.error :active::after { + width: 0%; +} .error input { - border-bottom-color: #ff6161; } + border-bottom-color: #ff4000; +} + .error textarea { - border-bottom-color: #ff6161; } + border-bottom-color: #ff4000; +} .error-data { - color: #ff6161; + color: #ff4000; font-size: 14px; position: absolute; left: 0; - bottom: -21px; } + bottom: -21px; +} .modal { position: fixed; @@ -970,7 +1187,8 @@ textarea { height: 100%; outline: 0; overflow-y: auto; - z-index: 999; } + z-index: 999; +} .modal__inner { flex: 0 1 auto; @@ -982,7 +1200,8 @@ textarea { opacity: 0; transform: translateY(200px); transition: transform 0.5s cubic-bezier(0.4, 0, 0.2, 1); - z-index: 1050; } + z-index: 1050; +} .modal__content { position: relative; @@ -990,9 +1209,12 @@ textarea { display: flex; flex-direction: column; background-color: #fff; - border-radius: 4px; } - .modal__content h1 { - text-align: center; } + border-radius: 4px; +} + +.modal__content h1 { + text-align: center; +} .modal__close-button { position: absolute; @@ -1002,9 +1224,12 @@ textarea { border: 0; outline: 0; color: #373431; - cursor: pointer; } - .modal__close-button:hover { - background-color: transparent; } + cursor: pointer; +} + +.modal__close-button:hover { + background-color: transparent; +} .modal__overlay { position: fixed; @@ -1018,10 +1243,12 @@ textarea { z-index: 1040; opacity: 0; background-color: rgba(0, 0, 0, 0.75); - transition: opacity 1s ease 0.1s; } + transition: opacity 1s ease 0.1s; +} body.modal--open { - overflow: hidden; } + overflow: hidden; +} table { display: table; @@ -1032,226 +1259,298 @@ table { border-spacing: 0; border: 1px solid #ededed; border-radius: 4px; - font-size: 14.5px; } - table th { - background-color: #f9f9f9; } - table th, - table td { - padding: 6px 13px; - border: 1px solid #ededed; } + font-size: 14.5px; +} + +table th { + background-color: #f9f9f9; +} + +table th, +table td { + padding: 6px 13px; + border: 1px solid #ededed; +} .highlight table td { - padding: 5px; } + padding: 5px; +} .highlight table pre { - margin: 0; } + margin: 0; +} .highlight .cm { color: #999988; - font-style: italic; } + font-style: italic; +} .highlight .cp { color: #999999; - font-weight: bold; } + font-weight: bold; +} .highlight .c1 { color: #999988; - font-style: italic; } + font-style: italic; +} .highlight .cs { color: #999999; font-weight: bold; - font-style: italic; } + font-style: italic; +} -.highlight .c, .highlight .cd { +.highlight .c, +.highlight .cd { color: #999988; - font-style: italic; } + font-style: italic; +} .highlight .err { color: #a61717; - background-color: #e3d2d2; } + background-color: #e3d2d2; +} .highlight .gd { color: #000000; - background-color: #ffdddd; } + background-color: #ffdddd; +} .highlight .ge { color: #000000; - font-style: italic; } + font-style: italic; +} .highlight .gr { - color: #aa0000; } + color: #aa0000; +} .highlight .gh { - color: #999999; } + color: #999999; +} .highlight .gi { color: #000000; - background-color: #ddffdd; } + background-color: #ddffdd; +} .highlight .go { - color: #888888; } + color: #888888; +} .highlight .gp { - color: #555555; } + color: #555555; +} .highlight .gs { - font-weight: bold; } + font-weight: bold; +} .highlight .gu { - color: #aaaaaa; } + color: #aaaaaa; +} .highlight .gt { - color: #aa0000; } + color: #aa0000; +} .highlight .kc { color: #000000; - font-weight: bold; } + font-weight: bold; +} .highlight .kd { color: #000000; - font-weight: bold; } + font-weight: bold; +} .highlight .kn { color: #000000; - font-weight: bold; } + font-weight: bold; +} .highlight .kp { color: #000000; - font-weight: bold; } + font-weight: bold; +} .highlight .kr { color: #000000; - font-weight: bold; } + font-weight: bold; +} .highlight .kt { color: #445588; - font-weight: bold; } + font-weight: bold; +} -.highlight .k, .highlight .kv { +.highlight .k, +.highlight .kv { color: #000000; - font-weight: bold; } + font-weight: bold; +} .highlight .mf { - color: #009999; } + color: #009999; +} .highlight .mh { - color: #009999; } + color: #009999; +} .highlight .il { - color: #009999; } + color: #009999; +} .highlight .mi { - color: #009999; } + color: #009999; +} .highlight .mo { - color: #009999; } + color: #009999; +} -.highlight .m, .highlight .mb, .highlight .mx { - color: #009999; } +.highlight .m, +.highlight .mb, +.highlight .mx { + color: #009999; +} .highlight .sb { - color: #d14; } + color: #d14; +} .highlight .sc { - color: #d14; } + color: #d14; +} .highlight .sd { - color: #d14; } + color: #d14; +} .highlight .s2 { - color: #d14; } + color: #d14; +} .highlight .se { - color: #d14; } + color: #d14; +} .highlight .sh { - color: #d14; } + color: #d14; +} .highlight .si { - color: #d14; } + color: #d14; +} .highlight .sx { - color: #d14; } + color: #d14; +} .highlight .sr { - color: #009926; } + color: #009926; +} .highlight .s1 { - color: #d14; } + color: #d14; +} .highlight .ss { - color: #990073; } + color: #990073; +} .highlight .s { - color: #d14; } + color: #d14; +} .highlight .na { - color: #008080; } + color: #008080; +} .highlight .bp { - color: #999999; } + color: #999999; +} .highlight .nb { - color: #0086B3; } + color: #0086B3; +} .highlight .nc { color: #445588; - font-weight: bold; } + font-weight: bold; +} .highlight .no { - color: #008080; } + color: #008080; +} .highlight .nd { color: #3c5d5d; - font-weight: bold; } + font-weight: bold; +} .highlight .ni { - color: #800080; } + color: #800080; +} .highlight .ne { color: #990000; - font-weight: bold; } + font-weight: bold; +} .highlight .nf { color: #990000; - font-weight: bold; } + font-weight: bold; +} .highlight .nl { color: #990000; - font-weight: bold; } + font-weight: bold; +} .highlight .nn { - color: #555555; } + color: #555555; +} .highlight .nt { - color: #000080; } + color: #000080; +} .highlight .vc { - color: #008080; } + color: #008080; +} .highlight .vg { - color: #008080; } + color: #008080; +} .highlight .vi { - color: #008080; } + color: #008080; +} .highlight .nv { - color: #008080; } + color: #008080; +} .highlight .ow { color: #000000; - font-weight: bold; } + font-weight: bold; +} .highlight .o { color: #000000; - font-weight: bold; } + font-weight: bold; +} .highlight .w { - color: #bbbbbb; } + color: #bbbbbb; +} .highlight { - background-color: #f8f8f8; } + background-color: #f8f8f8; +} .hero { margin: 3.75rem auto 0; @@ -1261,48 +1560,62 @@ table { background-color: #dde5ea; background-repeat: no-repeat; background-position: 50%; - background-size: cover; } - @media only screen and (min-width: 62em) { - .hero { - margin: 0 auto; - height: 36em; } } - .hero::before { - position: absolute; - display: block; - content: ""; - top: 0; - left: 0; - width: 100%; - height: 100%; - background: rgba(51, 41, 34, 0.8); } + background-size: cover; +} + +@media only screen and (min-width: 62em) { + .hero { + margin: 0 auto; + height: 36em; + } +} + +.hero::before { + position: absolute; + display: block; + content: ""; + top: 0; + left: 0; + width: 100%; + height: 100%; + background: rgba(51, 41, 34, 0.8); +} /* Added by us */ .hero.nooverlay::before { - background: none; } + background: none; +} /* Added by us. * Fix image top-cropping when screen is wide. */ .hero.nooverlay { - margin-top: 60px; } + margin-top: 60px; +} .hero--small { margin: 3.75rem auto 0; min-height: 8.75rem; width: 100%; position: relative; - background-color: #373431; } - @media only screen and (min-width: 62em) { - .hero--small { - height: 12.5em; } } - .hero--small::before { - position: absolute; - display: block; - content: ""; - top: 0; - left: 0; - width: 100%; - height: 100%; - background: rgba(51, 41, 34, 0.8); } + background-color: #373431; +} + +@media only screen and (min-width: 62em) { + .hero--small { + height: 12.5em; + } +} + +.hero--small::before { + position: absolute; + display: block; + content: ""; + top: 0; + left: 0; + width: 100%; + height: 100%; + background: rgba(51, 41, 34, 0.8); +} .hero__wrap { position: absolute; @@ -1314,107 +1627,163 @@ table { color: rgba(255, 255, 255, 0.8); width: 100%; max-width: 90%; - z-index: 1; } - @media only screen and (min-width: 48em) { - .hero__wrap { - max-width: 40em; } } + z-index: 1; +} + +@media only screen and (min-width: 48em) { + .hero__wrap { + max-width: 40em; + } +} + +.hero__wrap .hero__title { + font-size: 1.8em; + color: #fff; +} + +@media only screen and (min-width: 48em) { .hero__wrap .hero__title { - font-size: 1.8em; - color: #fff; } - @media only screen and (min-width: 48em) { - .hero__wrap .hero__title { - padding: 1rem 0; - font-size: 2.625em; - line-height: 3.125rem; } } + padding: 1rem 0; + font-size: 2.625em; + line-height: 3.125rem; + } +} /* Added by us */ .hero.titleleft .hero__wrap { - padding-left: 20px; } - @media only screen and (min-width: 36em) { - .hero.titleleft .hero__wrap { - margin: 0 auto; - max-width: 540px; } } - @media only screen and (min-width: 48em) { - .hero.titleleft .hero__wrap { - margin: 0 auto; - max-width: 720px; } } - @media only screen and (min-width: 62em) { - .hero.titleleft .hero__wrap { - margin: 0 auto; - max-width: 960px; } } - @media only screen and (min-width: 75em) { - .hero.titleleft .hero__wrap { - margin: 0 auto; - max-width: 1170px; } } + padding-left: 20px; +} + +@media only screen and (min-width: 36em) { + .hero.titleleft .hero__wrap { + margin: 0 auto; + max-width: 540px; + } +} + +@media only screen and (min-width: 48em) { + .hero.titleleft .hero__wrap { + margin: 0 auto; + max-width: 720px; + } +} + +@media only screen and (min-width: 62em) { + .hero.titleleft .hero__wrap { + margin: 0 auto; + max-width: 960px; + } +} + +@media only screen and (min-width: 75em) { + .hero.titleleft .hero__wrap { + margin: 0 auto; + max-width: 1170px; + } +} + .hero.titleleft .hero__title { color: black; - text-align: left; } + text-align: left; +} + .hero.titleleft p.hero__meta { color: black; text-align: left; max-width: 50%; - font-size: 16pt; } + font-size: 16pt; +} .page-content { max-width: 52.5rem; margin: 0 auto; - padding: 2.5em 0; } - @media only screen and (min-width: 48em) { - .page-content { - padding: 3.75rem 0; } } + padding: 2.5em 0; +} + +@media only screen and (min-width: 48em) { + .page-content { + padding: 3.75rem 0; + } +} .blog { - background-color: #f9f9f9; } + background-color: #f9f9f9; +} .post-list { padding-top: 2.5em; display: flex; flex-wrap: wrap; - flex: 1 0 auto; } - @media only screen and (min-width: 48em) { - .post-list { - padding-top: 5em; } } + flex: 1 0 auto; +} + +@media only screen and (min-width: 48em) { + .post-list { + padding-top: 5em; + } +} .post-content { max-width: 52.5rem; margin: 0 auto; - padding-top: 2.5em; } - @media only screen and (min-width: 48em) { - .post-content { - padding-top: 5em; } } + padding-top: 2.5em; +} + +@media only screen and (min-width: 48em) { + .post-content { + padding-top: 5em; + } +} .comments { padding: 50px 0; - background-color: #fafafa; } + background-color: #fafafa; +} .controls__inner { display: flex; align-items: center; justify-content: space-between; padding: 1.375rem 0 1.25rem; - border-top: 1px solid #ededed; } - .controls__inner .prev { - align-items: flex-start; - text-align: left; } - .controls__inner .next { - align-items: flex-end; - text-align: right; } + border-top: 1px solid #ededed; +} + +.controls__inner .prev { + align-items: flex-start; + text-align: left; +} + +.controls__inner .next { + align-items: flex-end; + text-align: right; +} .controls__item { display: flex; flex-direction: column; - align-items: flex-start; } - .controls__item span { - font-size: 0.875rem; - color: #8d8883; } - .controls__item a { - color: #373431; - font-weight: bold; - border-bottom: 0; } - .controls__item a svg { - transition: all .2s linear; } - .controls__item a:hover { - color: #ef7f24; - border-bottom: 0; } - .controls__item a:hover svg { - fill: #ef7f24; } + align-items: flex-start; +} + +.controls__item span { + font-size: 0.875rem; + color: #8d8883; +} + +.controls__item a { + color: #373431; + font-weight: bold; + border-bottom: 0; +} + +.controls__item a svg { + transition: all .2s linear; +} + +.controls__item a:hover { + color: #ff5300; + border-bottom: 0; +} + +.controls__item a:hover svg { + fill: #ff5300; +} \ No newline at end of file diff --git a/assets/css/tools-suite.css b/assets/css/tools-suite.css new file mode 100644 index 0000000..31554e8 --- /dev/null +++ b/assets/css/tools-suite.css @@ -0,0 +1,77 @@ +/* CSS Specific for tools-suite page */ +.tool-cards-container { + display: flex; + gap: 10px; + flex-wrap: wrap; + flex-direction: row; + justify-content: space-around; + align-content: center; + align-items: flex-start; + margin: 10px; +} + +.tool-card { + display: flex; + flex-direction: column; + align-items: center; + width: 30%; + min-height: 200px; + transition: transform .3s; +} + +.tool-card:hover { + -ms-transform: scale(1.2); + -webkit-transform: scale(1.2); + transform: scale(1.2); + z-index: 5; +} + +.tool-card>* { + width: 100%; + padding-left: 5px; + background: rgb(249, 249, 249); + padding-right: 5px; + border-left: 1px solid #c3c3c3; + border-right: 1px solid #c3c3c3; + margin: 0; + font-size: small; + flex: 1; +} + +.tool-card>*:last-child { + padding-bottom: 5px; + border: 1px solid #c3c3c3; + border-bottom-left-radius: 10px; + border-bottom-right-radius: 10px; + flex: 0; + text-align: center; +} + +.tool-card>*:first-child { + padding-top: 5px; + border: 1px solid #c3c3c3; + background: #ffe0d1; + border-top-left-radius: 10px; + border-top-right-radius: 10px; + flex: 0; + text-align: center; + font-size: initial; +} + +.tool-card img { + padding: 10px; + max-height: 200px; +} + +.tool-card p:has(img) { + text-align: center; +} + +.tool-card ul { + padding: revert; + padding-inline-start: 20px; +} + +* { + scroll-behavior: smooth; +} \ No newline at end of file diff --git a/assets/donjonlogo.png b/assets/donjonlogo.png deleted file mode 100644 index 389cb51..0000000 Binary files a/assets/donjonlogo.png and /dev/null differ diff --git a/assets/img/icons/icon-x.svg b/assets/img/icons/icon-x.svg new file mode 100644 index 0000000..c3b5162 --- /dev/null +++ b/assets/img/icons/icon-x.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/assets/img/tools-suite/curmea.png b/assets/img/tools-suite/curmea.png new file mode 100644 index 0000000..822c739 Binary files /dev/null and b/assets/img/tools-suite/curmea.png differ diff --git a/assets/img/tools-suite/pystages.png b/assets/img/tools-suite/pystages.png new file mode 100644 index 0000000..d1e38ab Binary files /dev/null and b/assets/img/tools-suite/pystages.png differ diff --git a/assets/img/tools-suite/scaffold-board-anim.gif b/assets/img/tools-suite/scaffold-board-anim.gif new file mode 100644 index 0000000..05abfec Binary files /dev/null and b/assets/img/tools-suite/scaffold-board-anim.gif differ diff --git a/assets/img/tools-suite/scaffold-board.png b/assets/img/tools-suite/scaffold-board.png new file mode 100644 index 0000000..bf12197 Binary files /dev/null and b/assets/img/tools-suite/scaffold-board.png differ diff --git a/assets/img/tools-suite/shutter-controller.png b/assets/img/tools-suite/shutter-controller.png new file mode 100644 index 0000000..dcb5abf Binary files /dev/null and b/assets/img/tools-suite/shutter-controller.png differ diff --git a/assets/img/tools-suite/silicontoaster.png b/assets/img/tools-suite/silicontoaster.png new file mode 100644 index 0000000..4c88464 Binary files /dev/null and b/assets/img/tools-suite/silicontoaster.png differ diff --git a/assets/img/tools-suite/visplot.gif b/assets/img/tools-suite/visplot.gif new file mode 100644 index 0000000..78ace95 Binary files /dev/null and b/assets/img/tools-suite/visplot.gif differ diff --git a/assets/ledgerdonjon_banner.png b/assets/ledgerdonjon_banner.png new file mode 100644 index 0000000..d02e218 Binary files /dev/null and b/assets/ledgerdonjon_banner.png differ diff --git a/assets_blogDonjon/fonts/museo/MuseoSans_300.otf b/assets_blogDonjon/fonts/museo/MuseoSans_300.otf deleted file mode 100644 index e399aad..0000000 Binary files a/assets_blogDonjon/fonts/museo/MuseoSans_300.otf and /dev/null differ diff --git a/gulpfile.babel.js b/gulpfile.babel.js index 6472672..8c7e33f 100644 --- a/gulpfile.babel.js +++ b/gulpfile.babel.js @@ -2,35 +2,35 @@ "use strict"; // Gulp and node -const gulp = require( "gulp" ); -const cp = require( "child_process" ); -const notify = require( "gulp-notify" ); -const size = require( "gulp-size" ); +const gulp = require("gulp"); +const cp = require("child_process"); +const notify = require("gulp-notify"); +const size = require("gulp-size"); // Basic workflow plugins -const browserSync = require( "browser-sync" ); -const browserify = require( "browserify" ); -const source = require( "vinyl-source-stream" ); -const buffer = require( "vinyl-buffer" ); -const clean = require( "gulp-clean" ); -const sass = require( "gulp-sass" ); +const browserSync = require("browser-sync"); +const browserify = require("browserify"); +const source = require("vinyl-source-stream"); +const buffer = require("vinyl-buffer"); +const clean = require("gulp-clean"); +const sass = require("gulp-sass"); const jekyll = process.platform === "win32" ? "jekyll.bat" : "jekyll"; const messages = { - jekyllBuild: "Running: $ jekyll build" + jekyllBuild: "Running: $ jekyll build" }; // Performance workflow plugins -const htmlmin = require( "gulp-htmlmin" ); -const prefix = require( "gulp-autoprefixer" ); -const sourcemaps = require( "gulp-sourcemaps" ); -const uglify = require( "gulp-uglify" ); -const critical = require( "critical" ); -const sw = require( "sw-precache" ); +const htmlmin = require("gulp-htmlmin"); +const prefix = require("gulp-autoprefixer"); +const sourcemaps = require("gulp-sourcemaps"); +const uglify = require("gulp-uglify"); +const critical = require("critical"); +const sw = require("sw-precache"); // Image Generation -const responsive = require( "gulp-responsive" ); -const rename = require( "gulp-rename" ); -const imagemin = require( "gulp-imagemin" ); +const responsive = require("gulp-responsive"); +const rename = require("gulp-rename"); +const imagemin = require("gulp-imagemin"); const src = { css: "_sass/jekyll-sleek.scss", @@ -42,56 +42,56 @@ const dist = { }; function handleErrors() { - var args = Array.prototype.slice.call( arguments ); - notify.onError( { + var args = Array.prototype.slice.call(arguments); + notify.onError({ title: "Compile Error", message: "<%= error.message %>" - } ).apply( this, args ); - this.emit( "end" ); // Keep gulp from hanging on this task + }).apply(this, args); + this.emit("end"); // Keep gulp from hanging on this task } // SASS -gulp.task( "sass", () => { - return gulp.src( src.css ) - .pipe( sourcemaps.init() ) - .pipe( sass( { +gulp.task("sass", () => { + return gulp.src(src.css) + .pipe(sourcemaps.init()) + .pipe(sass({ outputStyle: "compressed", - includePaths: [ "scss" ], + includePaths: ["scss"], onError: browserSync.notify - } ).on( "error", sass.logError ) ) - .pipe( sourcemaps.write( { includeContent: false } ) ) - .pipe( sourcemaps.init( { loadMaps: true } ) ) - .pipe( prefix() ) - .pipe( sourcemaps.write( "./" ) ) - .pipe( rename( { basename: "main" } ) ) - .pipe( gulp.dest( dist.css ) ) - .pipe( browserSync.reload( { stream: true } ) ) - .pipe( gulp.dest( "assets/css" ) ); -} ); + }).on("error", sass.logError)) + .pipe(sourcemaps.write({ includeContent: false })) + .pipe(sourcemaps.init({ loadMaps: true })) + .pipe(prefix()) + .pipe(sourcemaps.write("./")) + .pipe(rename({ basename: "main" })) + .pipe(gulp.dest(dist.css)) + .pipe(browserSync.reload({ stream: true })) + .pipe(gulp.dest("assets/css")); +}); // JS -gulp.task( "js", () => { - return browserify( src.js, { debug: true, extensions: [ "es6" ] } ) - .transform( "babelify", { presets: [ "es2015" ] } ) +gulp.task("js", () => { + return browserify(src.js, { debug: true, extensions: ["es6"] }) + .transform("babelify", { presets: ["es2015"] }) .bundle() - .on( "error", handleErrors ) - .pipe( source( "bundle.js" ) ) - .pipe( buffer() ) - .pipe( sourcemaps.init( { loadMaps: true } ) ) - .pipe( uglify() ) - .pipe( sourcemaps.write( "./maps" ) ) - .pipe( size() ) - .pipe( gulp.dest( dist.js ) ) - .pipe( browserSync.reload( { stream: true } ) ) - .pipe( gulp.dest( "assets/js" ) ); -} ); - -gulp.task( "critical", done => { - critical.generate( { + .on("error", handleErrors) + .pipe(source("bundle.js")) + .pipe(buffer()) + .pipe(sourcemaps.init({ loadMaps: true })) + .pipe(uglify()) + .pipe(sourcemaps.write("./maps")) + .pipe(size()) + .pipe(gulp.dest(dist.js)) + .pipe(browserSync.reload({ stream: true })) + .pipe(gulp.dest("assets/js")); +}); + +gulp.task("critical", done => { + critical.generate({ base: "_site/", src: "index.html", - css: [ "assets/css/main.css" ], - dimensions: [ { + css: ["assets/css/main.css", "assets/css/tools-suite.css"], + dimensions: [{ width: 320, height: 480 }, { @@ -100,75 +100,75 @@ gulp.task( "critical", done => { }, { width: 1280, height: 960 - } ], + }], dest: "../_includes/critical.css", minify: true, extract: false, - ignore: [ "@font-face" ] - } ); + ignore: ["@font-face"] + }); done(); -} ); +}); // Minify HTML -gulp.task( "html", done => { - gulp.src( "./_site/index.html" ) - .pipe( htmlmin( { collapseWhitespace: true } ) ) - .pipe( gulp.dest( "./_site" ) ); - gulp.src( "./_site/*/*html" ) - .pipe( htmlmin( { collapseWhitespace: true } ) ) - .pipe( gulp.dest( "./_site/./" ) ); - done(); -} ); +gulp.task("html", done => { + gulp.src("./_site/index.html") + .pipe(htmlmin({ collapseWhitespace: true })) + .pipe(gulp.dest("./_site")); + gulp.src("./_site/*/*html") + .pipe(htmlmin({ collapseWhitespace: true })) + .pipe(gulp.dest("./_site/./")); + done(); +}); // Service Worker -gulp.task( "sw", () => { +gulp.task("sw", () => { const rootDir = "./"; const distDir = "./_site"; - return sw.write( `${rootDir}/sw.js`, { - staticFileGlobs: [ distDir + "/**/*.{js,html,css,png,jpg,svg}" ], + return sw.write(`${rootDir}/sw.js`, { + staticFileGlobs: [distDir + "/**/*.{js,html,css,png,jpg,svg}"], stripPrefix: distDir - } ); -} ); + }); +}); // Images -gulp.task( "img", () => { - return gulp.src( "_img/posts/*.{png,jpg}" ) - .pipe( responsive( { - "*": [ // For all the images in the posts folder - { - width: 230, - rename: { suffix: "_placehold" } - }, - { // thubmnail - width: 535, - rename: { suffix: "_thumb" } - }, - { // thumbnail @2x - width: 535 * 2, - rename: { suffix: "_thumb@2x" } - }, - { - width: 575, - rename: { suffix: "_xs" } - }, - { - width: 767, - rename: { suffix: "_sm" } - }, - { - width: 991, - rename: { suffix: "_md" } - }, - { - width: 1999, - rename: { suffix: "_lg" } - }, - { // max-width hero - width: 1920 - } - ] - }, +gulp.task("img", () => { + return gulp.src("_img/posts/*.{png,jpg}") + .pipe(responsive({ + "*": [ // For all the images in the posts folder + { + width: 230, + rename: { suffix: "_placehold" } + }, + { // thubmnail + width: 535, + rename: { suffix: "_thumb" } + }, + { // thumbnail @2x + width: 535 * 2, + rename: { suffix: "_thumb@2x" } + }, + { + width: 575, + rename: { suffix: "_xs" } + }, + { + width: 767, + rename: { suffix: "_sm" } + }, + { + width: 991, + rename: { suffix: "_md" } + }, + { + width: 1999, + rename: { suffix: "_lg" } + }, + { // max-width hero + width: 1920 + } + ] + }, { quality: 70, progressive: true, @@ -176,64 +176,64 @@ gulp.task( "img", () => { errorOnEnlargement: false, errorOnUnusedConfig: false, silent: true - } ) ) - .pipe( imagemin() ) - .pipe( gulp.dest( "assets/img/posts/" ) ); -} ); + })) + .pipe(imagemin()) + .pipe(gulp.dest("assets/img/posts/")); +}); // Build the Jekyll Site -gulp.task( "jekyll-build", done => { - browserSync.notify( messages.jekyllBuild ); - return cp.spawn( jekyll, [ "build" ], { stdio: "inherit" } ) - .on( "close", done ); -} ); +gulp.task("jekyll-build", done => { + browserSync.notify(messages.jekyllBuild); + return cp.spawn(jekyll, ["build"], { stdio: "inherit" }) + .on("close", done); +}); // Rebuild Jekyll & do page reload -gulp.task( "rebuild", - gulp.series( [ "jekyll-build" ], done => { +gulp.task("rebuild", + gulp.series(["jekyll-build"], done => { browserSync.reload(); done(); - } ) + }) ); -gulp.task( "clean", () => { - return gulp.src( "_site", { read: false, allowEmpty: true } ) - .pipe( clean() ); -} ); +gulp.task("clean", () => { + return gulp.src("_site", { read: false, allowEmpty: true }) + .pipe(clean()); +}); -gulp.task( "serve", function() { - return browserSync( { +gulp.task("serve", function () { + return browserSync({ server: { baseDir: "_site" } - } ); -} ); + }); +}); -gulp.task( "styles", gulp.series( [ "sass", "critical" ] ) ); +gulp.task("styles", gulp.series(["sass", "critical"])); -gulp.task( "watch", () => { - gulp.watch( "_sass/**/*.scss", gulp.series( "styles" ) ); - gulp.watch( [ +gulp.task("watch", () => { + gulp.watch("_sass/**/*.scss", gulp.series("styles")); + gulp.watch([ "*.html", "_layouts/*.html", "_includes/*.html", "_posts/*.md", "pages_/*.md", "_include/*html" - ], gulp.series( "rebuild" ) ); - gulp.watch( "_js/**/*.js", gulp.series( "js" ) ); -} ); + ], gulp.series("rebuild")); + gulp.watch("_js/**/*.js", gulp.series("js")); +}); -gulp.task( "build", gulp.series( [ +gulp.task("build", gulp.series([ "clean", - gulp.parallel( [ "sass", "js", "img" ] ), + gulp.parallel(["sass", "js", "img"]), "jekyll-build", "critical", "sw" -] ) ); +])); -gulp.task( "default", gulp.series( [ +gulp.task("default", gulp.series([ "build", "serve", "watch" -] ) ); +])); diff --git a/sw.js b/sw.js index 5601138..6b191b8 100644 --- a/sw.js +++ b/sw.js @@ -37,7 +37,7 @@ /* eslint-disable indent, no-unused-vars, no-multiple-empty-lines, max-nested-callbacks, space-before-function-paren, quotes, comma-spacing */ 'use strict'; -var precacheConfig = [["/404/index.html","0c657efbcdcfd712cec0e3ab376fe5b4"],["/about/index.html","cd19f1b540246a1e1743c018c9222e1e"],["/assets/css/main.css","73ff5a40cabab1694556be3e13adef75"],["/assets/img/favicon.jpg","ffb9f5c8afdda7fa4f3fd697e5147182"],["/assets/img/icons/android-chrome-192x192.png","4df4c8779d47bcaa69516050281773b9"],["/assets/img/icons/android-chrome-256x256.png","939ec88a61f407945a27d867fca1651d"],["/assets/img/icons/apple-touch-icon.png","366666899d15cf8f6811cc73ee0d63de"],["/assets/img/icons/favicon-16x16.png","f625044491b20a5df78571ba266cbcf6"],["/assets/img/icons/favicon-32x32.png","67502381e45848a4ab76123364675ffe"],["/assets/img/icons/icon-github.svg","4e06335104a29f91e08d4ef420da7679"],["/assets/img/icons/icon-instagram.svg","1e1119e2628235ee4c8771bff15eb2ca"],["/assets/img/icons/icon-twitter.svg","30551913d5399d6520e8a74b6f1e23f0"],["/assets/img/icons/mstile-150x150.png","1cea2ceb806d1a018330a51a1d8b73b6"],["/assets/img/icons/safari-pinned-tab.svg","398ef6b25c0f7f3f6e54c112a8facc5f"],["/assets/img/posts/emile-perron-190221.jpg","4705474281b975b7a213b96e71f772e7"],["/assets/img/posts/emile-perron-190221_lg.jpg","aafe35b1dc6d9dc9293c8c2ef4121046"],["/assets/img/posts/emile-perron-190221_md.jpg","03ed35ed656429599daba312f0990a0f"],["/assets/img/posts/emile-perron-190221_placehold.jpg","67f40708f69ab671cee04d624258b85c"],["/assets/img/posts/emile-perron-190221_sm.jpg","4ce4178a62d5a456e90e7bc47bde50f5"],["/assets/img/posts/emile-perron-190221_thumb.jpg","f20085dfe2e36854f8a12f1fd6c50425"],["/assets/img/posts/emile-perron-190221_thumb@2x.jpg","b8fa22c3237de529316037f093b9cb4d"],["/assets/img/posts/emile-perron-190221_xs.jpg","ac32cbd525d72e932499668af5647d03"],["/assets/img/posts/shane-rounce-205187.jpg","bb774d6e05b2b55ffdabe11a8aac7c56"],["/assets/img/posts/shane-rounce-205187_lg.jpg","83cd838024fff9c3faec59fa1da97872"],["/assets/img/posts/shane-rounce-205187_md.jpg","628cf27bf658cf6de9df79ab9bf2cb2d"],["/assets/img/posts/shane-rounce-205187_placehold.jpg","249fc4a09bcfcbd7d5764f14c14ae82e"],["/assets/img/posts/shane-rounce-205187_sm.jpg","a2400a468e10d7d64528ac9c6bc3b6f0"],["/assets/img/posts/shane-rounce-205187_thumb.jpg","c3b2dd0d95a6d3a44d7702f8c06b1e78"],["/assets/img/posts/shane-rounce-205187_thumb@2x.jpg","b0722b63a92c92a44cd92c0201fc92a4"],["/assets/img/posts/shane-rounce-205187_xs.jpg","cd58fd23f3b3c1de2183beb9ed08327b"],["/assets/img/posts/sleek.jpg","a32252a618ffe8ae57c9ce9ab157a01b"],["/assets/img/posts/sleek_lg.jpg","95a1338aa524727f34950f269133e904"],["/assets/img/posts/sleek_md.jpg","4e35ceb2f5fffd3d758fade699b0b85a"],["/assets/img/posts/sleek_placehold.jpg","0f48050cd7776895b98c6ce21597ff39"],["/assets/img/posts/sleek_sm.jpg","f30af3d30b7df905d962e494750f5da0"],["/assets/img/posts/sleek_thumb.jpg","f7b8a94ac9da8e5ea36bb9e459872400"],["/assets/img/posts/sleek_thumb@2x.jpg","e67e2129dc58a100b98a5e027c964dbc"],["/assets/img/posts/sleek_xs.jpg","c8212cace6d446950556a3bf6efe4520"],["/assets/js/bundle.js","df854a763d7d3fd95381b95081eb822f"],["/categories/index.html","02b986099815b7b5c68eee59ff4eebda"],["/contact/index.html","97bb3b239b650de38bb3a17da3878bdd"],["/getting-started/index.html","2a154f59d239dada3a1d156e52b390e4"],["/index.html","f2b2672b95b1d78662fde8b91af4b743"],["/markdown-cheatsheet/index.html","8651f910f3d436f2e59aa53eaa3c49ef"],["/super-long-article/index.html","d5f5f0af6ca2ae87ead69cff8823ed02"],["/sw.js","cf1b3e3d6b8da4fe588cf5c71c95129a"],["/welcome-to-jekyll/index.html","b5edde946d309f1578f8b646f7e07ed6"]]; +var precacheConfig = [["/404/index.html", "0c657efbcdcfd712cec0e3ab376fe5b4"], ["/about/index.html", "cd19f1b540246a1e1743c018c9222e1e"], ["/assets/img/favicon.jpg", "ffb9f5c8afdda7fa4f3fd697e5147182"], ["/assets/img/icons/android-chrome-192x192.png", "4df4c8779d47bcaa69516050281773b9"], ["/assets/img/icons/android-chrome-256x256.png", "939ec88a61f407945a27d867fca1651d"], ["/assets/img/icons/apple-touch-icon.png", "366666899d15cf8f6811cc73ee0d63de"], ["/assets/img/icons/favicon-16x16.png", "f625044491b20a5df78571ba266cbcf6"], ["/assets/img/icons/favicon-32x32.png", "67502381e45848a4ab76123364675ffe"], ["/assets/img/icons/icon-github.svg", "4e06335104a29f91e08d4ef420da7679"], ["/assets/img/icons/icon-instagram.svg", "1e1119e2628235ee4c8771bff15eb2ca"], ["/assets/img/icons/icon-x.svg", "30551913d5399d6520e8a74b6f1e23f0"], ["/assets/img/icons/mstile-150x150.png", "1cea2ceb806d1a018330a51a1d8b73b6"], ["/assets/img/icons/safari-pinned-tab.svg", "398ef6b25c0f7f3f6e54c112a8facc5f"], ["/assets/img/posts/emile-perron-190221.jpg", "4705474281b975b7a213b96e71f772e7"], ["/assets/img/posts/emile-perron-190221_lg.jpg", "aafe35b1dc6d9dc9293c8c2ef4121046"], ["/assets/img/posts/emile-perron-190221_md.jpg", "03ed35ed656429599daba312f0990a0f"], ["/assets/img/posts/emile-perron-190221_placehold.jpg", "67f40708f69ab671cee04d624258b85c"], ["/assets/img/posts/emile-perron-190221_sm.jpg", "4ce4178a62d5a456e90e7bc47bde50f5"], ["/assets/img/posts/emile-perron-190221_thumb.jpg", "f20085dfe2e36854f8a12f1fd6c50425"], ["/assets/img/posts/emile-perron-190221_thumb@2x.jpg", "b8fa22c3237de529316037f093b9cb4d"], ["/assets/img/posts/emile-perron-190221_xs.jpg", "ac32cbd525d72e932499668af5647d03"], ["/assets/img/posts/shane-rounce-205187.jpg", "bb774d6e05b2b55ffdabe11a8aac7c56"], ["/assets/img/posts/shane-rounce-205187_lg.jpg", "83cd838024fff9c3faec59fa1da97872"], ["/assets/img/posts/shane-rounce-205187_md.jpg", "628cf27bf658cf6de9df79ab9bf2cb2d"], ["/assets/img/posts/shane-rounce-205187_placehold.jpg", "249fc4a09bcfcbd7d5764f14c14ae82e"], ["/assets/img/posts/shane-rounce-205187_sm.jpg", "a2400a468e10d7d64528ac9c6bc3b6f0"], ["/assets/img/posts/shane-rounce-205187_thumb.jpg", "c3b2dd0d95a6d3a44d7702f8c06b1e78"], ["/assets/img/posts/shane-rounce-205187_thumb@2x.jpg", "b0722b63a92c92a44cd92c0201fc92a4"], ["/assets/img/posts/shane-rounce-205187_xs.jpg", "cd58fd23f3b3c1de2183beb9ed08327b"], ["/assets/img/posts/sleek.jpg", "a32252a618ffe8ae57c9ce9ab157a01b"], ["/assets/img/posts/sleek_lg.jpg", "95a1338aa524727f34950f269133e904"], ["/assets/img/posts/sleek_md.jpg", "4e35ceb2f5fffd3d758fade699b0b85a"], ["/assets/img/posts/sleek_placehold.jpg", "0f48050cd7776895b98c6ce21597ff39"], ["/assets/img/posts/sleek_sm.jpg", "f30af3d30b7df905d962e494750f5da0"], ["/assets/img/posts/sleek_thumb.jpg", "f7b8a94ac9da8e5ea36bb9e459872400"], ["/assets/img/posts/sleek_thumb@2x.jpg", "e67e2129dc58a100b98a5e027c964dbc"], ["/assets/img/posts/sleek_xs.jpg", "c8212cace6d446950556a3bf6efe4520"], ["/assets/js/bundle.js", "df854a763d7d3fd95381b95081eb822f"], ["/categories/index.html", "02b986099815b7b5c68eee59ff4eebda"], ["/contact/index.html", "97bb3b239b650de38bb3a17da3878bdd"], ["/index.html", "f2b2672b95b1d78662fde8b91af4b743"], ["/sw.js", "cf1b3e3d6b8da4fe588cf5c71c95129a"]]; var cacheName = 'sw-precache-v3--' + (self.registration ? self.registration.scope : ''); @@ -46,92 +46,92 @@ var ignoreUrlParametersMatching = [/^utm_/]; var addDirectoryIndex = function (originalUrl, index) { - var url = new URL(originalUrl); - if (url.pathname.slice(-1) === '/') { - url.pathname += index; - } - return url.toString(); - }; + var url = new URL(originalUrl); + if (url.pathname.slice(-1) === '/') { + url.pathname += index; + } + return url.toString(); +}; var cleanResponse = function (originalResponse) { - // If this is not a redirected response, then we don't have to do anything. - if (!originalResponse.redirected) { - return Promise.resolve(originalResponse); - } + // If this is not a redirected response, then we don't have to do anything. + if (!originalResponse.redirected) { + return Promise.resolve(originalResponse); + } - // Firefox 50 and below doesn't support the Response.body stream, so we may - // need to read the entire body to memory as a Blob. - var bodyPromise = 'body' in originalResponse ? - Promise.resolve(originalResponse.body) : - originalResponse.blob(); - - return bodyPromise.then(function(body) { - // new Response() is happy when passed either a stream or a Blob. - return new Response(body, { - headers: originalResponse.headers, - status: originalResponse.status, - statusText: originalResponse.statusText - }); + // Firefox 50 and below doesn't support the Response.body stream, so we may + // need to read the entire body to memory as a Blob. + var bodyPromise = 'body' in originalResponse ? + Promise.resolve(originalResponse.body) : + originalResponse.blob(); + + return bodyPromise.then(function (body) { + // new Response() is happy when passed either a stream or a Blob. + return new Response(body, { + headers: originalResponse.headers, + status: originalResponse.status, + statusText: originalResponse.statusText }); - }; + }); +}; var createCacheKey = function (originalUrl, paramName, paramValue, - dontCacheBustUrlsMatching) { - // Create a new URL object to avoid modifying originalUrl. - var url = new URL(originalUrl); - - // If dontCacheBustUrlsMatching is not set, or if we don't have a match, - // then add in the extra cache-busting URL parameter. - if (!dontCacheBustUrlsMatching || - !(url.pathname.match(dontCacheBustUrlsMatching))) { - url.search += (url.search ? '&' : '') + - encodeURIComponent(paramName) + '=' + encodeURIComponent(paramValue); - } + dontCacheBustUrlsMatching) { + // Create a new URL object to avoid modifying originalUrl. + var url = new URL(originalUrl); + + // If dontCacheBustUrlsMatching is not set, or if we don't have a match, + // then add in the extra cache-busting URL parameter. + if (!dontCacheBustUrlsMatching || + !(url.pathname.match(dontCacheBustUrlsMatching))) { + url.search += (url.search ? '&' : '') + + encodeURIComponent(paramName) + '=' + encodeURIComponent(paramValue); + } - return url.toString(); - }; + return url.toString(); +}; var isPathWhitelisted = function (whitelist, absoluteUrlString) { - // If the whitelist is empty, then consider all URLs to be whitelisted. - if (whitelist.length === 0) { - return true; - } + // If the whitelist is empty, then consider all URLs to be whitelisted. + if (whitelist.length === 0) { + return true; + } - // Otherwise compare each path regex to the path of the URL passed in. - var path = (new URL(absoluteUrlString)).pathname; - return whitelist.some(function(whitelistedPathRegex) { - return path.match(whitelistedPathRegex); - }); - }; + // Otherwise compare each path regex to the path of the URL passed in. + var path = (new URL(absoluteUrlString)).pathname; + return whitelist.some(function (whitelistedPathRegex) { + return path.match(whitelistedPathRegex); + }); +}; var stripIgnoredUrlParameters = function (originalUrl, - ignoreUrlParametersMatching) { - var url = new URL(originalUrl); - // Remove the hash; see https://github.com/GoogleChrome/sw-precache/issues/290 - url.hash = ''; - - url.search = url.search.slice(1) // Exclude initial '?' - .split('&') // Split into an array of 'key=value' strings - .map(function(kv) { - return kv.split('='); // Split each 'key=value' string into a [key, value] array - }) - .filter(function(kv) { - return ignoreUrlParametersMatching.every(function(ignoredRegex) { - return !ignoredRegex.test(kv[0]); // Return true iff the key doesn't match any of the regexes. - }); - }) - .map(function(kv) { - return kv.join('='); // Join each [key, value] array into a 'key=value' string - }) - .join('&'); // Join the array of 'key=value' strings into a string with '&' in between each - - return url.toString(); - }; + ignoreUrlParametersMatching) { + var url = new URL(originalUrl); + // Remove the hash; see https://github.com/GoogleChrome/sw-precache/issues/290 + url.hash = ''; + + url.search = url.search.slice(1) // Exclude initial '?' + .split('&') // Split into an array of 'key=value' strings + .map(function (kv) { + return kv.split('='); // Split each 'key=value' string into a [key, value] array + }) + .filter(function (kv) { + return ignoreUrlParametersMatching.every(function (ignoredRegex) { + return !ignoredRegex.test(kv[0]); // Return true iff the key doesn't match any of the regexes. + }); + }) + .map(function (kv) { + return kv.join('='); // Join each [key, value] array into a 'key=value' string + }) + .join('&'); // Join the array of 'key=value' strings into a string with '&' in between each + + return url.toString(); +}; var hashParamName = '_sw-precache'; var urlsToCacheKeys = new Map( - precacheConfig.map(function(item) { + precacheConfig.map(function (item) { var relativeUrl = item[0]; var hash = item[1]; var absoluteUrl = new URL(relativeUrl, self.location); @@ -141,25 +141,25 @@ var urlsToCacheKeys = new Map( ); function setOfCachedUrls(cache) { - return cache.keys().then(function(requests) { - return requests.map(function(request) { + return cache.keys().then(function (requests) { + return requests.map(function (request) { return request.url; }); - }).then(function(urls) { + }).then(function (urls) { return new Set(urls); }); } -self.addEventListener('install', function(event) { +self.addEventListener('install', function (event) { event.waitUntil( - caches.open(cacheName).then(function(cache) { - return setOfCachedUrls(cache).then(function(cachedUrls) { + caches.open(cacheName).then(function (cache) { + return setOfCachedUrls(cache).then(function (cachedUrls) { return Promise.all( - Array.from(urlsToCacheKeys.values()).map(function(cacheKey) { + Array.from(urlsToCacheKeys.values()).map(function (cacheKey) { // If we don't have a key matching url in the cache already, add it. if (!cachedUrls.has(cacheKey)) { - var request = new Request(cacheKey, {credentials: 'same-origin'}); - return fetch(request).then(function(response) { + var request = new Request(cacheKey, { credentials: 'same-origin' }); + return fetch(request).then(function (response) { // Bail out of installation unless we get back a 200 OK for // every request. if (!response.ok) { @@ -167,7 +167,7 @@ self.addEventListener('install', function(event) { 'response with status ' + response.status); } - return cleanResponse(response).then(function(responseToCache) { + return cleanResponse(response).then(function (responseToCache) { return cache.put(cacheKey, responseToCache); }); }); @@ -175,39 +175,39 @@ self.addEventListener('install', function(event) { }) ); }); - }).then(function() { - + }).then(function () { + // Force the SW to transition from installing -> active state return self.skipWaiting(); - + }) ); }); -self.addEventListener('activate', function(event) { +self.addEventListener('activate', function (event) { var setOfExpectedUrls = new Set(urlsToCacheKeys.values()); event.waitUntil( - caches.open(cacheName).then(function(cache) { - return cache.keys().then(function(existingRequests) { + caches.open(cacheName).then(function (cache) { + return cache.keys().then(function (existingRequests) { return Promise.all( - existingRequests.map(function(existingRequest) { + existingRequests.map(function (existingRequest) { if (!setOfExpectedUrls.has(existingRequest.url)) { return cache.delete(existingRequest); } }) ); }); - }).then(function() { - + }).then(function () { + return self.clients.claim(); - + }) ); }); -self.addEventListener('fetch', function(event) { +self.addEventListener('fetch', function (event) { if (event.request.method === 'GET') { // Should we call event.respondWith() inside this fetch event handler? // This needs to be determined synchronously, which will give other fetch @@ -231,9 +231,9 @@ self.addEventListener('fetch', function(event) { // request, and if so, whether the URL matches navigateFallbackWhitelist. var navigateFallback = ''; if (!shouldRespond && - navigateFallback && - (event.request.mode === 'navigate') && - isPathWhitelisted([], event.request.url)) { + navigateFallback && + (event.request.mode === 'navigate') && + isPathWhitelisted([], event.request.url)) { url = new URL(navigateFallback, self.location).toString(); shouldRespond = urlsToCacheKeys.has(url); } @@ -242,14 +242,14 @@ self.addEventListener('fetch', function(event) { // event.respondWith(), using the appropriate cache key. if (shouldRespond) { event.respondWith( - caches.open(cacheName).then(function(cache) { - return cache.match(urlsToCacheKeys.get(url)).then(function(response) { + caches.open(cacheName).then(function (cache) { + return cache.match(urlsToCacheKeys.get(url)).then(function (response) { if (response) { return response; } throw Error('The cached response that was expected is missing.'); }); - }).catch(function(e) { + }).catch(function (e) { // Fall back to just fetch()ing the request if some unexpected error // prevented the cached response from being valid. console.warn('Couldn\'t serve response for "%s" from cache: %O', event.request.url, e); diff --git a/tools-suite.md b/tools-suite.md new file mode 100644 index 0000000..48b9c58 --- /dev/null +++ b/tools-suite.md @@ -0,0 +1,220 @@ +--- +layout: page +title: Donjon Tools Suite +permalink: /tools-suite/ +--- + +## Ledger Donjon's Tools Suite + +The Security Team working in the Donjon develops their own tools for +their research and assessments. Most of these tools are intended to +be shared with the community by providing their source code in +order to allow people to contribute to their development. + +This page presents these tools in different categories, +[Software](#software-tools) and [Hardware](#hardware-tools) related. + +You can also check out the [Ledger-Donjon Git organization](https://github.com/Ledger-Donjon). + +### Hardware Attack & Analysis Tools {#hardware-tools} + +#### Boards + +
+ +
+ +#### Scaffold + +![Scaffold's photograph](/assets/img/tools-suite/scaffold-board.png) + +Multi-purpose board to control devices with embedded features such as: + +- current consumption measurement, +- multiple communication protocols (SPI, I2C, UART...), +- command triggering, +- pulse generators... + +[Repository](https://github.com/Ledger-Donjon/scaffold/) + +
+ +
+ +#### Curmea + +![Curmea](/assets/img/tools-suite/curmea.png) + +Simple board for differential current consumption measurement. + +[Repository](https://github.com/Ledger-Donjon/curmea/) + +
+ +
+ +#### Silicon Toaster + +![Silicon Toaster's photograph](/assets/img/tools-suite/silicontoaster.png) + +Board to inject electromagnetic pulses from a bank of capacitors, that can be +loaded to a programmable level of voltage, and discharged with a triggering +input source. + +[Repository](https://github.com/Ledger-Donjon/silicontoaster/) + +
+ +
+ +#### Shutter Controller + +![Shutter Controller's photograph](/assets/img/tools-suite/shutter-controller.png) + +A low-cost motorized add-on of optical tower on [ALPhANOV](https://www.alphanov.com/)'s [Laser Microscope Station](https://www.alphanov.com/en/products-services/single-laser-fault-injection) to control a mechanical shutter. + +[Repository](https://github.com/Ledger-Donjon/shutter-controller/) + +
+
+ +#### Software and utilities + +Useful utilities while performing hardware attacks. + +
+ +
+ +#### Laser Studio + +Multi-environment python3 software controlling hardware benches +to conduct automatized evaluations. + +[Repository](https://github.com/Ledger-Donjon/laserstudio/) + +
+ +
+ +#### pystages + +![Pystages logo](/assets/img/tools-suite/pystages.png) + +Python module for managing the positions of physical actuators, +such as CNCs, Corvus, or Newport. + +Also provides a simple User Interface to make easy and quick moves of actuators. + +[Repository](https://github.com/Ledger-Donjon/pystages/) + +
+ +
+ +#### pyPDM + +This python module can control the +[Pulse-on-Demand Modules](https://www.alphanov.com/en/products-services/pdm-laser-sources) +from [ALPhANOV](https://www.alphanov.com/). + +[Repository](https://github.com/Ledger-Donjon/pypdm/) + +
+ +
+ +#### Quicklog + +Python module for creating log files during a fault injection campaign. + +It can link each entry to curve as binary data, for instance retrieved +from an oscilloscope. + +[Repository](https://github.com/Ledger-Donjon/quicklog/) + +
+ +
+ +#### Quicklog Explorer + +GUI utility for viewing, filtering and plotting generated with [Quicklog](#quicklog). + +[Repository](https://github.com/Ledger-Donjon/quicklog-explorer/) + +
+ +
+ +#### Visplot + +![Visplot](/assets/img/tools-suite/visplot.gif) + +A side-channel traces visualizer based on [vispy](https://github.com/vispy). + +[Repository](https://github.com/Ledger-Donjon/visplot/) + +
+ +
+ +#### Rainbow + +Makes Unicorn traces. Generic Side-Channel and Fault Injection simulator. + +[Repository](https://github.com/Ledger-Donjon/rainbow/) + +
+
+ +#### Side-channel Tools + +
+
+ +#### Muscat + +Side-channel analysis tool written in Rust for performance +optimizations. + +[Repository](https://github.com/Ledger-Donjon/muscat/) + +
+ +
+ +#### Scadl + +Side-channel analysis tool with Deep-Learning features. + +[Repository](https://github.com/Ledger-Donjon/scadl/) + +
+ +
+ +#### Lascar + +Our legacy side-channel python3 library. + +[Repository](https://github.com/Ledger-Donjon/lascar/) + +
+
+ +### Software Attack & Analysis Tools {#software-tools} + +
+
+ +#### cargo-checkct + +Written in Rust, it verifies formally if a software is compiled down to +constant-time machine code. +More information in [this article](https://www.ledger.com/blog-cargo-checkct-our-home-made-tool-guarding-against-timing-attacks-is-now-open-source). + +[Repository](https://github.com/Ledger-Donjon/cargo-checkct). + +
+