# Components

Specs for the CNO admin components. Each lists the values; build with the tokens in `design-tokens.md`.

## Admin shell

Black left nav with the white CNO logo, the uppercase section links and a content area. Collapses to a top bar below 720px.

| Property | Value |
| --- | --- |
| Sidebar | fill var(--color-ink), width var(--sidebar-width), sticky full height; logo 160px wide, padding 24px |
| Item | var(--font-size-nav) / 700 uppercase, padding 12px 24px, hover white at 12%, 150ms |
| Active item | white at 18% fill and a 4px bar (var(--nav-indicator-height)) in var(--color-accent) |
| Main | padding var(--page-padding); on the white pages the main area is var(--color-surface) |
| Mobile | at 720px the sidebar becomes a 64px top bar; the arrow button opens the menu |

```css
.side{width:var(--sidebar-width);background:var(--color-ink);color:var(--color-text-on-dark)}
.side nav a{padding:12px 24px;font:700 var(--font-size-nav)/var(--line-height-nav) var(--font-family);text-transform:uppercase}
.side nav a[aria-current=page]{box-shadow:inset var(--nav-indicator-height) 0 0 var(--color-accent)}
```

## Page title and section rule

The site's heading style: extra bold, with a hairline rule under the title and under each section header.

| Property | Value |
| --- | --- |
| Title | var(--font-size-title) / var(--line-height-title), weight 800; var(--font-size-display) from the wide breakpoint on the site |
| Rule | 1px solid var(--color-border) with 12px padding above it (the site's front-page section headers use border-bottom gray-950) |
| Lead | sans (var(--font-family)) at var(--font-size-md); the admin uses no serif |

```css
h1{font:800 var(--font-size-title)/var(--line-height-title) var(--font-family);padding-bottom:12px;border-bottom:1px solid var(--color-border)}
```

## Buttons

The site's pill buttons (.cno-button): bold 16px text on a fully rounded fill. Subscribe orange is the one loud button.

| Property | Value |
| --- | --- |
| Large | height 44px, padding 0 28px, 18px / 700, radius var(--radius-btn-lg) |
| Medium | height 40px, padding 0 24px, 16px / 700, radius var(--radius-btn-md) |
| Small | height 32px, padding 0 20px, 16px / 700, radius var(--radius-btn-sm) |
| Fill | Subscribe: var(--color-accent) (public site only). The admin has no filled buttons: its actions are icon links (next component) |
| Motion | color and background fade 150ms ease-in-out (var(--transition-focus)) |
| Disabled | var(--color-disabled-bg) fill, var(--color-disabled-text) text |

```css
.cno-button{display:inline-block;height:40px;padding:0 24px;border:0;border-radius:var(--radius-btn-md);
  background:var(--color-accent);color:#fff;font:700 var(--font-size-md)/40px var(--font-family);
  transition:background-color var(--duration-hover) var(--ease-standard)}
.cno-button:hover{background:var(--color-ink)}
```

## Icon link

The admin's quiet action: a text link with a 18px icon, no fill or border. Used for Open the page, Copy link, Back to all pages and Open developer spec.

| Property | Value |
| --- | --- |
| Text | var(--font-size-md) / 600, var(--color-primary), no underline at rest |
| Icon | 18px Material icon in currentColor, 4px from the text; leading for navigation back / open, trailing for forward |
| Hover | var(--color-primary-hover) with a 2px-offset underline, 150ms |
| Focus | 2px outline var(--color-primary) |
| Where | cno-admin/admin/admin.css (.ilink) |

```css
.ilink{display:inline-flex;align-items:center;gap:var(--space-1);color:var(--color-primary);font:600 var(--font-size-md)/var(--line-height-md) var(--font-family)}
.ilink svg{width:18px;height:18px;fill:currentColor}
.ilink:hover{color:var(--color-primary-hover);text-decoration:underline;text-underline-offset:2px}
```

## Links

Public links are light blue and darken on hover; the admin tables use the dark blue with a faint underline.

| Property | Value |
| --- | --- |
| Site link | var(--color-link), no underline, hover var(--color-primary), 150ms (a{color:var(--cno-blue)}) |
| Admin link | var(--color-primary), underline var(--color-link-underline), full colour underline on hover |

```css
a{color:var(--color-link);text-decoration:none;transition:color var(--duration-hover) var(--ease-standard)}
a:hover{color:var(--color-primary)}
```

## Card and tiles

Flat white card with a hairline border. The admin home tiles lift to elevation 8 on hover.

| Property | Value |
| --- | --- |
| Card | var(--color-surface), 1px var(--color-border-light) border, radius var(--radius-sm), padding var(--card-padding) |
| Tile title | var(--font-size-lg) / 700 in var(--color-primary), hover var(--color-primary-hover) |
| Hover | var(--shadow-8), 150ms |

```css
.card{background:var(--color-surface);border:1px solid var(--color-border-light);border-radius:var(--radius-sm);padding:var(--card-padding)}
```

## List table with developer row

The Public page list: one row per page, a twisty that opens a dark-on-grey developer box with the files, tokens, AI files and skill, and an inline code viewer.

| Property | Value |
| --- | --- |
| Head cell | var(--font-size-thead) / 800 uppercase, 1px var(--color-border-light) rule |
| Body cell | var(--font-size-table), padding 8px, 51px rows |
| Twisty | 40px round button, Material ChevronRight 24px, turns 90deg while open (150ms) |
| Developer box | var(--color-page-bg), 1px var(--color-border), radius var(--radius-sm), padding 16px |
| Code viewer | opens inside the box: header with file name, copy and close; 12px monospace; max height 360px |

```css
table{border-collapse:collapse;width:100%}
th{font:800 var(--font-size-thead)/var(--line-height-thead) var(--font-family);text-transform:uppercase}
td{padding:8px;font-size:var(--font-size-table);border-bottom:1px solid var(--color-border-light)}
```

## Status chips

Small pill labels for state. Colour is the meaning; light fill with dark text.

| Property | Value |
| --- | --- |
| Shape | height 24px, padding 0 12px, radius var(--radius-btn-sm), 13px / 700 |
| Success | var(--color-success-bg) fill, var(--color-success-text) text |
| Warning | var(--color-warning-bg) fill, var(--color-ink) text |
| Error | var(--color-danger-bg) fill, var(--color-danger-text) text |

```css
.chip{display:inline-flex;align-items:center;height:24px;padding:0 12px;border-radius:var(--radius-btn-sm);font:700 13px var(--font-family)}
.chip--ok{background:var(--color-success-bg);color:var(--color-success-text)}
```

## Gift pill (share full article)

The site's small outlined pill button with a gift icon. It opens the Gift Articles popover. Shown only on paywalled articles to subscribers.

| Property | Value |
| --- | --- |
| Size | height 2rem, padding 0 1rem 0 .75rem, radius .9375rem (the site's .cno-button--small), gap .5rem; icon 1.125rem in currentColor |
| Text | ProximaNova 700, 1rem / 2rem, colour var(--cno-gray-100), no wrap |
| Border and fill | 1px solid var(--cno-gray-100), transparent; hover and open fill var(--cno-gray-1100) |
| Motion | color and background-color 150ms ease-in-out (var(--cno-transition-speed-default)) |
| Focus | 2px outline var(--cno-blue-dark), offset 2px |
| Phones | below 640px the label is hidden and the pill becomes a 1.875rem round icon button |
| Visibility | only when the article is paywalled and the viewer is a subscriber |
| Where | cno-article-share/share.css (.cno-pill) and share.js |

```css
.cno-pill{display:inline-flex;align-items:center;gap:.5rem;height:2rem;padding:0 1rem 0 .75rem;border:1px solid var(--cno-gray-100);
  border-radius:.9375rem;background:transparent;color:var(--cno-gray-100);font:700 1rem/2rem var(--cno-base-font-family);
  transition:color var(--cno-transition-speed-default) ease-in-out,background-color var(--cno-transition-speed-default) ease-in-out}
.cno-pill:hover,.cno-pill[aria-expanded=true]{background:var(--cno-gray-1100)}
```

## Share icon and popover

One round share icon replaces the icon row (option A). Hover or tap opens a popover with the share options. The gift pill opens the same popover with the gift URL.

| Property | Value |
| --- | --- |
| Icon button | 1.875rem round, fill var(--cno-gray-900), icon 1rem in var(--cno-gray-100) (the same disc as .social-link in .share-links--gray-black); hover and open fill var(--cno-gray-800) |
| Popover box | white, 1px solid var(--cno-gray-950), radius var(--cno-border-radius), padding 1rem 1.25rem .5rem, width 18rem (max 100vw - 2.5rem), shadow 0 .25rem .75rem rgba(0,0,0,.12) (the one shadow; the site has none), z-index 40 |
| Position | 0.625rem below the button, left-aligned; shifted left to stay 12px inside the viewport; a .75rem caret follows the button centre |
| Title and text | title ProximaNova 800 1rem / 1.5rem; text 400 1rem / 1.5rem in var(--cno-gray-500), .75rem below |
| Rows | flex, gap .75rem, padding .5rem 0, 600 1rem / 1.5rem, separated by 1px var(--cno-gray-1000); hover text var(--cno-blue-dark); 1.875rem grey disc icon (var(--cno-gray-900) fill, .9rem icon) |
| Open / close | hover (desktop) opens after 120ms and closes 250ms after leaving unless pinned by a click; click or tap toggles; Esc and outside click close; one open at a time |
| Phones | below 640px the share icon calls navigator.share({title, url}) and falls back to this popover |
| Where | cno-article-share/share.css (.cno-iconbtn, .cno-pop) and share.js |

```css
.cno-pop{position:absolute;top:calc(100% + .625rem);left:0;z-index:40;width:18rem;max-width:calc(100vw - 2.5rem);
  padding:1rem 1.25rem .5rem;background:var(--cno-white);border:1px solid var(--cno-gray-950);
  border-radius:var(--cno-border-radius);box-shadow:0 .25rem .75rem rgba(0,0,0,.12)}
.cno-pop__row{display:flex;align-items:center;gap:.75rem;padding:.5rem 0;font:600 1rem/1.5rem var(--cno-base-font-family)}
```

## Toast

Short confirmation, used for Link copied.

| Property | Value |
| --- | --- |
| Box | fixed, centred, 1.5rem from the bottom, padding .5rem 1.25rem, radius 1.25rem, fill var(--cno-gray-100), white text 700 1rem / 1.5rem |
| Motion | fades and rises 1rem over var(--cno-transition-speed-default); visible for 1.8s; role=status, aria-live=polite |

```css
.cno-toast{position:fixed;left:50%;bottom:1.5rem;padding:.5rem 1.25rem;border-radius:1.25rem;background:var(--cno-gray-100);color:var(--cno-white);font:700 1rem/1.5rem var(--cno-base-font-family)}
```

## Footer

The site footer is a light grey band (gray-1100) with generous padding.

| Property | Value |
| --- | --- |
| Bar | var(--color-surface-alt), padding 60px var(--footer-padding) 120px on the site |
| Text | var(--font-size-md) |

```css
footer{background:var(--color-surface-alt);padding:60px var(--footer-padding) 120px}
```
