{
  "id": "v1-tm-7675",
  "long_id": "v1.terminal.app.s07.p06.t07.u05",
  "name": "Terminal, a chat client in commander blue",
  "era": {
    "slug": "terminal",
    "code": "tm",
    "name": "Terminal",
    "years": [
      2015,
      2026
    ],
    "description": "The text-terminal look of 2015 to 2026: a monospace face for everything, bright text on a dark screen, boxes and rules drawn with borders like character frames, prompts and cursors, status lines and key hints instead of buttons with chrome."
  },
  "archetype": "app",
  "mode": "mix",
  "viewport": {
    "width": 1280,
    "fluid": false,
    "responsive": true
  },
  "summary": "This is a chat client of 2015 to 2026 that dresses as the text-mode programs people ran in a terminal for the same job: a topic line at the top, a log of timed lines beside a column of names, and at the foot a bar that lists the open windows above the line you type into. One monospace face sets everything, on the blue screen of the DOS file managers and editors with their cyan bars, grey key line, yellow titles and hard black shadows. It was the look of web front ends to chat networks, of community chats of software projects, and of the dashboards their people built for themselves.",
  "url": "https://chrono.skin/s/v1-tm-7675",
  "preview_url": "https://chrono.skin/s/v1-tm-7675/specimen.html",
  "files": {
    "STYLE.md": "# Terminal, a chat client in commander blue\n\n## Summary\n\nThis is a chat client of 2015 to 2026 that dresses as the text-mode programs people ran in a terminal for the same job: a topic line at the top, a log of timed lines beside a column of names, and at the foot a bar that lists the open windows above the line you type into. One monospace face sets everything, on the blue screen of the DOS file managers and editors with their cyan bars, grey key line, yellow titles and hard black shadows. It was the look of web front ends to chat networks, of community chats of software projects, and of the dashboards their people built for themselves.\n\n## Layout\n\n- The page is designed for a 1280px window and does not stretch beyond it: `.ds-client` is a column of `--size-page` (1280px) on `--color-canvas`, at least as tall as the window. Top to bottom it holds the topic line `.ds-topbar`, `.ds-main` (the views, padded `--space-3` and `2ch`), the `.ds-footer`, and the `.ds-dock`.\n- The navigation is at the foot, not at the top. `.ds-dock` sticks to the lower edge of the window and holds `.ds-nav`, the window list on `--fill-bar-alt` (a clock, the windows as numbered words in brackets, the count of unread lines at the right), and under it `.ds-dock__input`, the line the reader types into. The window that shows is a hole in the bar: `--color-canvas` with `--color-heading`.\n- `.ds-topbar` is one line on `--fill-bar`: the `.ds-brand`, the topic of the place in `.ds-topbar__topic`, and one pulled-down `.ds-menu` at the right.\n- Every view is `.ds-cols`: the work at the left and `.ds-side`, a column of `--size-side` (260px) at the right, parted from it by one upright line that runs the height of the view. `--form` is 3 to 2 without that line (settings, help). `.ds-col` is a column that may shrink; `.ds-stack` piles frames `--space-3` apart.\n- The home view (the lobby) stacks in its left column: `.ds-hero`, the message of the day as a box that stands off the screen with `--shadow-dialog`; the `.ds-stats` line; then `.ds-section` blocks `--space-4` (32px) apart, each opened by a `.ds-section__title` rule: the `.ds-grid` of four pinned channels and the table of channels. The side column holds the names that are on, a panel about the server with two `.ds-progress` bars, and a panel of lines that named the reader.\n- Inner pages have no hero. They open with the `.ds-breadcrumb` as a path, then `.ds-page-header`, then `.ds-cols`. Notices sit directly above the log; tabs sit directly above the list they sort.\n- Views. The specimen is one small client with five views, one showing at a time; topic line, footer and dock are written once around them. `lobby` is the home view. `channel` is one channel: two notices, the `.ds-log` with a day rule, joins, a line that names the reader and a line of links, pagination to older lines, beside the names and the legend of badges. `logs` is a typed search, tabs, the list of hits, the empty state of shared files, beside the archive as a folding tree. `settings` is the account form with its error and four buttons, beside the switches and the question before a nick is dropped. `help` is the rules as running text beside the commands as a folding tree and a panel of keys. A view is `<section class=\"ds-view\" id=\"...\">`; links between views are plain `href=\"#id\"`.\n- Spacing scale, in parts of one 16px step: `--space-1` 4px is the vertical padding of bar items, buttons, inputs, table cells, tabs and log lines; `--space-2` 8px the padding above the text in a frame, the gap between a rule and what follows, between list rows and between notices; `--space-3` 16px the gap between paragraphs, between frames in a stack, under a page header and around the text of the hero; `--space-4` 32px the gap between sections and under the hero, which leaves room for its shadow; `--space-5` 48px is kept for a break larger than a section. Horizontal steps are character cells written in `ch`.\n- Fixed sizes: `--size-label` 140px the label column of a form, `--size-field` 420px a text input, `--size-date` 100px the date column of the list, `--size-dialog` 400px a dialog.\n- Below 900px there is one column: the side column goes under the work with a rule above it, the topic is left out, the window list keeps its numbers and shows a name only for the window that is open (the clock and the word before the count are left out), a log line puts time and name on one row and the text under them, the stats line and the grid become two by two, form labels sit above their fields, list dates sit above their entries, and table cells marked `.ds-table__extra` are left out. The dock stays stuck to the foot. The page never scrolls sideways.\n\n## Typography and colour roles\n\nThis style combines the parts of different styles of one era. Where a note below names a value that differs from `tokens.css`, the tokens are right.\n\n- One face for everything: `--font-body`, `--font-heading`, `--font-ui` and `--font-mono` are the same monospace stack (\"Cascadia Mono\", Consolas, \"Lucida Console\", Menlo, \"Liberation Mono\", monospace). Weights are `--weight-body` 400 and 700 for headings, names, bar items (`--weight-ui`) and the brand. Nothing is tracked and nothing is set in capitals: `--heading-transform` and `--ui-transform` are none.\n- Sizes are one size with two exceptions, as on a screen of 80 by 25 cells: `--text-base` 16px with `--line-body` 1.2 is all running text, `--text-ui` 16px bars, buttons, inputs, tabs and pagination, `--text-small` 15px meta lines, hints, badges, the footer and code blocks, `--text-large` 18px the hero's lead and the brand name. `--text-display` 26px is the hero title only, `--text-h1` 20px a page title, a figure and the first heading of running text; `--text-h2` and `--text-h3` are 16px and differ from text by weight and colour.\n- The DOS screen: `--color-page` #000070 is the desktop behind the program (`--fill-page` dithers it with a 4px check of a darker blue), `--color-canvas` #0000a8 the screen, `--color-surface` #0000a8 the inside of frames and table rows, `--color-surface-alt` #00008c alternate rows and code, `--color-surface-strong` #1818c4 group rows, inline code, the cell of an avatar and a line that names the reader. `--color-text` #c6c6c6 is running text, `--color-text-muted` #86a4dc times, counts and hints, `--color-heading` #ffffff headings, names and figures, `--color-heading-alt` #ffff54 frame titles, third headings and tags.\n- Links: `--color-link` #54ffff, `--color-link-quiet` #a8e0ff for breadcrumb, tabs, sidebar and footer links, `--color-link-visited` #dca8ff, `--color-link-hover` #ffffff, `--color-link-active` #ffff54. `--link-decoration` is none: a link is known by its colour, and takes `--link-decoration-hover` (underline) when hovered.\n- Bars: `--color-bar` #00a8a8 with `--color-bar-text` #000000 is the topic line and the head row of a table. `--color-bar-alt` #a8a8a8 with `--color-bar-alt-text` #000000 is the window list. `--color-inverse` #54ffff with `--color-inverse-text` #000000 is inverse video: the current tab, page number and sidebar link, the selected table row, the hovered menu item, the half of a switch that holds.\n- Lines: `--color-border` #a8a8a8 at `--border-width` 1px `--border-style` solid draws every frame and rule; `--color-border-strong` #ffffff at `--border-width-strong` 3px is the rule under a page header, the left edge of the hero, of a notice and of a mentioned line, and the frame of a dialog and a menu; `--color-border-muted` #3c3cd0 parts rows inside a frame.\n- Accents: `--color-accent` #ffff54 with `--color-accent-text` #000000 is the count badge and the mark of a mentioned line; `--color-accent-alt` #54ff54 is the prompt sign, the reader's own name at the input line and the fold marks of a tree. `--color-fill-1` to `--color-fill-4` (#0000a8, #00008c, #004c8c, #1818c4) are the four grid cells and two of the avatar cells. Status words are text in brackets: `--color-success` #54ff54, `--color-warning` #ffb454, `--color-danger` #ff8080; progress bars use the same three.\n- Controls: the primary button is `--color-button` #00a800 with `--color-button-text` #000000; the secondary button is `--color-button-secondary` #000070 with `--color-button-secondary-text` #54ffff and a frame in `--color-border`; fields are `--color-input` #000058 with `--color-input-text` #ffffff and a line in `--color-input-border` #00a8a8; disabled is `--color-disabled` #00008c with `--color-disabled-text` #6464e0. The notice is `--color-notice` #005c78 with `--color-notice-text` #ffffff, the error notice `--color-danger-surface` #400014 with `--color-danger`. `--color-overlay` #000058 is the block a dialog stands on; `--color-focus` #ffff54 is the focus outline.\n- Surface: everything is square and every shadow is a hard black block, as a text screen draws it: `--shadow-control` 3px 3px on buttons and fields (1px 1px when pressed), `--shadow-panel` 6px 5px on frames, `--shadow-dialog` 16px 12px on the hero, a dialog and a pulled-down menu, none of them blurred. `--shadow-text` is none. Buttons and fields are filled (`--fill-button-secondary`, `--fill-input`); `--fill-button-hover` lightens the button (60% of it over white). All four radii are 0, `--backdrop-blur` is 0px, `--focus-ring` is 3px solid var(--color-focus), `--transition` is none.\n- The era's rule for which text stands on which fill (every layout of the era keeps it, so any palette works with any layout): `--color-text`, `--color-text-muted`, the two heading colours, every link colour and the three status colours stand on `--fill-page`, `--color-canvas`, the three surfaces, `--fill-panel` and the four fills, and on nothing else. `--color-bar-text` only on `--fill-bar`; `--color-bar-alt-text` only on `--fill-bar-alt`; `--color-inverse-text` only on `--fill-inverse`; `--color-accent-text` only on `--fill-accent`; `--color-button-text` and `--color-button-hover-text` only on `--fill-button` and its hover; `--color-notice-text` only on `--color-notice`; `--color-danger` also on `--color-danger-surface`; `--color-disabled-text` on `--color-disabled`. `--color-button-secondary-text` and `--color-input-text` must read on their own fills and on the canvas and surfaces, because a surface set may leave those controls unfilled. The current item of a bar is a hole in it: `--color-canvas` with `--color-heading`. Nothing but a link in the bar's own text colour, a badge or a key label stands on a bar or an inverse block.\n- One-off sizes written with `calc()` or `ch`: a frame title is lifted by half of `--text-h3` times `--line-body` so that the frame's top line runs through it; the brand tile is one text line square; the log's columns are `6ch` for the time and `17ch` for the name; an avatar is at least `4ch` wide; a pulled-down menu is at least `28ch` and a tooltip at most `34ch` wide; horizontal paddings and gaps are whole character cells.\n\n## Components\n\n- `.ds-page` on `<body>`: page fill and base type, no margin. `.ds-client` is the screen; `.ds-main` holds the views; `.ds-cols` (`--form`) are the column pairs, `.ds-col` a column, `.ds-side` the column of names at the right, `.ds-stack` a pile of frames, `.ds-section` a block of the page.\n- `.ds-nav`: the window list in the dock at the foot. `.ds-nav__clock` is the time in brackets, `.ds-nav__list` holds `.ds-nav__link` items, each a `.ds-nav__num` and a `.ds-nav__name` in brackets, and `.ds-nav__act` at the right holds a `.ds-nav__word` and the count of unread lines as a `.ds-badge`. The stylesheet marks the link whose `href` names the view that is showing (one selector per view, and the first when the address names none); on a page of its own give the link `is-current`. `.ds-dock` is the sticky block around it; `.ds-dock__input` is the input line: `.ds-dock__who`, the reader's name in brackets, and a `.ds-form__input`.\n- `.ds-topbar`: the topic line at the top, on `--fill-bar`: the brand, `.ds-topbar__topic` (one line, cut with an ellipsis) and a `.ds-menu`.\n- `.ds-hero`: the message of the day on the home view: a box in `--color-border-strong` with a heavy left edge and `--shadow-dialog`. It holds `.ds-hero__motd` (a small line opened by `.ds-hero__sign`, the `-!-` of a server line), `.ds-hero__title` (`--text-display`), `.ds-hero__lead`, a `.ds-buttons` row and `.ds-hero__note`.\n- `.ds-footer`: one quiet line above the dock, with a faint rule: a `.ds-keys` list of `.ds-footer__link` items and `.ds-footer__text` at the right.\n- `.ds-brand`: the site's mark and name, a link to the home view, first thing in the topic line. `.ds-brand__mark` is a tile one text line square, dressed like the primary button (`--fill-button`, `--color-button-text`, `--radius-control`) with a line in the bar's text colour; `.ds-brand__name` is bold at `--text-large`. The name `chronoskin` and the mark are placeholders for the installing project's own name and logo.\n- `.ds-breadcrumb`: a path: `.ds-breadcrumb__link` items with `.ds-breadcrumb__sep` (`/`) between them, ending in a bold `.ds-breadcrumb__current`.\n- `.ds-page-header`: the head of an inner page: `.ds-page-header__main` with `.ds-page-header__title` (`--text-h1`) and one muted `.ds-page-header__text` line (in a channel, its topic); `.ds-page-header__action` at the right holds one button. A rule of `--border-width-strong` closes it.\n- `.ds-prose`: running text, at most 78 characters wide: h1, h2, h3, paragraphs, lists whose bullet is a typed dash, `code` on `--color-surface-strong`, `strong` in the heading colour. Anything typed literally goes in `.ds-code`, a `<pre>` at `--text-small` on `--color-surface-alt` in a frame; it scrolls sideways inside itself.\n- `.ds-link`: text link with `is-visited`, `is-hover`, `is-active`, `is-focus`. `.ds-link--quiet` for meta and tool links, `.ds-link--bracket` for a link written as a word in brackets. `.ds-links` sets several in a wrapping line.\n- `.ds-button`: a `<button>`, or an `<a>` when it only leads to another view. It is a word in square brackets, which the stylesheet adds. The primary one is a block of `--fill-button`; `.ds-button--secondary` is a frame in `--color-border`; `.ds-button--danger` is the destructive action in `--color-danger` on `--color-danger-surface`; `disabled` or `is-disabled` is greyed. `is-hover`, `is-active` and `is-focus` show the states. Group with `.ds-buttons`.\n- `.ds-form`: rows (`.ds-form__row`) of a `.ds-form__label` and a `.ds-form__field`. Controls take `.ds-form__input` (`--wide` for the full width, `--auto` for selects). `is-invalid` plus a bold `.ds-form__error` marks a validation error, `.ds-form__hint` is help text, `.ds-form__check` holds a `.ds-form__checkbox` (one empty cell, a filled block when set), and `.ds-form__actions` lines the buttons up with the fields.\n- `.ds-table`: aligned columns under a head row on `--fill-bar`. `.ds-table__num` right-aligns a numeric column, `.ds-table__code` is a bold first column, `.ds-table__date` a muted one, `tr.is-alt` an alternate row, `.ds-table__group` a group row, `tr.is-selected` the row under the cursor in inverse video, `tr.is-unread` a bold row, `.ds-table__title` the link in a row, `.ds-table__extra` cells a phone leaves out.\n- `.ds-list`: dated entries, here the hits of a search. Each `.ds-list__item` is a muted `.ds-list__date` in a `--size-date` column and a `.ds-list__main` with a bold `.ds-list__title` link, a `.ds-list__excerpt` and a small `.ds-list__meta` line; faint rules part the items.\n- `.ds-log`: the lines of a channel, an ordered list. A `.ds-log__line` is a `.ds-log__time`, a right-aligned bold `.ds-log__nick` and the `.ds-log__text` behind an upright line. `.ds-log__line--event` is a muted server line (a join, a mode change) whose name is `-!-`; `is-mention` sets a line that names the reader on `--color-surface-strong` with a mark in `--color-accent` at its left edge; `.ds-log__day` is the rule with the date that parts two days.\n- `.ds-panel`: a frame with its `.ds-panel__title` cut into the top line, and a `.ds-panel__body` of `.ds-panel__text` paragraphs. The title row draws the top line itself, so the frame works on any fill and with any border style; a panel always has a title.\n- `.ds-stat`: one figure: a `.ds-stat__value` at `--text-h1` followed on the same line by a small muted `.ds-stat__label`. `.ds-stats` is the row: four figures between two rules, parted by upright rules.\n- `.ds-grid`: four `.ds-grid__cell` boxes (four across, two by two on a phone), each a frame on `--color-fill-1` (`--2`, `--3`, `--4` select the other fills), with a `.ds-grid__title`, `.ds-grid__text` and a muted `.ds-grid__label`.\n- `.ds-tabs`: a row of words on a rule; each `.ds-tabs__tab` is a link, the current one a `<span class=\"ds-tabs__tab is-current\">` in inverse video. Content goes in `.ds-tabs__body`.\n- `.ds-badge`: a count: bold `--text-small` on `--fill-accent`. `.ds-badge--tag` is a word after a `#` in `--color-heading-alt`. Status labels are `.ds-badge--success`, `.ds-badge--warning` and `.ds-badge--danger`: a word in brackets in the status colour, with no fill and no frame. `.ds-badges` sets several in a line.\n- `.ds-sidebar`: the names of a channel, in the side column at the right. Each `.ds-sidebar__block` is a frame with a `.ds-sidebar__title` cut into its top line and a `.ds-sidebar__list` of `.ds-sidebar__link` items (`is-current` in inverse video), each opened by a `.ds-avatar` and followed by an optional `.ds-sidebar__count` (a sign or a word); `.ds-sidebar__text` is a small muted paragraph.\n- `.ds-notice`: a sentence in a frame of `--color-border-strong` with a heavy left edge, starting with a bold `.ds-notice__title`. `.ds-notice--error` uses `--color-danger` on `--color-danger-surface`. Stack several in `.ds-notices`.\n- `.ds-pagination`: a line of `.ds-pagination__link` items: older, numbers, newer. The current page is a `<span>` with `is-current` in inverse video; `is-disabled` is muted.\n- `.ds-dialog`: a frame in `--color-border-strong`, `--size-dialog` wide, with `--shadow-dialog`. It sits in the page flow on `.ds-dialog__backdrop`, a flat block of `--color-overlay`; it has a `.ds-dialog__title`, a `.ds-dialog__body`, `.ds-dialog__text` and `.ds-dialog__actions`. No dimming of the page, no blur.\n- `.ds-empty`: a faint frame with a centred muted `.ds-empty__text` sentence and one secondary button.\n- `.ds-menu`: a pulled-down menu, a `<details>` in a bar. `.ds-menu__title` is its `<summary>`, a word in brackets with a `v`; open, it is a hole in the bar. `.ds-menu__list` is the framed list under it, on `--color-surface` with `--shadow-dialog`; each `.ds-menu__item` is a link with its command in a muted `.ds-menu__key` at the right, inverse video when hovered (`is-hover`); `.ds-menu__rule` parts two groups. It is closed until asked for.\n- `.ds-accordion`: a folding tree. Each `.ds-accordion__item` is a `<details>`; its `.ds-accordion__title` is the `<summary>`, marked `[+]` when closed and `[-]` when open; `.ds-accordion__body` is indented four cells.\n- `.ds-tooltip`: a word with a dotted underline that can take the focus; its `.ds-tooltip__tip` is a small boxed hint on `--color-surface-strong` that shows above it on hover or focus (`is-open` shows it statically).\n- `.ds-switch`: an on/off setting, a `<label>` holding `.ds-switch__label`, a hidden `.ds-switch__input` checkbox and `.ds-switch__track`, which draws the pair `on` `off`; the half that holds is inverse video. `.ds-setting` is a ruled row for one.\n- `.ds-progress`: a quantity: a muted `.ds-progress__label`, a `.ds-progress__bar` typed in cells between brackets (`#` for the filled part in `.ds-progress__on`, `.` for the rest; `--warning` and `--danger` recolour it) and a bold `.ds-progress__value`.\n- `.ds-avatar`: a person as two initials in a cell on `--color-surface-strong`; `--2` and `--3` use two of the block fills. Used before a name in the lists of names.\n- Text-mode pieces: `.ds-prompt` is a typed command line (`.ds-prompt__sign` the command, `.ds-prompt__path` its option); `.ds-cursor` is the block cursor; `.ds-key` is a key hint whose `.ds-key__cap` is set in brackets, several in a `.ds-keys` line; `.ds-meter` is the older name of a typed bar; `.ds-section__title` is a heading followed by a rule to the right edge; `.ds-note` is a small muted line under a block.\n\n## Never\n\n- `font-families <= 1`: one monospace face sets everything, headings and buttons included.\n- `font-size <= 26px`: the largest text is the hero title; everything else is within a few pixels of the body size.\n- `font-size >= 15px`: small text is the meta size; nothing is set smaller.\n- `letter-spacing <= 0px`: the grid of the typeface is never stretched.\n- `uppercase-text <= 5%`: nothing is set in capitals by the stylesheet but the initials of an avatar.\n- `line-height <= 1.4`: lines sit as close as an 80 by 25 screen sets them.\n- `border-radius <= 0px`: a character cell has no round corner; every tile, button and field is square.\n- `box-shadow-blur <= 0px`: nothing is soft and nothing floats.\n- `gradient-fills <= 0%`: every fill is one flat colour.\n- `border-width <= 1px`: every line is one pixel.\n- `text-shadow = none`: text does not glow.\n- `transition = none`: states change at once, as a screen redraws.\n\n## Extending\n\nDerive a new component from the nearest one in the specimen. A boxed thing copies `.ds-panel`: a frame of `--border-width` in `--color-border` with its title cut into the top line and `--space-2` and `2ch` of padding. A row type copies a `.ds-log__line`, a `.ds-table` row or a `.ds-list__item`. A set of choices copies `.ds-tabs`, and whatever is current or selected is inverse video (`--fill-inverse` with `--color-inverse-text`), or a hole when it stands in a bar. A status is a word in brackets in its status colour; a quantity is a `.ds-progress` typed in cells; a setting that is on or off is a `.ds-switch`; an action is a word dressed as `.ds-button`, or a line in a `.ds-menu` when the bar should offer it. Use only the tokens of `tokens.css` and the `--size-*` and `--space-*` tokens of `components.css`, write horizontal steps in `ch`, and pair each text token with its own fill as listed above. When in doubt do less: text before a box, a rule before a fill, a typed character before an icon, and never a radius, a soft shadow, a picture or a second typeface.\n",
    "components.css": "/* Layout tokens (structure part). Vertical steps are quarters, halves and\n   multiples of one 16px step; horizontal steps are written in ch. */\n:root {\n  --size-page: 1280px;\n  --size-side: 260px;\n  --size-label: 140px;\n  --size-field: 420px;\n  --size-dialog: 400px;\n  --size-date: 100px;\n  --space-1: 4px;\n  --space-2: 8px;\n  --space-3: 16px;\n  --space-4: 32px;\n  --space-5: 48px;\n}\n\n/* ---------- shell: one face, one size, a screen of text ---------- */\n.ds-page {\n  margin: 0;\n  padding: 0;\n  background: var(--fill-page);\n  color: var(--color-text);\n  font-family: var(--font-body);\n  font-size: var(--text-base);\n  font-weight: var(--weight-body);\n  line-height: var(--line-body);\n}\n/* Selection is inverse video. */\n.ds-page ::selection {\n  background: var(--fill-inverse);\n  color: var(--color-inverse-text);\n}\n/* ---------- views: one screen of the example site shows at a time ---------- */\n.ds-view { display: none; }\n.ds-view:target, .ds-page:not(:has(.ds-view:target)) .ds-view--home { display: block; }\n.ds-view:target { scroll-margin-top: 100vh; }\n\n/* ---------- frames: a box of 1-cell lines with its title cut into the top edge.\n   The top edge is drawn by the title row (a short rule, the title, a long rule),\n   so it works on any fill and with any border style. ---------- */\n.ds-panel,\n.ds-dialog,\n.ds-sidebar__block,\n.ds-term {\n  position: relative;\n  display: flow-root;\n  box-sizing: border-box;\n  min-width: 0;\n  margin: calc(var(--text-h3) * var(--line-body) * 0.5) 0 0;\n  border: var(--border-width) var(--border-style) var(--color-border);\n  border-top: 0;\n  border-radius: var(--radius-panel);\n  background: var(--fill-panel);\n  box-shadow: var(--shadow-panel);\n}\n.ds-panel__title,\n.ds-dialog__title,\n.ds-sidebar__title,\n.ds-term__title {\n  display: flex;\n  align-items: center;\n  gap: 1ch;\n  margin: calc(var(--text-h3) * var(--line-body) * -0.5) calc(var(--border-width) * -1) 0;\n  padding: 0;\n  overflow: hidden;\n  white-space: nowrap;\n  color: var(--color-heading-alt);\n  font-family: var(--font-heading);\n  font-size: var(--text-h3);\n  font-weight: var(--weight-heading);\n  line-height: var(--line-body);\n  letter-spacing: var(--heading-tracking);\n  text-transform: var(--heading-transform);\n}\n.ds-panel__title::before,\n.ds-dialog__title::before,\n.ds-sidebar__title::before,\n.ds-term__title::before {\n  content: \"\";\n  flex: none;\n  width: 1ch;\n  border-top: var(--border-width) var(--border-style) var(--color-border);\n}\n.ds-panel__title::after,\n.ds-dialog__title::after,\n.ds-sidebar__title::after,\n.ds-term__title::after {\n  content: \"\";\n  flex: 1;\n  min-width: 1ch;\n  border-top: var(--border-width) var(--border-style) var(--color-border);\n}\n.ds-panel__body {\n  padding: var(--space-2) 2ch var(--space-3);\n}\n.ds-panel__text {\n  margin: 0 0 var(--space-2);\n}\n.ds-panel__text:last-child {\n  margin-bottom: 0;\n}\n\n/* ---------- a section rule: the name, then a line to the right edge ---------- */\n.ds-section {\n  margin: 0 0 var(--space-4);\n}\n.ds-section__title {\n  display: flex;\n  align-items: center;\n  gap: 1ch;\n  margin: var(--space-3) 0 var(--space-2);\n  color: var(--color-heading);\n  font-family: var(--font-heading);\n  font-size: var(--text-h2);\n  font-weight: var(--weight-heading);\n  line-height: var(--line-heading);\n  letter-spacing: var(--heading-tracking);\n  text-transform: var(--heading-transform);\n}\n.ds-section__title:first-child {\n  margin-top: 0;\n}\n.ds-section__title::after {\n  content: \"\";\n  flex: 1;\n  border-top: var(--border-width) var(--border-style) var(--color-border);\n}\n.ds-note:last-child {\n  margin-bottom: 0;\n}\n.ds-note {\n  margin: var(--space-2) 0 var(--space-3);\n  color: var(--color-text-muted);\n  font-size: var(--text-small);\n}\n\n/* ---------- prompt, cursor, key hints, meters ---------- */\n.ds-prompt {\n  margin: 0 0 var(--space-2);\n  color: var(--color-heading);\n  font-family: var(--font-mono);\n  font-weight: var(--weight-bold);\n  overflow-wrap: anywhere;\n}\n.ds-prompt__sign {\n  color: var(--color-accent-alt);\n}\n.ds-prompt__path {\n  color: var(--color-heading-alt);\n}\n/* The block cursor: one cell of inverse video. It holds a no-break space. */\n.ds-cursor {\n  background: currentColor;\n}\n@media (prefers-reduced-motion: no-preference) {\n  .ds-cursor {\n    animation: ds-blink 1.2s steps(1) infinite;\n  }\n}\n@keyframes ds-blink {\n  0% { opacity: 1; }\n  50% { opacity: 0; }\n  100% { opacity: 0; }\n}\n.ds-key {\n  white-space: nowrap;\n}\n.ds-key__cap {\n  font-weight: var(--weight-bold);\n}\n.ds-key__cap::before {\n  content: \"[\";\n}\n.ds-key__cap::after {\n  content: \"]\";\n}\n/* A progress bar typed in block characters. */\n.ds-meter {\n  color: var(--color-border);\n  white-space: nowrap;\n}\n.ds-code {\n  box-sizing: border-box;\n  max-width: 100%;\n  margin: 0 0 var(--space-3);\n  padding: var(--space-2) 2ch;\n  overflow-x: auto;\n  border: var(--border-width) var(--border-style) var(--color-border);\n  border-radius: var(--radius-panel);\n  background: var(--color-surface-alt);\n  color: var(--color-text);\n  font-family: var(--font-mono);\n  font-size: var(--text-small);\n  line-height: var(--line-body);\n  white-space: pre;\n}\n.ds-code:last-child {\n  margin-bottom: 0;\n}\n\n/* ---------- links ---------- */\n.ds-link {\n  color: var(--color-link);\n  text-decoration: var(--link-decoration);\n}\n.ds-link:visited,\n.ds-link.is-visited {\n  color: var(--color-link-visited);\n}\n.ds-link:hover,\n.ds-link.is-hover {\n  color: var(--color-link-hover);\n  text-decoration: var(--link-decoration-hover);\n}\n.ds-link:active,\n.ds-link.is-active {\n  color: var(--color-link-active);\n  text-decoration: var(--link-decoration-hover);\n}\n.ds-link:focus-visible,\n.ds-link.is-focus {\n  outline: var(--focus-ring);\n}\n.ds-link--quiet,\n.ds-link--quiet:visited,\n.ds-link--quiet.is-visited {\n  color: var(--color-link-quiet);\n  text-decoration: var(--link-decoration-quiet);\n}\n.ds-link--quiet:hover,\n.ds-link--quiet.is-hover {\n  color: var(--color-link-hover);\n  text-decoration: var(--link-decoration-hover);\n}\n/* A link marked by brackets instead of an underline: [copy]. */\n.ds-link--bracket,\n.ds-link--bracket:visited {\n  color: var(--color-link);\n  text-decoration: none;\n  white-space: nowrap;\n}\n.ds-link--bracket::before {\n  content: \"[\";\n}\n.ds-link--bracket::after {\n  content: \"]\";\n}\n.ds-links {\n  display: flex;\n  flex-wrap: wrap;\n  gap: var(--space-1) 3ch;\n  margin: 0;\n  padding: 0;\n  list-style: none;\n}\n\n/* ---------- brand: the mark on a one-line tile dressed like the primary button ---------- */\n.ds-brand {\n  display: inline-flex;\n  align-items: center;\n  gap: 1ch;\n  color: var(--color-heading);\n  text-decoration: none;\n}\n.ds-brand__mark {\n  flex: none;\n  display: block;\n  box-sizing: border-box;\n  width: calc(var(--text-base) * var(--line-body));\n  height: calc(var(--text-base) * var(--line-body));\n  border: var(--border-width) var(--border-style) var(--color-button);\n  border-radius: var(--radius-control);\n  background: var(--fill-button);\n  box-shadow: var(--shadow-control);\n  color: var(--color-button-text);\n}\n.ds-brand__mark svg {\n  display: block;\n  width: 100%;\n  height: 100%;\n}\n.ds-brand__name {\n  font-family: var(--font-heading);\n  font-size: var(--text-large);\n  font-weight: var(--weight-display);\n  line-height: var(--line-heading);\n  letter-spacing: var(--display-tracking);\n  text-shadow: var(--shadow-text);\n}\n.ds-brand:hover .ds-brand__name,\n.ds-brand.is-hover .ds-brand__name {\n  text-decoration: var(--link-decoration-hover);\n}\n.ds-brand:focus-visible,\n.ds-brand.is-focus {\n  outline: var(--focus-ring);\n}\n\n/* ---------- breadcrumb: a path ---------- */\n.ds-breadcrumb {\n  display: flex;\n  flex-wrap: wrap;\n  gap: 0 1ch;\n  margin: 0 0 var(--space-2);\n  padding: 0;\n  list-style: none;\n}\n.ds-breadcrumb__link {\n  color: var(--color-link-quiet);\n  text-decoration: var(--link-decoration-quiet);\n}\n.ds-breadcrumb__link:hover,\n.ds-breadcrumb__link.is-hover {\n  color: var(--color-link-hover);\n  text-decoration: var(--link-decoration-hover);\n}\n.ds-breadcrumb__sep {\n  color: var(--color-text-muted);\n}\n.ds-breadcrumb__current {\n  color: var(--color-heading);\n  font-weight: var(--weight-bold);\n}\n\n/* ---------- page header: title, one line, an action at the right, a heavy rule ---------- */\n.ds-page-header {\n  display: flex;\n  justify-content: space-between;\n  align-items: flex-end;\n  gap: var(--space-2) 2ch;\n  margin: 0 0 var(--space-3);\n  padding: 0 0 var(--space-2);\n  border-bottom: var(--border-width-strong) var(--border-style) var(--color-border-strong);\n}\n.ds-page-header__main {\n  min-width: 0;\n}\n.ds-page-header__title {\n  margin: 0;\n  color: var(--color-heading);\n  font-family: var(--font-heading);\n  font-size: var(--text-h1);\n  font-weight: var(--weight-heading);\n  line-height: var(--line-heading);\n  letter-spacing: var(--heading-tracking);\n  text-transform: var(--heading-transform);\n  text-shadow: var(--shadow-text);\n}\n.ds-page-header__text {\n  margin: var(--space-1) 0 0;\n  color: var(--color-text-muted);\n}\n.ds-page-header__action {\n  flex: none;\n}\n\n/* ---------- stats ---------- */\n.ds-stats {\n  display: grid;\n  grid-template-columns: repeat(4, minmax(0, 1fr));\n  margin: 0;\n  padding: 0;\n  list-style: none;\n}\n.ds-stat {\n  min-width: 0;\n}\n.ds-stat__value {\n  color: var(--color-heading);\n  font-family: var(--font-heading);\n  font-weight: var(--weight-display);\n}\n.ds-stat__label {\n  color: var(--color-text-muted);\n}\n\n/* ---------- prose ---------- */\n.ds-prose {\n  max-width: 78ch;\n}\n.ds-prose h1,\n.ds-prose h2,\n.ds-prose h3 {\n  margin: 0 0 var(--space-2);\n  color: var(--color-heading);\n  font-family: var(--font-heading);\n  font-weight: var(--weight-heading);\n  line-height: var(--line-heading);\n  letter-spacing: var(--heading-tracking);\n  text-transform: var(--heading-transform);\n}\n.ds-prose h1 {\n  font-size: var(--text-h1);\n}\n.ds-prose h2 {\n  margin-top: var(--space-4);\n  font-size: var(--text-h2);\n}\n.ds-prose h3 {\n  margin-top: var(--space-3);\n  font-size: var(--text-h3);\n  color: var(--color-heading-alt);\n}\n.ds-prose p {\n  margin: 0 0 var(--space-3);\n}\n.ds-prose ul,\n.ds-prose ol {\n  margin: 0 0 var(--space-3);\n  padding: 0 0 0 3ch;\n}\n.ds-prose ul {\n  list-style-type: \"- \";\n  padding-left: 2ch;\n}\n.ds-prose code {\n  padding: 0 0.5ch;\n  background: var(--color-surface-strong);\n  color: var(--color-heading);\n  font-family: var(--font-mono);\n}\n.ds-prose strong {\n  color: var(--color-heading);\n  font-weight: var(--weight-bold);\n}\n.ds-prose > :first-child {\n  margin-top: 0;\n}\n.ds-prose > :last-child {\n  margin-bottom: 0;\n}\n\n/* ---------- buttons: a word in brackets, the primary one in inverse video ---------- */\n.ds-buttons {\n  display: flex;\n  flex-wrap: wrap;\n  align-items: center;\n  gap: var(--space-2) 2ch;\n}\n.ds-button {\n  display: inline-block;\n  box-sizing: border-box;\n  margin: 0;\n  padding: var(--space-1) 1ch;\n  border: var(--border-width) var(--border-style) var(--color-button);\n  border-radius: var(--radius-control);\n  background: var(--fill-button);\n  box-shadow: var(--shadow-control);\n  color: var(--color-button-text);\n  font-family: var(--font-ui);\n  font-size: var(--text-ui);\n  font-weight: var(--weight-ui);\n  line-height: var(--line-body);\n  text-transform: var(--ui-transform);\n  text-decoration: none;\n  white-space: nowrap;\n  transition: var(--transition);\n  cursor: pointer;\n}\n.ds-button::before {\n  content: \"[ \";\n}\n.ds-button::after {\n  content: \" ]\";\n}\n.ds-button:hover,\n.ds-button.is-hover {\n  background: var(--fill-button-hover);\n  box-shadow: var(--shadow-control-hover);\n  color: var(--color-button-hover-text);\n}\n.ds-button:active,\n.ds-button.is-active {\n  box-shadow: var(--shadow-control-pressed);\n}\n.ds-button:focus-visible,\n.ds-button.is-focus {\n  outline: var(--focus-ring);\n}\n.ds-button--secondary,\n.ds-button--secondary:hover,\n.ds-button--secondary.is-hover {\n  border-color: var(--color-border);\n  background: var(--fill-button-secondary);\n  color: var(--color-button-secondary-text);\n}\n.ds-button--secondary:hover,\n.ds-button--secondary.is-hover {\n  border-color: var(--color-border-strong);\n}\n.ds-button--danger,\n.ds-button--danger:hover,\n.ds-button--danger.is-hover {\n  border-color: var(--color-danger);\n  background: var(--color-danger-surface);\n  color: var(--color-danger);\n}\n.ds-button:disabled,\n.ds-button.is-disabled {\n  border-color: var(--color-border-muted);\n  background: var(--color-disabled);\n  box-shadow: none;\n  color: var(--color-disabled-text);\n  cursor: default;\n}\n\n/* ---------- form ---------- */\n.ds-form {\n  margin: 0;\n}\n.ds-form__row {\n  display: grid;\n  grid-template-columns: var(--size-label) minmax(0, 1fr);\n  gap: 0 2ch;\n  align-items: start;\n  margin: 0 0 var(--space-2);\n}\n.ds-form__label {\n  padding: var(--space-1) 0;\n  color: var(--color-heading);\n}\n.ds-form__field {\n  min-width: 0;\n}\n.ds-form__input {\n  box-sizing: border-box;\n  width: 100%;\n  max-width: var(--size-field);\n  margin: 0;\n  padding: var(--space-1) 1ch;\n  border: var(--border-width) var(--border-style) var(--color-input-border);\n  border-radius: var(--radius-control);\n  background: var(--fill-input);\n  box-shadow: var(--shadow-control);\n  color: var(--color-input-text);\n  font-family: var(--font-ui);\n  font-size: var(--text-ui);\n  line-height: var(--line-body);\n  transition: var(--transition);\n}\n.ds-form__input--wide {\n  max-width: none;\n}\n.ds-form__input--auto {\n  width: auto;\n}\n.ds-form__input:focus-visible,\n.ds-form__input.is-focus {\n  outline: var(--focus-ring);\n}\n.ds-form__input:disabled,\n.ds-form__input.is-disabled {\n  background: var(--color-disabled);\n  color: var(--color-disabled-text);\n}\n.ds-form__input.is-invalid {\n  border-color: var(--color-danger);\n}\n.ds-form__error {\n  margin: var(--space-1) 0 0;\n  color: var(--color-danger);\n  font-weight: var(--weight-bold);\n}\n.ds-form__hint {\n  margin: var(--space-1) 0 0;\n  color: var(--color-text-muted);\n  font-size: var(--text-small);\n}\n.ds-form__check {\n  display: flex;\n  align-items: center;\n  gap: 1ch;\n  padding: var(--space-1) 0;\n}\n/* A checkbox is one cell: an empty box, or a filled block when set. */\n.ds-form__checkbox {\n  appearance: none;\n  flex: none;\n  box-sizing: border-box;\n  width: 2ch;\n  height: 2ch;\n  margin: 0;\n  border: var(--border-width) var(--border-style) var(--color-input-border);\n  border-radius: var(--radius-control);\n  background: var(--fill-input);\n}\n.ds-form__checkbox:checked {\n  border-style: solid;\n  background: var(--color-input-text);\n}\n.ds-form__checkbox:focus-visible {\n  outline: var(--focus-ring);\n}\n.ds-form__actions {\n  display: flex;\n  flex-wrap: wrap;\n  gap: var(--space-2) 2ch;\n  margin: var(--space-3) 0 0;\n  padding-left: calc(var(--size-label) + 2ch);\n}\n\n/* ---------- table: aligned columns under a head line in the bar colours ---------- */\n.ds-table {\n  width: 100%;\n  border-collapse: collapse;\n  border-radius: var(--radius-panel);\n}\n.ds-table th,\n.ds-table td {\n  padding: var(--space-1) 1ch;\n  border-style: var(--border-style);\n  border-color: var(--color-border-muted);\n  border-width: 0 0 var(--border-width);\n  text-align: left;\n  vertical-align: top;\n}\n.ds-table th {\n  background: var(--fill-bar);\n  color: var(--color-bar-text);\n  border-color: var(--color-border);\n  font-family: var(--font-heading);\n  font-weight: var(--weight-bold);\n  text-transform: var(--heading-transform);\n  white-space: nowrap;\n}\n.ds-table td {\n  background: var(--color-surface);\n}\n.ds-table tr.is-alt td,\n.ds-table__row--alt td {\n  background: var(--color-surface-alt);\n}\n.ds-table th.ds-table__num,\n.ds-table td.ds-table__num {\n  text-align: right;\n  white-space: nowrap;\n}\n.ds-table td.ds-table__code {\n  color: var(--color-heading);\n  font-family: var(--font-mono);\n  font-weight: var(--weight-bold);\n  white-space: nowrap;\n}\n.ds-table td.ds-table__date {\n  color: var(--color-text-muted);\n  white-space: nowrap;\n}\n.ds-table__group td {\n  background: var(--color-surface-strong);\n  color: var(--color-heading-alt);\n  font-weight: var(--weight-bold);\n}\n/* The row under the cursor: inverse video. */\n.ds-table tr.is-selected td {\n  background: var(--fill-inverse);\n  color: var(--color-inverse-text);\n}\n.ds-table tr.is-selected .ds-table__title {\n  color: var(--color-inverse-text);\n}\n.ds-table tr.is-unread td {\n  font-weight: var(--weight-bold);\n}\n.ds-table__title {\n  color: var(--color-link);\n  text-decoration: var(--link-decoration);\n}\n.ds-table__title:visited,\n.ds-table__title.is-visited {\n  color: var(--color-link-visited);\n}\n.ds-table__title:hover,\n.ds-table__title.is-hover {\n  color: var(--color-link-hover);\n  text-decoration: var(--link-decoration-hover);\n}\n\n/* ---------- list ---------- */\n.ds-list {\n  margin: 0;\n  padding: 0;\n  list-style: none;\n}\n.ds-list__item {\n  display: grid;\n  grid-template-columns: var(--size-date) minmax(0, 1fr);\n  gap: 0 2ch;\n  padding: var(--space-2) 0;\n  border-bottom: var(--border-width) var(--border-style) var(--color-border-muted);\n}\n.ds-list__item:first-child {\n  padding-top: 0;\n}\n.ds-list__item:last-child {\n  padding-bottom: 0;\n  border-bottom: 0;\n}\n.ds-list__date {\n  color: var(--color-text-muted);\n  white-space: nowrap;\n}\n.ds-list__main {\n  min-width: 0;\n}\n.ds-list__title {\n  color: var(--color-link);\n  font-weight: var(--weight-bold);\n  text-decoration: var(--link-decoration);\n}\n.ds-list__title:visited,\n.ds-list__title.is-visited {\n  color: var(--color-link-visited);\n}\n.ds-list__title:hover,\n.ds-list__title.is-hover {\n  color: var(--color-link-hover);\n  text-decoration: var(--link-decoration-hover);\n}\n.ds-list__excerpt {\n  margin: 0;\n}\n.ds-list__meta {\n  margin: 0;\n  color: var(--color-text-muted);\n  font-size: var(--text-small);\n}\n\n/* ---------- grid: four framed cells on the block fills ---------- */\n.ds-grid {\n  display: grid;\n  grid-template-columns: repeat(4, minmax(0, 1fr));\n  gap: var(--space-2) 2ch;\n}\n.ds-grid__cell {\n  min-width: 0;\n  padding: var(--space-2) 2ch var(--space-3);\n  border: var(--border-width) var(--border-style) var(--color-border);\n  border-radius: var(--radius-page);\n  background: var(--color-fill-1);\n}\n.ds-grid__cell--2 {\n  background: var(--color-fill-2);\n}\n.ds-grid__cell--3 {\n  background: var(--color-fill-3);\n}\n.ds-grid__cell--4 {\n  background: var(--color-fill-4);\n}\n.ds-grid__label {\n  margin: 0;\n  color: var(--color-text-muted);\n  font-size: var(--text-small);\n}\n.ds-grid__title {\n  margin: 0 0 var(--space-1);\n  color: var(--color-heading);\n  font-family: var(--font-heading);\n  font-size: var(--text-h3);\n  font-weight: var(--weight-heading);\n  line-height: var(--line-heading);\n  letter-spacing: var(--heading-tracking);\n  text-transform: var(--heading-transform);\n}\n.ds-grid__text {\n  margin: 0;\n}\n\n/* ---------- tabs: words on a rule, the current one in inverse video ---------- */\n.ds-tabs {\n  display: flex;\n  flex-wrap: wrap;\n  gap: 0 1ch;\n  margin: 0;\n  padding: 0;\n  list-style: none;\n  border-bottom: var(--border-width) var(--border-style) var(--color-border);\n  font-family: var(--font-ui);\n  font-size: var(--text-ui);\n  font-weight: var(--weight-ui);\n  text-transform: var(--ui-transform);\n}\n.ds-tabs__tab {\n  display: block;\n  padding: var(--space-1) 1ch;\n  color: var(--color-link-quiet);\n  text-decoration: var(--link-decoration-quiet);\n}\n.ds-tabs__tab:hover,\n.ds-tabs__tab.is-hover {\n  color: var(--color-link-hover);\n  text-decoration: var(--link-decoration-hover);\n}\n.ds-tabs__tab:focus-visible,\n.ds-tabs__tab.is-focus {\n  outline: var(--focus-ring);\n}\n.ds-tabs__tab.is-current {\n  background: var(--fill-inverse);\n  color: var(--color-inverse-text);\n  font-weight: var(--weight-bold);\n  text-decoration: none;\n}\n.ds-tabs__body {\n  padding: var(--space-2) 0 var(--space-3);\n}\n\n/* ---------- badge: a count on the accent fill; a tag; a status word in brackets ---------- */\n.ds-prose + .ds-links {\n  margin-top: var(--space-3);\n}\n.ds-badges {\n  margin: 0 0 var(--space-2);\n  display: flex;\n  flex-wrap: wrap;\n  align-items: center;\n  gap: var(--space-1) 2ch;\n}\n.ds-badge {\n  display: inline-block;\n  padding: 0 1ch;\n  border-radius: var(--radius-pill);\n  background: var(--fill-accent);\n  color: var(--color-accent-text);\n  font-family: var(--font-ui);\n  font-size: var(--text-small);\n  font-weight: var(--weight-bold);\n  line-height: var(--line-body);\n  white-space: nowrap;\n}\n.ds-badge--tag,\n.ds-badge--success,\n.ds-badge--warning,\n.ds-badge--danger {\n  padding: 0;\n  background: transparent;\n  font-weight: var(--weight-body);\n}\n.ds-badge--tag {\n  color: var(--color-heading-alt);\n}\n.ds-badge--tag::before {\n  content: \"#\";\n}\n.ds-badge--success::before,\n.ds-badge--warning::before,\n.ds-badge--danger::before {\n  content: \"[\";\n}\n.ds-badge--success::after,\n.ds-badge--warning::after,\n.ds-badge--danger::after {\n  content: \"]\";\n}\n.ds-badge--success {\n  color: var(--color-success);\n}\n.ds-badge--warning {\n  color: var(--color-warning);\n}\n.ds-badge--danger {\n  color: var(--color-danger);\n}\n\n/* ---------- sidebar: framed blocks of links ---------- */\n.ds-sidebar {\n  display: grid;\n  gap: var(--space-2);\n  align-content: start;\n  min-width: 0;\n}\n.ds-sidebar__list {\n  margin: 0;\n  padding: var(--space-1) 1ch var(--space-2);\n  list-style: none;\n}\n.ds-sidebar__list li {\n  display: flex;\n  justify-content: space-between;\n  gap: 1ch;\n}\n.ds-sidebar__link {\n  flex: 1;\n  min-width: 0;\n  padding: 0 1ch;\n  color: var(--color-link-quiet);\n  text-decoration: var(--link-decoration-quiet);\n}\n.ds-sidebar__link:hover,\n.ds-sidebar__link.is-hover {\n  color: var(--color-link-hover);\n  text-decoration: var(--link-decoration-hover);\n}\n.ds-sidebar__link.is-current {\n  background: var(--fill-inverse);\n  color: var(--color-inverse-text);\n  font-weight: var(--weight-bold);\n  text-decoration: none;\n}\n.ds-sidebar__count {\n  flex: none;\n  padding: 0 1ch 0 0;\n  color: var(--color-text-muted);\n}\n.ds-sidebar__text {\n  margin: 0;\n  padding: var(--space-1) 2ch var(--space-2);\n  color: var(--color-text-muted);\n  font-size: var(--text-small);\n}\n\n/* ---------- notice: a box with a heavy left edge ---------- */\n.ds-notices {\n  display: grid;\n  gap: var(--space-2);\n  margin: 0 0 var(--space-3);\n}\n.ds-notice {\n  margin: 0;\n  padding: var(--space-2) 2ch;\n  border: var(--border-width) var(--border-style) var(--color-border-strong);\n  border-left-width: var(--border-width-strong);\n  border-radius: var(--radius-panel);\n  background: var(--color-notice);\n  color: var(--color-notice-text);\n}\n.ds-notice__title {\n  font-weight: var(--weight-bold);\n  text-transform: var(--heading-transform);\n}\n.ds-notice--error {\n  border-color: var(--color-danger);\n  background: var(--color-danger-surface);\n  color: var(--color-danger);\n}\n\n/* ---------- pagination ---------- */\n.ds-pagination {\n  display: flex;\n  flex-wrap: wrap;\n  align-items: center;\n  gap: var(--space-1) 1ch;\n  margin: var(--space-3) 0 0;\n  padding: 0;\n  list-style: none;\n  font-family: var(--font-ui);\n  font-size: var(--text-ui);\n}\n.ds-pagination__link {\n  display: block;\n  padding: 0 1ch;\n  color: var(--color-link);\n  text-decoration: var(--link-decoration-quiet);\n}\n.ds-pagination__link:hover,\n.ds-pagination__link.is-hover {\n  color: var(--color-link-hover);\n  text-decoration: var(--link-decoration-hover);\n}\n.ds-pagination__link:focus-visible,\n.ds-pagination__link.is-focus {\n  outline: var(--focus-ring);\n}\n.ds-pagination__link.is-current {\n  background: var(--fill-inverse);\n  color: var(--color-inverse-text);\n  font-weight: var(--weight-bold);\n  text-decoration: none;\n}\n.ds-pagination__link.is-disabled {\n  color: var(--color-text-muted);\n  text-decoration: none;\n}\n\n/* ---------- dialog: a framed box on a block of the overlay colour, in the page flow ---------- */\n.ds-dialog__backdrop {\n  box-sizing: border-box;\n  padding: var(--space-3) 2ch;\n  border-radius: var(--radius-panel);\n  background: var(--color-overlay);\n}\n.ds-dialog {\n  max-width: var(--size-dialog);\n  margin-left: auto;\n  margin-right: auto;\n  border-color: var(--color-border-strong);\n  box-shadow: var(--shadow-dialog);\n}\n.ds-dialog__title::before,\n.ds-dialog__title::after {\n  border-color: var(--color-border-strong);\n}\n.ds-dialog__body {\n  padding: var(--space-2) 2ch var(--space-3);\n}\n.ds-dialog__text {\n  margin: 0 0 var(--space-3);\n}\n.ds-dialog__actions {\n  display: flex;\n  flex-wrap: wrap;\n  gap: var(--space-2) 2ch;\n}\n\n/* ---------- empty ---------- */\n.ds-empty {\n  padding: var(--space-3) 2ch;\n  border: var(--border-width) var(--border-style) var(--color-border-muted);\n  border-radius: var(--radius-panel);\n  text-align: center;\n}\n.ds-empty__text {\n  margin: 0 0 var(--space-2);\n  color: var(--color-text-muted);\n}\n.ds-note code,\n.ds-notice code,\n.ds-panel__text code {\n  color: var(--color-heading);\n  font-family: var(--font-mono);\n}\n.ds-notice code {\n  color: inherit;\n  font-weight: var(--weight-bold);\n}\n\n/* ---------- pieces of the period beyond the checklist ---------- */\n/* menu: an item of a bar that pulls down a framed list. A <details>; closed until asked for. */\n.ds-menu {\n  position: relative;\n  flex: none;\n}\n.ds-menu__title {\n  display: block;\n  padding: var(--space-1) 1ch;\n  color: inherit;\n  font-weight: var(--weight-ui);\n  text-transform: var(--ui-transform);\n  white-space: nowrap;\n  list-style: none;\n  cursor: pointer;\n}\n.ds-menu__title::-webkit-details-marker {\n  display: none;\n}\n.ds-menu__title::after {\n  content: \" v\";\n  text-transform: none;\n}\n.ds-menu__title:hover,\n.ds-menu__title.is-hover,\n.ds-menu[open] > .ds-menu__title {\n  background: var(--color-canvas);\n  color: var(--color-heading);\n}\n.ds-menu__title:focus-visible,\n.ds-menu__title.is-focus {\n  outline: var(--focus-ring);\n}\n.ds-menu__list {\n  position: absolute;\n  z-index: 4;\n  top: 100%;\n  right: 0;\n  box-sizing: border-box;\n  min-width: 28ch;\n  max-width: 90vw;\n  margin: 0;\n  padding: var(--space-1) 0;\n  list-style: none;\n  border: var(--border-width) var(--border-style) var(--color-border-strong);\n  border-radius: var(--radius-panel);\n  background: var(--color-surface);\n  box-shadow: var(--shadow-dialog);\n  color: var(--color-text);\n  font-weight: var(--weight-body);\n  text-shadow: none;\n}\n.ds-menu__item {\n  display: flex;\n  justify-content: space-between;\n  gap: 2ch;\n  padding: 0 1ch;\n  color: var(--color-link-quiet);\n  text-decoration: var(--link-decoration-quiet);\n  white-space: nowrap;\n}\n.ds-menu__item:hover,\n.ds-menu__item.is-hover {\n  background: var(--fill-inverse);\n  color: var(--color-inverse-text);\n}\n.ds-menu__key {\n  color: var(--color-text-muted);\n}\n.ds-menu__item:hover .ds-menu__key,\n.ds-menu__item.is-hover .ds-menu__key {\n  color: inherit;\n}\n.ds-menu__rule {\n  margin: var(--space-1) 0;\n  border-top: var(--border-width) var(--border-style) var(--color-border-muted);\n}\n\n/* accordion: nodes of a tree that fold; [+] closed, [-] open */\n.ds-accordion {\n  margin: 0;\n}\n.ds-accordion__item {\n  border-bottom: var(--border-width) var(--border-style) var(--color-border-muted);\n}\n.ds-accordion__item:last-child {\n  border-bottom: 0;\n}\n.ds-accordion__title {\n  display: block;\n  padding: var(--space-1) 0;\n  color: var(--color-heading);\n  font-weight: var(--weight-bold);\n  list-style: none;\n  cursor: pointer;\n}\n.ds-accordion__title::-webkit-details-marker {\n  display: none;\n}\n.ds-accordion__title::before {\n  content: \"[+] \";\n  color: var(--color-accent-alt);\n}\n.ds-accordion__item[open] > .ds-accordion__title::before {\n  content: \"[-] \";\n}\n.ds-accordion__title:hover,\n.ds-accordion__title.is-hover {\n  color: var(--color-link-hover);\n}\n.ds-accordion__title:focus-visible,\n.ds-accordion__title.is-focus {\n  outline: var(--focus-ring);\n}\n.ds-accordion__body {\n  margin: 0;\n  padding: 0 0 var(--space-2) 4ch;\n}\n.ds-accordion__body p {\n  margin: 0 0 var(--space-1);\n}\n.ds-accordion__body code {\n  color: var(--color-heading);\n  font-family: var(--font-mono);\n}\n\n/* tooltip: a boxed hint over its trigger, shown on hover or focus only */\n.ds-tooltip {\n  text-decoration: underline dotted;\n  cursor: help;\n}\n.ds-tooltip:focus-visible {\n  outline: var(--focus-ring);\n}\n.ds-tooltip__tip {\n  display: none;\n  position: absolute;\n  z-index: 3;\n  left: 1ch;\n  box-sizing: border-box;\n  width: max-content;\n  max-width: min(34ch, calc(100% - 2ch));\n  padding: 0 1ch;\n  border: var(--border-width) var(--border-style) var(--color-border-strong);\n  border-radius: var(--radius-panel);\n  background: var(--color-surface-strong);\n  box-shadow: var(--shadow-panel);\n  color: var(--color-text);\n  font-size: var(--text-small);\n  font-weight: var(--weight-body);\n  letter-spacing: 0;\n  text-align: left;\n  text-transform: none;\n  white-space: normal;\n}\n.ds-tooltip:hover .ds-tooltip__tip,\n.ds-tooltip:focus .ds-tooltip__tip,\n.ds-tooltip.is-open .ds-tooltip__tip {\n  display: block;\n}\n\n/* switch: an on/off pair over a checkbox; the half that holds is inverse video */\n.ds-switch {\n  position: relative;\n  display: flex;\n  align-items: center;\n  justify-content: space-between;\n  gap: 2ch;\n  padding: var(--space-1) 0;\n  cursor: pointer;\n}\n.ds-switch__label {\n  min-width: 0;\n}\n.ds-switch__input {\n  position: absolute;\n  appearance: none;\n  margin: 0;\n  opacity: 0;\n}\n.ds-switch__track {\n  flex: none;\n  display: inline-flex;\n  border: var(--border-width) var(--border-style) var(--color-input-border);\n  border-radius: var(--radius-control);\n  background: var(--fill-input);\n  color: var(--color-input-text);\n  font-size: var(--text-small);\n  white-space: nowrap;\n}\n.ds-switch__track::before {\n  content: \"on\";\n  padding: 0 1ch;\n}\n.ds-switch__track::after {\n  content: \"off\";\n  padding: 0 1ch;\n  background: var(--fill-inverse);\n  color: var(--color-inverse-text);\n  font-weight: var(--weight-bold);\n}\n.ds-switch__input:checked + .ds-switch__track::before {\n  background: var(--fill-inverse);\n  color: var(--color-inverse-text);\n  font-weight: var(--weight-bold);\n}\n.ds-switch__input:checked + .ds-switch__track::after {\n  background: transparent;\n  color: inherit;\n  font-weight: var(--weight-body);\n}\n.ds-switch__input:focus-visible + .ds-switch__track {\n  outline: var(--focus-ring);\n}\n\n/* progress: a bar typed in cells between brackets, then its figure */\n.ds-progress {\n  display: flex;\n  flex-wrap: wrap;\n  align-items: baseline;\n  gap: 0 1ch;\n  margin: 0 0 var(--space-2);\n}\n.ds-progress:last-child {\n  margin-bottom: 0;\n}\n.ds-progress__label {\n  color: var(--color-text-muted);\n}\n.ds-progress__bar {\n  color: var(--color-border);\n  white-space: nowrap;\n}\n.ds-progress__bar::before {\n  content: \"[\";\n  color: var(--color-text-muted);\n}\n.ds-progress__bar::after {\n  content: \"]\";\n  color: var(--color-text-muted);\n}\n.ds-progress__on {\n  color: var(--color-success);\n}\n.ds-progress__on--warning {\n  color: var(--color-warning);\n}\n.ds-progress__value {\n  color: var(--color-heading);\n  font-weight: var(--weight-bold);\n}\n\n/* avatar: initials in a cell */\n.ds-avatar {\n  display: inline-block;\n  box-sizing: border-box;\n  min-width: 4ch;\n  padding: 0 0.5ch;\n  border-radius: var(--radius-pill);\n  background: var(--color-surface-strong);\n  color: var(--color-heading-alt);\n  font-weight: var(--weight-bold);\n  text-align: center;\n  text-transform: uppercase;\n  white-space: nowrap;\n}\n.ds-avatar--2 {\n  background: var(--color-fill-3);\n  color: var(--color-heading);\n}\n.ds-avatar--3 {\n  background: var(--color-fill-4);\n  color: var(--color-accent-alt);\n}\n\n/* ---------- layout 7: a chat client: a topic line at the top, the log beside a\n   column of names, and the window list with the input line docked at the foot ---------- */\n.ds-client {\n  display: flex;\n  flex-direction: column;\n  box-sizing: border-box;\n  max-width: var(--size-page);\n  min-height: 100vh;\n  margin: 0 auto;\n  border-radius: var(--radius-page);\n  background: var(--color-canvas);\n}\n.ds-main {\n  flex: 1;\n  min-width: 0;\n  padding: var(--space-3) 2ch var(--space-4);\n}\n.ds-cols {\n  display: grid;\n  grid-template-columns: minmax(0, 1fr) var(--size-side);\n  gap: var(--space-3) 2ch;\n  align-items: stretch;\n}\n.ds-cols--form {\n  grid-template-columns: minmax(0, 3fr) minmax(0, 2fr);\n}\n.ds-col {\n  min-width: 0;\n}\n/* the column of names: parted from the log by one upright line */\n.ds-side {\n  display: flex;\n  flex-direction: column;\n  gap: var(--space-3);\n  min-width: 0;\n  padding: 0 0 0 2ch;\n  border-left: var(--border-width) var(--border-style) var(--color-border);\n}\n.ds-stack {\n  display: grid;\n  gap: var(--space-3);\n  align-content: start;\n  min-width: 0;\n}\n\n/* topic line: the name, what the place is about, one pulled-down menu */\n.ds-topbar {\n  position: relative;\n  z-index: 3;\n  display: flex;\n  align-items: center;\n  gap: 0 2ch;\n  padding: 0 2ch;\n  background: var(--fill-bar);\n  color: var(--color-bar-text);\n  font-family: var(--font-ui);\n  font-size: var(--text-ui);\n}\n.ds-topbar .ds-brand {\n  padding: var(--space-1) 0;\n}\n.ds-topbar .ds-brand,\n.ds-topbar .ds-brand__name {\n  color: var(--color-bar-text);\n}\n.ds-topbar .ds-brand__mark {\n  border-color: var(--color-bar-text);\n  box-shadow: none;\n}\n.ds-topbar__topic {\n  flex: 1;\n  min-width: 0;\n  margin: 0;\n  overflow: hidden;\n  text-overflow: ellipsis;\n  white-space: nowrap;\n}\n.ds-menu__title::before {\n  content: \"[\";\n}\n.ds-menu__title::after {\n  content: \" v]\";\n}\n\n/* dock: the window list (the navigation) and the input line, stuck to the foot of the window */\n.ds-dock {\n  position: sticky;\n  z-index: 2;\n  bottom: 0;\n  background: var(--color-canvas);\n}\n.ds-nav {\n  display: flex;\n  flex-wrap: wrap;\n  align-items: center;\n  gap: 0 1ch;\n  padding: 0 1ch;\n  background: var(--fill-bar-alt);\n  color: var(--color-bar-alt-text);\n  font-family: var(--font-ui);\n  font-size: var(--text-ui);\n  font-weight: var(--weight-ui);\n}\n.ds-nav__clock,\n.ds-nav__act {\n  flex: none;\n  margin: 0;\n  padding: var(--space-1) 0;\n  font-weight: var(--weight-body);\n}\n.ds-nav__act {\n  margin-left: auto;\n}\n.ds-nav__word {\n  font-weight: var(--weight-body);\n}\n.ds-nav__list {\n  display: flex;\n  flex-wrap: wrap;\n  margin: 0;\n  padding: 0;\n  list-style: none;\n}\n.ds-nav__link {\n  display: block;\n  padding: var(--space-1) 1ch;\n  color: var(--color-bar-alt-text);\n  text-decoration: var(--link-decoration-quiet);\n  text-transform: var(--ui-transform);\n  white-space: nowrap;\n}\n.ds-nav__link::before {\n  content: \"[\";\n}\n.ds-nav__link::after {\n  content: \"]\";\n}\n.ds-nav__num {\n  font-weight: var(--weight-bold);\n}\n.ds-nav__name::before {\n  content: \":\";\n}\n.ds-nav__link:hover,\n.ds-nav__link.is-hover {\n  text-decoration: var(--link-decoration-hover);\n}\n.ds-nav__link:focus-visible,\n.ds-nav__link.is-focus {\n  outline: var(--focus-ring);\n}\n/* the window that is showing is a hole in the bar */\n.ds-nav__link.is-current,\n.ds-page:not(:has(.ds-view:target)) .ds-nav__link[href=\"#lobby\"],\n.ds-page:has(#lobby:target) .ds-nav__link[href=\"#lobby\"],\n.ds-page:has(#channel:target) .ds-nav__link[href=\"#channel\"],\n.ds-page:has(#logs:target) .ds-nav__link[href=\"#logs\"],\n.ds-page:has(#settings:target) .ds-nav__link[href=\"#settings\"],\n.ds-page:has(#help:target) .ds-nav__link[href=\"#help\"] {\n  background: var(--color-canvas);\n  color: var(--color-heading);\n  text-decoration: none;\n}\n.ds-dock__input {\n  display: flex;\n  align-items: center;\n  gap: 1ch;\n  padding: var(--space-1) 1ch var(--space-2);\n}\n.ds-dock__who {\n  flex: none;\n  color: var(--color-accent-alt);\n  font-weight: var(--weight-bold);\n}\n.ds-dock__input .ds-form__input {\n  flex: 1;\n  min-width: 0;\n  max-width: none;\n}\n\n/* hero: the message of the day, a box that stands off the screen */\n.ds-hero {\n  box-sizing: border-box;\n  margin: 0 0 var(--space-4);\n  padding: var(--space-3) 3ch;\n  border: var(--border-width) var(--border-style) var(--color-border-strong);\n  border-left-width: var(--border-width-strong);\n  border-radius: var(--radius-page);\n  background: var(--fill-panel);\n  box-shadow: var(--shadow-dialog);\n}\n.ds-hero__motd {\n  margin: 0 0 var(--space-2);\n  color: var(--color-text-muted);\n  font-size: var(--text-small);\n}\n.ds-hero__sign {\n  color: var(--color-accent-alt);\n}\n.ds-hero__title {\n  margin: 0 0 var(--space-2);\n  color: var(--color-heading);\n  font-family: var(--font-heading);\n  font-size: var(--text-display);\n  font-weight: var(--weight-display);\n  line-height: var(--line-display);\n  letter-spacing: var(--display-tracking);\n  text-transform: var(--heading-transform);\n  text-shadow: var(--shadow-text);\n}\n.ds-hero__lead {\n  max-width: 72ch;\n  margin: 0 0 var(--space-3);\n  font-size: var(--text-large);\n}\n.ds-hero__note {\n  margin: var(--space-2) 0 0;\n  color: var(--color-text-muted);\n  font-size: var(--text-small);\n}\n\n/* stats: one ruled line of figures, each a number and its word */\n.ds-stats {\n  margin: 0 0 var(--space-4);\n  border-style: var(--border-style);\n  border-color: var(--color-border);\n  border-width: var(--border-width) 0;\n}\n.ds-stat {\n  display: flex;\n  flex-wrap: wrap;\n  align-items: baseline;\n  gap: 0 1ch;\n  padding: var(--space-2) 2ch;\n  border-left: var(--border-width) var(--border-style) var(--color-border);\n}\n.ds-stat:first-child {\n  padding-left: 0;\n  border-left: 0;\n}\n.ds-stat__value {\n  font-size: var(--text-h1);\n  line-height: var(--line-heading);\n  text-shadow: var(--shadow-text);\n}\n.ds-stat__label {\n  font-size: var(--text-small);\n}\n\n/* the log: time, name, what was said; one line an entry */\n.ds-log {\n  margin: 0 0 var(--space-3);\n  padding: 0;\n  list-style: none;\n}\n.ds-log__day {\n  display: flex;\n  align-items: center;\n  gap: 1ch;\n  margin: var(--space-2) 0;\n  color: var(--color-text-muted);\n  font-size: var(--text-small);\n}\n.ds-log__day::before,\n.ds-log__day::after {\n  content: \"\";\n  flex: 1;\n  border-top: var(--border-width) var(--border-style) var(--color-border-muted);\n}\n.ds-log__line {\n  display: grid;\n  grid-template-columns: 6ch 17ch minmax(0, 1fr);\n  gap: 0 1ch;\n  padding: var(--space-1) 1ch var(--space-1) 0;\n  border-left: var(--border-width-strong) var(--border-style) transparent;\n}\n.ds-log__time {\n  color: var(--color-text-muted);\n  text-align: right;\n}\n.ds-log__nick {\n  overflow: hidden;\n  color: var(--color-heading);\n  font-weight: var(--weight-bold);\n  text-align: right;\n  white-space: nowrap;\n}\n.ds-log__text {\n  min-width: 0;\n  margin: 0;\n  padding: 0 0 0 1ch;\n  border-left: var(--border-width) var(--border-style) var(--color-border);\n  overflow-wrap: anywhere;\n}\n.ds-log__text code {\n  padding: 0 0.5ch;\n  background: var(--color-surface-alt);\n  color: var(--color-heading);\n  font-family: var(--font-mono);\n}\n.ds-log__line--event .ds-log__nick,\n.ds-log__line--event .ds-log__text {\n  color: var(--color-text-muted);\n  font-weight: var(--weight-body);\n}\n/* a line that names the reader */\n.ds-log__line.is-mention {\n  border-left-color: var(--color-accent);\n  background: var(--color-surface-strong);\n}\n.ds-log__line.is-mention .ds-log__nick {\n  color: var(--color-heading-alt);\n}\n.ds-log__text .ds-links {\n  display: inline-flex;\n}\n\n/* names in a sidebar block carry their cell of initials */\n.ds-sidebar__link .ds-avatar {\n  margin-right: 1ch;\n}\n.ds-panel__text code {\n  white-space: nowrap;\n}\n.ds-setting {\n  border-bottom: var(--border-width) var(--border-style) var(--color-border-muted);\n}\n.ds-setting:last-child {\n  border-bottom: 0;\n}\n.ds-keys {\n  display: flex;\n  flex-wrap: wrap;\n  gap: 0 2ch;\n  margin: 0;\n  padding: 0;\n  list-style: none;\n}\n\n/* footer: one quiet line above the dock */\n.ds-footer {\n  display: flex;\n  flex-wrap: wrap;\n  justify-content: space-between;\n  gap: var(--space-1) 3ch;\n  padding: var(--space-2) 2ch;\n  border-top: var(--border-width) var(--border-style) var(--color-border-muted);\n  color: var(--color-text-muted);\n  font-size: var(--text-small);\n}\n.ds-footer__text {\n  margin: 0;\n}\n.ds-footer__link {\n  color: var(--color-link-quiet);\n  text-decoration: var(--link-decoration-quiet);\n}\n.ds-footer__link:hover,\n.ds-footer__link.is-hover {\n  color: var(--color-link-hover);\n  text-decoration: var(--link-decoration-hover);\n}\n\n/* ---------- narrow windows: one column, nothing scrolls sideways but code ---------- */\n@media (max-width: 900px) {\n  .ds-page-header {\n    flex-direction: column;\n    align-items: flex-start;\n  }\n  .ds-stats,\n  .ds-grid {\n    grid-template-columns: repeat(2, minmax(0, 1fr));\n  }\n  .ds-form__row {\n    grid-template-columns: minmax(0, 1fr);\n  }\n  .ds-form__label {\n    padding: 0;\n  }\n  .ds-form__actions {\n    padding-left: 0;\n  }\n  .ds-table__extra {\n    display: none;\n  }\n  .ds-dialog__backdrop {\n    padding: var(--space-3) 1ch;\n  }\n  .ds-button {\n    white-space: normal;\n  }\n  .ds-table td.ds-table__code {\n    white-space: normal;\n    overflow-wrap: anywhere;\n  }\n  .ds-list__item {\n    grid-template-columns: minmax(0, 1fr);\n  }\n\n  .ds-main {\n    padding: var(--space-3) 2ch var(--space-4);\n  }\n  .ds-topbar {\n    padding: 0 1ch;\n  }\n  .ds-topbar__topic {\n    visibility: hidden;\n  }\n  .ds-cols,\n  .ds-cols--form {\n    grid-template-columns: minmax(0, 1fr);\n  }\n  .ds-side {\n    padding: var(--space-3) 0 0;\n    border-left: 0;\n    border-top: var(--border-width) var(--border-style) var(--color-border);\n  }\n  .ds-hero {\n    padding: var(--space-3) 2ch;\n  }\n  .ds-hero__title {\n    font-size: var(--text-h1);\n  }\n  .ds-stat:nth-child(odd) {\n    padding-left: 0;\n    border-left: 0;\n  }\n  .ds-stat:nth-child(n + 3) {\n    border-top: var(--border-width) var(--border-style) var(--color-border);\n  }\n  .ds-log__line {\n    grid-template-columns: 6ch minmax(0, 1fr);\n  }\n  .ds-log__line {\n    padding-left: 1ch;\n  }\n  .ds-log__time,\n  .ds-log__nick {\n    text-align: left;\n  }\n  .ds-nav__link {\n    padding: var(--space-1) 0.5ch;\n  }\n  .ds-log__text {\n    grid-column: 1 / -1;\n    padding: 0;\n    border-left: 0;\n  }\n  /* the window list keeps its numbers; only the window that shows keeps its name */\n  .ds-nav__name {\n    display: none;\n  }\n  .ds-nav__link.is-current .ds-nav__name,\n  .ds-page:not(:has(.ds-view:target)) .ds-nav__link[href=\"#lobby\"] .ds-nav__name,\n  .ds-page:has(#lobby:target) .ds-nav__link[href=\"#lobby\"] .ds-nav__name,\n  .ds-page:has(#channel:target) .ds-nav__link[href=\"#channel\"] .ds-nav__name,\n  .ds-page:has(#logs:target) .ds-nav__link[href=\"#logs\"] .ds-nav__name,\n  .ds-page:has(#settings:target) .ds-nav__link[href=\"#settings\"] .ds-nav__name,\n  .ds-page:has(#help:target) .ds-nav__link[href=\"#help\"] .ds-nav__name {\n    display: inline;\n  }\n  .ds-nav__clock,\n  .ds-nav__word {\n    display: none;\n  }\n}\n",
    "specimen.html": "<!doctype html>\n<html lang=\"en\">\n<head>\n<meta charset=\"utf-8\">\n<meta name=\"viewport\" content=\"width=device-width, initial-scale=1\">\n<title>chronoskin chat: a text-mode chat client. Terminal, 2015 to 2026: specimen</title>\n<link rel=\"stylesheet\" href=\"tokens.css\">\n<link rel=\"stylesheet\" href=\"components.css\">\n</head>\n<body class=\"ds-page\" data-component=\"shell\">\n<div class=\"ds-client\">\n\n<header class=\"ds-topbar\">\n  <a class=\"ds-brand\" data-component=\"brand\" href=\"#lobby\"><span class=\"ds-brand__mark\"><svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2.6\" stroke-linecap=\"butt\" stroke-linejoin=\"miter\" aria-hidden=\"true\"><polyline points=\"4,6 11,12 4,18\"/><line x1=\"13\" y1=\"19\" x2=\"21\" y2=\"19\"/></svg></span><span class=\"ds-brand__name\">chronoskin</span></a>\n  <p class=\"ds-topbar__topic\">chat.chronoskin.example | 42 online in 12 channels | release 3.2 is out, notes in #announce</p>\n  <details class=\"ds-menu\">\n    <summary class=\"ds-menu__title\">server</summary>\n    <ul class=\"ds-menu__list\">\n      <li><a class=\"ds-menu__item\" href=\"#channel\">join a channel <span class=\"ds-menu__key\">/join</span></a></li>\n      <li><a class=\"ds-menu__item\" href=\"#logs\">search the logs <span class=\"ds-menu__key\">/search</span></a></li>\n      <li><a class=\"ds-menu__item is-hover\" href=\"#settings\">change nick <span class=\"ds-menu__key\">/nick</span></a></li>\n      <li class=\"ds-menu__rule\"></li>\n      <li><a class=\"ds-menu__item\" href=\"#help\">all commands <span class=\"ds-menu__key\">/help</span></a></li>\n      <li><a class=\"ds-menu__item\" href=\"#lobby\">disconnect <span class=\"ds-menu__key\">/quit</span></a></li>\n    </ul>\n  </details>\n</header>\n\n<main class=\"ds-main\">\n\n<!-- View 1, the lobby: message of the day, figures, pinned channels and the channel list, beside who is on. -->\n<section class=\"ds-view ds-view--home\" id=\"lobby\">\n  <div class=\"ds-cols\">\n    <div class=\"ds-col\">\n      <section class=\"ds-hero\" data-component=\"hero\">\n        <p class=\"ds-hero__motd\"><span class=\"ds-hero__sign\">-!-</span> message of the day, set by the operators on 2026-10-05</p>\n        <h1 class=\"ds-hero__title\">Welcome to chronoskin chat</h1>\n        <p class=\"ds-hero__lead\">One server, twelve channels, plain text. Ask about the program in #help, follow the work in #dev, and say hello in #general.</p>\n        <div class=\"ds-buttons\">\n          <a class=\"ds-button\" href=\"#channel\">Join #general</a>\n          <a class=\"ds-button ds-button--secondary\" href=\"#help\">Read the rules</a>\n          <a class=\"ds-link ds-link--bracket\" href=\"#logs\">search the logs</a>\n        </div>\n        <p class=\"ds-hero__note\">You are connected as <strong>reader</strong> over TLS. Your nick is not registered yet.</p>\n      </section>\n\n      <ul class=\"ds-stats\" data-component=\"stats\">\n        <li class=\"ds-stat\"><span class=\"ds-stat__value\">42</span><span class=\"ds-stat__label\">people online</span></li>\n        <li class=\"ds-stat\"><span class=\"ds-stat__value\">12</span><span class=\"ds-stat__label\">channels</span></li>\n        <li class=\"ds-stat\"><span class=\"ds-stat__value\">1,204</span><span class=\"ds-stat__label\">lines today</span></li>\n        <li class=\"ds-stat\"><span class=\"ds-stat__value\">311 d</span><span class=\"ds-stat__label\">server uptime</span></li>\n      </ul>\n\n      <section class=\"ds-section\">\n        <h2 class=\"ds-section__title\">pinned channels</h2>\n        <div class=\"ds-grid\" data-component=\"grid\">\n          <div class=\"ds-grid__cell\">\n            <h3 class=\"ds-grid__title\"><a class=\"ds-link\" href=\"#channel\">#general</a></h3>\n            <p class=\"ds-grid__text\">Everything about the program that has no better place.</p>\n            <p class=\"ds-grid__label\">31 here, 3 unread</p>\n          </div>\n          <div class=\"ds-grid__cell ds-grid__cell--2\">\n            <h3 class=\"ds-grid__title\"><a class=\"ds-link\" href=\"#channel\">#help</a></h3>\n            <p class=\"ds-grid__text\">Questions and answers. Paste the error, not a picture of it.</p>\n            <p class=\"ds-grid__label\">18 here, quiet</p>\n          </div>\n          <div class=\"ds-grid__cell ds-grid__cell--3\">\n            <h3 class=\"ds-grid__title\"><a class=\"ds-link\" href=\"#channel\">#dev</a></h3>\n            <p class=\"ds-grid__text\">Patches, reviews and the build. Logged in public.</p>\n            <p class=\"ds-grid__label\">9 here, 1 mention</p>\n          </div>\n          <div class=\"ds-grid__cell ds-grid__cell--4\">\n            <h3 class=\"ds-grid__title\"><a class=\"ds-link\" href=\"#channel\">#announce</a></h3>\n            <p class=\"ds-grid__text\">Releases and planned downtime. Operators write, all read.</p>\n            <p class=\"ds-grid__label\">40 here, read only</p>\n          </div>\n        </div>\n      </section>\n\n      <section class=\"ds-section\">\n        <h2 class=\"ds-section__title\">/list</h2>\n        <table class=\"ds-table\" data-component=\"table\">\n          <thead>\n            <tr><th>channel</th><th class=\"ds-table__extra\">topic</th><th class=\"ds-table__num\">here</th><th class=\"ds-table__num\">lines today</th><th class=\"ds-table__extra\">last line</th></tr>\n          </thead>\n          <tbody>\n            <tr class=\"is-selected\"><td class=\"ds-table__code\">#general</td><td class=\"ds-table__extra\">Release 3.2 is out. Be kind, stay on topic.</td><td class=\"ds-table__num\">31</td><td class=\"ds-table__num\">486</td><td class=\"ds-table__extra\">14:01</td></tr>\n            <tr class=\"is-alt\"><td class=\"ds-table__code\"><a class=\"ds-table__title\" href=\"#channel\">#help</a></td><td class=\"ds-table__extra\">Ask your question, then wait. Someone will read it.</td><td class=\"ds-table__num\">18</td><td class=\"ds-table__num\">212</td><td class=\"ds-table__date ds-table__extra\">13:48</td></tr>\n            <tr><td class=\"ds-table__code\"><a class=\"ds-table__title\" href=\"#channel\">#dev</a></td><td class=\"ds-table__extra\">Freeze for 3.3 starts on 2026-10-19.</td><td class=\"ds-table__num\">9</td><td class=\"ds-table__num\">340</td><td class=\"ds-table__date ds-table__extra\">13:57</td></tr>\n            <tr class=\"is-alt\"><td class=\"ds-table__code\"><a class=\"ds-table__title\" href=\"#channel\">#announce</a></td><td class=\"ds-table__extra\">Releases and downtime.</td><td class=\"ds-table__num\">40</td><td class=\"ds-table__num\">2</td><td class=\"ds-table__date ds-table__extra\">09:30</td></tr>\n            <tr><td class=\"ds-table__code\"><a class=\"ds-table__title\" href=\"#channel\">#themes</a></td><td class=\"ds-table__extra\">Show your colours. One screenshot a day, please.</td><td class=\"ds-table__num\">14</td><td class=\"ds-table__num\">97</td><td class=\"ds-table__date ds-table__extra\">12:20</td></tr>\n            <tr class=\"is-alt\"><td class=\"ds-table__code\"><a class=\"ds-table__title\" href=\"#channel\">#offtopic</a></td><td class=\"ds-table__extra\">Everything else.</td><td class=\"ds-table__num\">22</td><td class=\"ds-table__num\">67</td><td class=\"ds-table__date ds-table__extra\">13:15</td></tr>\n          </tbody>\n        </table>\n        <p class=\"ds-note\">6 of 12 channels shown. Type <code>/list -all</code> for the rest, or <code>/join #name</code> to open one.</p>\n      </section>\n    </div>\n\n    <aside class=\"ds-side\">\n      <div class=\"ds-sidebar\">\n        <div class=\"ds-sidebar__block\">\n          <h2 class=\"ds-sidebar__title\">on now</h2>\n          <ul class=\"ds-sidebar__list\">\n            <li><a class=\"ds-sidebar__link\" href=\"#channel\"><span class=\"ds-avatar\">mk</span>mika</a><span class=\"ds-sidebar__count\">op</span></li>\n            <li><a class=\"ds-sidebar__link\" href=\"#channel\"><span class=\"ds-avatar ds-avatar--2\">jo</span>jonas</a><span class=\"ds-sidebar__count\">op</span></li>\n            <li><a class=\"ds-sidebar__link\" href=\"#channel\"><span class=\"ds-avatar ds-avatar--3\">ai</span>aiko</a></li>\n            <li><a class=\"ds-sidebar__link\" href=\"#channel\"><span class=\"ds-avatar\">te</span>tereza</a></li>\n            <li><a class=\"ds-sidebar__link\" href=\"#channel\"><span class=\"ds-avatar ds-avatar--2\">ld</span>ludo</a></li>\n            <li><a class=\"ds-sidebar__link\" href=\"#channel\"><span class=\"ds-avatar ds-avatar--3\">bt</span>buildbot</a><span class=\"ds-sidebar__count\">bot</span></li>\n          </ul>\n          <p class=\"ds-sidebar__text\">36 more. <a class=\"ds-link ds-link--quiet\" href=\"#channel\">/names</a> lists them all.</p>\n        </div>\n      </div>\n      <div class=\"ds-panel\" data-component=\"panel\">\n        <h2 class=\"ds-panel__title\">this server</h2>\n        <div class=\"ds-panel__body\">\n          <p class=\"ds-panel__text\">Run by volunteers. Channels are logged for 90 days, private messages never.</p>\n          <p class=\"ds-progress\"><span class=\"ds-progress__label\">history</span><span class=\"ds-progress__bar\"><span class=\"ds-progress__on\">########</span>....</span><span class=\"ds-progress__value\">67%</span></p>\n          <p class=\"ds-progress\"><span class=\"ds-progress__label\">log disk</span><span class=\"ds-progress__bar\"><span class=\"ds-progress__on ds-progress__on--warning\">##########</span>..</span><span class=\"ds-progress__value\">84%</span></p>\n          <p class=\"ds-panel__text\"><span class=\"ds-tooltip\" tabindex=\"0\">lag 38 ms<span class=\"ds-tooltip__tip\" role=\"tooltip\">The time a line takes from your key to the server and back.</span></span>, last netsplit 61 days ago.</p>\n        </div>\n      </div>\n      <div class=\"ds-panel\">\n        <h2 class=\"ds-panel__title\">named you</h2>\n        <div class=\"ds-panel__body\">\n          <p class=\"ds-panel__text\"><a class=\"ds-link\" href=\"#channel\">#general 13:50</a> jonas: your patch for the status line went in.</p>\n          <p class=\"ds-panel__text\"><a class=\"ds-link\" href=\"#channel\">#dev 11:32</a> mika: reader, can you test the tarball?</p>\n          <p class=\"ds-panel__text\"><a class=\"ds-link is-visited\" href=\"#logs\">#help yesterday</a> aiko: thanks, reader, that fixed it.</p>\n        </div>\n      </div>\n    </aside>\n  </div>\n</section>\n\n<!-- View 2, a channel: the log with its day rule, joins and a mention, beside the names. -->\n<section class=\"ds-view\" id=\"channel\">\n  <ol class=\"ds-breadcrumb\" data-component=\"breadcrumb\">\n    <li><a class=\"ds-breadcrumb__link\" href=\"#lobby\">chronoskin</a></li>\n    <li class=\"ds-breadcrumb__sep\">/</li>\n    <li><a class=\"ds-breadcrumb__link\" href=\"#lobby\">channels</a></li>\n    <li class=\"ds-breadcrumb__sep\">/</li>\n    <li class=\"ds-breadcrumb__current\">#general</li>\n  </ol>\n  <header class=\"ds-page-header\" data-component=\"page-header\">\n    <div class=\"ds-page-header__main\">\n      <h1 class=\"ds-page-header__title\">#general</h1>\n      <p class=\"ds-page-header__text\">Topic: release 3.2 is out. Be kind, stay on topic. Set by mika on 2026-10-05.</p>\n    </div>\n    <div class=\"ds-page-header__action\"><a class=\"ds-button ds-button--secondary\" href=\"#lobby\">Leave</a></div>\n  </header>\n  <div class=\"ds-cols\">\n    <div class=\"ds-col\">\n      <div class=\"ds-notices\" data-component=\"notice\">\n        <p class=\"ds-notice\"><span class=\"ds-notice__title\">Joined.</span> You are in #general with 30 others. The last 200 lines were replayed.</p>\n        <p class=\"ds-notice ds-notice--error\"><span class=\"ds-notice__title\">Bridge down.</span> Lines from the mail gateway are late since 13:20. Nothing is lost.</p>\n      </div>\n      <ol class=\"ds-log\">\n        <li class=\"ds-log__day\">Tuesday, 6 October 2026</li>\n        <li class=\"ds-log__line\"><time class=\"ds-log__time\">13:41</time><span class=\"ds-log__nick\">mika</span><p class=\"ds-log__text\">3.2 is tagged. Packages follow within the hour.</p></li>\n        <li class=\"ds-log__line\"><time class=\"ds-log__time\">13:42</time><span class=\"ds-log__nick\">aiko</span><p class=\"ds-log__text\">Does the new pager keep its place after a resize?</p></li>\n        <li class=\"ds-log__line\"><time class=\"ds-log__time\">13:42</time><span class=\"ds-log__nick\">mika</span><p class=\"ds-log__text\">It does. Set <code>pager.keep = true</code> if you ran an older config.</p></li>\n        <li class=\"ds-log__line ds-log__line--event\"><time class=\"ds-log__time\">13:44</time><span class=\"ds-log__nick\">-!-</span><p class=\"ds-log__text\">ludo has joined #general</p></li>\n        <li class=\"ds-log__line\"><time class=\"ds-log__time\">13:45</time><span class=\"ds-log__nick\">ludo</span><p class=\"ds-log__text\">Morning. The tarball builds clean on my old laptop, 41 seconds.</p></li>\n        <li class=\"ds-log__line\"><time class=\"ds-log__time\">13:47</time><span class=\"ds-log__nick\">buildbot</span><p class=\"ds-log__text\">Build 3.2.0 passed on 6 of 6 targets.</p></li>\n        <li class=\"ds-log__line is-mention\"><time class=\"ds-log__time\">13:50</time><span class=\"ds-log__nick\">jonas</span><p class=\"ds-log__text\">reader: your patch for the status line went in, thank you.</p></li>\n        <li class=\"ds-log__line\"><time class=\"ds-log__time\">13:52</time><span class=\"ds-log__nick\">tereza</span><p class=\"ds-log__text\">Where do the release notes live now?</p></li>\n        <li class=\"ds-log__line\"><time class=\"ds-log__time\">13:53</time><span class=\"ds-log__nick\">buildbot</span><div class=\"ds-log__text\"><ul class=\"ds-links\" data-component=\"links\">\n          <li><a class=\"ds-link\" href=\"#help\">release notes</a></li>\n          <li><a class=\"ds-link is-visited\" href=\"#help\">upgrade guide (visited)</a></li>\n          <li><a class=\"ds-link is-hover\" href=\"#logs\">yesterday's log (hover)</a></li>\n          <li><a class=\"ds-link is-active\" href=\"#help\">known issues (active)</a></li>\n        </ul></div></li>\n        <li class=\"ds-log__line ds-log__line--event\"><time class=\"ds-log__time\">13:55</time><span class=\"ds-log__nick\">-!-</span><p class=\"ds-log__text\">mode/#general [+v ludo] by mika</p></li>\n        <li class=\"ds-log__line\"><time class=\"ds-log__time\">13:58</time><span class=\"ds-log__nick\">aiko</span><p class=\"ds-log__text\">Upgraded two machines. Nothing to report, which is the best report.</p></li>\n        <li class=\"ds-log__line\"><time class=\"ds-log__time\">14:01</time><span class=\"ds-log__nick\">ludo</span><p class=\"ds-log__text\">Same here. Off to read the notes.</p></li>\n      </ol>\n      <ul class=\"ds-pagination\" data-component=\"pagination\">\n        <li><a class=\"ds-pagination__link\" href=\"#logs\">&lt; older</a></li>\n        <li><a class=\"ds-pagination__link\" href=\"#logs\">1</a></li>\n        <li><a class=\"ds-pagination__link\" href=\"#logs\">2</a></li>\n        <li><span class=\"ds-pagination__link is-current\">3</span></li>\n        <li><span class=\"ds-pagination__link is-disabled\">newer &gt;</span></li>\n      </ul>\n    </div>\n\n    <aside class=\"ds-side\">\n      <div class=\"ds-sidebar\" data-component=\"sidebar\">\n        <div class=\"ds-sidebar__block\">\n          <h2 class=\"ds-sidebar__title\">operators</h2>\n          <ul class=\"ds-sidebar__list\">\n            <li><a class=\"ds-sidebar__link\" href=\"#channel\"><span class=\"ds-avatar\">mk</span>mika</a><span class=\"ds-sidebar__count\">@</span></li>\n            <li><a class=\"ds-sidebar__link\" href=\"#channel\"><span class=\"ds-avatar ds-avatar--2\">jo</span>jonas</a><span class=\"ds-sidebar__count\">@</span></li>\n          </ul>\n        </div>\n        <div class=\"ds-sidebar__block\">\n          <h2 class=\"ds-sidebar__title\">here, 31</h2>\n          <ul class=\"ds-sidebar__list\">\n            <li><a class=\"ds-sidebar__link\" href=\"#channel\"><span class=\"ds-avatar ds-avatar--3\">ai</span>aiko</a></li>\n            <li><a class=\"ds-sidebar__link\" href=\"#channel\"><span class=\"ds-avatar ds-avatar--3\">bt</span>buildbot</a><span class=\"ds-sidebar__count\">bot</span></li>\n            <li><a class=\"ds-sidebar__link\" href=\"#channel\"><span class=\"ds-avatar ds-avatar--2\">ld</span>ludo</a><span class=\"ds-sidebar__count\">+</span></li>\n            <li><a class=\"ds-sidebar__link is-current\" href=\"#settings\"><span class=\"ds-avatar\">re</span>reader</a><span class=\"ds-sidebar__count\">you</span></li>\n            <li><a class=\"ds-sidebar__link\" href=\"#channel\"><span class=\"ds-avatar\">te</span>tereza</a></li>\n          </ul>\n          <p class=\"ds-sidebar__text\">26 more are idle. <span class=\"ds-tooltip\" tabindex=\"0\">What the signs mean<span class=\"ds-tooltip__tip\" role=\"tooltip\">@ may set the topic and remove people. + may speak when the channel is moderated.</span></span></p>\n        </div>\n      </div>\n      <div class=\"ds-panel\">\n        <h2 class=\"ds-panel__title\">status words</h2>\n        <div class=\"ds-panel__body\">\n          <div class=\"ds-badges\" data-component=\"badge\">\n            <span class=\"ds-badge\">3</span>\n            <span class=\"ds-badge ds-badge--success\">here</span>\n            <span class=\"ds-badge ds-badge--warning\">away</span>\n            <span class=\"ds-badge ds-badge--danger\">muted</span>\n            <span class=\"ds-badge ds-badge--tag\">release</span>\n          </div>\n          <p class=\"ds-panel__text\">The count is unread lines that name you.</p>\n        </div>\n      </div>\n    </aside>\n  </div>\n</section>\n\n<!-- View 3, the logs: a search, its hits under tabs, the empty state of shared files, the archive by month. -->\n<section class=\"ds-view\" id=\"logs\">\n  <ol class=\"ds-breadcrumb\">\n    <li><a class=\"ds-breadcrumb__link\" href=\"#lobby\">chronoskin</a></li>\n    <li class=\"ds-breadcrumb__sep\">/</li>\n    <li class=\"ds-breadcrumb__current\">logs</li>\n  </ol>\n  <header class=\"ds-page-header\">\n    <div class=\"ds-page-header__main\">\n      <h1 class=\"ds-page-header__title\">Logs</h1>\n      <p class=\"ds-page-header__text\">Every public channel, kept for 90 days. Search them or read a day from the top.</p>\n    </div>\n    <div class=\"ds-page-header__action\"><a class=\"ds-button ds-button--secondary\" href=\"#settings\">Log settings</a></div>\n  </header>\n  <div class=\"ds-cols\">\n    <div class=\"ds-col\">\n      <p class=\"ds-prompt\"><span class=\"ds-prompt__sign\">/search</span> <span class=\"ds-prompt__path\">-channel #general</span> pager resize</p>\n      <ul class=\"ds-tabs\" data-component=\"tabs\">\n        <li><span class=\"ds-tabs__tab is-current\">lines 18</span></li>\n        <li><a class=\"ds-tabs__tab\" href=\"#logs\">files 0</a></li>\n        <li><a class=\"ds-tabs__tab\" href=\"#logs\">pinned 3</a></li>\n      </ul>\n      <div class=\"ds-tabs__body\">\n        <ul class=\"ds-list\" data-component=\"list\">\n          <li class=\"ds-list__item\">\n            <span class=\"ds-list__date\">10-06 13:42</span>\n            <div class=\"ds-list__main\">\n              <a class=\"ds-list__title\" href=\"#channel\">#general, aiko</a>\n              <p class=\"ds-list__excerpt\">Does the new pager keep its place after a resize?</p>\n              <p class=\"ds-list__meta\">2 replies in the next minute</p>\n            </div>\n          </li>\n          <li class=\"ds-list__item\">\n            <span class=\"ds-list__date\">10-02 09:15</span>\n            <div class=\"ds-list__main\">\n              <a class=\"ds-list__title is-visited\" href=\"#channel\">#dev, jonas</a>\n              <p class=\"ds-list__excerpt\">The pager loses its line on resize when wrapping is off. Patch attached.</p>\n              <p class=\"ds-list__meta\">7 replies, closed by a commit</p>\n            </div>\n          </li>\n          <li class=\"ds-list__item\">\n            <span class=\"ds-list__date\">09-28 21:03</span>\n            <div class=\"ds-list__main\">\n              <a class=\"ds-list__title\" href=\"#channel\">#help, tereza</a>\n              <p class=\"ds-list__excerpt\">After a resize the pager jumps to the top. Is that a setting?</p>\n              <p class=\"ds-list__meta\">4 replies, answered</p>\n            </div>\n          </li>\n          <li class=\"ds-list__item\">\n            <span class=\"ds-list__date\">09-11 16:40</span>\n            <div class=\"ds-list__main\">\n              <a class=\"ds-list__title\" href=\"#channel\">#general, ludo</a>\n              <p class=\"ds-list__excerpt\">Small request: let the pager remember its place when the window changes size.</p>\n              <p class=\"ds-list__meta\">11 replies, where it all began</p>\n            </div>\n          </li>\n        </ul>\n      </div>\n      <h2 class=\"ds-section__title\">files 0</h2>\n      <div class=\"ds-empty\" data-component=\"empty\">\n        <p class=\"ds-empty__text\">No file that matches was shared in the last 90 days.</p>\n        <a class=\"ds-button ds-button--secondary\" href=\"#logs\">Search all channels</a>\n      </div>\n    </div>\n    <aside class=\"ds-side\">\n      <div class=\"ds-panel\">\n        <h2 class=\"ds-panel__title\">archive</h2>\n        <div class=\"ds-panel__body\">\n          <div class=\"ds-accordion\">\n            <details class=\"ds-accordion__item\" open>\n              <summary class=\"ds-accordion__title\">2026-10</summary>\n              <div class=\"ds-accordion__body\">\n                <p><a class=\"ds-link\" href=\"#channel\">10-06, today</a></p>\n                <p><a class=\"ds-link is-visited\" href=\"#channel\">10-05, 1,512 lines</a></p>\n                <p><a class=\"ds-link\" href=\"#channel\">10-04, 640 lines</a></p>\n              </div>\n            </details>\n            <details class=\"ds-accordion__item\">\n              <summary class=\"ds-accordion__title\">2026-09</summary>\n              <div class=\"ds-accordion__body\"><p>30 days, 28,204 lines.</p></div>\n            </details>\n            <details class=\"ds-accordion__item\">\n              <summary class=\"ds-accordion__title\">2026-08</summary>\n              <div class=\"ds-accordion__body\"><p>31 days, 24,880 lines.</p></div>\n            </details>\n          </div>\n        </div>\n      </div>\n      <div class=\"ds-panel\">\n        <h2 class=\"ds-panel__title\">search words</h2>\n        <div class=\"ds-panel__body\">\n          <p class=\"ds-panel__text\"><code>-channel</code> limits to one channel, <code>-nick</code> to one person, <code>-since</code> to a date.</p>\n        </div>\n      </div>\n    </aside>\n  </div>\n</section>\n\n<!-- View 4, settings: the account form beside the switches and the question before an account is removed. -->\n<section class=\"ds-view\" id=\"settings\">\n  <ol class=\"ds-breadcrumb\">\n    <li><a class=\"ds-breadcrumb__link\" href=\"#lobby\">chronoskin</a></li>\n    <li class=\"ds-breadcrumb__sep\">/</li>\n    <li class=\"ds-breadcrumb__current\">settings</li>\n  </ol>\n  <header class=\"ds-page-header\">\n    <div class=\"ds-page-header__main\">\n      <h1 class=\"ds-page-header__title\">Settings</h1>\n      <p class=\"ds-page-header__text\">Your nick, what counts as a mention, and what the client shows.</p>\n    </div>\n    <div class=\"ds-page-header__action\"><a class=\"ds-button ds-button--secondary\" href=\"#help\">Help</a></div>\n  </header>\n  <div class=\"ds-cols ds-cols--form\">\n    <div class=\"ds-col\">\n      <h2 class=\"ds-section__title\">account</h2>\n      <form class=\"ds-form\" data-component=\"form\">\n        <div class=\"ds-form__row\">\n          <label class=\"ds-form__label\" for=\"f-nick\">nick</label>\n          <div class=\"ds-form__field\"><input class=\"ds-form__input\" id=\"f-nick\" type=\"text\" value=\"reader\"></div>\n        </div>\n        <div class=\"ds-form__row\">\n          <label class=\"ds-form__label\" for=\"f-mail\">mail</label>\n          <div class=\"ds-form__field\">\n            <input class=\"ds-form__input is-invalid\" id=\"f-mail\" type=\"text\" value=\"reader@example\">\n            <p class=\"ds-form__error\">This address has no domain ending. A nick is registered by mail.</p>\n          </div>\n        </div>\n        <div class=\"ds-form__row\">\n          <label class=\"ds-form__label\" for=\"f-away\">when away</label>\n          <div class=\"ds-form__field\">\n            <select class=\"ds-form__input ds-form__input--auto\" id=\"f-away\">\n              <option>keep the lines for me</option>\n              <option>mail me the mentions</option>\n              <option>do nothing</option>\n            </select>\n          </div>\n        </div>\n        <div class=\"ds-form__row\">\n          <label class=\"ds-form__label\" for=\"f-words\">mention on</label>\n          <div class=\"ds-form__field\">\n            <textarea class=\"ds-form__input ds-form__input--wide\" id=\"f-words\" rows=\"3\">reader\nstatus line\npager</textarea>\n            <p class=\"ds-form__hint\">One word or phrase a line. Your nick always counts.</p>\n          </div>\n        </div>\n        <div class=\"ds-form__row\">\n          <span class=\"ds-form__label\">privacy</span>\n          <div class=\"ds-form__field\">\n            <label class=\"ds-form__check\"><input class=\"ds-form__checkbox\" type=\"checkbox\" checked> hide my address from /whois</label>\n          </div>\n        </div>\n        <div class=\"ds-form__actions\" data-component=\"buttons\">\n          <button class=\"ds-button\" type=\"button\">Save</button>\n          <button class=\"ds-button ds-button--secondary\" type=\"button\">Reset</button>\n          <button class=\"ds-button ds-button--danger\" type=\"button\">Drop nick</button>\n          <button class=\"ds-button\" type=\"button\" disabled>Export</button>\n        </div>\n      </form>\n    </div>\n    <div class=\"ds-stack\">\n      <div class=\"ds-panel\">\n        <h2 class=\"ds-panel__title\">the client shows</h2>\n        <div class=\"ds-panel__body\">\n          <div class=\"ds-setting\"><label class=\"ds-switch\"><span class=\"ds-switch__label\">joins and parts</span><input class=\"ds-switch__input\" type=\"checkbox\" checked><span class=\"ds-switch__track\"></span></label></div>\n          <div class=\"ds-setting\"><label class=\"ds-switch\"><span class=\"ds-switch__label\">seconds in the time</span><input class=\"ds-switch__input\" type=\"checkbox\"><span class=\"ds-switch__track\"></span></label></div>\n          <div class=\"ds-setting\"><label class=\"ds-switch\"><span class=\"ds-switch__label\">a bell on mentions</span><input class=\"ds-switch__input\" type=\"checkbox\" checked><span class=\"ds-switch__track\"></span></label></div>\n          <div class=\"ds-setting\"><label class=\"ds-switch\"><span class=\"ds-switch__label\">names in colour</span><input class=\"ds-switch__input\" type=\"checkbox\"><span class=\"ds-switch__track\"></span></label></div>\n        </div>\n      </div>\n      <div class=\"ds-dialog__backdrop\">\n        <div class=\"ds-dialog\" data-component=\"dialog\" role=\"dialog\" aria-labelledby=\"dlg-1\">\n          <h2 class=\"ds-dialog__title\" id=\"dlg-1\">drop the nick?</h2>\n          <div class=\"ds-dialog__body\">\n            <p class=\"ds-dialog__text\">reader will be free for anyone to take after 30 days. Your lines stay in the logs.</p>\n            <div class=\"ds-dialog__actions\">\n              <button class=\"ds-button ds-button--danger\" type=\"button\">Drop it</button>\n              <a class=\"ds-button ds-button--secondary\" href=\"#settings\">Keep it</a>\n            </div>\n          </div>\n        </div>\n      </div>\n    </div>\n  </div>\n</section>\n\n<!-- View 5, help: the rules and first steps as running text, beside the commands as a folding tree. -->\n<section class=\"ds-view\" id=\"help\">\n  <ol class=\"ds-breadcrumb\">\n    <li><a class=\"ds-breadcrumb__link\" href=\"#lobby\">chronoskin</a></li>\n    <li class=\"ds-breadcrumb__sep\">/</li>\n    <li class=\"ds-breadcrumb__current\">help</li>\n  </ol>\n  <header class=\"ds-page-header\">\n    <div class=\"ds-page-header__main\">\n      <h1 class=\"ds-page-header__title\">Help</h1>\n      <p class=\"ds-page-header__text\">The rules of the place and the commands that get you around it.</p>\n    </div>\n    <div class=\"ds-page-header__action\"><a class=\"ds-button\" href=\"#channel\">Ask in #help</a></div>\n  </header>\n  <div class=\"ds-cols ds-cols--form\">\n    <div class=\"ds-col\">\n      <div class=\"ds-prose\" data-component=\"typography\">\n        <h1>Rules and first steps</h1>\n        <p>chronoskin chat is a small server for people who use and build <strong>chronoskin</strong>. It speaks a plain line protocol, so any client works; this page is one of them.</p>\n        <h2>Three rules</h2>\n        <ul>\n          <li>Be kind. Disagree with the idea, not with the person.</li>\n          <li>Paste text, not pictures of text. Long pastes go to a file.</li>\n          <li>Ask your question at once; do not ask whether you may ask.</li>\n        </ul>\n        <h2>Getting around</h2>\n        <p>Everything is a command typed into the input line at the foot. A command starts with a slash: <code>/join #help</code> opens a channel, <code>/part</code> leaves it.</p>\n        <h3>Windows</h3>\n        <p>Each channel is a window with a number. The window list above the input line shows them, and the one you are reading is cut out of the bar.</p>\n        <h3>Mentions</h3>\n        <p>A line that names you is set on a stronger ground with a mark at its left edge, and its window gets a count.</p>\n      </div>\n    </div>\n    <div class=\"ds-stack\">\n      <div class=\"ds-panel\">\n        <h2 class=\"ds-panel__title\">commands</h2>\n        <div class=\"ds-panel__body\">\n          <div class=\"ds-accordion\">\n            <details class=\"ds-accordion__item\" open>\n              <summary class=\"ds-accordion__title\">channels</summary>\n              <div class=\"ds-accordion__body\">\n                <p><code>/join #name</code> open a channel</p>\n                <p><code>/part</code> leave this one</p>\n                <p><code>/topic text</code> set the topic</p>\n              </div>\n            </details>\n            <details class=\"ds-accordion__item\">\n              <summary class=\"ds-accordion__title\">people</summary>\n              <div class=\"ds-accordion__body\"><p><code>/msg nick text</code> write to one person</p></div>\n            </details>\n            <details class=\"ds-accordion__item\">\n              <summary class=\"ds-accordion__title\">yourself</summary>\n              <div class=\"ds-accordion__body\"><p><code>/nick name</code> take another name</p></div>\n            </details>\n            <details class=\"ds-accordion__item\">\n              <summary class=\"ds-accordion__title\">the server</summary>\n              <div class=\"ds-accordion__body\"><p><code>/list</code> every public channel</p></div>\n            </details>\n          </div>\n        </div>\n      </div>\n      <div class=\"ds-panel\">\n        <h2 class=\"ds-panel__title\">keys</h2>\n        <div class=\"ds-panel__body\">\n          <ul class=\"ds-keys\">\n            <li class=\"ds-key\"><span class=\"ds-key__cap\">alt 1..9</span> window</li>\n            <li class=\"ds-key\"><span class=\"ds-key__cap\">tab</span> finish a nick</li>\n            <li class=\"ds-key\"><span class=\"ds-key__cap\">pgup</span> older lines</li>\n            <li class=\"ds-key\"><span class=\"ds-key__cap\">ctrl l</span> redraw</li>\n          </ul>\n        </div>\n      </div>\n    </div>\n  </div>\n</section>\n\n</main>\n\n<footer class=\"ds-footer\" data-component=\"footer\">\n  <ul class=\"ds-keys\">\n    <li><a class=\"ds-footer__link\" href=\"#help\">rules</a></li>\n    <li><a class=\"ds-footer__link\" href=\"#logs\">logs</a></li>\n    <li><a class=\"ds-footer__link\" href=\"#settings\">settings</a></li>\n  </ul>\n  <p class=\"ds-footer__text\">chronoskin chat 3.2.0, a plain text server run by its users</p>\n</footer>\n\n<div class=\"ds-dock\">\n  <nav class=\"ds-nav\" data-component=\"nav\">\n    <p class=\"ds-nav__clock\">[14:02]</p>\n    <ul class=\"ds-nav__list\">\n      <li><a class=\"ds-nav__link\" href=\"#lobby\"><span class=\"ds-nav__num\">1</span><span class=\"ds-nav__name\">lobby</span></a></li>\n      <li><a class=\"ds-nav__link\" href=\"#channel\"><span class=\"ds-nav__num\">2</span><span class=\"ds-nav__name\">#general</span></a></li>\n      <li><a class=\"ds-nav__link\" href=\"#logs\"><span class=\"ds-nav__num\">3</span><span class=\"ds-nav__name\">logs</span></a></li>\n      <li><a class=\"ds-nav__link\" href=\"#settings\"><span class=\"ds-nav__num\">4</span><span class=\"ds-nav__name\">settings</span></a></li>\n      <li><a class=\"ds-nav__link\" href=\"#help\"><span class=\"ds-nav__num\">5</span><span class=\"ds-nav__name\">help</span></a></li>\n    </ul>\n    <p class=\"ds-nav__act\"><span class=\"ds-nav__word\">unread</span> <span class=\"ds-badge\">3</span></p>\n  </nav>\n  <label class=\"ds-dock__input\"><span class=\"ds-dock__who\">[reader]</span><input class=\"ds-form__input\" type=\"text\" placeholder=\"type a line, or /help\"></label>\n</div>\n\n</div>\n</body>\n</html>\n",
    "style.json": "{\n  \"id\": \"v1.terminal.app.s07.p06.t07.u05\",\n  \"library\": \"2026.10.09-1346\",\n  \"era\": {\n    \"slug\": \"terminal\",\n    \"years\": [\n      2015,\n      2026\n    ]\n  },\n  \"archetype\": \"app\",\n  \"mode\": \"mix\",\n  \"markup\": \"modern\",\n  \"viewport\": {\n    \"width\": 1280,\n    \"fluid\": false,\n    \"responsive\": true\n  },\n  \"source\": \"https://chrono.skin/s/v1-tm-7675\",\n  \"short\": \"v1-tm-7675\"\n}\n",
    "tokens.css": "/* @part palette */\n:root {\n  --color-page: #070400;\n  --color-canvas: #120a00;\n  --color-surface: #1a0f00;\n  --color-surface-alt: #241500;\n  --color-surface-strong: #382100;\n  --color-bar: #ffb000;\n  --color-bar-text: #120a00;\n  --color-bar-alt: #382100;\n  --color-bar-alt-text: #ffc955;\n  --color-inverse: #ffcf70;\n  --color-inverse-text: #120a00;\n  --color-text: #e89b00;\n  --color-text-muted: #a86c00;\n  --color-heading: #ffcf70;\n  --color-heading-alt: #fff1b8;\n  --color-link: #ffd98f;\n  --color-link-quiet: #e89b00;\n  --color-link-visited: #c98f52;\n  --color-link-hover: #fff7dd;\n  --color-link-active: #ffffff;\n  --color-border: #7d4c00;\n  --color-border-strong: #e89b00;\n  --color-border-muted: #472b00;\n  --color-accent: #fff1b8;\n  --color-accent-text: #120a00;\n  --color-accent-alt: #ff7a1a;\n  --color-fill-1: #1a0f00;\n  --color-fill-2: #241500;\n  --color-fill-3: #382100;\n  --color-fill-4: #241500;\n  --color-button: #e89b00;\n  --color-button-text: #120a00;\n  --color-button-hover-text: #000000;\n  --color-button-secondary: #241500;\n  --color-button-secondary-text: #ffcf70;\n  --color-input: #070400;\n  --color-input-text: #ffcf70;\n  --color-input-border: #7d4c00;\n  --color-disabled: #241500;\n  --color-disabled-text: #7d4c00;\n  --color-danger: #ff5a36;\n  --color-danger-surface: #2a0800;\n  --color-success: #b5e853;\n  --color-warning: #ffee58;\n  --color-notice: #241500;\n  --color-notice-text: #ffcf70;\n  --color-focus: #fff1b8;\n  --color-shadow: #000000;\n  --color-overlay: #382100;\n}\n\n/* @part type */\n:root {\n  --font-body: \"Cascadia Mono\", Consolas, \"Lucida Console\", Menlo, \"Liberation Mono\", monospace;\n  --font-heading: \"Cascadia Mono\", Consolas, \"Lucida Console\", Menlo, \"Liberation Mono\", monospace;\n  --font-ui: \"Cascadia Mono\", Consolas, \"Lucida Console\", Menlo, \"Liberation Mono\", monospace;\n  --font-mono: \"Cascadia Mono\", Consolas, \"Lucida Console\", Menlo, \"Liberation Mono\", monospace;\n  --text-base: 16px;\n  --text-small: 15px;\n  --text-ui: 16px;\n  --text-large: 18px;\n  --text-display: 26px;\n  --text-h1: 20px;\n  --text-h2: 16px;\n  --text-h3: 16px;\n  --line-body: 1.2;\n  --line-heading: 1.2;\n  --line-display: 1.1;\n  --weight-body: 400;\n  --weight-bold: 700;\n  --weight-heading: 700;\n  --weight-display: 700;\n  --weight-ui: 700;\n  --heading-transform: none;\n  --heading-tracking: 0;\n  --display-tracking: 0;\n  --figure-shift: 0em;\n  --ui-transform: none;\n  --link-decoration: none;\n  --link-decoration-hover: underline;\n  --link-decoration-quiet: none;\n}\n\n/* @part surface */\n:root {\n  --border-width: 1px;\n  --border-width-strong: 1px;\n  --border-style: solid;\n  --radius-control: 0;\n  --radius-panel: 0;\n  --radius-pill: 0;\n  --radius-page: 0;\n  --shadow-panel: 1px 1px 0 var(--color-shadow);\n  --shadow-control: none;\n  --shadow-control-hover: inset 0 -2px 0 var(--color-focus);\n  --shadow-control-pressed: inset 0 0 0 1px var(--color-shadow);\n  --shadow-dialog: 4px 4px 0 var(--color-shadow);\n  --shadow-text: none;\n  --fill-page: var(--color-page);\n  --fill-bar: var(--color-bar);\n  --fill-bar-alt: var(--color-bar-alt);\n  --fill-inverse: var(--color-inverse);\n  --fill-accent: var(--color-accent);\n  --fill-panel: var(--color-canvas);\n  --fill-button: var(--color-button);\n  --fill-button-hover: color-mix(in srgb, var(--color-button) 75%, black);\n  --fill-button-secondary: var(--color-button-secondary);\n  --fill-input: var(--color-input);\n  --focus-ring: 1px dashed var(--color-focus);\n  --transition: none;\n  --backdrop-blur: 0px;\n}\n"
  }
}
