/* ========================================================================== Fonts ========================================================================== */ @import url('https://fonts.cdnfonts.com/css/jetbrains-mono-2'); /* ========================================================================== Berkeley Mono™ © Copyright 2025, U.S. Graphics, LLC. Licensed under SKU LT-02 to Eric Taylor (Taylor IT Solutions LLC) https://usgraphics.com/products/berkeley-mono ========================================================================== */ @font-face { font-family: 'Berkeley Mono'; src: url('http://erictaylor.me/files/font/BerkeleyMono-Regular.woff2') format('woff2'), url('http://erictaylor.me/files/font/BerkeleyMono-Regular.woff') format('woff'); font-weight: normal; font-style: normal; } @font-face { font-family: 'Berkeley Mono'; src: url('http://erictaylor.me/files/font/BerkeleyMono-Bold.woff2') format('woff2'), url('http://erictaylor.me/files/font/BerkeleyMono-Bold.woff') format('woff'); font-weight: bold; font-style: normal; } @font-face { font-family: 'Berkeley Mono'; src: url('http://erictaylor.me/files/font/BerkeleyMono-Italic.woff2') format('woff2'), url('http://erictaylor.me/files/font/BerkeleyMono-Italic.woff') format('woff'); font-weight: normal; font-style: italic; } /* ========================================================================== Base & Variables ========================================================================== */ @font-face { font-family: 'Berkeley Mono'; src: url('http://erictaylor.me/files/font/BerkeleyMono-BoldItalic.woff2') format('woff2'), url('http://erictaylor.me/files/font/BerkeleyMono-BoldItalic.woff') format('woff'); font-weight: bold; font-style: italic; } :root { --font-family: "Berkeley Mono", "JetBrains Mono", "Cascadia Code", "Fira Code", "Source Code Pro", Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace; --line-height: 1.20rem; --border-thickness: 2px; --text-color: #000; --text-color-alt: #666; --background-color: #fff; --background-color-alt: #eee; --font-weight-normal: 500; --font-weight-medium: 600; --font-weight-bold: 800; font-family: var(--font-family); font-optical-sizing: auto; font-weight: var(--font-weight-normal); font-style: normal; font-variant-numeric: tabular-nums lining-nums; font-size: 16px; } @media (prefers-color-scheme: dark) { :root { --text-color: #fff; --text-color-alt: #aaa; --background-color: #000; --background-color-alt: #222; } } [data-theme="dark"] { --text-color: #fff; --text-color-alt: #aaa; --background-color: #000; --background-color-alt: #222; } [data-theme="light"] { --text-color: #000; --text-color-alt: #666; --background-color: #fff; --background-color-alt: #eee; } * { box-sizing: border-box; } *+* { margin-top: var(--line-height); } .theme-toggle { cursor: pointer; display: inline-flex; align-items: center; vertical-align: middle; width: 1.5ch; height: 1.5ch; margin: 0 0 0 0; } .theme-toggle svg { width: 100%; height: 100%; fill: var(--text-color); } .theme-toggle:hover svg { fill: var(--text-color-alt); } /* ========================================================================== Layout & Grid ========================================================================== */ html { display: flex; width: 100%; margin: 0; padding: 0; flex-direction: column; align-items: center; background: var(--background-color); color: var(--text-color); } body { position: relative; width: 100%; margin: 0; padding: var(--line-height) 2ch; max-width: calc(min(80ch, round(down, 100%, 1ch))); line-height: var(--line-height); overflow-x: hidden; } @media screen and (max-width: 480px) { :root { font-size: 14px; } body { padding: var(--line-height) 1ch; } } @media print { .page, .page-break { break-after: page; } } /* Override universal margins for grid */ .grid { margin-top: 0; } .grid>* { margin-top: 0; } /* Fix grid spacing */ .grid { --grid-cells: 0; display: flex; gap: 1ch; width: calc(round(down, 100%, (1ch * var(--grid-cells)) - (1ch * var(--grid-cells) - 1))); margin-bottom: var(--line-height); } .grid>*, .grid>input { flex: 0 0 calc(round(down, (100% - (1ch * (var(--grid-cells) - 1))) / var(--grid-cells), 1ch)); } .grid:has(> :last-child:nth-child(1)) { --grid-cells: 1; } .grid:has(> :last-child:nth-child(2)) { --grid-cells: 2; } .grid:has(> :last-child:nth-child(3)) { --grid-cells: 3; } .grid:has(> :last-child:nth-child(4)) { --grid-cells: 4; } .grid:has(> :last-child:nth-child(5)) { --grid-cells: 5; } .grid:has(> :last-child:nth-child(6)) { --grid-cells: 6; } .grid:has(> :last-child:nth-child(7)) { --grid-cells: 7; } .grid:has(> :last-child:nth-child(8)) { --grid-cells: 8; } .grid:has(> :last-child:nth-child(9)) { --grid-cells: 9; } /* ========================================================================== Typography ========================================================================== */ h1, h2, h3, h4, h5, h6 { font-weight: var(--font-weight-bold); margin: calc(var(--line-height) * 2) 0 var(--line-height); line-height: var(--line-height); } h1 { font-size: 2rem; line-height: calc(2 * var(--line-height)); margin-bottom: calc(var(--line-height) * 2); text-transform: uppercase; } h2 { font-size: 1rem; text-transform: uppercase; } .header-anchor { opacity: 0; text-decoration: none; margin-left: 1ch; font-weight: normal; } h1:hover .header-anchor, h2:hover .header-anchor, h3:hover .header-anchor, h4:hover .header-anchor, h5:hover .header-anchor, h6:hover .header-anchor { opacity: 1; } hr { position: relative; display: block; height: var(--line-height); margin: calc(var(--line-height) * 1.5) 0; border: none; color: var(--text-color); } hr:after { display: block; content: ""; position: absolute; top: calc(var(--line-height) / 2 - var(--border-thickness)); left: 0; width: 100%; border-top: calc(var(--border-thickness) * 3) double var(--text-color); height: 0; } hr.thin { position: relative; height: var(--line-height); margin: var(--line-height) 0; } hr.thin:after { display: block; content: ""; position: absolute; top: calc(var(--line-height) / 2); left: 0; width: 100%; border-top: var(--border-thickness) solid var(--text-color-alt); height: 0; } p { word-break: break-word; word-wrap: break-word; hyphens: auto; margin-bottom: var(--line-height); } strong { font-weight: var(--font-weight-bold); } em { font-style: italic; } a { text-decoration-thickness: var(--border-thickness); } a:link, a:visited { color: var(--text-color); } sub { position: relative; display: inline-block; margin: 0; vertical-align: sub; line-height: 0; width: calc(1ch / 0.75); font-size: .75rem; } /* ========================================================================== Components ========================================================================== */ /* Tables */ table { position: relative; top: calc(var(--line-height) / 2); width: calc(round(down, 100%, 1ch)); border-collapse: collapse; margin: 0 0 calc(var(--line-height) * 2); } th, td { border: var(--border-thickness) solid var(--text-color); padding: calc((var(--line-height) / 2)) calc(1ch - var(--border-thickness) / 2) calc((var(--line-height) / 2) - (var(--border-thickness))); line-height: var(--line-height); vertical-align: top; text-align: left; } table tbody tr:first-child>* { padding-top: calc((var(--line-height) / 2) - var(--border-thickness)); } th { font-weight: var(--font-weight-bold); } /* Forms */ input, button, textarea { border: var(--border-thickness) solid var(--text-color); padding: calc(var(--line-height) / 2 - var(--border-thickness)) calc(1ch - var(--border-thickness)); margin: 0; font: inherit; font-weight: inherit; height: calc(var(--line-height) * 2); width: auto; overflow: visible; background: var(--background-color); color: var(--text-color); line-height: normal; -webkit-font-smoothing: inherit; -moz-osx-font-smoothing: inherit; -webkit-appearance: none; } input[type=checkbox], input[type=radio] { display: inline-grid; place-content: center; vertical-align: top; width: 2ch; height: var(--line-height); cursor: pointer; } input[type=checkbox]:checked:before, input[type=radio]:checked:before { content: ""; width: 1ch; height: calc(var(--line-height) / 2); background: var(--text-color); } input[type=radio], input[type=radio]:before { border-radius: 100%; } button:focus, input:focus { --border-thickness: 3px; outline: none; } input { width: calc(round(down, 100%, 1ch)); } ::placeholder { color: var(--text-color-alt); opacity: 1; } ::-ms-input-placeholder { color: var(--text-color-alt); } button::-moz-focus-inner { padding: 0; border: 0; } button { text-transform: uppercase; font-weight: var(--font-weight-medium); cursor: pointer; } button:hover { background: var(--background-color-alt); } button:active { transform: translate(2px, 2px); } label { display: block; width: calc(round(down, 100%, 1ch)); height: auto; line-height: var(--line-height); font-weight: var(--font-weight-medium); margin: 0; } label input { width: 100%; } .tree, .tree ul { position: relative; padding-left: 0; list-style-type: none; line-height: var(--line-height); } .tree ul { margin: 0; } .tree ul li { position: relative; padding-left: 1.5ch; margin-left: calc(1.5ch - var(--border-thickness)); border-left: var(--border-thickness) solid var(--text-color); } .tree ul li:before { position: absolute; display: block; top: calc(var(--line-height) / 2); left: 0; content: ""; width: 1ch; border-bottom: var(--border-thickness) solid var(--text-color); } .tree ul li:last-child { border-left: none; padding-left: calc(1.5ch + var(--border-thickness)); } .tree ul li:last-child:after { position: absolute; display: block; top: 0; left: 0; content: ""; height: calc(var(--line-height) / 2); border-left: var(--border-thickness) solid var(--text-color); } /* Code Blocks */ pre { white-space: pre; overflow-x: auto; margin: var(--line-height) 0; overflow-y: hidden; } pre, code { font-family: var(--font-family); } code { font-weight: var(--font-weight-medium); } code:not(pre code) { background: var(--background-color-alt); padding: 0 0.5ch; border-radius: 2px; font-size: 0.95em; white-space: nowrap; } pre code { display: block; padding: calc(var(--line-height) / 2) 2ch; background: var(--background-color-alt); border-radius: 2px; overflow-x: auto; line-height: var(--line-height); margin: 0; } pre code::-webkit-scrollbar { height: calc(var(--line-height) / 2); } pre code::-webkit-scrollbar-thumb { background: var(--text-color-alt); border-radius: 2px; } pre code::-webkit-scrollbar-track { background: transparent; } /* Lists */ ul, ol { padding: 0; margin: 0 0 var(--line-height); } ul { list-style-type: square; padding: 0 0 0 2ch; } ol { list-style-type: none; counter-reset: item; padding: 0; } ol ul, ol ol, ul ol, ul ul { padding: 0 0 0 3ch; margin: 0; } ol li:before { content: counters(item, ".") ". "; counter-increment: item; font-weight: var(--font-weight-medium); } li { margin: 0; padding: 0; } li::marker { line-height: 0; } /* Blockquotes */ blockquote { margin: var(--line-height) 3ch; padding-left: 2ch; border-left: var(--border-thickness) solid var(--text-color); color: var(--text-color-alt); } blockquote p { margin: 0; } blockquote+blockquote { margin-top: 0; } /* Details */ details { border: var(--border-thickness) solid var(--text-color); padding: calc(var(--line-height) - var(--border-thickness)) 1ch; margin-bottom: var(--line-height); } summary { font-weight: var(--font-weight-medium); cursor: pointer; } details[open] summary { margin-bottom: var(--line-height); } details ::marker { display: inline-block; content: '▶'; margin: 0; } details[open] ::marker { content: '▼'; } details :last-child { margin-bottom: 0; } /* Media */ img, video { display: block; width: 100%; object-fit: contain; overflow: hidden; } img { font-style: italic; color: var(--text-color-alt); } figure { margin: calc(var(--line-height) * 2) 3ch; overflow-x: auto; overflow-y: hidden; } figcaption { display: block; font-style: italic; margin-top: var(--line-height); } /* ========================================================================== Utilities ========================================================================== */ .width-min { width: 0%; } .width-auto { width: 100%; } .header { margin-bottom: calc(var(--line-height) * 2); } .header h1 { margin: 0; } .header tr td:last-child { text-align: right; } /* ========================================================================== Debug ========================================================================== */ .debug .debug-grid { --color: color-mix(in srgb, var(--text-color) 10%, var(--background-color) 90%); position: absolute; top: 0; left: 0; right: 0; bottom: 0; z-index: -1; background-image: repeating-linear-gradient(var(--color) 0 1px, transparent 1px 100%), repeating-linear-gradient(90deg, var(--color) 0 1px, transparent 1px 100%); background-size: 1ch var(--line-height); margin: 0; } .debug .off-grid { background: rgba(255, 0, 0, 0.1); } .debug-toggle-label { text-align: right; } /* ========================================================================== Miscellaneous ========================================================================== */ /* Product Cards */ .product-card { display: flex; flex-direction: column; } .product-card > *:not(nav) { flex: 1 0 auto; } .product-card nav { display: flex; gap: 1ch; align-items: stretch; margin-top: auto; } .product-card nav a { flex: 1; display: flex; align-items: center; justify-content: center; padding: calc(var(--line-height) / 4) 0; background: var(--background-color-alt); text-decoration: none; min-height: calc(var(--line-height) * 1.5); margin-top: 0; } .product-card nav a:hover { background: var(--text-color); color: var(--background-color); } .product-card { border: var(--border-thickness) solid var(--text-color); padding: calc(var(--line-height) - var(--border-thickness)) 1ch; width: 100%; margin-top: var(--line-height); } .product-card img, .product-card video { margin: 0 -1ch; width: calc(100% + 2ch); max-height: calc(var(--line-height) * 8); object-fit: cover; } .product-card h3 { margin-top: var(--line-height); margin-bottom: 0; font-weight: var(--font-weight-bold); } .product-card p { color: var(--text-color-alt); margin-bottom: var(--line-height); } .product-card table { font-size: 0.9em; margin-bottom: var(--line-height); } /* Override the universal margin for nav elements and their children */ nav, nav + *, nav > *, nav > * + * { margin-top: 0; } /* Also override for nav when it's inside a product-card */ .product-card nav { margin-top: auto; /* This pushes the nav to the bottom while removing the default margin */ } /* Ensure nav children (links/buttons) don't have top margin */ .product-card nav > * { margin-top: 0; } /* Transformations */ .rotate-90 { transform: rotate(90deg); transform-origin: center center; height: 100%; display: flex; align-items: center; justify-content: center; } /* theme-aware images */ .theme-aware-image { filter: none; } [data-theme="dark"] .theme-aware-image:not(.no-invert) { filter: invert(1) hue-rotate(180deg); } /* Optional: Add specific adjustments for certain images if needed */ [data-theme="dark"] .theme-aware-image.adjust-contrast { filter: invert(1) hue-rotate(180deg) contrast(0.8); }