From 203ea0c69dd0f7d3ba4d43b972b63260e9930a44 Mon Sep 17 00:00:00 2001 From: AJ Isaacs Date: Sun, 2 Aug 2026 20:57:17 +0000 Subject: [PATCH] style(web): compact CutList typography --- CutList.Web/Components/App.razor | 3 +++ CutList.Web/Components/Layout/NavMenu.razor.css | 2 +- CutList.Web/wwwroot/css/app.css | 14 +++++++------- tests/test_nav_menu_brand_contrast.py | 11 +++++++++++ 4 files changed, 22 insertions(+), 8 deletions(-) diff --git a/CutList.Web/Components/App.razor b/CutList.Web/Components/App.razor index 46e7609..0c07b74 100644 --- a/CutList.Web/Components/App.razor +++ b/CutList.Web/Components/App.razor @@ -6,6 +6,9 @@ + + + diff --git a/CutList.Web/Components/Layout/NavMenu.razor.css b/CutList.Web/Components/Layout/NavMenu.razor.css index 0e70078..4a19eef 100644 --- a/CutList.Web/Components/Layout/NavMenu.razor.css +++ b/CutList.Web/Components/Layout/NavMenu.razor.css @@ -2,7 +2,7 @@ .brand-lockup { display: flex; align-items: center; gap: .75rem; } .brand-mark { align-items: center; background: #2b75a8; border-radius: .45rem; color: #fff; display: flex; font-size: 1rem; height: 2.25rem; justify-content: center; text-decoration: none; transform: rotate(-8deg); width: 2.25rem; } .brand-mark i { transform: rotate(8deg); } -.navbar-brand { color: #17212b; font-family: Georgia, 'Times New Roman', serif; font-size: 1.45rem; font-weight: 700; letter-spacing: -.06em; line-height: .9; text-decoration: none; } +.navbar-brand { color: #17212b; font-family: "IBM Plex Sans", Inter, ui-sans-serif, system-ui, sans-serif; font-size: 1.25rem; font-weight: 700; letter-spacing: -.035em; line-height: .95; text-decoration: none; } .navbar-brand .brand-cut { color: #2b75a8; } .navbar-brand .brand-list { color: #17212b; } .navbar-brand small { color: #60778b; display: block; font-family: Arial, sans-serif; font-size: .48rem; font-weight: 700; letter-spacing: .14em; margin-top: .45rem; } diff --git a/CutList.Web/wwwroot/css/app.css b/CutList.Web/wwwroot/css/app.css index a7e4c70..f853fec 100644 --- a/CutList.Web/wwwroot/css/app.css +++ b/CutList.Web/wwwroot/css/app.css @@ -239,7 +239,7 @@ h1 { --rail: #18242e; } -html, body { background: var(--paper); color: var(--ink); font-family: Inter, ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif; } +html, body { background: var(--paper); color: var(--ink); font-family: "IBM Plex Sans", Inter, ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif; } body { letter-spacing: -.01em; } main { background: var(--paper); box-shadow: none; min-width: 0; } .sidebar { background: var(--rail); border-right: 1px solid #314653; } @@ -248,10 +248,10 @@ main { background: var(--paper); box-shadow: none; min-width: 0; } .workspace-eyebrow, .eyebrow { color: var(--muted); font-size: .68rem; font-weight: 800; letter-spacing: .14em; margin: 0; text-transform: uppercase; } .workspace-status { align-items: center; color: var(--muted); display: flex; font-size: .78rem; font-weight: 650; gap: .45rem; } .status-dot { background: #3d9b78; border-radius: 50%; box-shadow: 0 0 0 3px rgba(61,155,120,.14); height: .45rem; width: .45rem; } -h1, h2, h3, h4, h5, h6 { color: var(--ink); font-family: Georgia, "Times New Roman", serif; font-weight: 700; letter-spacing: -.045em; } -h1 { font-size: clamp(2.25rem, 4vw, 4.1rem); line-height: .98; } -h2 { font-size: clamp(1.6rem, 2.5vw, 2.25rem); } -.job-title { font-size: clamp(1.75rem, 2.5vw, 2.5rem); line-height: 1.1; } +h1, h2, h3, h4, h5, h6 { color: var(--ink); font-family: "IBM Plex Sans", Inter, ui-sans-serif, system-ui, sans-serif; font-weight: 650; letter-spacing: -.025em; } +h1 { font-size: clamp(1.85rem, 3.2vw, 3.15rem); line-height: 1.04; } +h2 { font-size: clamp(1.35rem, 2vw, 1.85rem); line-height: 1.12; } +.job-title { font-size: clamp(1.5rem, 2.1vw, 2.1rem); line-height: 1.12; } a, .btn-link { color: var(--accent-dark); } .btn { border-radius: .35rem; font-size: .85rem; font-weight: 750; letter-spacing: .01em; padding: .65rem 1rem; } .btn-primary { background: var(--accent); border-color: var(--accent); color: #fff; } @@ -279,10 +279,10 @@ a, .btn-link { color: var(--accent-dark); } .overview-actions { display: flex; flex: 0 0 auto; flex-wrap: wrap; gap: .65rem; } .overview-stats { display: grid; gap: 1px; grid-template-columns: repeat(3, minmax(0, 1fr)); margin: 2rem 0; background: var(--line); border: 1px solid var(--line); } .overview-stat { background: var(--paper-bright); color: var(--ink); display: grid; gap: .25rem; padding: 1.4rem 1.5rem; text-decoration: none; } -.overview-stat:hover { background: #edf4f8; color: var(--ink); }.overview-stat-label { color: var(--muted); font-size: .68rem; font-weight: 800; letter-spacing: .1em; text-transform: uppercase; }.overview-stat strong { font-family: Georgia, "Times New Roman", serif; font-size: 2.25rem; letter-spacing: -.06em; line-height: 1; }.overview-stat small { color: var(--muted); font-size: .78rem; } +.overview-stat:hover { background: #edf4f8; color: var(--ink); }.overview-stat-label { color: var(--muted); font-size: .68rem; font-weight: 800; letter-spacing: .1em; text-transform: uppercase; }.overview-stat strong { font-family: "IBM Plex Sans", Inter, ui-sans-serif, system-ui, sans-serif; font-size: 2rem; letter-spacing: -.04em; line-height: 1; }.overview-stat small { color: var(--muted); font-size: .78rem; } .overview-grid { align-items: start; display: grid; gap: 1.5rem; grid-template-columns: minmax(0, 1.25fr) minmax(300px, .75fr); } .overview-recent-jobs { min-width: 0; } -.overview-panel { background: var(--paper-bright); border: 1px solid var(--line); }.overview-panel-heading { align-items: start; display: flex; gap: 1rem; justify-content: space-between; padding: 1.5rem 1.5rem 1.2rem; }.overview-panel-heading h2 { font-size: 1.5rem; margin: .3rem 0 0; }.overview-panel-heading > a { font-size: .78rem; font-weight: 750; text-decoration: none; white-space: nowrap; } +.overview-panel { background: var(--paper-bright); border: 1px solid var(--line); }.overview-panel-heading { align-items: start; display: flex; gap: 1rem; justify-content: space-between; padding: 1.5rem 1.5rem 1.2rem; }.overview-panel-heading h2 { font-size: 1.25rem; margin: .3rem 0 0; }.overview-panel-heading > a { font-size: .78rem; font-weight: 750; text-decoration: none; white-space: nowrap; } .overview-job-list { border-top: 1px solid var(--line); }.overview-job-row { align-items: center; border-bottom: 1px solid var(--line); color: var(--ink); display: grid; gap: .3rem 1rem; grid-template-columns: 7.5rem minmax(9rem, 1fr) minmax(8rem, .85fr) 3.75rem 1rem; padding: 1rem 1.5rem; text-decoration: none; }.overview-job-row:last-child { border-bottom: 0; }.overview-job-row:hover { background: #f2f6f8; color: var(--ink); }.overview-job-id { color: var(--accent-dark); font-size: .75rem; font-weight: 800; letter-spacing: .04em; }.overview-job-name { font-weight: 750; }.overview-job-meta, .overview-job-row time { color: var(--muted); font-size: .78rem; }.overview-job-row time { text-align: right; }.overview-row-arrow, .overview-lock { color: var(--muted); font-size: .85rem; text-align: right; }.overview-lock { color: #9c6a20; } .overview-panel-note { color: var(--muted); font-size: .8rem; line-height: 1.5; margin: -.25rem 1.5rem 1rem; }.overview-stock-list { border-top: 1px solid var(--line); list-style: none; margin: 0; padding: 0; }.overview-stock-list li { align-items: center; border-bottom: 1px solid var(--line); display: grid; gap: .85rem; grid-template-columns: 1.7rem minmax(0, 1fr) auto; padding: 1rem 1.5rem; }.overview-stock-list li:last-child { border-bottom: 0; }.overview-stock-rank { color: #8796a1; font-size: .66rem; font-weight: 800; letter-spacing: .08em; }.overview-stock-list strong, .overview-stock-list span { display: block; }.overview-stock-list strong { font-size: .88rem; }.overview-stock-list div > span { color: var(--muted); font-size: .76rem; margin-top: .15rem; }.overview-stock-count { color: var(--accent-dark); font-size: 1.2rem; font-weight: 800; text-align: right; }.overview-stock-count small { color: var(--muted); display: block; font-size: .66rem; font-weight: 700; text-transform: uppercase; }.overview-empty { align-items: center; color: var(--muted); display: flex; flex-direction: column; gap: 1rem; justify-content: center; min-height: 265px; padding: 2rem; text-align: center; }.overview-empty .bi { color: #9baab4; font-size: 1.8rem; }.overview-empty p { line-height: 1.5; margin: 0; max-width: 20rem; }.overview-empty-compact { min-height: 190px; } diff --git a/tests/test_nav_menu_brand_contrast.py b/tests/test_nav_menu_brand_contrast.py index 9b9add7..3830a20 100644 --- a/tests/test_nav_menu_brand_contrast.py +++ b/tests/test_nav_menu_brand_contrast.py @@ -10,6 +10,7 @@ REPO_ROOT = Path(__file__).resolve().parents[1] NAV_MENU = REPO_ROOT / "CutList.Web/Components/Layout/NavMenu.razor" NAV_MENU_CSS = REPO_ROOT / "CutList.Web/Components/Layout/NavMenu.razor.css" APP_CSS = REPO_ROOT / "CutList.Web/wwwroot/css/app.css" +APP_SHELL = REPO_ROOT / "CutList.Web/Components/App.razor" def selector_color(css: str, selector: str) -> str: @@ -58,6 +59,16 @@ class NavMenuBrandContrastTests(unittest.TestCase): css = NAV_MENU_CSS.read_text() self.assertIn(".top-row { justify-content: flex-start;", css) + def test_typography_uses_a_sans_serif_face_and_compact_heading_scale(self) -> None: + shell = APP_SHELL.read_text() + css = APP_CSS.read_text() + self.assertIn("family=IBM+Plex+Sans", shell) + self.assertIn('font-family: "IBM Plex Sans",', css) + self.assertIn("h1 { font-size: clamp(1.85rem, 3.2vw, 3.15rem);", css) + self.assertIn("h2 { font-size: clamp(1.35rem, 2vw, 1.85rem);", css) + self.assertIn(".overview-panel-heading h2 { font-size: 1.25rem;", css) + self.assertIn('font-family: "IBM Plex Sans",', NAV_MENU_CSS.read_text()) + if __name__ == "__main__": unittest.main()