diff options
Diffstat (limited to 'mod/web')
| -rw-r--r-- | mod/web/blog/.gitignore | 2 | ||||
| -rw-r--r-- | mod/web/blog/config.toml | 8 | ||||
| -rw-r--r-- | mod/web/blog/content/posts/_index.md | 6 | ||||
| -rw-r--r-- | mod/web/blog/content/posts/deterministic-hostnames.md | 80 | ||||
| -rw-r--r-- | mod/web/blog/content/posts/nohup.md | 26 | ||||
| -rw-r--r-- | mod/web/blog/content/posts/stateless-compute-networks.md | 41 | ||||
| -rw-r--r-- | mod/web/blog/content/posts/vim-compilers.md | 20 | ||||
| -rw-r--r-- | mod/web/blog/default.nix | 30 | ||||
| -rw-r--r-- | mod/web/blog/templates/404.html | 9 | ||||
| -rw-r--r-- | mod/web/blog/templates/base.html | 88 | ||||
| -rw-r--r-- | mod/web/blog/templates/index.html | 16 | ||||
| -rw-r--r-- | mod/web/blog/templates/post.html | 14 | ||||
| -rw-r--r-- | mod/web/resistors/default.nix | 12 | ||||
| -rw-r--r-- | mod/web/resistors/index.html | 339 | ||||
| -rw-r--r-- | mod/web/resistors/styles.css | 127 |
15 files changed, 0 insertions, 818 deletions
diff --git a/mod/web/blog/.gitignore b/mod/web/blog/.gitignore deleted file mode 100644 index decc3f8..0000000 --- a/mod/web/blog/.gitignore +++ /dev/null @@ -1,2 +0,0 @@ -public/ -nohup.out diff --git a/mod/web/blog/config.toml b/mod/web/blog/config.toml deleted file mode 100644 index 69c389b..0000000 --- a/mod/web/blog/config.toml +++ /dev/null @@ -1,8 +0,0 @@ -base_url = "https://4kb.net" -build_search_index = false -compile_sass = false -generate_feeds = true -minify_html = true - -[markdown] -highlight_code = false diff --git a/mod/web/blog/content/posts/_index.md b/mod/web/blog/content/posts/_index.md deleted file mode 100644 index 9efc62e..0000000 --- a/mod/web/blog/content/posts/_index.md +++ /dev/null @@ -1,6 +0,0 @@ -+++ -title = "Posts" -sort_by = "date" -page_template = "post.html" -redirect_to="/" -+++ diff --git a/mod/web/blog/content/posts/deterministic-hostnames.md b/mod/web/blog/content/posts/deterministic-hostnames.md deleted file mode 100644 index 43dc7d8..0000000 --- a/mod/web/blog/content/posts/deterministic-hostnames.md +++ /dev/null @@ -1,80 +0,0 @@ ---- -title: "Deterministic and unique network hostnames" -date: "2024-11-10" ---- - -As part of building out a Kubernetes cluster, I wanted to build and distribute a -single OS image to create stateless worker nodes. Using network booting, and -some clever tricks to differentiate nodes, we can create a scaleable and -efficient farm of workers for a cluster that don't even need disks. - -The idea came from a plan to build a cluster using the -[compute blade](https://computeblade.com/), and a few Raspberry Pi SBCs I -already own. Running the cluster from an SD card is not recommended due to the -not-so-great reliability of the flash used by most manufacturers, so I wanted to -try PXE booting each Pi to save money rather than purchasing an SSD for each -one. The compute blades do support an NVMe disk, but I plan to use those for a -storage cluster later, so they need to remain empty. - -## Base image - -Alpine Linux has been my preferred server OS for a long time. It provides a very -lightweight base system, and bundles an excellent bootstrapping system, -[apkovl](https://wiki.alpinelinux.org/wiki/Alpine_local_backup), that allows the -user to save a set of customisations to an system as an overlay to a stock -Alpine live image. In other words, we can create our image once, save the -changes as an `apkovl.tar.gz` file, and apply the same changes to a base system -on boot. This file can even be provided as a -[kernel parameter](https://wiki.alpinelinux.org/wiki/PXE_boot#Guide_to_options) -and will be fetched from a remote webserver automatically! - -Since the image and configuration will be shipped to the node via the network, -an added benefit of using Alpine is its tiny space consumption. I'm not using -enough nodes for this to really matter, but it's a cool optimization regardless. - -## Differentiating the nodes - -One of the main goals of this project is that there should be no persistent -storage required outside the boot image itself. Since every node will download -and generate the same root file-system on startup, the first problem that arises -is how the nodes will identify themselves both on the network and the cluster, -given that it's not possible to name them ahead of time. In other words, any -given node has to generate a unique hostname that won't collide with other -workers, and that will be the same each time that node boots. - -Since these nodes will not have a predefined name, we have to rely on -characteristics of the hardware to differentiate each one. The hardware MAC -address is perfect for this, since it's unique to to each node and will not be -wiped away after the node reboots. On a system like Linux that exposes its -hardware through a _sysfs_, we can find a file containing the address at -`/sys/class/net/eth0/address`. I don't really like the idea of attaching the -literal MAC address of the node to its network hostname, since it's a security -risk, and a bit too verbose. Instead, we can transform it into something safer -using a `sha1sum`, which is already present on our Alpine base system: - -```console -sha1sum /sys/class/net/eth0/address | head -c 6 | awk '{print "worker-" $0}' -``` - -### Applying the new name - -Ideally, the node should apply its generated hostname before reaching out for an -address over DHCP or joining the cluster. We can make sure it happens before any -traffic is sent out by adding a `pre-up` command to the right interface in -`/etc/network/interfaces`: - -``` - -... - -auto eth0 -iface eth0 inet dhcp - pre-up sha1sum /sys/class/net/eth0/address | head -c 6 | awk '{print "worker-" $0}' > /etc/hostname - -... -``` - -The VM I tested with looks outputs `worker-e2fae8`. Pretty clean result, and if -you want to know the physical node that maps to each hostname, you can take note -of the MAC address beforehand and generate the same hash on another computer to -match them up. diff --git a/mod/web/blog/content/posts/nohup.md b/mod/web/blog/content/posts/nohup.md deleted file mode 100644 index 64f7983..0000000 --- a/mod/web/blog/content/posts/nohup.md +++ /dev/null @@ -1,26 +0,0 @@ ---- -title: "Spawning background processes" -date: "2024-11-17" ---- - -Working in a terminal, -I often pair my editor with a background process watching files. -Before reaching for terminal multiplexers, -see if you can get away with simple tty job control. -Spawn the background process, -still attached to the terminal instance: - -``` -program args & -``` - -Also redirect its output to a file, -for when the process writes to the tty from the background: - -``` -nohup program args & -``` - -Extra reading: - -- <https://jvns.ca/blog/2024/07/03/reasons-to-use-job-control/> diff --git a/mod/web/blog/content/posts/stateless-compute-networks.md b/mod/web/blog/content/posts/stateless-compute-networks.md deleted file mode 100644 index bac9e5d..0000000 --- a/mod/web/blog/content/posts/stateless-compute-networks.md +++ /dev/null @@ -1,41 +0,0 @@ ---- -title: "On stateless compute networks" -date: "2024-11-10" -draft: true ---- - -On the topic of distributed systems and clustering, -I am quite invested in the idea of compute nodes that rely entirely on the network for configuration. -Arbitrary nodes can join a pre-existing cluster, -offering their CPU time and memory for computation without relying on any pre-existing configuration on the node itself. -In other words, any computer could pick up work, -only needing power and a network connection to the cluster. - -Perhaps this eventually leads into a "self-healing" cluster where only one node is manually bootstrapped, -which then serves a _configuration endpoint_ for other stateless nodes to reach out to for their instructions, -which they will then also serve once they are themselves ready. - -Early revisions of these notes mention Kubernetes, -but I am also trying to achieve similar results with NixOS on a custom project. -In any case, these are my ever-updating notes towards a general implementation of a stateless distributed systems architecture. - -## Self healing cluster - -Assuming control of an external DHCP server, -a self healing Kubernetes cluster would be feasible, -with the PXE boot artifacts supplied by the cluster itself. -That is, as long as one node is running the pod hosting the artifacts on a given endpoint, -other nodes can boot those artifacts and join the cluster, -thereby being able to host the artifacts as well. - -## Configuration endpoint - -The nodes shouldn't require a disk installed to be able to join the network. -Rather, the lofty goal of zero-configuration compute nodes passes the job of node initialization to the supporting network. -This is accomplished with PXE boot instructions supplied over DHCP. - -I delegate the following tasks to a single node in the subnet: - -- Gateway: Optional outbound connections if required -- DHCP server: Cluster IPAM -- TFTP and HTTP server: Serves iPXE firmware and kernel/initrd artifacts diff --git a/mod/web/blog/content/posts/vim-compilers.md b/mod/web/blog/content/posts/vim-compilers.md deleted file mode 100644 index f735228..0000000 --- a/mod/web/blog/content/posts/vim-compilers.md +++ /dev/null @@ -1,20 +0,0 @@ ---- -title: "Neovim's built-in compilers" -date: "2025-01-17" ---- - -Today I learned that neovim's `:make` comes with many -[backends](https://neovim.io/doc/user/quickfix.html#_6.-selecting-a-compiler) -already configured. -This works for checking c/cpp and python files, among other, but I was -most interested to see [Typst] and [Pandoc] listed as well. - -I was looking to add this functionality with a plugin or implementing it -manually, -where a document can be compiled on the fly from the editor. -After setting `:compiler pandoc`, -generating a pdf is done with `:make pdf`, -with other pandoc options just appended afterwards if needed. - -[typst]: https://typst.app -[pandoc]: https://github.com/jgm/pandoc diff --git a/mod/web/blog/default.nix b/mod/web/blog/default.nix deleted file mode 100644 index 1f91a68..0000000 --- a/mod/web/blog/default.nix +++ /dev/null @@ -1,30 +0,0 @@ -{ pkgs, depot, ... }: -let - inherit (pkgs) - symlinkJoin - ; - - posts = pkgs.stdenvNoCC.mkDerivation { - pname = "4kb.net"; - version = "1.0"; - src = ./.; - - nativeBuildInputs = with pkgs; [ - zola - ]; - - buildPhase = "zola build"; - installPhase = '' - mkdir -p $out - cp -r public/* $out/ - ''; - }; - -in -symlinkJoin { - name = "site"; - paths = [ - posts - depot.misc.cv - ]; -} diff --git a/mod/web/blog/templates/404.html b/mod/web/blog/templates/404.html deleted file mode 100644 index a4669df..0000000 --- a/mod/web/blog/templates/404.html +++ /dev/null @@ -1,9 +0,0 @@ -{% extends "base.html" %} - -{% block content %} -<head> - <title>Error 404!</title> -</head> - -404! -{% endblock content %} diff --git a/mod/web/blog/templates/base.html b/mod/web/blog/templates/base.html deleted file mode 100644 index 5a91df5..0000000 --- a/mod/web/blog/templates/base.html +++ /dev/null @@ -1,88 +0,0 @@ -<!doctype html> -<html lang="en"> - <head> - <meta charset="utf-8" /> - <meta name="viewport" content="width=device-width, initial-scale=1.0" /> - <title>{% block title %}4kb.net{% endblock title %}</title> - </head> - <style> - :root { - --bg: #181616; - --fg: #c5c9c5; - --link: #76946a; - --linkhover: #98bb6c; - } - - html { - scroll-behavior: smooth; - color-scheme: dark; - } - - body { - font-family: serif; - padding: 0 0.75em; - max-width: 42em; - margin: auto; - background: var(--bg); - color: var(--fg); - } - - p { - line-height: 1.3em; - } - - th, - td { - padding: 0.2em 0.4em; - border: thin solid; - } - - table { - border: thin solid; - border-collapse: collapse; - } - - a, - a:link { - color: var(--link); - } - - a:hover { - color: var(--linkhover); - } - - article img { - display: block; - margin: 0 auto; - max-width: 80%; - height: auto; - object-fit: contain; - } - - pre { - padding: 1em; - overflow-x: scroll; - } - </style> - <body> - <header - style=" - margin: 3em 0 3em 0; - display: flex; - gap: 8px; - flex-direction: column; - font-family: monospace; - " - > - <span - >Kleidi Bujari <<a href="mailto:mail@4kb.net">mail@4kb.net</a>></span - > - <nav style="display: flex; gap: 8px"> - <span><a href="/">4kb.net</a> |</span> - <a target="_blank" href="https://github.com/kbujari">git</a> - <a href="/atom.xml">rss</a> - </nav> - </header> - <main>{% block content %} {% endblock %}</main> - </body> -</html> diff --git a/mod/web/blog/templates/index.html b/mod/web/blog/templates/index.html deleted file mode 100644 index 6e8a2af..0000000 --- a/mod/web/blog/templates/index.html +++ /dev/null @@ -1,16 +0,0 @@ -{% extends "base.html" %} {% block content %} - -<div> - {% set section = get_section(path="posts/_index.md") %} - - <ul style="list-style: none; padding-left: 0"> - {% for page in section.pages %} - <li style="display: flex; gap: 1em; margin-bottom: 0.3em"> - <span sty>{{ page.date }}</span> - <a href="{{ page.permalink | safe }}">{{ page.title }}</a> - </li> - {% endfor %} - </ul> - - {% endblock content %} -</div> diff --git a/mod/web/blog/templates/post.html b/mod/web/blog/templates/post.html deleted file mode 100644 index b819520..0000000 --- a/mod/web/blog/templates/post.html +++ /dev/null @@ -1,14 +0,0 @@ -{% extends "base.html" %} - -{% block title%} - {{ page.title }} - {{ super() }} -{% endblock title %} - -{% block content %} - -<h1 style="text-align: center">{{ page.title }}</h1> -<article> - {{ page.content | safe }} -</article> - -{% endblock content %} diff --git a/mod/web/resistors/default.nix b/mod/web/resistors/default.nix deleted file mode 100644 index 5fca68b..0000000 --- a/mod/web/resistors/default.nix +++ /dev/null @@ -1,12 +0,0 @@ -{ pkgs, ... }: - -pkgs.stdenvNoCC.mkDerivation { - pname = "resistors"; - version = "0.0"; - src = ./.; - - buildInputs = [ pkgs.nodePackages.prettier ]; - - phases = [ "installPhase" ]; - installPhase = "mkdir -p $out; cp -r $src/*.{css,html} $out/"; -} diff --git a/mod/web/resistors/index.html b/mod/web/resistors/index.html deleted file mode 100644 index 0683f49..0000000 --- a/mod/web/resistors/index.html +++ /dev/null @@ -1,339 +0,0 @@ -<!doctype html> -<head> - <meta charset="utf-8" /> - <title>rs-calc</title> - <link rel="stylesheet" href="styles.css" /> - <meta name="viewport" content="initial-scale=1.0" /> -</head> - -<body> - <h1>rs-calc</h1> - - <input id="resistor-query" placeholder="e.g. 3.3K" /> - <label class="resistor-query-label" for="resistor-query">Ω</label> - - <div id="resistor-result" style="display: none"> - <h2>four bands</h2> - <div class="resistor-diagram resistor-diagram-4"> - <div id="resistor-stripe-4-1" class="resistor-stripe"></div> - <div id="resistor-stripe-4-2" class="resistor-stripe"></div> - <div id="resistor-stripe-4-3" class="resistor-stripe"></div> - <div id="resistor-stripe-4-4" class="resistor-stripe"> - <br /> - </div> - <div - class="resistor-stripe-tolerance resistor-stripe" - style="color: #000; background-color: #cfb53b" - > - gold<br />±5% - </div> - </div> - <h2>five bands</h2> - <div class="resistor-diagram resistor-diagram-5"> - <div id="resistor-stripe-5-1" class="resistor-stripe"></div> - <div id="resistor-stripe-5-2" class="resistor-stripe"></div> - <div id="resistor-stripe-5-3" class="resistor-stripe"></div> - <div id="resistor-stripe-5-4" class="resistor-stripe"></div> - <div - class="resistor-stripe-tolerance resistor-stripe" - style="color: #fff; background-color: #964b00" - > - brown<br />±1% - </div> - </div> - <h2>surface mount</h2> - <div id="resistor-smt-3" class="resistor-smt"></div> - </div> - - <footer> - <p> - forked from - <a href="https://github.com/joewalnes/resisto.rs/" target="_blank">this</a - >, with removed analytics, cleaned up code. - <a href="https://github.com/kleidib" target="_blank">my github</a> - </p> - </footer> -</body> - -<script> - // Resistor calculator. - // -Joe Walnes - // See resistors-test.html - - var resistors = {}; - - // These hex codes came from - // http://en.wikipedia.org/wiki/Electronic_color_code - resistors.digitsToColors = { - "-2": { hex: "#c0c0c0", label: "#000", name: "silver", multiplier: "0.01" }, - "-1": { hex: "#cfb53b", label: "#000", name: "gold", multiplier: "0.1" }, - 0: { hex: "#000000", label: "#fff", name: "black", figure: "0" }, - 1: { - hex: "#964b00", - label: "#fff", - name: "brown", - figure: "1", - multiplier: "10", - }, - 2: { - hex: "#ff0000", - label: "#fff", - name: "red", - figure: "2", - multiplier: "100", - }, - 3: { - hex: "#ffa500", - label: "#000", - name: "orange", - figure: "3", - multiplier: "1K", - }, - 4: { - hex: "#ffff00", - label: "#000", - name: "yellow", - figure: "4", - multiplier: "10K", - }, - 5: { - hex: "#9acd32", - label: "#000", - name: "green", - figure: "5", - multiplier: "100K", - }, - 6: { - hex: "#6495ed", - label: "#000", - name: "blue", - figure: "6", - multiplier: "1M", - }, - 7: { - hex: "#ee82ee", - label: "#000", - name: "purple", - figure: "7", - multiplier: "10M", - }, - 8: { - hex: "#a0a0a0", - label: "#000", - name: "gray", - figure: "8", - multiplier: "100M", - }, - 9: { - hex: "#ffffff", - label: "#000", - name: "white", - figure: "9", - multiplier: "1000M", - }, - }; - - resistors.query = function (input) { - input = input - .replace(/ +?/g, "") - .replace(/ohm[s]?/, "") - .replace(/\u2126/, "") - .replace(/\.$/, ""); - - var value = this.parseValue(input); - - if (value !== null) { - value = this.roundToSignificantPlaces(value, 3); - - if ((value <= 99900000000 && value >= 1) || value === 0) { - var colors5 = this.numberTo5ColorDigits(value); - var colors4 = this.numberTo4ColorDigits(value); - var smt3 = value < 10 ? colors4[0].toString() : colors4.join(""); - var self = this; - - return { - value: value, - smt3: smt3, - //smt4: smt4, - //smtEia96: smtEia96, - formatted: this.formatValue(value), - colors5: colors5.map(function (d) { - return self.digitsToColors[d]; - }), - colors4: colors4.map(function (d) { - return self.digitsToColors[d]; - }), - }; - } - } - - return null; - }; - - /** - * Given ohm rating as string (e.g. 3.2m or 3M2), return - * integer value (e.g. 3200000). - */ - resistors.parseValue = function (input) { - var multiplier = 1; - var match; - - if ((match = input.match(/^(\d+)(\.(\d+))?([km])?$/i))) { - // e.g. 123, 1.23, 1M, 1.23M - var unit = match[4]; - if (unit) { - if (unit == "k" || unit == "K") { - multiplier = 1000; - } - if (unit == "m" || unit == "M") { - multiplier = 1000000; - } - } - - return (match[1] + "." + (match[3] || 0)) * multiplier; - } else if ((match = input.match(/^(\d+)([km])(\d+)$/i))) { - // e.g. 12K3 - var unit = match[2]; - if (unit) { - if (unit == "k" || unit == "K") { - multiplier = 1000; - } - if (unit == "m" || unit == "M") { - multiplier = 1000000; - } - } - return (match[1] + "." + (match[3] || 0)) * multiplier; - } else { - return null; - } - }; - - /** - * Round a value to significant places. - * e.g. (123456789, 3) -> 123000000) - * (0.0045678, 3) -> 0.00457) - */ - resistors.roundToSignificantPlaces = function (value, significant) { - if (!value) { - return 0; - } - var nearest = Math.pow( - 10, - Math.floor(Math.log(Math.abs(value)) / Math.log(10)) - (significant - 1), - ); - return Math.round(value / nearest) * nearest; - }; - - /** - * Given ohm rating as integer (e.g. 470000), return - * array of color digits (e.g. 4, 7, 0, 3). See digitsTo_Colors. - */ - resistors.numberTo5ColorDigits = function (value) { - if (!value) { - return [0, 0, 0, 0]; // Special case - } - - var precision = 5; - var digits = ( - Math.floor(value * 100 * Math.pow(10, precision)) / - Math.pow(10, precision) - ).toString(); - function getDigit(digits, i) { - var d = parseInt(digits[i]); - return isNaN(d) ? 0 : d; - } - return [ - getDigit(digits, 0), - getDigit(digits, 1), - getDigit(digits, 2), - digits.length - 5, - ]; - }; - - /** - * Given ohm rating as integer (e.g. 470000), return - * array of color digits (e.g. 4, 7, 0, 3). See digitsTo_Colors. - */ - resistors.numberTo4ColorDigits = function (value) { - if (!value) { - return [0, 0, 0]; // Special case - } - - var precision = 5; - var digits = ( - Math.floor(value * 100 * Math.pow(10, precision)) / - Math.pow(10, precision) - ).toString(); - function getDigit(digits, i) { - var d = parseInt(digits[i]); - return isNaN(d) ? 0 : d; - } - return [getDigit(digits, 0), getDigit(digits, 1), digits.length - 4]; - }; - - /** - * Given a numeric value, format it like '3.2M' etc. - */ - resistors.formatValue = function (value) { - if (value >= 1000000) { - return value / 1000000 + "M"; - } else if (value >= 1000) { - return value / 1000 + "K"; - } else { - return value.toString(); - } - }; -</script> -<script> - var queryEl = document.getElementById("resistor-query"), - resultEl = document.getElementById("resistor-result"); - - function showStripes(colors, prefix) { - for (var i = 0; i < colors.length; i++) { - var color = colors[i]; - var stripeEl = document.getElementById( - "resistor-stripe-" + prefix + "-" + (i + 1), - ); - stripeEl.style.backgroundColor = color.hex; - stripeEl.style.color = color.label; - var text = color.name + "<br>"; - - if (i == colors.length - 1) { - if (color.multiplier !== undefined) { - text += "×" + color.multiplier; - } else { - text += " "; - } - } else { - text += color.figure; - } - stripeEl.innerHTML = text; - } - } - - queryEl.onchange = queryEl.onkeyup = function () { - location.hash = encodeURIComponent(queryEl.value); - var result = resistors.query(queryEl.value); - - if (result) { - resultEl.style.display = "block"; - showStripes(result.colors4, "4"); - showStripes(result.colors5, "5"); - document.getElementById("resistor-smt-3").innerHTML = result.smt3; - } else { - resultEl.style.display = "none"; - } - }; - - if (location.hash) { - queryEl.value = decodeURIComponent(location.hash.substring(1)); - queryEl.onchange(); - } - - window.onhashchange = function () { - queryEl.value = decodeURIComponent(location.hash.substring(1)); - queryEl.onchange(); - }; - - queryEl.focus(); -</script> diff --git a/mod/web/resistors/styles.css b/mod/web/resistors/styles.css deleted file mode 100644 index e2823e4..0000000 --- a/mod/web/resistors/styles.css +++ /dev/null @@ -1,127 +0,0 @@ -* { - /*font-family: 'firacode';*/ - text-rendering: optimizeLegibility; -} - -body { - margin: 10px 20px; - color: #cccccc; - background: #252525; - background-attachment: fixed !important; -} - -h1 { - font-weight: normal; - font-size: 50px; - margin: -10px 0 10px 0; -} - -h2 { - font-weight: normal; - font-size: 15px; -} - -strong { - font-weight: normal; -} - -footer { - position: absolute; - font-size: 12px; - color: #555; - bottom: 0; - left: 0; - right: 0; - padding: 20px; -} - -a { - text-decoration: none; -} - -a:hover { - text-decoration: underline; -} - -footer a { - color: #775; -} - -#resistor-query { - font-size: 20px; - border: 1px solid #999; - color: #fff; - background-color: #444; - outline: none; - width: 180px; -} - -.resistor-stripe { - width: 80px; - height: 150px; - display: inline-block; - padding: 4px 4px; -} - -.resistor-smt { - display: inline-block; - padding: 0px 10px; - font-size: 35px; - background-color: #000; - border-left: 15px solid silver; - border-right: 15px solid silver; - border-top: 1px solid silver; - border-bottom: 1px solid silver; - margin-right: 10px; -} - -@media print, screen and (max-width: 520px) { - .resistor-stripe { - width: 55px; - font-size: 80%; - height: 100px; - } - .resistor-smt { - font-size: 25px; - border-left: 12px solid silver; - border-right: 12px solid silver; - } -} - -@media print, screen and (max-width: 410px) { - .resistor-stripe { - width: 35px; - font-size: 55%; - height: 70px; - } - .resistor-smt { - font-size: 18px; - border-left: 8px solid silver; - border-right: 8px solid silver; - } -} - -@media print, screen and (max-width: 300px) { - .resistor-stripe { - width: 25px; - font-size: 50%; - height: 60px; - padding: 2px; - } - .resistor-smt { - font-size: 13px; - border-left: 6px solid silver; - border-right: 6px solid silver; - padding: 2px 4px; - } -} - -@media print, screen and (max-height: 660px) { - .resistor-stripe { - height: 55px; - } - footer { - position: inherit; - padding: 10px 0; - } -} |
