/*!
 * namespace.css
 * A 1-bit component library where a terminal and a 1984 Macintosh share one screen.
 * No build step, no dependencies, no JavaScript. One file.
 * MIT licensed.
 */

/* ==========================================================================
   1. TOKENS
   ========================================================================== */

:root {
  color-scheme: light only;

  /* Ink and paper. The whole system is two colors plus dither. */
  --ns-paper: #ffffff;
  --ns-ink: #000000;
  --ns-ink-soft: #565656;
  --ns-ink-faint: #8b8b8b;
  --ns-wash: #f2f2ee;
  --ns-rule: #c8c8c2;
  --ns-danger: #8f2525;

  /* Metrics */
  --ns-unit: 4px;
  --ns-border: 1px;
  --ns-chrome-height: 22px;
  --ns-shadow: 2px 2px 0 var(--ns-ink);
  --ns-shadow-deep: 4px 4px 0 var(--ns-ink);

  /* The mark inside a chip: the badge pip is drawn, not typed, so it centres
     on the box instead of hanging off a baseline. */
  --ns-pip: 6px;

  /* How far each window in a deck steps down and across from the one behind. */
  --ns-deck-step: calc(var(--ns-unit) * 6);

  /* Two corners, not four. Controls get one small modern radius and
     surfaces stay square, so nothing has to guess. */
  --ns-radius: 3px;
  --ns-radius-surface: 0px;

  /* Control heights. Everything you can click lands on one of these three,
     so a button, an input and a tag never disagree about the baseline. */
  --ns-h-lg: 28px;
  --ns-h-md: 24px;
  --ns-h-sm: 20px;

  /* Type */
  --ns-font-ui: "ChicagoFLF", "Chicago", "Charcoal", "Geneva", "IBM Plex Mono",
    ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
  --ns-font-mono: "IBM Plex Mono", ui-monospace, SFMono-Regular, Menlo, Consolas,
    "Liberation Mono", monospace;

  /* One base, one scale. --ns-size sets the root, --ns-text-base is that root
     expressed as a step, and every other step is a multiple of it. Nothing in
     this file states a font size any other way, so a heading, a button and a
     chip cannot drift apart, and moving the base moves all of them together. */
  --ns-size: 15px;
  --ns-text-base: 1rem;
  --ns-text-xs: calc(var(--ns-text-base) * 0.7);
  --ns-text-sm: calc(var(--ns-text-base) * 0.8);
  --ns-text-md: calc(var(--ns-text-base) * 0.9);
  --ns-text-lg: calc(var(--ns-text-base) * 1.2);
  --ns-text-xl: calc(var(--ns-text-base) * 1.45);
  --ns-text-2xl: calc(var(--ns-text-base) * 1.75);

  /* The one relative step. Code set inside running text follows its host
     rather than the scale, because it has to match the line it sits on. */
  --ns-text-code: 0.9em;

  /* The menu strip, used for the desktop bar and for the sub-nav under a
     window title. Override these four and every strip on the page follows. */
  --ns-nav-height: var(--ns-chrome-height);
  --ns-nav-size: var(--ns-text-sm);
  --ns-nav-pad: calc(var(--ns-unit) * 2);
  --ns-nav-bg: var(--ns-paper);
  --ns-nav-ink: var(--ns-ink);

  /* Ordered dither patterns, drawn as pixels rather than faked with opacity. */
  --ns-dither-12: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='4' height='4' shape-rendering='crispEdges'%3E%3Cpath d='M0 0h1v1H0zM2 2h1v1H2z' fill='%23000'/%3E%3C/svg%3E");
  --ns-dither-25: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='2' height='2' shape-rendering='crispEdges'%3E%3Cpath d='M0 0h1v1H0z' fill='%23000'/%3E%3C/svg%3E");
  --ns-dither-50: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='2' height='2' shape-rendering='crispEdges'%3E%3Cpath d='M0 0h1v1H0zM1 1h1v1H1z' fill='%23000'/%3E%3C/svg%3E");
  --ns-dither-75: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='2' height='2' shape-rendering='crispEdges'%3E%3Cpath d='M0 0h2v1H0zM0 1h1v1H0z' fill='%23000'/%3E%3C/svg%3E");

  /* The title bar rule stack. Six lines, two pixels apart. */
  --ns-pinstripe: repeating-linear-gradient(
    to bottom,
    var(--ns-ink) 0 1px,
    transparent 1px 2px
  );
}

/* ==========================================================================
   2. RESET AND BASE
   ========================================================================== */

*,
*::before,
*::after {
  box-sizing: border-box;
}

html {
  background: var(--ns-paper);
  font-size: var(--ns-size);
  -webkit-text-size-adjust: 100%;
}

body {
  margin: 0;
  background: var(--ns-paper);
  color: var(--ns-ink);
  font-family: var(--ns-font-mono);
  font-variant-numeric: tabular-nums;
  line-height: 1.55;
}

img,
svg,
video {
  max-width: 100%;
  height: auto;
}

/* Screenshots, avatars and any 1-bit art stay chunky instead of smoothed. */
.ns-pixel,
.ns-pixel img {
  image-rendering: pixelated;
  filter: grayscale(1) contrast(1.1);
}

::selection {
  background: var(--ns-ink);
  color: var(--ns-paper);
}

:focus-visible {
  outline: 2px solid var(--ns-ink);
  outline-offset: 2px;
}

hr {
  height: 0;
  margin: calc(var(--ns-unit) * 6) 0;
  border: 0;
  border-top: 1px solid var(--ns-rule);
}

a {
  color: inherit;
  text-underline-offset: 0.18em;
}

a:hover {
  text-decoration-thickness: 2px;
}

/* ==========================================================================
   3. TYPE
   ========================================================================== */

h1,
h2,
h3,
h4,
h5,
h6 {
  margin: 0 0 calc(var(--ns-unit) * 2);
  color: var(--ns-ink);
  font-family: var(--ns-font-ui);
  font-weight: 700;
  letter-spacing: -0.02em;
  line-height: 1.2;
}

h1 { font-size: var(--ns-text-2xl); }
h2 { font-size: var(--ns-text-xl); }
h3 { font-size: var(--ns-text-lg); }
h4 { font-size: var(--ns-text-base); }
h5 { font-size: var(--ns-text-md); }
h6 { font-size: var(--ns-text-sm); }

p {
  margin: 0 0 calc(var(--ns-unit) * 3);
}

code,
pre,
samp {
  font-family: var(--ns-font-mono);
  font-size: var(--ns-text-code);
}

pre {
  margin: 0;
  padding: calc(var(--ns-unit) * 3);
  overflow-x: auto;
  border: 1px solid var(--ns-ink);
  background: var(--ns-wash);
}

small,
.ns-small {
  font-size: var(--ns-text-xs);
}

/* Small capital labels used above panels and stats. */
.ns-eyebrow {
  display: block;
  color: var(--ns-ink-soft);
  font-family: var(--ns-font-ui);
  font-size: var(--ns-text-xs);
  letter-spacing: 0.09em;
  text-transform: uppercase;
}

.ns-dim {
  color: var(--ns-ink-soft);
}

/* Text painted with a dither pattern, the way the Mac greyed out anything
   you were not allowed to touch. */
.ns-dimmed {
  background-image: var(--ns-dither-50);
  background-clip: text;
  -webkit-background-clip: text;
  color: transparent;
}

/* ==========================================================================
   4. DITHER SURFACES
   ========================================================================== */

.ns-desktop {
  min-height: 100%;
  background-color: var(--ns-paper);
  background-image: var(--ns-dither-50);
}

.ns-dither-12 { background-image: var(--ns-dither-12); }
.ns-dither-25 { background-image: var(--ns-dither-25); }
.ns-dither-50 { background-image: var(--ns-dither-50); }
.ns-dither-75 { background-image: var(--ns-dither-75); }

/* ==========================================================================
   5. MENU BAR AND SUB-NAV
   ========================================================================== */

/* One strip does two jobs: the desktop menu bar across the top of a page, and
   the sub-nav under a window title bar. Both are optional. A window with no
   strip loses nothing, and a page with no menu bar is still a page.

   Everything the strip draws comes out of the --ns-nav-* tokens, so a variant
   is a token change rather than a second component. Set them on .ns-menubar
   for one strip or on :root for all of them. */
.ns-menubar {
  display: flex;
  align-items: stretch;
  height: var(--ns-nav-height);
  border-bottom: var(--ns-border) solid var(--ns-ink);
  background: var(--ns-nav-bg);
  color: var(--ns-nav-ink);
  font-family: var(--ns-font-ui);
  font-size: var(--ns-nav-size);
  -webkit-font-smoothing: none;
  user-select: none;
}

/* An item is the same box whether you write it as a span, a link or a button,
   so a strip can mix static labels with things that actually do something. */
.ns-menubar__item {
  display: inline-flex;
  flex: 0 0 auto;
  align-items: center;
  height: 100%;
  margin: 0;
  padding: 0 var(--ns-nav-pad);
  border: 0;
  border-radius: 0;
  background: none;
  appearance: none;
  color: inherit;
  font: inherit;
  letter-spacing: inherit;
  text-decoration: none;
  white-space: nowrap;
  cursor: pointer;
}

/* Highlight is the strip's own two colours, swapped. Invert the strip and the
   highlight inverts with it, with nothing else to change. */
.ns-menubar__item:hover,
.ns-menubar__item.is-open,
.ns-menubar__item.is-active {
  background: var(--ns-nav-ink);
  color: var(--ns-nav-bg);
}

/* A label that is not a control: a clock, a version, an app name. */
.ns-menubar__item.is-static {
  cursor: default;
}

.ns-menubar__item.is-static:hover {
  background: none;
  color: inherit;
}

/* The leading mark, if you want one. Optional, like everything else here. */
.ns-menubar__mark {
  font-weight: 700;
}

/* Pushes the clock and status items to the right edge. */
.ns-menubar__gap {
  flex: 1 1 auto;
}

/* Strip variants. Each one is a handful of tokens and no new rules. */
.ns-menubar.is-inverted {
  --ns-nav-bg: var(--ns-ink);
  --ns-nav-ink: var(--ns-paper);
}

.ns-menubar.is-quiet {
  --ns-nav-bg: var(--ns-wash);
}

.ns-menubar.is-tall {
  --ns-nav-height: var(--ns-h-lg);
}

.ns-menubar.is-compact {
  --ns-nav-height: var(--ns-h-sm);
  --ns-nav-size: var(--ns-text-xs);
}

.ns-menubar.is-roomy {
  --ns-nav-pad: calc(var(--ns-unit) * 3);
}

/* A strip that sits between two edges, such as a sub-nav under a title bar,
   keeps its rule at the bottom only. A free-standing one takes a full box. */
.ns-menubar.is-boxed {
  border: var(--ns-border) solid var(--ns-ink);
}

.ns-menubar.is-center { justify-content: center; }
.ns-menubar.is-end { justify-content: flex-end; }

/* ==========================================================================
   6. WINDOW
   ========================================================================== */

.ns-window {
  border: 1px solid var(--ns-ink);
  background: var(--ns-paper);
  box-shadow: var(--ns-shadow);
}

.ns-window__bar {
  display: flex;
  align-items: center;
  gap: calc(var(--ns-unit) * 2);
  height: var(--ns-chrome-height);
  padding: 0 calc(var(--ns-unit) * 2);
  border-bottom: 1px solid var(--ns-ink);
  background-image: var(--ns-pinstripe);
  background-position: 0 4px;
  background-repeat: repeat-x;
  background-size: 100% 12px;
  font-family: var(--ns-font-ui);
  font-size: var(--ns-text-sm);
  -webkit-font-smoothing: none;
  user-select: none;
}

/* Shrink to the text so the stripes stay visible on both sides of it. */
.ns-window__title {
  flex: 0 1 auto;
  min-width: 0;
  margin: 0 auto;
  padding: 0 calc(var(--ns-unit) * 2);
  overflow: hidden;
  background: var(--ns-paper);
  font-weight: 700;
  text-align: center;
  text-overflow: ellipsis;
  white-space: nowrap;
}

/* Title bar controls sit on the stripes with a paper gap around them. The
   original Mac left these boxes empty and expected you to know. These carry
   the marks people read now: close is an X, zoom is a square, shade is a bar.
   Only close is expected. The other two are optional. */
.ns-window__close,
.ns-window__zoom,
.ns-window__shade {
  position: relative;
  flex: 0 0 auto;
  width: 14px;
  height: 14px;
  padding: 0;
  border: 1px solid currentColor;
  border-radius: var(--ns-radius);
  background: var(--ns-paper);
  box-shadow: 0 0 0 2px var(--ns-paper);
  color: var(--ns-ink);
  cursor: pointer;
}

.ns-window__close:hover,
.ns-window__zoom:hover,
.ns-window__shade:hover {
  background: var(--ns-ink);
  color: var(--ns-paper);
}

.ns-window__close:active,
.ns-window__zoom:active,
.ns-window__shade:active {
  background: var(--ns-ink-soft);
  color: var(--ns-paper);
}

/* The X, drawn rather than typed so it stays crisp and inverts on hover. */
.ns-window__close::before,
.ns-window__close::after {
  content: "";
  position: absolute;
  top: 50%;
  left: 50%;
  width: 9px;
  height: 1px;
  background: currentColor;
}

.ns-window__close::before { transform: translate(-50%, -50%) rotate(45deg); }
.ns-window__close::after { transform: translate(-50%, -50%) rotate(-45deg); }

/* Zoom carries a square. */
.ns-window__zoom::after {
  content: "";
  position: absolute;
  top: 50%;
  left: 50%;
  width: 7px;
  height: 7px;
  border: 1px solid currentColor;
  transform: translate(-50%, -50%);
}

/* Shade carries a single bar. */
.ns-window__shade::after {
  content: "";
  position: absolute;
  top: 50%;
  left: 50%;
  width: 8px;
  height: 1px;
  background: currentColor;
  transform: translate(-50%, -50%);
}

.ns-window__body {
  padding: calc(var(--ns-unit) * 4);
}

.ns-window__footer {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: calc(var(--ns-unit) * 2);
  padding: calc(var(--ns-unit) * 1.5) calc(var(--ns-unit) * 3);
  border-top: 1px solid var(--ns-ink);
  color: var(--ns-ink-soft);
  font-size: var(--ns-text-xs);
}

/* An unfocused window loses its stripes and its shadow, exactly like System 7.
   It keeps its frame and its layout, so the window behind reads as the quiet
   one rather than the broken one, and nothing moves when it comes forward. */
.ns-window.is-inactive {
  box-shadow: none;
}

.ns-window.is-inactive .ns-window__bar {
  background-color: var(--ns-wash);
  background-image: none;
}

.ns-window.is-inactive .ns-window__title {
  background: none;
  color: var(--ns-ink-soft);
  font-weight: 400;
}

/* The controls stay put as empty outlines. The Mac dropped them altogether;
   keeping the boxes and losing the marks says the same thing without the
   title bar rearranging itself every time focus changes. */
.ns-window.is-inactive .ns-window__close,
.ns-window.is-inactive .ns-window__zoom,
.ns-window.is-inactive .ns-window__shade {
  border-color: var(--ns-ink-faint);
  background: var(--ns-wash);
  box-shadow: none;
  color: var(--ns-ink-faint);
  cursor: default;
  pointer-events: none;
}

.ns-window.is-inactive .ns-window__close::before,
.ns-window.is-inactive .ns-window__close::after,
.ns-window.is-inactive .ns-window__zoom::after,
.ns-window.is-inactive .ns-window__shade::after {
  content: none;
}

/* Its contents step back with it, so the eye lands on the front window. */
.ns-window.is-inactive .ns-window__body,
.ns-window.is-inactive .ns-terminal,
.ns-window.is-inactive .ns-window__footer {
  color: var(--ns-ink-soft);
}

.ns-window.is-inactive .ns-menubar {
  --ns-nav-bg: var(--ns-wash);
  --ns-nav-ink: var(--ns-ink-soft);
}

/* Windows that overlap, the way a desktop actually looks. Children share one
   cell and each one after the first steps down and across, so write the
   window behind first and the front one last. */
.ns-deck {
  display: grid;
  padding: 0 var(--ns-deck-step) var(--ns-deck-step) 0;
}

.ns-deck > * {
  grid-area: 1 / 1;
  align-self: start;
}

.ns-deck > * + * {
  transform: translate(var(--ns-deck-step), var(--ns-deck-step));
}

/* ==========================================================================
   7. BOX AND PANEL
   ========================================================================== */

.ns-box {
  padding: calc(var(--ns-unit) * 4);
  border: 1px solid var(--ns-rule);
  border-radius: var(--ns-radius-surface);
  background: var(--ns-paper);
  color: var(--ns-ink);
}

.ns-box.is-tight { padding: calc(var(--ns-unit) * 2); }
.ns-box.is-hard { border-color: var(--ns-ink); }
.ns-box.has-shadow { border-color: var(--ns-ink); box-shadow: var(--ns-shadow); }
.ns-box.is-inset { background: var(--ns-wash); }
.ns-box.is-dashed { border-style: dashed; }

.ns-box.is-danger {
  border-color: var(--ns-danger);
  color: var(--ns-danger);
}

/* A titled group of controls, drawn as a labelled rule. */
.ns-group {
  margin: 0 0 calc(var(--ns-unit) * 4);
  padding: calc(var(--ns-unit) * 4);
  border: 1px solid var(--ns-ink);
}

.ns-group > legend {
  padding: 0 calc(var(--ns-unit) * 1.5);
  font-family: var(--ns-font-ui);
  font-size: var(--ns-text-xs);
  letter-spacing: 0.08em;
  text-transform: uppercase;
}

/* ==========================================================================
   8. BUTTONS
   ========================================================================== */

/* Every variant is the same box. A primary button is a colour change and
   nothing else, so a row of buttons never steps up and down. */
.ns-button,
button.ns-button,
input[type="submit"].ns-button {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: calc(var(--ns-unit) * 1.5);
  min-height: var(--ns-h-lg);
  margin: 0;
  padding: 0 12px;
  border: 1px solid var(--ns-ink);
  border-radius: var(--ns-radius);
  background: var(--ns-paper);
  color: var(--ns-ink);
  font-family: var(--ns-font-ui);
  font-size: var(--ns-text-sm);
  font-weight: 700;
  line-height: 1;
  text-decoration: none;
  white-space: nowrap;
  cursor: pointer;
  -webkit-font-smoothing: none;
}

.ns-button:hover {
  background: var(--ns-wash);
}

/* The Mac never highlighted on hover, it inverted on press. */
.ns-button:active {
  background: var(--ns-ink);
  color: var(--ns-paper);
}

.ns-button.is-primary {
  background: var(--ns-ink);
  color: var(--ns-paper);
}

.ns-button.is-primary:hover {
  background: var(--ns-ink-soft);
}

.ns-button.is-primary:active {
  background: var(--ns-paper);
  color: var(--ns-ink);
}

.ns-button.is-danger {
  border-color: var(--ns-danger);
  color: var(--ns-danger);
}

.ns-button.is-danger:hover {
  background: var(--ns-danger);
  color: var(--ns-paper);
}

.ns-button.is-link {
  min-height: 0;
  padding: 0;
  border-color: transparent;
  background: transparent;
  font-family: var(--ns-font-mono);
  font-weight: 400;
  text-decoration: underline;
}

.ns-button.is-link:hover {
  background: transparent;
  color: var(--ns-danger);
}

.ns-button.is-small { min-height: var(--ns-h-md); padding: 0 10px; font-size: var(--ns-text-xs); }
.ns-button.is-tiny { min-height: var(--ns-h-sm); padding: 0 8px; font-size: var(--ns-text-xs); }
.ns-button.is-square { border-radius: 0; }
.ns-button.is-block { display: flex; width: 100%; }

/* Disabled means dithered text, the way the Mac greyed things out. */
.ns-button:disabled,
.ns-button.is-disabled {
  border-color: var(--ns-ink-faint);
  background: var(--ns-paper);
  background-image: var(--ns-dither-50);
  background-clip: text;
  -webkit-background-clip: text;
  color: transparent;
  cursor: default;
  pointer-events: none;
}

/* A welded run of buttons, sharing borders. */
.ns-button-group {
  display: inline-flex;
}

.ns-button-group .ns-button {
  margin: 0;
  border-radius: 0;
  box-shadow: none;
}

.ns-button-group .ns-button + .ns-button {
  border-left-width: 0;
}

.ns-button-group .ns-button:first-child {
  border-radius: var(--ns-radius) 0 0 var(--ns-radius);
}

.ns-button-group .ns-button:last-child {
  border-radius: 0 var(--ns-radius) var(--ns-radius) 0;
}

.ns-button-group .ns-button.is-active {
  background: var(--ns-ink);
  color: var(--ns-paper);
}

/* Convenience row so ringed default buttons never collide. */
.ns-actions {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: calc(var(--ns-unit) * 2);
}

.ns-actions.is-end {
  justify-content: flex-end;
}

/* ==========================================================================
   9. FORM CONTROLS
   ========================================================================== */

.ns-field {
  margin: 0 0 calc(var(--ns-unit) * 4);
}

.ns-field > label,
.ns-label {
  display: block;
  margin: 0 0 calc(var(--ns-unit) * 1);
  color: var(--ns-ink-soft);
  font-family: var(--ns-font-ui);
  font-size: var(--ns-text-xs);
  letter-spacing: 0.07em;
  text-transform: uppercase;
}

/* The terminal half of the system speaks in prompts. */
.ns-field > label::before,
.ns-label::before {
  content: "> ";
  color: var(--ns-ink);
}

.ns-input,
.ns-field input[type="text"],
.ns-field input[type="email"],
.ns-field input[type="password"],
.ns-field input[type="number"],
.ns-field input[type="search"],
.ns-field input[type="tel"],
.ns-field input[type="url"],
.ns-field input[type="date"],
.ns-field input[type="time"],
.ns-field input[type="datetime-local"],
.ns-field textarea,
.ns-field select {
  width: 100%;
  min-height: var(--ns-h-lg);
  padding: 4px 8px;
  border: 1px solid var(--ns-ink);
  border-radius: var(--ns-radius);
  background: var(--ns-paper);
  color: var(--ns-ink);
  font-family: var(--ns-font-mono);
  font-size: var(--ns-text-md);
  caret-color: var(--ns-ink);
}

.ns-field textarea {
  min-height: 6rem;
  resize: vertical;
}

.ns-input:focus,
.ns-field input:focus,
.ns-field textarea:focus,
.ns-field select:focus {
  outline: 0;
  box-shadow: 2px 2px 0 var(--ns-ink);
}

.ns-input::placeholder,
.ns-field textarea::placeholder {
  color: var(--ns-ink-faint);
  opacity: 1;
}

/* Popup menus keep the shadowed edge and the downward triangle. */
.ns-field select,
.ns-select {
  padding-right: 26px;
  appearance: none;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='9' height='6'%3E%3Cpath d='M0 0h9L4.5 6z' fill='%23000'/%3E%3C/svg%3E");
  background-position: right 8px center;
  background-repeat: no-repeat;
  box-shadow: 2px 2px 0 var(--ns-ink);
  cursor: pointer;
}

/* Checkboxes get the X. That is the part everybody remembers. */
.ns-field input[type="checkbox"],
.ns-checkbox {
  width: 14px;
  height: 14px;
  margin: 0 6px 0 0;
  padding: 0;
  border: 1px solid var(--ns-ink);
  border-radius: var(--ns-radius);
  background: var(--ns-paper);
  appearance: none;
  cursor: pointer;
  vertical-align: -2px;
}

.ns-field input[type="checkbox"]:checked,
.ns-checkbox:checked {
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 12 12'%3E%3Cpath d='M1 1 11 11M11 1 1 11' stroke='%23000' stroke-width='2'/%3E%3C/svg%3E");
  background-size: 100% 100%;
}

.ns-field input[type="radio"],
.ns-radio {
  width: 14px;
  height: 14px;
  margin: 0 6px 0 0;
  padding: 0;
  border: 1px solid var(--ns-ink);
  border-radius: 50%;
  background: var(--ns-paper);
  appearance: none;
  cursor: pointer;
  vertical-align: -2px;
}

.ns-field input[type="radio"]:checked,
.ns-radio:checked {
  background-image: radial-gradient(circle at 50% 50%, var(--ns-ink) 0 3px, transparent 3.5px);
}

/* Inline choices sit on one line with their own caption. */
.ns-choice {
  display: flex;
  align-items: center;
  min-height: var(--ns-h-md);
  font-size: var(--ns-text-md);
}

.ns-choice label {
  margin: 0;
  color: var(--ns-ink);
  font-family: var(--ns-font-mono);
  font-size: var(--ns-text-md);
  letter-spacing: 0;
  text-transform: none;
}

.ns-choice label::before {
  content: none;
}

/* Sliders keep a dithered track and a square black thumb. */
.ns-field input[type="range"],
.ns-range {
  width: 100%;
  height: 16px;
  background: transparent;
  appearance: none;
  cursor: pointer;
}

.ns-field input[type="range"]::-webkit-slider-runnable-track,
.ns-range::-webkit-slider-runnable-track {
  height: 6px;
  border: 1px solid var(--ns-ink);
  background-color: var(--ns-paper);
  background-image: var(--ns-dither-25);
}

.ns-field input[type="range"]::-webkit-slider-thumb,
.ns-range::-webkit-slider-thumb {
  width: 10px;
  height: 16px;
  margin-top: -6px;
  border: 1px solid var(--ns-ink);
  background: var(--ns-paper);
  box-shadow: 1px 1px 0 var(--ns-ink);
  appearance: none;
}

.ns-field input[type="range"]::-moz-range-track,
.ns-range::-moz-range-track {
  height: 6px;
  border: 1px solid var(--ns-ink);
  background-color: var(--ns-paper);
  background-image: var(--ns-dither-25);
}

.ns-field input[type="range"]::-moz-range-thumb,
.ns-range::-moz-range-thumb {
  width: 10px;
  height: 16px;
  border: 1px solid var(--ns-ink);
  border-radius: 0;
  background: var(--ns-paper);
}

.ns-field input[type="file"] {
  font-family: var(--ns-font-mono);
  font-size: var(--ns-text-sm);
}

/* Comment lines under a control, borrowed from the terminal. */
.ns-hint {
  margin: calc(var(--ns-unit) * 1) 0 0;
  color: var(--ns-ink-soft);
  font-size: var(--ns-text-xs);
}

.ns-hint::before {
  content: "// ";
}

.ns-field.is-invalid input,
.ns-field.is-invalid textarea,
.ns-field.is-invalid select {
  border-color: var(--ns-danger);
}

.ns-field.is-invalid .ns-hint {
  color: var(--ns-danger);
}

/* ==========================================================================
   10. TAGS, BADGES AND KEYS
   ========================================================================== */

/* Tags, badges and keys share one height, one size and one line box, so
   they sit on the same line as each other without drifting. */
.ns-tag {
  display: inline-flex;
  align-items: center;
  min-height: var(--ns-h-sm);
  padding: 0 6px;
  border: 1px solid var(--ns-rule);
  border-radius: var(--ns-radius);
  background: var(--ns-paper);
  color: var(--ns-ink-soft);
  font-size: var(--ns-text-xs);
  line-height: 1;
  letter-spacing: 0.04em;
  text-decoration: none;
  white-space: nowrap;
}

.ns-tag::before {
  content: "#";
  color: var(--ns-ink);
}

.ns-tag:hover {
  border-color: var(--ns-ink);
  color: var(--ns-ink);
}

.ns-tag.is-solid {
  border-color: var(--ns-ink);
  background: var(--ns-ink);
  color: var(--ns-paper);
}

.ns-tag.is-solid::before {
  color: var(--ns-paper);
}

.ns-badge {
  display: inline-flex;
  align-items: center;
  gap: 4px;
  min-height: var(--ns-h-sm);
  padding: 0 6px;
  border: 1px solid var(--ns-ink);
  border-radius: var(--ns-radius);
  background: var(--ns-paper);
  font-family: var(--ns-font-ui);
  font-size: var(--ns-text-xs);
  line-height: 1;
  letter-spacing: 0.06em;
  text-transform: uppercase;
}

.ns-badge.is-live {
  background: var(--ns-ink);
  color: var(--ns-paper);
}

/* The pip is drawn rather than typed. A bullet character hangs off the text
   baseline and sits a fraction low next to capitals; a box with a radius
   centres on the badge itself and stays centred in any font. */
.ns-badge.is-live::before {
  content: "";
  flex: 0 0 auto;
  width: var(--ns-pip);
  height: var(--ns-pip);
  border-radius: 50%;
  background: currentColor;
}

.ns-badge.is-quiet {
  border-color: var(--ns-rule);
  color: var(--ns-ink-soft);
}

.ns-kbd,
kbd {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-width: var(--ns-h-sm);
  height: var(--ns-h-sm);
  padding: 0 5px;
  border: 1px solid var(--ns-ink);
  border-radius: var(--ns-radius);
  background: var(--ns-paper);
  box-shadow: 1px 1px 0 var(--ns-ink);
  color: var(--ns-ink);
  font-family: var(--ns-font-ui);
  font-size: var(--ns-text-xs);
  line-height: 1;
  text-transform: uppercase;
}

/* ==========================================================================
   11. TABLES AND ROWS
   ========================================================================== */

.ns-table {
  width: 100%;
  border-collapse: collapse;
  font-size: var(--ns-text-md);
}

.ns-table th {
  height: var(--ns-h-md);
  padding: 0 6px;
  border-bottom: 1px solid var(--ns-ink);
  color: var(--ns-ink-soft);
  font-family: var(--ns-font-ui);
  font-size: var(--ns-text-xs);
  font-weight: 400;
  letter-spacing: 0.08em;
  text-align: left;
  text-transform: uppercase;
}

.ns-table td {
  height: calc(var(--ns-h-lg) + 6px);
  padding: 0 6px;
  border-bottom: 1px solid var(--ns-rule);
}

.ns-table tbody tr:hover td {
  background: var(--ns-wash);
}

.ns-table tbody tr.is-selected td {
  background: var(--ns-ink);
  color: var(--ns-paper);
}

.ns-table .ns-num {
  text-align: right;
  font-variant-numeric: tabular-nums;
}

/* A list row with a leading control, a body and trailing meta. */
.ns-row {
  display: grid;
  grid-template-columns: auto minmax(0, 1fr) auto;
  align-items: center;
  gap: calc(var(--ns-unit) * 3);
  padding: 8px 6px;
  border-bottom: 1px solid var(--ns-rule);
  color: inherit;
  text-decoration: none;
}

.ns-row:hover {
  background: var(--ns-wash);
}

.ns-row__body {
  min-width: 0;
}

.ns-row__title {
  display: block;
  margin: 0;
  overflow: hidden;
  font-family: var(--ns-font-mono);
  font-size: var(--ns-text-md);
  font-weight: 500;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.ns-row__meta {
  display: block;
  margin: 0;
  color: var(--ns-ink-soft);
  font-size: var(--ns-text-xs);
}

.ns-row.is-done .ns-row__title {
  color: var(--ns-ink-faint);
  text-decoration: line-through;
}

/* ==========================================================================
   12. TABS
   ========================================================================== */

.ns-tabs {
  display: flex;
  gap: 3px;
  margin-bottom: -1px;
  padding-left: calc(var(--ns-unit) * 2);
}

.ns-tab {
  display: inline-flex;
  align-items: center;
  min-height: var(--ns-h-md);
  padding: 0 12px;
  border: 1px solid var(--ns-ink);
  border-bottom: 0;
  border-radius: var(--ns-radius) var(--ns-radius) 0 0;
  background: var(--ns-wash);
  color: var(--ns-ink-soft);
  font-family: var(--ns-font-ui);
  font-size: var(--ns-text-sm);
  line-height: 1;
  text-decoration: none;
  cursor: pointer;
}

.ns-tab.is-active {
  position: relative;
  z-index: 1;
  background: var(--ns-paper);
  color: var(--ns-ink);
  font-weight: 700;
}

.ns-tab-panel {
  padding: calc(var(--ns-unit) * 4);
  border: 1px solid var(--ns-ink);
  background: var(--ns-paper);
}

/* ==========================================================================
   13. MENUS
   ========================================================================== */

.ns-menu {
  min-width: 12rem;
  padding: 2px 0;
  border: 1px solid var(--ns-ink);
  background: var(--ns-paper);
  box-shadow: var(--ns-shadow);
  font-family: var(--ns-font-ui);
  font-size: var(--ns-text-sm);
  -webkit-font-smoothing: none;
}

.ns-menu__item {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: calc(var(--ns-unit) * 6);
  min-height: var(--ns-h-md);
  padding: 0 12px;
  color: var(--ns-ink);
  text-decoration: none;
  white-space: nowrap;
  cursor: pointer;
}

.ns-menu__item:hover {
  background: var(--ns-ink);
  color: var(--ns-paper);
}

.ns-menu__item.is-disabled {
  background-image: var(--ns-dither-50);
  background-clip: text;
  -webkit-background-clip: text;
  color: transparent;
  pointer-events: none;
}

.ns-menu__item span {
  color: var(--ns-ink-faint);
}

.ns-menu__item:hover span {
  color: var(--ns-paper);
}

.ns-menu__sep {
  height: 1px;
  margin: 3px 0;
  background: var(--ns-rule);
}

/* A menu that falls out of whatever you hang it on. Pointer, keyboard and an
   .is-open class all open it, so it works with no JavaScript at all and still
   takes a class when you have some. Wrap a trigger and a .ns-menu together:

   <div class="ns-dropdown">
     <button class="ns-menubar__item" aria-haspopup="true">File</button>
     <div class="ns-menu">...</div>
   </div> */
.ns-dropdown {
  position: relative;
  display: inline-flex;
  align-items: stretch;
}

.ns-dropdown > .ns-menu {
  position: absolute;
  top: 100%;
  left: 0;
  z-index: 40;
  display: none;
}

.ns-dropdown:hover > .ns-menu,
.ns-dropdown:focus-within > .ns-menu,
.ns-dropdown.is-open > .ns-menu {
  display: block;
}

/* Hang it off the right edge instead when the trigger is near one. */
.ns-dropdown.is-end > .ns-menu {
  right: 0;
  left: auto;
}

/* In a strip the trigger stays inverted for as long as its menu is down. */
.ns-menubar .ns-dropdown:hover > .ns-menubar__item,
.ns-menubar .ns-dropdown:focus-within > .ns-menubar__item,
.ns-menubar .ns-dropdown.is-open > .ns-menubar__item {
  background: var(--ns-nav-ink);
  color: var(--ns-nav-bg);
}

/* ==========================================================================
   14. DIALOGS AND NOTICES
   ========================================================================== */

.ns-alert {
  display: grid;
  grid-template-columns: auto minmax(0, 1fr);
  gap: calc(var(--ns-unit) * 4);
  max-width: 30rem;
  padding: calc(var(--ns-unit) * 4);
  border: 2px solid var(--ns-ink);
  background: var(--ns-paper);
  box-shadow: var(--ns-shadow-deep);
}

.ns-alert__icon {
  display: grid;
  place-items: center;
  width: 38px;
  height: 38px;
  border: 2px solid var(--ns-ink);
  border-radius: 50%;
  font-family: var(--ns-font-ui);
  font-size: var(--ns-text-xl);
  font-weight: 700;
}

.ns-alert__body p {
  margin: 0 0 calc(var(--ns-unit) * 3);
  font-size: var(--ns-text-md);
}

.ns-alert__body p:last-child {
  margin-bottom: 0;
}

/* A flash strip, pinned or inline. */
.ns-flash {
  display: flex;
  align-items: center;
  min-height: var(--ns-h-lg);
  padding: 4px 10px;
  border: 1px solid var(--ns-ink);
  border-radius: var(--ns-radius-surface);
  background: var(--ns-paper);
  box-shadow: var(--ns-shadow);
  font-size: var(--ns-text-md);
}

/* The mark is a flex item now, so it needs a margin rather than a space. */
.ns-flash::before {
  content: "!";
  margin-right: 6px;
  font-weight: 700;
}

.ns-flash.is-notice::before {
  content: "\2713";
}

.ns-flash.is-error {
  border-color: var(--ns-danger);
  color: var(--ns-danger);
}

/* ==========================================================================
   15. PROGRESS
   ========================================================================== */

.ns-progress {
  height: 12px;
  overflow: hidden;
  border: 1px solid var(--ns-ink);
  background: var(--ns-paper);
}

.ns-progress__bar {
  height: 100%;
  background-color: var(--ns-ink);
  background-image: repeating-linear-gradient(
    -45deg,
    var(--ns-paper) 0 1px,
    transparent 1px 5px
  );
}

/* The barber pole that meant the Mac was thinking. */
.ns-progress.is-indeterminate .ns-progress__bar {
  width: 100%;
  background-size: 7.07px 7.07px;
  animation: ns-barber 0.4s linear infinite;
}

@keyframes ns-barber {
  to { background-position: 7.07px 0; }
}

/* A thin meter for counts and scores. */
.ns-meter {
  height: 3px;
  background: var(--ns-rule);
}

.ns-meter > div {
  height: 100%;
  background: var(--ns-ink);
}

/* ==========================================================================
   16. STATS AND GRIDS
   ========================================================================== */

.ns-stats {
  display: grid;
  grid-auto-flow: column;
  grid-auto-columns: 1fr;
  border: 1px solid var(--ns-ink);
}

.ns-stat {
  padding: calc(var(--ns-unit) * 3);
  border-right: 1px solid var(--ns-rule);
}

.ns-stat:last-child {
  border-right: 0;
}

.ns-stat strong {
  display: block;
  font-family: var(--ns-font-ui);
  font-size: var(--ns-text-2xl);
  font-weight: 700;
  letter-spacing: -0.04em;
  line-height: 1.1;
}

.ns-stat.is-inverted {
  background: var(--ns-ink);
  color: var(--ns-paper);
}

.ns-stat.is-inverted .ns-eyebrow {
  color: var(--ns-paper);
  opacity: 0.7;
}

/* Activity grid, four dither levels plus empty. */
.ns-grid {
  display: grid;
  grid-auto-flow: column;
  grid-auto-columns: 11px;
  grid-template-rows: repeat(7, 11px);
  justify-content: start;
  gap: 2px;
  overflow-x: auto;
}

.ns-grid i {
  width: 11px;
  height: 11px;
  border: 1px solid var(--ns-rule);
  background-color: var(--ns-paper);
}

.ns-grid i.lvl-1 { border-color: var(--ns-ink); background-image: var(--ns-dither-12); }
.ns-grid i.lvl-2 { border-color: var(--ns-ink); background-image: var(--ns-dither-25); }
.ns-grid i.lvl-3 { border-color: var(--ns-ink); background-image: var(--ns-dither-50); }
.ns-grid i.lvl-4 { border-color: var(--ns-ink); background-color: var(--ns-ink); }

/* ==========================================================================
   17. TERMINAL
   ========================================================================== */

.ns-terminal {
  padding: calc(var(--ns-unit) * 4);
  background: var(--ns-paper);
  font-family: var(--ns-font-mono);
  font-size: var(--ns-text-md);
  line-height: 1.7;
}

.ns-terminal p {
  margin: 0;
}

.ns-terminal p::before {
  content: "~ ";
  color: var(--ns-ink-faint);
}

.ns-terminal p.is-out::before {
  content: "\00a0\00a0";
}

.ns-cursor {
  animation: ns-blink 1.1s steps(1, end) infinite;
}

@keyframes ns-blink {
  50% { opacity: 0; }
}

/* ==========================================================================
   18. DISCLOSURE AND EMPTY STATES
   ========================================================================== */

.ns-details > summary {
  list-style: none;
  cursor: pointer;
  font-size: var(--ns-text-md);
}

.ns-details > summary::-webkit-details-marker {
  display: none;
}

.ns-details > summary::before {
  content: "\25B8\00a0";
}

.ns-details[open] > summary::before {
  content: "\25BE\00a0";
}

.ns-empty {
  padding: calc(var(--ns-unit) * 10) calc(var(--ns-unit) * 4);
  border: 1px dashed var(--ns-ink);
  background: var(--ns-paper);
  color: var(--ns-ink-soft);
  text-align: center;
}

.ns-empty strong {
  display: block;
  margin-bottom: calc(var(--ns-unit) * 1.5);
  color: var(--ns-ink);
  font-family: var(--ns-font-ui);
}

/* ==========================================================================
   19. SCROLLBARS
   ========================================================================== */

/* A drawn scrollbar, because the real one is not yours to style everywhere.
   Pair it with .ns-scroll inside .ns-pane for the full window look. */
.ns-pane {
  display: flex;
  align-items: stretch;
  min-height: 0;
}

.ns-pane > .ns-scroll {
  flex: 1 1 auto;
  min-width: 0;
}

.ns-scrollbar {
  display: flex;
  flex: 0 0 auto;
  flex-direction: column;
  width: 15px;
  border-left: 1px solid var(--ns-ink);
}

.ns-scrollbar__arrow {
  flex: 0 0 auto;
  height: 15px;
  background-color: var(--ns-paper);
  background-repeat: no-repeat;
  background-position: center;
}

.ns-scrollbar__arrow.is-up {
  border-bottom: 1px solid var(--ns-ink);
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='9' height='6'%3E%3Cpath d='M4.5 0 9 6H0z' fill='%23000'/%3E%3C/svg%3E");
}

.ns-scrollbar__arrow.is-down {
  border-top: 1px solid var(--ns-ink);
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='9' height='6'%3E%3Cpath d='M0 0h9L4.5 6z' fill='%23000'/%3E%3C/svg%3E");
}

.ns-scrollbar__track {
  flex: 1 1 auto;
  padding: 0;
  background-color: var(--ns-paper);
  background-image: var(--ns-dither-25);
}

.ns-scrollbar__thumb {
  height: 38%;
  border: 1px solid var(--ns-ink);
  border-inline: 0;
  background: var(--ns-paper);
}

/* Setting scrollbar-color makes Chrome ignore ::-webkit-scrollbar, so the
   standard properties are kept for engines that have no webkit pseudos.
   Browsers using overlay scrollbars ignore both, which is why .ns-scrollbar
   exists. */
.ns-scroll {
  overflow: auto;
}

@supports not selector(::-webkit-scrollbar) {
  .ns-scroll {
    scrollbar-width: thin;
    scrollbar-color: var(--ns-ink) var(--ns-wash);
  }
}

.ns-scroll::-webkit-scrollbar {
  width: 15px;
  height: 15px;
}

.ns-scroll::-webkit-scrollbar-track {
  border-left: 1px solid var(--ns-ink);
  background-color: var(--ns-paper);
  background-image: var(--ns-dither-25);
}

.ns-scroll::-webkit-scrollbar-thumb {
  border: 1px solid var(--ns-ink);
  background: var(--ns-paper);
}

.ns-scroll::-webkit-scrollbar-button:vertical:start {
  height: 15px;
  border: 1px solid var(--ns-ink);
  background: var(--ns-paper) url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='9' height='6'%3E%3Cpath d='M4.5 0 9 6H0z' fill='%23000'/%3E%3C/svg%3E") no-repeat center;
  display: block;
}

.ns-scroll::-webkit-scrollbar-button:vertical:end {
  height: 15px;
  border: 1px solid var(--ns-ink);
  background: var(--ns-paper) url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='9' height='6'%3E%3Cpath d='M0 0h9L4.5 6z' fill='%23000'/%3E%3C/svg%3E") no-repeat center;
  display: block;
}

/* ==========================================================================
   20. LAYOUT HELPERS
   ========================================================================== */

.ns-stack > * + * { margin-top: calc(var(--ns-unit) * 4); }
.ns-inline { display: flex; flex-wrap: wrap; align-items: center; gap: calc(var(--ns-unit) * 2); }
.ns-split { display: flex; align-items: center; justify-content: space-between; gap: calc(var(--ns-unit) * 4); }
.ns-page { width: min(100%, 62rem); margin: 0 auto; padding: calc(var(--ns-unit) * 6); }
.ns-clip { position: absolute; width: 1px; height: 1px; overflow: hidden; clip-path: inset(50%); }

@media (prefers-reduced-motion: reduce) {
  *,
  *::before,
  *::after {
    animation-duration: 0.01ms !important;
    transition-duration: 0.01ms !important;
  }
}
