Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
37 changes: 37 additions & 0 deletions app/assets/stylesheets/_base.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
body {
text-wrap: pretty;
}

// Keep the footer below the fold on short pages.
body > main > .container {
min-height: 60vh;
}

// Page titles rendered by the shared page header / article headers.
article > header > h1,
article > header > h2 {
font-weight: 600;
margin: 1rem 0 1.5rem;
}

// Prose links: keep underline (a11y) with a comfortable offset; nav/cards opt out.
a {
text-underline-offset: .15em;
}

ol.breadcrumb {
font-size: .86rem;
padding: .5rem 0;
}

label.required::after {
content: '*';
color: var(--bs-danger);
margin-inline-start: .125rem;
}

// Code, MAC/IP addresses, hex values keep LTR order even in RTL locales.
code, kbd, pre, samp, .text-data {
direction: ltr;
unicode-bidi: embed;
}
44 changes: 44 additions & 0 deletions app/assets/stylesheets/_fonts.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
// Self-hosted IBM Plex. The woff2 files live in public/fonts/ and are copied
// verbatim from the @fontsource packages by `yarn build:fonts`.
//
// Self-hosted rather than fetched from fonts.googleapis.com: the CDN import
// this replaces made every visitor's browser announce itself to Google before
// the page could paint, and it is the same argument that moved the legacy logo
// off a maintainer's personal CDN in d60729a.
//
// Subsets: latin covers English, latin-ext the accented names in the partner
// wall, cyrillic the Russian copy. Chinese falls back to the system stack --
// IBM Plex Sans has no CJK glyphs, and the CJK families that do are megabytes.

$plex-subsets: (
'latin': (U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308,
U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD),
'latin-ext': (U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308,
U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0,
U+2113, U+2C60-2C7F, U+A720-A7FF),
'cyrillic': (U+0301, U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116),
);

@each $subset, $range in $plex-subsets {
@each $weight in (400, 500, 600, 700) {
@font-face {
font-family: 'IBM Plex Sans';
font-style: normal;
font-display: swap;
font-weight: $weight;
src: url('/fonts/ibm-plex-sans-#{$subset}-#{$weight}-normal.woff2') format('woff2');

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Action required

1. Fonts bypass asset pipeline 📘 Rule violation ☼ Reliability

The new @font-face rules reference /fonts/*.woff2 directly, and the fonts are manually committed
under public/ rather than produced or resolved by the configured asset build pipeline. This
violates the required asset-routing mechanism and makes delivery depend on separate
static-file-server behavior.
Agent Prompt
## Issue description
The new font URLs bypass the Rails asset pipeline and refer directly to manually committed files under `public/fonts`.

## Issue Context
Production disables runtime asset compilation, and compliance rule 2 requires application assets to use Rails asset helpers or be produced by the configured CSS/JavaScript build pipeline. Move the font files into a pipeline-managed source location or add a build step that emits them as configured build outputs, then generate resolved URLs from SCSS rather than hardcoding `/fonts`.

## Fix Focus Areas
- app/assets/stylesheets/_fonts.scss[29-40]
- app/assets/stylesheets/application.bootstrap.scss[15-19]
- tools/copy-fonts.mjs[23-60]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools

unicode-range: $range;
}
}

@each $weight in (400, 600) {
@font-face {
font-family: 'IBM Plex Mono';
font-style: normal;
font-display: swap;
font-weight: $weight;
src: url('/fonts/ibm-plex-mono-#{$subset}-#{$weight}-normal.woff2') format('woff2');
unicode-range: $range;
}
}
}
36 changes: 36 additions & 0 deletions app/assets/stylesheets/_utilities.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
.x-small {
font-size: 0.8125rem;
}

.img-zoom:hover {
cursor: zoom-in;
}

.ratio {
overflow: auto;
}

.offcanvas {
--bs-offcanvas-width: 30vw;
min-width: 25rem;
}

// Responsive breakpoint debugger (enabled via body.debug from a fixed IP).
@media (max-width: 575.98px) { body.debug:before { content: 'xs' } }
@media (min-width: 576px) and (max-width: 767.98px) { body.debug:before { content: 'sm' } }
@media (min-width: 768px) and (max-width: 991.98px) { body.debug:before { content: 'md' } }
@media (min-width: 992px) and (max-width: 1199.98px) { body.debug:before { content: 'lg' } }
@media (min-width: 1200px) and (max-width: 1399.98px) { body.debug:before { content: 'xl' } }
@media (min-width: 1400px) { body.debug:before { content: 'xxl' } }
body.debug:before {
color: #4c60d811;
display: block;
font-size: 10rem;
font-variant: all-small-caps;
font-weight: 700;
line-height: 1;
position: fixed;
right: 3rem;
top: 3rem;
z-index: -1;
}
88 changes: 88 additions & 0 deletions app/assets/stylesheets/_variables.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
// Theme: "engineering workbench" — light body, dark ink anchor sections, brand indigo.
// These overrides MUST load after bootstrap/scss/functions and before the main bootstrap import.

// --- Brand palette ---
$indigo: #4c60d8; // brand color (5.3:1 on white — AA for text)
$primary: $indigo;
// Bootstrap emits --bs-blue from $blue, and the pre-relaunch rules in
// pages/_legacy.scss colour headings with var(--bs-blue). Left at Bootstrap's
// default those rules would render #0d6efd -- the same "two blues" split this
// file exists to close, just from the other side.
$blue: $indigo;
$ink: #0f1422; // navbar, hero, stats/CTA bands, footer
$ink-2: #1a2236; // raised surfaces on ink
$accent: #ffb454; // warm amber: Labs, live-dot, highlights; never text-on-white
$success: #33a867; // matches stage-done.svg
$danger: #d6453d;
$warning: #e8a13c;
$info: #3e8ed0;

// --- Neutrals (cool, indigo-tinted) ---
$body-bg: #ffffff;
$body-color: #1c2333;
$body-secondary-color: #5a6377;
$body-tertiary-bg: #f4f6fa;
$border-color: #e3e7f0;

// --- Typography ---
$font-family-sans-serif: 'IBM Plex Sans', system-ui, -apple-system, 'Segoe UI', sans-serif;
$font-family-monospace: 'IBM Plex Mono', ui-monospace, SFMono-Regular, Menlo, monospace;
$font-size-base: 1rem;
$line-height-base: 1.6;
$headings-font-weight: 600; // 700 reserved for hero/display
$display-font-weight: 700;
$h1-font-size: 2.25rem;
$h2-font-size: 1.75rem;
$h3-font-size: 1.375rem;
$code-color: #b23a78;

// --- Spacing (Bootstrap defaults + 6/7 for section rhythm: py-6/py-7) ---
$spacer: 1rem;
$spacers: (
0: 0,
1: $spacer * .25,
2: $spacer * .5,
3: $spacer,
4: $spacer * 1.5,
5: $spacer * 3,
6: $spacer * 4.5,
7: $spacer * 6,
);

// --- Shape ---
$border-radius: .375rem;
$border-radius-sm: .25rem;
$border-radius-lg: .625rem;
$border-radius-xl: 1rem;
$box-shadow-sm: 0 1px 2px rgba(15, 20, 34, .06);
$box-shadow: 0 8px 24px rgba(15, 20, 34, .10);
$card-border-color: $border-color;
$card-cap-bg: transparent;

// --- Links / buttons / focus ---
$link-color: $indigo;
$link-decoration: underline;
$btn-font-weight: 600;
$btn-padding-x: 1.125rem;
$btn-padding-y: .5rem;
$btn-padding-x-lg: 1.5rem;
$btn-padding-y-lg: .75rem;
$focus-ring-color: rgba($indigo, .3);

// --- Components ---
$carousel-transition-duration: .3s; // carried over; the Open Wall slideshow relies on it
$enable-dark-mode: true; // needed for scoped data-bs-theme="dark" sections
$navbar-dark-color: rgba(#fff, .78);
$navbar-dark-hover-color: #fff;
$badge-font-weight: 600;
$table-cell-padding-y: .6rem;

// --- Project status stages (NEQ/R&D/HLP/WIP/MVP/DONE) ---
$stage-colors: (
'neq': #8a93a6,
'rnd': #7a5cd6,
'hlp': #3e8ed0,
'wip': #0fa3a3,
'mvp': #e8a13c,
'done': #33a867,
);
Loading
Loading