sgit newsroom v0.1.29 · snapshot 2026-09-24

Reading room · coding.sgit.ai · llms-full

On this page

Reading room / coding.sgit.ai / llms-full.txt · section 8 of 14

03 — HTML and CSS

37 HTML files, 38 CSS files. Both follow from the component system in 02__, and CSS carries the estate's alignment discipline further than any other language.


1. HTML — the component's markup half

sg-compute-left-nav.html, verbatim:

<nav class="left-nav" role="navigation" aria-label="Main navigation">

  <button class="nav-item" data-view="compute" aria-label="Compute">
    <span class="nav-icon">⬡</span>
    <span class="nav-label">Compute</span>
  </button>

  <button class="nav-item" data-view="nodes" aria-label="Active Nodes">
    <span class="nav-icon">▣</span>
    <span class="nav-label">Nodes</span>
  </button>

Six conventions:

  1. A fragment, not a document. No <html>, no <head>, no wrapper <template>. SgComponent fetches it and puts it in the shadow root.
  2. 2-space indent — deliberately different from the 4 used in JS and CSS. The narrower indent keeps nested markup readable at the same line width.
  3. Semantic elements. <nav>, <button> — not <div onclick>. Every interactive control is a real control, so keyboard and focus work without code.
  4. ARIA on every interactive element. role, aria-label, and aria-current set dynamically from JS.
  5. data-* is the behaviour hook. data-view="compute" — JS reads btn.dataset.view. Classes are for styling, data- is for behaviour, and the two never mix. That single rule is worth its own line on the site.
  6. Unicode glyphs instead of icon fonts or SVG sprites. ⬡ ▣ — no asset pipeline, no icon dependency, consistent with the no-build-step position in 02__ §5.

2. The page-level conventions

Beyond components, the estate's HTML carries two site-wide patterns worth documenting:

Programmatically injected chrome. pki.sgit.ai's build injects nav, footers and version badges at build time rather than repeating them per page — "so it cannot drift." Hand-written static HTML plus generated furniture. The site should document the pattern, because it is the reason the sibling sites stay consistent.

The markdown twin. Every URL is also available with the extension swapped, and links inside the markdown point at markdown:

"every page is available as markdown at the same path with the extension swapped, and links inside the markdown point at markdown, so a traversing agent never has to parse HTML."

The mechanism is non-obvious and should be published: these are static files, so the browser will not run JavaScript on them — the rendering happens in a Lambda@Edge function. See 05__ §3, because this is an HTML convention that exists entirely for machine readers.


3. CSS — alignment as a convention

sg-compute-left-nav.css, verbatim:

:host { display: flex; flex-direction: column; height: 100%; overflow: hidden; }
[hidden] { display: none !important; }

.left-nav {
    display:        flex;
    flex-direction: column;
    align-items:    stretch;
    padding:        6px 0;
    height:         100%;
    background:     var(--bg-panel);
    border-right:   1px solid var(--border-1);
    gap:            2px;
}

.nav-item {
    display:         flex;
    flex-direction:  column;
    align-items:     center;
    justify-content: center;
    gap:             3px;
    padding:         10px 0;
    background:      transparent;

Property values are aligned to a column within each rule — exactly the discipline applied to Python attribute annotations and JS object keys. The column is set per rule by its own longest property name, so .left-nav and .nav-item align at different columns. The unit of alignment is the block, not the file.

Other conventions visible here:

That last point deserves a paragraph on the site. BEM exists to solve a problem shadow DOM removes. Naming conventions that fight the cascade are a cost you only pay if your styles are global.


4. Design tokens

Tokens come from the versioned CDN, adopted per component:

get sharedCssPaths() { return ['https://dev.tools.sgraph.ai/components/tokens/v1/v1.0/v1.0.0/sg-tokens.css'] }

Two naming families are in use, which is an inconsistency to resolve:

FamilyExamples
Unprefixed--bg-panel, --border-1, --text-1 … --text-4, --text-link, --shadow-1, --shadow-2, --warn, --warn-soft, --soon
--sg- prefixed--sg-text, --sg-text-muted, --sg-surface, --sg-sp-1 … --sg-sp-4, --sg-transition-fast
--sgl- prefixed--sgl-tab-h, --sgl-panel-h

Three prefixes for one token system. The numbered scales (--text-1..4, --sg-sp-1..4, --shadow-1..2) are a good pattern — a bounded ramp rather than arbitrary values — and the site should publish the ramps as the recommended approach. But pick one prefix before publishing, or document what each family means. 08__ Q3.


5. Theming

The token indirection is what makes theming possible: components reference var(--bg-panel) and never a literal, so a theme is a different sg-tokens.css. Verify before publishing that a dark/light switch actually exists — the token names suggest a dark-first palette (--bg-panel, --text-1..4) and this pack could not confirm a second theme file. 08__ §4.


6. What a linter config would encode

CSS (stylelint): 4-space indent · a custom rule requiring aligned values within a block · no literal colours outside the token file (highest value) · :host first · shorthand consistency.

HTML (htmlhint or a custom check): 2-space indent · every <button>/interactive element has an accessible name · no onclick attributes · data-* present where JS reads dataset · component fragments contain no <html>/<head>.

The two rules that would actually catch defects are no literal colours and every interactive element has an accessible name. The rest is formatting.


This document is released under the Creative Commons Attribution 4.0 International licence (CC BY 4.0).


source: /briefs/04__bash-and-generated-shell.md