/* Shared styles for yaks.app. Layers separate colour and spacing tokens,
   element defaults, reusable components, and page layouts. Later layers
   take precedence. /style-guide demonstrates the same stylesheet. */

@layer tokens, base, components, sections;

@layer tokens, base, components, sections;
@layer tokens {
/* Linen: yaks.app's colours. Light is a warm sheet of linen under cream
   cards, written in coffee, never black, with meadow green for what is lit
   and brick for a fault. Dark is the same room at night: a night-brown
   ground, cocoa cards, oat ink, moss for what is lit and rose for a fault.
   linen.ts holds the dark colours for a terminal.

   Its paints are named for what they look like (linen, cream, coffee,
   clay, taupe, shell, bark, cocoa, night, meadow, moss, brick, rose, dusk,
   sky, ember, blush, forest, oat), and a theme has more roles than a
   palette has hues, so roles share them: meadow is what is
   lit, what went well and who; brick a fault and the language's words;
   dusk something to know and a moment. yaks.app's own pages wear this
   theme (workers/yak/public). */
:root {
  color-scheme: light dark;
  --gap: 1rem;
  --radius: 4px;
  --measure: 38rem;
  --shadow: 0 12px 32px -16px light-dark(#5238283d, #1d1714b3);

  --font: 'Nunito', system-ui, -apple-system, 'Segoe UI', Roboto, sans-serif;
  --mono: ui-monospace, SFMono-Regular, Menlo, monospace;
  --size: 1.0625rem;
  --small: 0.9375rem;

  --bg: light-dark(#fdf7ee, #2b231f); /* linen; night */
  --surface: light-dark(#f7efe3, #392d27); /* a sheet behind the one in front */
  --card: light-dark(#fffbf5, #372c26); /* cream; cocoa */
  --border: light-dark(#efe3d2, #4d3d34); /* shell; bark */
  --border2: light-dark(#c9b7a6, #756255); /* the hairline, gone toward clay */

  --text: light-dark(#523828, #f1e6d8); /* coffee; oat */
  --muted: light-dark(#785b47, #c9b19c); /* clay; taupe */
  --dim: light-dark(#c9b19c, #785b47); /* taupe; clay */

  --accent: light-dark(#4c773e, #a7c080); /* meadow; moss */
  --link: light-dark(#4c773e, #a7c080);
  --heading: light-dark(#523828, #f1e6d8); /* the text's own ink */

  --info: light-dark(#34404a, #e5eef5); /* dusk; sky */
  --active: light-dark(#785b47, #f8e0c8); /* clay; blush */
  --positive: light-dark(#4c773e, #a7c080); /* meadow; moss */
  --negative: light-dark(#a8503f, #e67e80); /* brick; rose */
  --caution: light-dark(#a8503f, #e67e80); /* brick; rose */
  --special: light-dark(#785b47, #c9b19c); /* clay; taupe */

  --number: light-dark(#4e3b32, #f8e0c8); /* ember; blush */
  --literal: light-dark(#a8503f, #e67e80); /* brick; rose */
  --time: light-dark(#34404a, #e5eef5); /* dusk; sky */
  --who: light-dark(#4c773e, #a7c080); /* meadow; moss */

  --keyword: light-dark(#a8503f, #e67e80); /* brick; rose */
  --string: light-dark(#4c773e, #a7c080); /* meadow; moss */
  --fn: light-dark(#34404a, #fffbf5); /* dusk; cream */
  --type: light-dark(#4e3b32, #f8e0c8); /* ember; blush */
  --attr: light-dark(#785b47, #c9b19c); /* clay; taupe */

  --hue-0: light-dark(#4c773e, #a7c080); /* meadow; moss */
  --hue-1: light-dark(#4e3b32, #f8e0c8); /* ember; blush */
  --hue-2: light-dark(#34404a, #e5eef5); /* dusk; sky */
  --hue-3: light-dark(#a8503f, #e67e80); /* brick; rose */
  --hue-4: light-dark(#785b47, #c9b19c); /* clay; taupe */
  --hue-5: light-dark(#33493c, #f1e6d8); /* forest; oat */
}
@supports not (color: light-dark(#000, #fff)) {
:root {
  --shadow: 0 12px 32px -16px #5238283d;
  --bg: #fdf7ee;
  --surface: #f7efe3;
  --card: #fffbf5;
  --border: #efe3d2;
  --border2: #c9b7a6;
  --text: #523828;
  --muted: #785b47;
  --dim: #c9b19c;
  --accent: #4c773e;
  --link: #4c773e;
  --heading: #523828;
  --info: #34404a;
  --active: #785b47;
  --positive: #4c773e;
  --negative: #a8503f;
  --caution: #a8503f;
  --special: #785b47;
  --number: #4e3b32;
  --literal: #a8503f;
  --time: #34404a;
  --who: #4c773e;
  --keyword: #a8503f;
  --string: #4c773e;
  --fn: #34404a;
  --type: #4e3b32;
  --attr: #785b47;
  --hue-0: #4c773e;
  --hue-1: #4e3b32;
  --hue-2: #34404a;
  --hue-3: #a8503f;
  --hue-4: #785b47;
  --hue-5: #33493c;
}
@media (prefers-color-scheme: dark) {
:root {
  --shadow: 0 12px 32px -16px #1d1714b3;
  --bg: #2b231f;
  --surface: #392d27;
  --card: #372c26;
  --border: #4d3d34;
  --border2: #756255;
  --text: #f1e6d8;
  --muted: #c9b19c;
  --dim: #785b47;
  --accent: #a7c080;
  --link: #a7c080;
  --heading: #f1e6d8;
  --info: #e5eef5;
  --active: #f8e0c8;
  --positive: #a7c080;
  --negative: #e67e80;
  --caution: #e67e80;
  --special: #c9b19c;
  --number: #f8e0c8;
  --literal: #e67e80;
  --time: #e5eef5;
  --who: #a7c080;
  --keyword: #e67e80;
  --string: #a7c080;
  --fn: #fffbf5;
  --type: #f8e0c8;
  --attr: #c9b19c;
  --hue-0: #a7c080;
  --hue-1: #f8e0c8;
  --hue-2: #e5eef5;
  --hue-3: #e67e80;
  --hue-4: #c9b19c;
  --hue-5: #f1e6d8;
}
}
}

/* What every theme derives the same way: half its gap, a faint wash of its
   text, and the touch-target floor, which grows under a coarse pointer (fat
   fingers get fat targets, and only there).

   And the type every part reads, which a theme may set: --size for what a
   thing says, --small for the line that describes it, and nothing smaller.
   Headings climb from --size by one ratio, --scale, a step each: --h3, --h2,
   --h1. Every heading reads them, prose or part, so a page's h1 is the same
   size wherever it is drawn.
   Text comes in three inks. --text is what a thing says; --muted is what
   describes it (a key, a heading over a column, a fact, a stamp, an id, a
   count), and reads on every floor; --dim is only for what is not there (a
   nil, a ghost, a placeholder, a disabled step). The mono face is for what a
   person would copy or type (an id, a sha, code, a raw stored value), never
   for a label, a moment said the human way, or a count. A part that steps
   back is muted, small or both; never mono to look quiet, and never dim.
   And the width of what sits beside a page (a chat, what an agent gets):
   --side, never narrower than --side-min. */
:where(:root) {
  --half-gap: calc(var(--gap) / 2);
  --soft: color-mix(in srgb, var(--text) 6%, transparent);
  --tap: 0px;
  --size: 14px;
  --small: 12px;
  --scale: 1.2;
  --h3: calc(var(--size) * var(--scale));
  --h2: calc(var(--h3) * var(--scale));
  --h1: calc(var(--h2) * var(--scale));
  --side: 26rem;
  --side-min: 18rem;
}
@media (pointer: coarse) {
  :where(:root) {
    --tap: 2.5rem;
  }
}

}
@layer base {
/* Pencil: yaks.app's drawing, in place of the kit's document defaults. A
   part worth outlining is drawn: a graphite line around it with slightly
   rounded corners (--radius), given the paper's tooth by pencil.svg, which
   every drawn line goes through (--drawn). What can be pressed sits on a
   hatch it slides onto. What is typed into is a well pressed into the
   paper. A surface is flat. One grain of paper, yaks.app's own tile, lies
   over every page (paper/grain.css, laid over this).

   Everything here is :where() or a custom property, so any part's rule, and
   any page's, still wins. */
:root {
  --grain: url(_ui/packages/ui/pencil/paper.e48c5467b4.webp);
  --grain-opacity: .07;
  --drawn: url(_ui/packages/ui/pencil/pencil.8b0be94b38.svg#line);

  --graphite: color-mix(in srgb, var(--text) 88%, transparent);
  --stroke: 1.5px; /* the weight of a drawn line */
  --lift: 4px; /* how far what can be pressed sits off its hatch */
  --hatch: repeating-linear-gradient(-45deg, var(--graphite) 0 1px,
    transparent 1px 3px);
  /* A drawn rule is a line through the middle of a box --room taller on
     each side, so the pencil's wander stays inside what it draws. */
  --room: 4px;
  --rule: linear-gradient(var(--graphite) 0 0) center / 100% var(--stroke)
    no-repeat;
  /* A well: a fill a little darker than the paper, pressed in. */
  --well: light-dark(
    color-mix(in srgb, var(--card), var(--border) 45%),
    color-mix(in srgb, var(--card), var(--bg) 65%)
  );
  --shade: light-dark(
    color-mix(in srgb, #523828 24%, transparent),
    color-mix(in srgb, #1d1714 70%, transparent)
  ); /* coffee; soot: what a well's hollow is */
  --hollow: inset 0 2px 4px var(--shade); /* how deep a well sits */
  /* How tall a press or a field stands; a part that holds a row of them
     smaller re-points it. */
  --control-height: 2.25rem;
}
@supports not (color: light-dark(#000, #fff)) {
:root {
  --well: color-mix(in srgb, var(--card), var(--border) 45%);
  --shade: color-mix(in srgb, #523828 24%, transparent);
}
@media (prefers-color-scheme: dark) {
:root {
  --well: color-mix(in srgb, var(--card), var(--bg) 65%);
  --shade: color-mix(in srgb, #1d1714 70%, transparent);
}
}
}

:where(body) {
  margin: 0;
  background: var(--bg);
  color: var(--text);
  font: var(--size) / 1.6 var(--font);
  -webkit-font-smoothing: antialiased;
}

:where([hidden]) {
  display: none !important;
}

/* A control is pressed, not read: clicking or tapping one never selects its
   words. Links in prose, addresses, numbers and code stay selectable. */
:where(button, summary, label, select, [role='button'], [role='tab'], [role='menuitem'], .Button) {
  -webkit-user-select: none;
  user-select: none;
}

/* What is drawn wears its outline on ::after: a graphite line through the
   pencil, in --pencil where a part asks for another colour and dashed where
   --pencil-style says so. Each starts from a solid graphite line, so none
   takes the line of a box it sits in. */
:where(.Button, .Card, a.Chip, .Empty, .Drop_Zone) {
  --pencil: initial;
  --pencil-style: initial;
}
:where(.Button, .Card, a.Chip, .Empty, .Drop_Zone)::after {
  content: '';
  position: absolute;
  inset: -1px;
  border: var(--stroke) var(--pencil-style, solid)
    var(--pencil, var(--graphite));
  border-radius: var(--radius);
  filter: var(--drawn);
  pointer-events: none;
}

/* The grain: one tile of paper, speckled in ink and cream, over the whole
   page and scrolling with it. It is drawn above everything, faint enough to
   read through, and never takes a press. The tile is --grain, at
   --grain-opacity: each skin that lays this names its own (paper/base.css,
   pencil/base.css). */
:where(html) {
  position: relative;
  min-height: 100%;
}
:where(html)::after {
  content: '';
  position: absolute;
  inset: 0;
  z-index: 2147483647;
  background: var(--grain) 0 0 / 256px;
  opacity: var(--grain-opacity);
  pointer-events: none;
}

}
@layer components {
/* Pencil's press, yaks.app's: a flat fill on a hatch, the hatch what an
   offset copy of it would show past its right and bottom edges, and its
   outline drawn in pencil on ::after (--pencil, --pencil-style: each part
   starts from a solid graphite line, so none takes the line of a box it sits
   in). A hover lifts the button off the hatch and a press slides it onto it;
   the hatch stays put. It stands --control-height tall, as a field does,
   padded by --control-pad-inline, which a part that holds a row of them
   re-points.

   Plain is paper; -go, the one to press, the accent; -quiet steps back
   beside another and reads as a link, with no fill, outline or hatch.
   -danger says its word in the negative, and -add, which offers what is not
   there yet, is muted and its line dashed. The fill and the ink ride
   --button-fill and --button-ink, so a part can re-point them. */
.Button {
  box-sizing: border-box;
  height: var(--control-height);
  padding: 0 var(--control-pad-inline, .75rem);
  font: inherit;
  line-height: 1.25;
  vertical-align: middle;
  position: relative;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: .35rem;
  border: 1px solid transparent;
  border-radius: var(--radius);
  background: var(--button-fill, var(--card));
  color: var(--button-ink, var(--text));
  font-weight: 800;
  text-align: center;
  text-decoration: none;
  cursor: pointer;
}
.Button::before {
  content: '';
  position: absolute;
  inset: calc(var(--lift) - 1px) calc(-1px - var(--lift))
    calc(-1px - var(--lift)) calc(var(--lift) - 1px);
  border-radius: var(--radius);
  background: var(--hatch);
  clip-path: polygon(calc(100% - var(--lift)) 0, 100% 0, 100% 100%, 0 100%,
    0 calc(100% - var(--lift)), calc(100% - var(--lift))
    calc(100% - var(--lift)));
  pointer-events: none;
}
.Button:hover:not(:disabled, [aria-pressed='true']) {
  --lift: 5px;
  transform: translate(-1px, -1px);
  background: color-mix(in srgb, var(--button-fill, var(--card)),
    white 10%);
}
.Button:active:not(:disabled),
.Button[aria-pressed='true'] {
  --lift: 1.5px;
  transform: translate(2.5px, 2.5px);
}
.Button:disabled {
  --lift: 0px;
  opacity: .55;
  cursor: not-allowed;
}
.Button-go {
  --button-fill: var(--accent);
  --button-ink: var(--bg);
}
.Button-quiet {
  --button-ink: var(--accent);
}
.Button-quiet,
.Button-quiet:hover:not(:disabled, [aria-pressed='true']),
.Button-quiet:active:not(:disabled) {
  --lift: 0px;
  padding: 0;
  background: none;
  font-weight: inherit;
  text-decoration: underline;
  transform: none;
}
.Button-quiet::before,
.Button-quiet::after {
  content: none;
}
.Button-add {
  --pencil-style: dashed;
  --button-ink: var(--muted);
}
.Button-add:hover {
  --button-ink: var(--text);
}
.Button-danger {
  --button-ink: var(--negative);
}
.Button-go.Button-danger {
  --button-fill: var(--negative);
  --button-ink: var(--bg);
}

}
@layer components {
/* Pencil's field is a well: darker than the paper, a little hollow, its edge
   drawn in pencil, as tall as a press beside it (--control-height). The
   pencil keeps what lies inside the edge as it is, so what is typed stays
   crisp. Focus draws the edge in the accent. */
.Field {
  box-sizing: border-box;
  height: var(--control-height);
  min-width: 0;
  max-width: 100%;
  padding: 0 var(--control-pad-inline, .75rem);
  border: var(--stroke) solid var(--graphite);
  border-radius: var(--radius);
  background: var(--well);
  box-shadow: var(--hollow);
  color: var(--text);
  font: inherit;
  line-height: 1.25;
  vertical-align: middle;
  filter: var(--drawn);
}
.Field:focus-visible {
  outline: 0;
  border-color: var(--accent);
  box-shadow: inset 0 0 0 1px var(--accent), var(--hollow);
}
select.Field {
  cursor: pointer;
}
select.Field:not(:disabled):hover {
  border-color: var(--accent);
}
/* A textarea is as tall as what is typed in it, from two controls' height
   up to most of the window, where it starts to scroll. */
textarea.Field {
  field-sizing: content;
  height: auto;
  min-height: calc(var(--control-height) * 2);
  max-height: 60vh;
  padding-block: .5rem;
  vertical-align: top;
}
.Field:disabled {
  opacity: .55;
  cursor: not-allowed;
}
/* A bare field belongs inside a part already drawn: no well, no edge. */
.Field-bare,
.Field-bare:focus-visible {
  height: auto;
  min-height: 0;
  padding: 0;
  border: 0;
  border-radius: 0;
  background: none;
  box-shadow: none;
  filter: none;
}

}
@layer components {
/* Pencil's chip, yaks.app's: a word on a card, edged in a hairline. A link
   chip is underlined in the accent and drawn in pencil (on ::after, from a
   solid graphite line, as a press is), and a hover washes it in the accent;
   pressed, not read, its words never select. -quiet is a label on the floor
   (the address in a window bar), -code words to copy, in the mono face. A
   hue (-0 … -5) inks and washes it in its colour, a link too; a ghost is
   dim, its edge dashed. What a variant changes rides a --chip-* property. */
.Chip {
  display: inline-block;
  padding: var(--chip-pad, .3rem .75rem);
  border: var(--chip-edge, 1px solid var(--border));
  border-radius: var(--radius);
  background: var(--chip-fill, var(--card));
  color: var(--chip-ink, var(--chip-hue, var(--text)));
  font-family: var(--chip-font, inherit);
  font-size: var(--chip-size, var(--small));
  font-weight: var(--chip-weight, 600);
  line-height: 1.4;
  vertical-align: middle;
  text-decoration: none;
}
a.Chip {
  --chip-ink: var(--chip-hue, var(--accent));
  --chip-edge: 1px solid transparent;
  --chip-weight: 700;
  position: relative;
  text-decoration: underline;
  text-underline-offset: .18em;
}
:where(a.Chip) {
  -webkit-user-select: none;
  user-select: none;
}
a.Chip:hover {
  --pencil: var(--accent);
  --chip-fill: color-mix(in srgb, var(--accent) 7%, var(--card));
}
a.Chip:active {
  transform: translate(1px, 1px);
}
a.Chip:focus-visible {
  outline: 3px solid var(--accent);
  outline-offset: 3px;
}
.Chip_Tag {
  margin-left: .5rem;
  color: var(--muted);
  font-weight: 400;
  font-size: .85em;
}
.Chip-quiet {
  --chip-fill: var(--bg);
  --chip-ink: var(--muted);
  --chip-edge: 0;
  --chip-pad: 0.2rem 0.9rem;
  --chip-size: var(--small);
  --chip-weight: 600;
}
.Chip-code {
  --chip-pad: .2rem .5rem;
  --chip-fill: var(--bg);
  --chip-edge: 0;
  --chip-font: var(--mono);
  --chip-size: var(--small);
}
.Chip-0 {
  --chip-hue: var(--hue-0);
}
.Chip-1 {
  --chip-hue: var(--hue-1);
}
.Chip-2 {
  --chip-hue: var(--hue-2);
}
.Chip-3 {
  --chip-hue: var(--hue-3);
}
.Chip-4 {
  --chip-hue: var(--hue-4);
}
.Chip-5 {
  --chip-hue: var(--hue-5);
}
:is(.Chip-0, .Chip-1, .Chip-2, .Chip-3, .Chip-4, .Chip-5) {
  --chip-fill: color-mix(in srgb, var(--chip-hue) 12%, var(--card));
}
.Chip-ghost {
  --chip-ink: var(--dim);
  --chip-fill: none;
  --chip-edge: 1px dashed var(--border2);
}

}
@layer components {
/* Pencil's row of chips, yaks.app's: a handful of notes, wrapping. */
.Chips {
  display: flex;
  flex-wrap: wrap;
  gap: 0.625rem;
}

}
@layer components {
/* An address: muted, the name in it the text's own ink and weighted. */
.Address {
  color: var(--muted);
  font-weight: normal;
}
.Address_Name {
  color: var(--text);
  font-weight: 600;
}

/* Pencil's address, laid over the kit's: the name in it in yaks.app's
   heaviest weight. */
.Address_Name {
  font-weight: 800;
}

}
@layer components {
/* A list of rows, close together. A nested list hangs off a rule. */
.Rows {
  display: grid;
  gap: 1px;
  min-width: 0;
}
.Rows-nested {
  margin-left: var(--half-gap);
  padding-left: var(--half-gap);
  border-left: 1px solid var(--border2);
}
.Rows_Item {
  min-width: 0;
}
.Rows_More {
  font-size: var(--small);
  color: var(--muted);
}

/* What is kept but no longer live: every word in it muted, links too. */
.Rows-quiet,
.Rows-quiet :is(a, .Tile_Title, .Body) {
  color: var(--muted);
}

/* A feed of unlike things: each entry has its own edge and breathing room. */
.Rows-ruled > .Rows_Item {
  padding: var(--half-gap) 0;
  border-bottom: 1px solid var(--border2);
}
.Rows_Kind {
  font-size: var(--small);
  color: var(--muted);
}

/* An entry's whole surface opens it, including a renderer's secondary text. */
.Rows_Link {
  display: block;
  color: var(--text);
  text-decoration: none;
  min-width: 0;
  border-radius: var(--radius);
}
.Rows_Link:hover {
  background: var(--soft);
}
.Rows_Link:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 2px;
}

/* A list put in order by dragging its rows. A row that can be picked up says
   so under the pointer, and a line says where a dragged one would land. */
.Rows-ordered > .Rows_Item[draggable='true'] {
  cursor: grab;
}
.Rows_Item-before {
  box-shadow: 0 -2px 0 var(--accent);
}
.Rows_Item-after {
  box-shadow: 0 2px 0 var(--accent);
}

/* A row that opens in place: a glyph pressed beside what it says, and, while
   open, what it opens, beneath it, hung off a rule. */
.Rows_Line {
  display: flex;
  align-items: center;
  gap: var(--half-gap);
  min-width: 0;
}
.Rows_Line > :last-child {
  flex: 1;
  min-width: 0;
}
.Rows_Toggle {
  font: inherit;
  color: var(--muted);
  background: none;
  border: 0;
  border-radius: var(--radius);
  padding: 0 4px;
  min-height: var(--tap);
  cursor: pointer;
}
.Rows_Toggle:hover {
  color: var(--text);
  background: var(--soft);
}
.Rows_Toggle:focus-visible {
  outline: 2px solid var(--accent);
}
.Rows_Toggle:disabled {
  visibility: hidden;
}
.Rows_Detail {
  display: grid;
  gap: var(--half-gap);
  margin: var(--half-gap) 0 var(--gap) var(--gap);
  padding-left: var(--gap);
  border-left: 1px solid var(--border2);
  min-width: 0;
}

/* A row of like things: a thing's name over what describes it, and what
   acts on it at the far side, under it where there is no room beside. */
.Rows_Item:where(:has(> .Rows_Main)) {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--half-gap) var(--gap);
}
.Rows_Main {
  display: grid;
  flex: 1 1 12rem;
  gap: 2px;
  min-width: 0;
  overflow-wrap: anywhere;
}
.Rows_Name {
  color: var(--text);
  font-weight: 700;
}
.Rows_Meta {
  color: var(--muted);
  font-size: var(--small);
}
.Rows_Actions {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--half-gap);
  margin-left: auto;
}
.Rows_Actions form {
  display: contents;
}

/* Like things in rows, hairlines between them: each row its name and what
   describes it on the left, what acts on it on the right, its controls a
   size down. The kit's rows sit a pixel apart; these meet at the hairline.
   In a card the rows run to its edges (pencil/Card.css). */
.Rows {
  gap: 0;
  min-width: auto;
  margin: 0;
  padding: 0;
  list-style: none;
}
.Rows_Item {
  --control-height: 2rem;
  --control-pad-inline: 0.7rem;
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0.5rem 1rem;
  min-width: auto;
  padding: 0.75rem 0;
  border-top: 1px solid var(--border);
}
.Rows_Item:first-child {
  padding-top: 0;
  border-top: 0;
}
.Rows_Item:last-child {
  padding-bottom: 0;
}
.Rows_Main {
  gap: 0.15rem;
  line-height: 1.45;
}
.Rows_Meta {
  font-size: var(--fine, var(--small));
}
.Rows_Actions {
  gap: 0.5rem;
  margin: 0 0 0 auto;
}
.Rows_Actions .Button {
  font-size: var(--fine, var(--small));
}

}
@layer components {
/* A card: one surface holding related things, flat on the page. Depth
   belongs to what is pressed, so a card casts no shadow; its pencil box is
   what draws it. What it holds stacks a gap apart, never by margins of its
   own, and its head, when it has one, runs edge to edge across the top,
   ruled off under it: what it is on the left, its actions on the right.

   Its box is drawn as everything outlined is (base.css). A page's own
   surface is drawn by being a card. */
.Card {
  --pad-block: 1rem;
  --pad-inline: 1.25rem;
  position: relative;
  display: grid;
  align-content: start;
  gap: 0.75rem;
  min-width: 0;
  padding: var(--pad-block) var(--pad-inline);
  border: 1px solid transparent;
  border-radius: var(--radius);
  background: var(--card);
  overflow-wrap: break-word;
}
.Card > * {
  min-width: 0;
  margin: 0;
}

/* The head: a mark, the title, how it stands, and then whatever acts on
   the whole card, pushed to the right. Its controls are a size down, so a
   head is one compact line however many it holds; it wraps on a phone. */
.Card_Head {
  --control-height: 2rem;
  --control-pad-inline: 0.7rem;
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0.5rem 0.75rem;
  min-height: 3rem;
  position: relative;
  margin: calc(-1 * var(--pad-block)) calc(-1 * var(--pad-inline)) 0;
  padding: 0.5rem var(--pad-inline);
}
/* The rule under it meets the card's sides. */
.Card_Head::after {
  content: '';
  position: absolute;
  inset: auto -1px calc(-1 * var(--room));
  height: calc(var(--stroke) + 2 * var(--room));
  background: var(--rule);
  filter: var(--drawn);
}
.Card_Head:last-child {
  margin-bottom: calc(-1 * var(--pad-block));
}
.Card_Head:last-child::after {
  content: none;
}
.Card_Title {
  margin: 0;
  color: var(--text);
  font-size: 1rem;
  font-weight: 800;
  line-height: 1.3;
}
.Card_Title a {
  color: inherit;
  text-decoration: none;
}
.Card_Title a:hover {
  color: var(--accent);
  text-decoration: underline;
}
.Card_Mark {
  flex: none;
  width: 1.5rem;
  height: 1.5rem;
}
.Card_Actions {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0.5rem;
  margin: 0 0 0 auto;
}
.Card_Actions form {
  display: contents;
}
.Card_Actions .Button {
  font-size: var(--fine, var(--small));
}

/* What the card is, in a line, under its head. */
.Card_Sub {
  color: var(--muted);
  font-size: var(--small);
}

/* Rows in a card run to its edges, the hairlines between them meeting its
   sides. */
.Card > .Rows {
  margin-inline: calc(-1 * var(--pad-inline));
}
.Card > .Rows > .Rows_Item {
  padding-inline: var(--pad-inline);
}

}
@layer components {
/* A pip: a disc whose shape says a state and whose tone colours it. Shape
   and tone are separate variants, so a state is at most one of each. The
   glyphs are pseudo-elements drawn in floor ink, so they read as cutouts. */
.Dot {
  --dot: var(--dim);
  display: inline-block;
  position: relative;
  flex: none;
  width: 0.72em; /* em: the pip rides its line's font */
  height: 0.72em;
  border-radius: 50%;
  border: max(1px, 0.09em) solid var(--dot);
  background: var(--dot);
}
.Dot::before,
.Dot::after {
  position: absolute;
}

/* The shapes. */
.Dot-ring {
  background: transparent;
}
.Dot-dashed {
  background: transparent;
  border-style: dashed;
}
.Dot-half {
  background: linear-gradient(90deg, var(--dot) 50%, transparent 0);
}
/* Something happening right now: the full disc breathes. */
.Dot-pulse {
  animation: DotPulse 2.2s ease-out infinite;
}
@keyframes DotPulse {
  from {
    box-shadow: 0 0 0 0 color-mix(in srgb, var(--dot) 55%, transparent);
  }
  to {
    box-shadow: 0 0 0 0.45em color-mix(in srgb, var(--dot) 0%, transparent);
  }
}
@media (prefers-reduced-motion: reduce) {
  .Dot {
    animation: none; /* the full disc still says it; only the breath goes */
  }
}
.Dot-check::after {
  content: '';
  left: 50%;
  top: 50%;
  width: 0.3em;
  height: 0.16em;
  border-left: 0.09em solid var(--bg);
  border-bottom: 0.09em solid var(--bg);
  transform: translate(-50%, -65%) rotate(-45deg);
}
.Dot-cross::before,
.Dot-cross::after {
  content: '';
  left: 50%;
  top: 50%;
  width: 0.09em;
  height: 0.38em;
  border-radius: 0.04em;
  background: var(--bg);
}
.Dot-cross::before {
  transform: translate(-50%, -50%) rotate(45deg);
}
.Dot-cross::after {
  transform: translate(-50%, -50%) rotate(-45deg);
}
.Dot-alert::before {
  content: '';
  left: 50%;
  top: 0.1em;
  width: 0.09em;
  height: 0.24em;
  border-radius: 0.04em;
  translate: -50%;
  background: var(--bg);
}
.Dot-alert::after {
  content: '';
  left: 50%;
  bottom: 0.08em;
  width: 0.1em;
  height: 0.1em;
  border-radius: 50%;
  translate: -50%;
  background: var(--bg);
}

/* The tones. */
.Dot-info {
  --dot: var(--info);
}
.Dot-active {
  --dot: var(--active);
}
.Dot-positive {
  --dot: var(--positive);
}
.Dot-negative {
  --dot: var(--negative);
}
.Dot-caution {
  --dot: var(--caution);
}
.Dot-accent {
  --dot: var(--accent);
}
.Dot-special {
  --dot: var(--special);
}

}
@layer components {
/* How something stands: a word beside a dot. The word describes, so it is
   small and muted; the dot's tone says the state. */
.State {
  display: inline-flex;
  align-items: center;
  gap: 0.35em;
  color: var(--muted);
  font-size: var(--small);
  line-height: 1.3;
}

/* How something stands, as a word in its role's colour beside a dot of the
   same: -positive when it works, -negative when it needs the person. What
   works is said in the accent, the colour of what is lit. */
.State {
  gap: 0.35rem;
  color: var(--state, var(--muted));
  font-size: var(--fine, var(--small));
  font-weight: 700;
}
.State > .Dot {
  width: 0.5rem;
  height: 0.5rem;
  border: 0;
  background: currentColor;
}
.State-positive,
.State-accent {
  --state: var(--accent);
}
.State-negative {
  --state: var(--negative);
}
.State-info {
  --state: var(--info);
}
.State-active {
  --state: var(--active);
}
.State-caution {
  --state: var(--caution);
}
.State-special {
  --state: var(--special);
}

}
@layer components {
/* A heading over a run of cards: what they share, small and muted, so the
   cards' own titles lead. */
.Group {
  margin: 0;
  color: var(--muted);
  font-size: var(--small);
  font-weight: 700;
}

/* A heading over a run of cards that belong together, a gap after the run
   before it. */
.Group {
  margin: var(--gap) 0 0;
}
.Group:first-child {
  margin-top: 0;
}

}
@layer components {
/* Pencil's form: yaks.app's spacing, its fields at most 34rem wide and their
   hints a step under the small type (--fine, yaks.app's). */
.Form {
  display: grid;
  gap: .875rem;
  margin: 0;
}
.Form_Field {
  display: grid;
  gap: .35rem;
  min-width: 0;
  max-width: 34rem;
}
.Form_Label {
  margin: 0;
  color: var(--text);
  font-size: var(--small);
  font-weight: 700;
}
.Form_Optional {
  color: var(--muted);
  font-weight: 400;
}
.Form_Field > .Field {
  width: 100%;
}
.Form_Hint {
  margin: 0;
  color: var(--muted);
  font-size: var(--fine, var(--small));
}
/* A value shown where its control would be, which nobody changes here: its
   words as they are, every line and long word kept inside the field. */
.Form_Value {
  margin: 0;
  color: var(--text);
  white-space: pre-wrap;
  overflow-wrap: anywhere;
}
.Form_Value-none {
  color: var(--dim);
}
/* One field and the button that sends it, on one line while they fit. */
.Form_Line {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: .5rem;
  min-width: 0;
  margin: 0;
}
.Form_Line > .Field,
.Form_Line > .At {
  flex: 1 1 12rem;
}
.Form_Actions {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: .5rem;
}

}
@layer components {
/* Pencil's field with a fixed ending: yaks.app's spacing. */
.At {
  display: flex;
  align-items: center;
  gap: .35rem;
  min-width: 0;
}
.At > .Field {
  flex: 1 1 auto;
}
.At_End {
  flex: none;
  color: var(--muted);
}

}
@layer components {
/* Pencil's drop zone: a place for something rather than a thing, so its
   pencil line is dashed and light (--pencil, --pencil-style, on ::after, as
   every drawn part wears its line), solid in the accent while files are held
   over it. What is chosen sits under it on wells, a step under the small
   type where it describes (--fine, yaks.app's). */
.Drop {
  display: grid;
  gap: .5rem;
  min-width: 0;
}
.Drop_Zone {
  --pencil: var(--border2);
  --pencil-style: dashed;
  position: relative;
  display: grid;
  place-items: center;
  gap: .25rem;
  min-height: 6rem;
  padding: 1.25rem 1rem;
  border-radius: var(--radius);
  background: var(--bg);
  text-align: center;
  cursor: pointer;
}
.Drop_Zone:hover,
.Drop_Zone:has(.Drop_File:focus-visible) {
  --pencil: var(--accent);
}
.Drop_Zone:has(.Drop_File:focus-visible) {
  outline: 2px solid var(--accent);
  outline-offset: 2px;
}
.Drop_Zone-over {
  --pencil: var(--accent);
  --pencil-style: solid;
  background: var(--card);
}
.Drop_Zone:has(.Drop_File:disabled) {
  opacity: .55;
  cursor: not-allowed;
}
.Drop_File {
  position: absolute;
  width: 1px;
  height: 1px;
  opacity: 0;
  pointer-events: none;
}
.Drop_Say {
  color: var(--text);
}
.Drop_Choose {
  color: var(--accent);
  font-weight: 700;
  text-decoration: underline;
  text-underline-offset: .2em;
}
.Drop_Hint {
  color: var(--muted);
  font-size: var(--fine, var(--small));
}
.Drop_Chosen {
  display: grid;
  gap: .35rem;
  margin: 0;
  padding: 0;
  list-style: none;
}
.Drop_Chosen:empty {
  display: none;
}
.Drop_Item {
  --control-height: 2rem;
  --control-pad-inline: .7rem;
  display: flex;
  align-items: center;
  gap: .75rem;
  min-width: 0;
  padding: .35rem .5rem;
  border-radius: var(--radius);
  background: var(--well);
}
.Drop_Picture {
  flex: none;
  width: 2.5rem;
  height: 2.5rem;
  border-radius: var(--radius);
  object-fit: cover;
}
.Drop_Name {
  flex: 1 1 auto;
  min-width: 0;
  overflow: hidden;
  color: var(--text);
  font-weight: 700;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.Drop_Size {
  flex: none;
  color: var(--muted);
  font-size: var(--fine, var(--small));
}
.Drop_Item > .Button {
  flex: none;
  font-size: var(--fine, var(--small));
}
/* What was left out, past the input's ceilings. */
.Drop_Said {
  margin: 0;
  color: var(--muted);
  font-size: var(--fine, var(--small));
}
.Drop_Said:empty {
  display: none;
}
/* A file of a kind that is not read, with a line that says so. */
.Drop_Note {
  flex-basis: 100%;
  color: var(--muted);
  font-size: var(--fine, var(--small));
}
.Drop_Item-unread {
  flex-wrap: wrap;
}
/* A gathering part (a chat app's message box): it takes a drop or a paste
   anywhere on it, and what it holds sits along its top as chips, a picture
   as itself and any other file as its kind and name, each with a way to take
   it back. */
.Drop-gather {
  position: relative;
}
.Drop-over {
  outline: 2px dashed var(--accent);
  outline-offset: 2px;
}
.Drop-gather .Drop_Chosen {
  display: flex;
  flex-wrap: wrap;
  gap: .5rem;
}
.Drop-gather .Drop_Chosen:empty {
  display: none;
}
.Drop-gather .Drop_Item {
  position: relative;
  gap: .5rem;
  max-width: 16rem;
  padding: .35rem 2rem .35rem .35rem;
}
.Drop-gather .Drop_Picture {
  width: 3.5rem;
  height: 3.5rem;
}
.Drop-gather .Drop_Item > .Button {
  position: absolute;
  top: .2rem;
  right: .2rem;
  --control-height: 1.6rem;
  --control-pad-inline: .45rem;
}
.Drop_Kind {
  flex: none;
  display: grid;
  place-items: center;
  min-width: 2.5rem;
  height: 2.5rem;
  padding-inline: .3rem;
  border-radius: var(--radius);
  background: var(--card);
  color: var(--muted);
  font-size: var(--fine, var(--small));
  font-weight: 700;
}

}
@layer components {
/* Pencil's fold: yaks.app's spacing, and markdown someone wrote in it (a
   Body, theirs.ts in yaks.app), such as how to get a key, set close and
   ending where the body does. */
.More > summary {
  display: inline-flex;
  align-items: center;
  gap: .45rem;
  color: var(--accent);
  font-size: var(--small);
  font-weight: 700;
  cursor: pointer;
  list-style: none;
}
.More > summary::-webkit-details-marker {
  display: none;
}
.More > summary::before {
  content: '';
  flex: none;
  width: .4rem;
  height: .4rem;
  border: solid currentColor;
  border-width: 0 2px 2px 0;
  transform: rotate(-45deg);
  transition: transform .15s;
}
.More[open] > summary::before {
  transform: rotate(45deg);
}
.More_Body {
  display: grid;
  gap: .875rem;
  margin-top: .75rem;
}
.More_Body > *,
.More_Body > .Body > :last-child {
  margin: 0;
}
.More_Body > .Body {
  display: grid;
  gap: .625rem;
}
.More_Body > .Body :is(p, ol, ul, pre) {
  margin: 0;
}
.More_Body > .Body :is(ol, ul) {
  display: grid;
  gap: .375rem;
  padding-inline-start: 1.4rem;
}
.More_Body > .Body li {
  display: grid;
  gap: .375rem;
}
.More_Body > .Body ol {
  list-style: decimal;
}
.More_Body > .Body ul {
  list-style: disc;
}
.More_Body > .Body pre {
  padding: .6rem .8rem;
  background: var(--card);
  white-space: pre-wrap;
  overflow-wrap: anywhere;
}

}
@layer components {
/* The text of a thing: the ink at a reading measure, its paragraphs and
   quotes as the base sets prose. A short one is the gist: muted, smaller. */
.Body {
  min-width: 0;
  max-width: var(--measure);
  color: var(--text);
  line-height: 1.5;
  overflow-wrap: anywhere;
}
.Body-short {
  color: var(--muted);
  font-size: var(--small);
}
/* A text a press types into: the pointer says so, a text cursor over a
   faint wash. */
.Body-typed {
  cursor: text;
  border-radius: var(--radius);
}
.Body-typed:hover {
  background: var(--soft);
}
/* A document's source: its lines kept and wrapped at the measure, every
   character where it stands, smaller, in the face of what is typed. */
.Body-source > pre {
  margin: 0;
  white-space: pre-wrap;
  overflow-wrap: anywhere;
  font-size: var(--small);
  line-height: 1.5;
}

/* Pencil's body of text takes the page's measure and type, as yaks.app's
   rendered markdown always has: the kit's measure, line and ink give way to
   whatever holds it, a page's prose or a reply. */
.Body {
  min-width: auto;
  max-width: none;
  color: inherit;
  line-height: inherit;
  overflow-wrap: inherit;
}

}
@layer components {
/* A line said back, small and muted; a refusal in the negative. Empty, it
   takes no room. */
.Notice {
  margin: 0;
  color: var(--muted);
  font-size: var(--small);
}
.Notice:empty {
  display: none;
}
.Notice-negative {
  color: var(--negative);
}

}
@layer components {
/* Something at work: the yak doing it (yaks.app's mascot), then the words
   that say what it is, in the ink of wherever it sits. */
.Loading {
  display: flex;
  align-items: center;
  gap: 0.5rem;
}
.Loading_Mark,
.Loading_Mark img {
  display: block;
  flex: none;
  width: 40px;
  height: 40px;
}

}
@layer components {
/* Pencil's words to copy, yaks.app's: a strip of the floor a control tall,
   the words in the face around them, and the button beside it a paper press
   inked in the accent, a size down (pages.ts `copyable`). */
.Copy {
  display: flex;
  align-items: center;
  gap: .5rem;
  min-width: 0;
}
.Copy_Text {
  flex: 1;
  min-width: 0;
  min-height: var(--control-height);
  padding: .4rem .75rem;
  background: var(--bg);
  color: var(--text);
  overflow-wrap: anywhere;
  user-select: all;
}
/* In its Copy, so it outranks the press it wears, whichever sheet comes
   first. */
.Copy .Copy_Go {
  --button-ink: var(--accent);
  flex: none;
  font-size: var(--fine, var(--small));
}

}
@layer components {
/* Nothing here yet: what will be, and how to start. Its pencil line is
   dashed and light, a place for something rather than a thing. */
.Empty {
  --pencil: var(--border2);
  --pencil-style: dashed;
  position: relative;
  display: grid;
  justify-items: center;
  gap: 0.5rem;
  padding: 2rem 1.25rem;
  border: 1px solid transparent;
  border-radius: var(--radius);
  color: var(--muted);
  text-align: center;
}
.Empty > * {
  max-width: 30rem;
  margin: 0;
}
.Empty h2 {
  color: var(--text);
  font-size: 1.05rem;
  font-weight: 800;
}

}
@layer components {
/* A report: a card whose head says the total where its actions would sit,
   then a chart of the days, its first and last day under it, and short
   lists side by side, each name cut short before it would push its count
   out of its column. */
.Report {
  gap: 1.25rem;
}
.Report_Total {
  flex: none;
  margin: 0 0 0 auto;
  color: var(--text);
  font-size: var(--h3);
  font-weight: 700;
  font-variant-numeric: tabular-nums;
  line-height: 1.2;
}
.Report_Unit {
  color: var(--muted);
  font-size: var(--small);
  font-weight: 400;
}
.Report_Plot {
  display: grid;
  gap: 0.35rem;
  margin: 0;
}
.Report_Span {
  display: flex;
  justify-content: space-between;
  color: var(--muted);
  font-size: var(--small);
}
.Report_Tops {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: 1.5rem;
}
.Report_Column h3 {
  margin: 0 0 0.5rem;
  color: var(--muted);
  font-size: var(--small);
  font-weight: 700;
}
/* One column as wide as the list's own, so a long name is cut short with
   an ellipsis rather than widening the row past its column and over the
   next one; the count beside it keeps its whole width and one line. */
.Report_List {
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  gap: 0.4rem;
  margin: 0;
  padding: 0;
  list-style: none;
  font-size: var(--small);
}
.Report_List li {
  display: flex;
  justify-content: space-between;
  gap: 0.75rem;
}
.Report_List span {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.Report_List b {
  flex: none;
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
}
@media (max-width: 600px) {
  .Report_Tops {
    grid-template-columns: minmax(0, 1fr);
    gap: 1rem;
  }
}

/* A report drawn yaks.app's way: its total a little larger and heavier, and
   what describes it a step under the small type. */
.Report_Total {
  font-size: 1.25rem;
  font-weight: 800;
}
.Report_Unit,
.Report_Span,
.Report_Column h3 {
  font-size: var(--fine, var(--small));
}

}
@layer components {
/* A chart's marks. A number's words keep the page's ink; the marks are drawn
   in the theme's roles. */
.Chart {
  position: relative;
  touch-action: pan-y;
}
/* The point a pointer, a finger or an arrow key is on (the page's listener
   sets data-on and --at), and the tip that says it, floating clear of
   whatever clips the chart. */
.Chart[data-on]::after {
  content: '';
  position: absolute;
  top: 0;
  bottom: 0;
  left: var(--at);
  width: 1px;
  background: var(--muted);
  pointer-events: none;
}
.Chart-line {
  display: inline-block;
  vertical-align: middle;
}
.Chart-bars {
  display: block;
  height: 5rem;
  border-bottom: 1px solid var(--border2);
}
.Chart-bars .Chart_Plot {
  display: block;
  width: 100%;
  height: 100%;
}
.Chart_Line {
  fill: none;
  stroke: var(--muted);
  stroke-width: 1.5;
  stroke-linecap: round;
  stroke-linejoin: round;
}
.Chart_End,
.Chart_Bar {
  fill: var(--accent);
}
.Chart_Tip {
  position: fixed;
  z-index: 200;
  padding: 0.15rem 0.5rem;
  border-radius: var(--radius);
  background: var(--text);
  color: var(--card);
  font-size: var(--small);
  white-space: nowrap;
  pointer-events: none;
}

/* A chart in pencil: a graphite line through the pencil, ending in a dot on
   today, or a column a day over a hairline. A pointer over it is a
   crosshair, and the tip floats over every raised part of the page. */
.Chart {
  z-index: 1;
  cursor: crosshair;
}
.Chart:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 2px;
}
.Chart-line {
  margin-left: 0.5rem;
  padding: 0.25rem 0;
  line-height: 0;
}
.Chart-line .Chart_Plot {
  filter: var(--drawn);
  overflow: visible;
}
.Chart-bars {
  border-bottom: 1px solid var(--border);
}
.Chart_Line {
  stroke: var(--graphite);
  stroke-width: var(--stroke);
}
.Chart_Tip {
  z-index: var(--float, 200);
  font-size: var(--fine, var(--small));
}

}
@layer components {
/* Pencil's tabs: physical tabs on one sheet. Each tab is drawn in pencil on
   its top and sides; the panel's own top line is every tab's foot, and the
   lit tab covers it, so tab and panel are one sheet. In a set (`TabSet`)
   native radios own selection, arrow keys too, so it works without script:
   the checked radio's tab is the lit one. */
.Tabs {
  display: flex;
  flex-wrap: wrap;
  column-gap: .3rem;
  position: relative;
  min-width: 0;
  margin: 0;
  padding: 0;
  border: 0;
}
.Tabs_Legend {
  margin-bottom: 1rem;
  padding: 0;
  color: var(--text);
  font-weight: 800;
  text-align: left;
}
.Tabs_Item {
  display: contents;
}
.Tabs_Item > input {
  position: absolute;
  width: 1px;
  height: 1px;
  opacity: 0;
  pointer-events: none;
}
.Tabs_Tab {
  flex: 1 1 auto;
  display: flex;
  align-items: center;
  justify-content: center;
  position: relative;
  min-width: 0;
  min-height: 3rem;
  overflow-wrap: normal;
  margin: .35rem 0 0;
  padding: .55rem .45rem;
  border: 1px solid transparent;
  border-bottom: 0;
  border-radius: var(--radius) var(--radius) 0 0;
  background: var(--surface);
  color: var(--muted);
  font: inherit; /* a button's, as a label's is */
  font-size: .85rem;
  font-weight: 700;
  line-height: 1.25;
  text-align: center;
  text-decoration: none; /* a tab that links reads as a tab */
  cursor: pointer;
  -webkit-user-select: none;
  user-select: none;
}
.Tabs_Tab::after {
  content: '';
  position: absolute;
  inset: -1px -1px 0;
  border: var(--stroke) solid var(--graphite);
  border-bottom: 0;
  border-radius: var(--radius) var(--radius) 0 0;
  filter: var(--drawn);
  pointer-events: none;
}
@media (max-width: 480px) {
  .Tabs_Tab {
    padding-inline: .3rem;
    font-size: .8rem;
  }
}
.Tabs_Tab:hover,
.Tabs_Tab-hover {
  color: var(--text);
}
.Tabs_Panel {
  order: 1;
  flex: 1 1 100%;
  min-width: 0;
  position: relative;
  margin: 0;
  text-align: left;
  z-index: 1;
}
.Tabs_Tab-on,
.Tabs_Item > input:checked ~ .Tabs_Tab {
  margin-top: 0;
  padding-top: .9rem;
  background: var(--card);
  color: var(--text);
  z-index: 2;
}
/* The gap the lit tab opens in the panel's line. It stops short of the
   tab's sides, so they meet the line, and the first tab's meets the panel's
   corner. */
.Tabs_Tab-on::before,
.Tabs_Item > input:checked ~ .Tabs_Tab::before {
  content: '';
  position: absolute;
  inset: auto 2px calc(-1.5 * var(--room));
  height: calc(3 * var(--room));
  background: var(--card);
}
/* Only the checked radio's panel shows. Hiding the rest outranks a card's
   own display, wherever the card's rule comes. */
.Tabs_Item > input:not(:checked) ~ .Tabs_Panel {
  display: none;
}
.Tabs_Item > input:checked ~ .Tabs_Panel {
  display: grid;
}
.Tabs_Item > input:focus-visible ~ .Tabs_Tab {
  outline: 3px solid var(--accent);
  outline-offset: -5px;
}
/* Raised like a superscript; the shift is paint only, so the line keeps
   its height. */
.Tabs_Badge {
  position: relative;
  top: -0.5em;
  min-width: 1.1em;
  padding: 0 0.25em;
  border-radius: 1em;
  background: var(--accent);
  color: var(--bg);
  font-size: 0.65em;
  line-height: 1.5;
  font-variant-numeric: tabular-nums;
  text-align: center;
}

}
@layer components {
/* A glyph in lines: the words' height and a little more, sat on their
   baseline, stroked in their colour. */
.Icon {
  display: inline-block;
  width: 1.1em;
  height: 1.1em;
  flex: none;
  vertical-align: -.15em;
  fill: none;
  stroke: currentColor;
  stroke-width: 2;
  stroke-linecap: round;
  stroke-linejoin: round;
}

}
@layer components {
/* Pencil's side navigation: a column of links beside an edge, the edge
   between this nav and the panel it leans against. The current link is a
   tab drawn in pencil and filled with the panel, and it covers the edge, so
   it opens into the panel, which is what makes it read as the page you are
   on. A nav with no panel beside it points --nav-edge and --nav-panel at
   nothing, and --nav-shut at graphite to close the tab's open side, so its
   current link is a pencil box (every nav on a phone, and any page's that
   says so). */
.SideNav {
  --nav-panel: var(--card);
  --nav-edge: var(--graphite);
  --nav-shut: transparent;
  position: relative;
  display: grid;
  gap: .4rem;
}
.SideNav::after {
  content: '';
  position: absolute;
  inset: 0 calc(-1 * var(--room)) 0 auto;
  width: calc(var(--stroke) + 2 * var(--room));
  background: linear-gradient(var(--nav-edge) 0 0) center / var(--stroke)
    100% no-repeat;
  filter: var(--drawn);
  pointer-events: none;
}
.SideNav_Link {
  position: relative;
  display: flex;
  align-items: center;
  gap: .65rem;
  padding: .6rem .8rem;
  border: 1px solid transparent;
  border-radius: var(--radius);
  color: var(--muted);
  font-size: .95rem;
  text-decoration: none;
  -webkit-user-select: none;
  user-select: none;
}
.SideNav_Link:hover,
.SideNav_Link-hover {
  color: var(--text);
}
.SideNav_Link-on {
  background: var(--nav-panel);
  color: var(--text);
  font-weight: 800;
  z-index: 1;
}
.SideNav_Link-on::after {
  content: '';
  position: absolute;
  inset: -1px 0 -1px -1px;
  border: var(--stroke) solid var(--graphite);
  border-right-color: var(--nav-shut);
  border-radius: var(--radius);
  filter: var(--drawn);
  pointer-events: none;
}
/* The gap the current tab opens in the edge. */
.SideNav_Link-on::before {
  content: '';
  position: absolute;
  inset: 2px calc(-1.5 * var(--room)) 2px auto;
  width: calc(3 * var(--room));
  background: var(--nav-panel);
}
/* A rule between groups of links, stopping short of the edge. */
.SideNav_Rule {
  height: calc(var(--stroke) + 2 * var(--room));
  margin: calc(1rem - var(--room)) .8rem;
  border: 0;
  background: var(--rule);
  filter: var(--drawn);
}
@media (max-width: 700px) {
  .SideNav {
    --nav-panel: transparent;
    --nav-edge: transparent;
    --nav-shut: var(--graphite);
    display: flex;
    flex-wrap: wrap;
  }
}

}
@layer components {
/* Pencil's box and radio are drawn, not the browser's: a graphite edge on
   the card, filled with the accent once checked, a tick or a dot in the
   paper's colour, as tall as a press beside it (--control-height). */
.Check {
  display: inline-flex;
  align-items: center;
  gap: .5rem;
  min-height: var(--control-height);
  line-height: 1.4;
  cursor: pointer;
}
.Check input {
  appearance: none;
  display: grid;
  place-content: center;
  box-sizing: border-box;
  width: 1.125rem;
  height: 1.125rem;
  flex: none;
  margin: 0;
  border: var(--stroke) solid var(--graphite);
  background: var(--card);
  cursor: inherit;
}
.Check input[type='radio'] {
  border-radius: 50%;
}
.Check input::before {
  content: '';
  width: .45rem;
  height: .45rem;
  transform: scale(0);
}
.Check input[type='checkbox']::before {
  width: .3rem;
  height: .6rem;
  margin-top: -.15rem;
  border: solid var(--bg);
  border-width: 0 2px 2px 0;
  transform: rotate(45deg) scale(0);
}
.Check input[type='radio']::before {
  border-radius: 50%;
  background: var(--bg);
}
.Check input:checked {
  background: var(--accent);
  border-color: var(--accent);
}
.Check input:checked::before {
  transform: scale(1);
}
.Check input[type='checkbox']:checked::before {
  transform: rotate(45deg) scale(1);
}
.Check:has(input:disabled) {
  opacity: .55;
  cursor: not-allowed;
}
.Check input:focus-visible {
  outline: 3px solid var(--accent);
  outline-offset: 3px;
}

}
@layer components {
/* Things to browse, in groups. A group's heading is small, spaced capitals
   over a rule; an entry's title is large and ink, what it is muted under it,
   then what it shows. Entries stand well apart and groups further, so the
   eye finds each at a glance; a wide window gets a wider margin. The entry
   a link jumped to lights its title. */
.Catalog {
  display: grid;
  gap: calc(var(--gap) * 4);
  min-width: 0;
}
@media (min-width: 56rem) {
  .Catalog {
    padding: var(--gap) calc(var(--gap) * 2);
  }
}
.Catalog_Group {
  display: grid;
  gap: calc(var(--gap) * 2.5);
  min-width: 0;
  scroll-margin-top: var(--gap);
}
.Catalog_Heading {
  margin: 0;
  max-width: none;
  padding-bottom: var(--half-gap);
  border-bottom: 1px solid var(--border2);
  font-size: var(--small);
  font-weight: 600;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--heading);
}
.Catalog_Entry {
  display: grid;
  gap: 4px;
  min-width: 0;
  scroll-margin-top: var(--gap);
}
.Catalog_Title {
  margin: 0;
  font-size: var(--h3);
  font-weight: 600;
  line-height: 1.3;
  color: var(--text);
}
.Catalog_Entry:target > .Catalog_Title {
  color: var(--accent);
}
.Catalog_Sub {
  margin: 0 0 var(--gap);
  max-width: var(--measure);
  color: var(--muted);
}

}
@layer components {
/* Things side by side: as many figures to a line as fit, each as wide as
   what it shows asks, and no wider than the line. A figure is its caption,
   small and mono, over a stage: a raised panel with room all round, where
   what is shown sits as it would anywhere else. */
.Gallery {
  display: flex;
  flex-wrap: wrap;
  gap: var(--gap);
  min-width: 0;
}
.Gallery_Figure {
  flex: 0 1 max-content;
  min-width: 0;
  margin: 0;
  display: flex;
  flex-direction: column;
  gap: 6px;
}
.Gallery_Caption {
  padding: 0 2px;
  font-family: var(--mono);
  font-size: var(--small);
  line-height: 1.4;
  color: var(--muted);
  overflow-wrap: anywhere;
}
.Gallery_Stage {
  flex: 1 1 auto;
  min-width: 0;
  /* Roomy, and less so on a phone, where the room is the line's. */
  padding: clamp(var(--gap), 4vw, calc(var(--gap) * 1.75));
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  overflow-x: auto; /* what is wider than the line scrolls within its stage */
}

}

/* What every yaks.app page shares beside the kit (@yaks/ui, in _ui.css: the
   linen theme and the pencil skin, whose tokens draw yaks.app's lines): its
   face, Nunito, and the paints and measures its pages keep that are no
   theme's roles. */

/* Nunito, served from here so a first paint waits on no other site. One
   variable file per subset, and a page only fetches the subsets its text uses. */
@font-face {
  font-family: 'Nunito';
  font-weight: 400 800;
  font-display: swap;
  src: url(nunito-cyrillic-ext.88985ca614.woff2) format('woff2');
  unicode-range: U+0460-052F, U+1C80-1C8A, U+20B4, U+2DE0-2DFF, U+A640-A69F,
    U+FE2E-FE2F;
}
@font-face {
  font-family: 'Nunito';
  font-weight: 400 800;
  font-display: swap;
  src: url(nunito-cyrillic.63b14e3ef0.woff2) format('woff2');
  unicode-range: U+0301, U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116;
}
@font-face {
  font-family: 'Nunito';
  font-weight: 400 800;
  font-display: swap;
  src: url(nunito-vietnamese.61e5958cf3.woff2) format('woff2');
  unicode-range: U+0102-0103, U+0110-0111, U+0128-0129, U+0168-0169,
    U+01A0-01A1, U+01AF-01B0, U+0300-0301, U+0303-0304, U+0308-0309, U+0323,
    U+0329, U+1EA0-1EF9, U+20AB;
}
@font-face {
  font-family: 'Nunito';
  font-weight: 400 800;
  font-display: swap;
  src: url(nunito-latin-ext.2c8d792869.woff2) format('woff2');
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7,
    U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF,
    U+2020, U+20A0-20AB, U+20AD-20C4, U+2113, U+2C60-2C7F, U+A720-A7FF;
}
@font-face {
  font-family: 'Nunito';
  font-weight: 400 800;
  font-display: swap;
  src: url(nunito-latin.ba344451ea.woff2) format('woff2');
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA,
    U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193,
    U+2212, U+2215, U+FEFF, U+FFFD;
}

@layer tokens {
  :root {
    /* Paints of yaks.app's own pages: the person's bubble and the
       assistant's, and the ground of an embedded app's preview, which
       matches the app in either scheme. */
    --mine: light-dark(#f8e0c8, #4e3b32); /* blush; ember */
    --theirs: light-dark(#e5eef5, #34404a); /* sky; dusk */
    --preview: #33493c; /* forest */

    /* Type, beside the theme's --size and --small. */
    --lead: 1.125rem;
    --fine: 0.875rem; /* what describes a thing: a hint, a status, a count */

    /* Space. The gaps derive from the theme's --gap, and the frame a page
       is drawn in — header to footer, style.css — is --measure and the four
       after it: a page kind re-points them on its own <body>, and a page
       that names no kind is one reading column with nothing beside it, its
       sections a rhythm apart so no two of them ever touch. */
    --wide-measure: 72rem; /* multi-column layouts */
    --side: 0px; /* a sidebar before the reading column */
    --aside: 0px; /* a gutter after it */
    --rhythm: 2rem; /* how far apart what fills the column sits */
    --quarter-gap: calc(var(--gap) / 4);
    --half-gap: calc(var(--gap) / 2);
    --wide-gap: calc(var(--gap) * 1.5);

    /* What floats over the page (an open menu, a chart's tip) is drawn at
       --float, above every raised part in the flow: a current tab, a
       selected tab, a chart. */
    --float: 10;
  }
@supports not (color: light-dark(#000, #fff)) {
:root {
  --mine: #f8e0c8;
  --theirs: #e5eef5;
}
@media (prefers-color-scheme: dark) {
:root {
  --mine: #4e3b32;
  --theirs: #34404a;
}
}
}
}


@layer base {
  * {
    box-sizing: border-box;
  }

  body {
    margin: 0;
    background: var(--bg);
    color: var(--text);
    font-family: var(--font);
    font-size: var(--size);
    line-height: 1.6;
    -webkit-font-smoothing: antialiased;
  }

  h1,
  h2,
  h3,
  p,
  ul {
    margin: 0;
  }

  ul {
    padding: 0;
    list-style: none;
  }

  a {
    color: var(--accent);
    text-underline-offset: 0.18em;
    text-decoration-thickness: 0.08em;
  }

  [id] {
    scroll-margin-block-start: 1.5rem;
  }

  :focus-visible {
    outline: 3px solid var(--accent);
    outline-offset: 3px;
  }
}

@layer components {
  /* The yak: one transparent raster drawing, sized for the small page mark or
     the home page hero. */
  .Yak {
    display: block;
    height: auto;
  }

  /* The seated yak's frame has air around him, so the small mark is wider
     than his figure (mascot.ts `Idle`). */
  .Yak-small {
    width: 3.25rem;
  }

  .Foot .Yak {
    margin-inline: auto;
  }

  .Yak-big {
    width: min(11rem, 55vw);
    margin-inline: auto;
  }

  @media (prefers-reduced-motion: no-preference) {
    .Yak-big {
      animation: breathe 6s ease-in-out infinite;
    }
  }

  @keyframes breathe {
    50% {
      transform: translateY(-3px);
    }
  }

  /* Headings. One vocabulary, sized by variant: a section's heading is the
     plain one, a page's title is -page, the home page's opening line is
     -hero. */
  .Title {
    font-size: var(--title-size, 1.5rem);
    font-weight: 800;
    line-height: var(--title-leading, 1.6);
    text-wrap: balance;
  }

  .Title-hero {
    --title-size: clamp(2rem, 5vw + 1rem, 2.75rem);
    --title-leading: 1.15;
  }

  .Title-page {
    --title-size: clamp(1.75rem, 4vw + 1rem, 2.25rem);
    --title-leading: 1.2;
  }

  /* The quiet line next to the loud one: a lead, an aside, a caption. */
  .Note {
    color: var(--muted);
    font-size: var(--note-size, inherit);
    text-wrap: pretty;
  }

  .Note-lead {
    --note-size: var(--lead);
  }

  .Note-small {
    --note-size: var(--small);
  }

  /* A list of voices to play and pick from (the Operator's settings). */
  .Voices {
    display: grid;
    max-height: 24rem;
    overflow-y: auto;
  }

  .Voices_Row {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: .75rem;
  }

  /* A conversation. The frame is the point: it says at a glance that these
     words were spoken, by two people, as an example — not that the thing
     being described is what this page is selling. Who says what is a
     modifier: -you leans right in blush, -them leans left in sky. The tail
     is a rotated corner, one square, no extra markup. */
  .Chat {
    display: grid;
    gap: 0.75rem;
    padding: 1.125rem;
  }

  .Chat_Who {
    color: var(--muted);
    font-size: var(--small);
    font-weight: 700;
    text-align: var(--who-side, start);
  }

  .Chat_Who-you {
    --who-side: end;
  }

  .Chat_Bubble {
    --fill: var(--bg);
    position: relative;
    width: fit-content;
    max-width: 88%;
    padding: 0.875rem 1.125rem;
    background: var(--fill);
    text-wrap: pretty;
  }

  .Chat_Bubble::after {
    content: '';
    position: absolute;
    bottom: -0.25rem;
    width: 1rem;
    height: 1rem;
    background: var(--fill);
    transform: rotate(45deg);
  }

  .Chat_Bubble-you {
    --fill: var(--mine);
    margin-inline-start: auto;
  }

  .Chat_Bubble-you::after {
    right: 0.6rem;
  }

  .Chat_Bubble-them {
    --fill: var(--theirs);
  }

  .Chat_Bubble-them::after {
    left: 0.6rem;
  }

  /* The same voice, inside a running sentence: something a person says out
     loud to their assistant, mid-paragraph. It takes the fill of your own
     bubble and keeps it on every fragment when the line wraps
     (box-decoration-break), which is the whole difficulty of an inline box.
     It drops the quotation marks a <q> would otherwise draw, because the fill
     already says these are your words — with the stylesheet gone, the marks
     come back and the sentence still reads. */
  .Said {
    padding: 0.1rem 0.4rem;
    background: var(--mine);
    color: var(--text);
    -webkit-box-decoration-break: clone;
    box-decoration-break: clone;
  }

  .Said::before,
  .Said::after {
    content: none;
  }

  /* A little window: something finished, at its own address, drawn like a
     card, with its bar ruled off the way a card's head is. */
  .Window {
    position: relative;
    border: 1px solid transparent;
    border-radius: var(--radius);
    background: var(--card);
  }

  .Window::after {
    content: '';
    position: absolute;
    inset: -1px;
    border: var(--stroke) solid var(--graphite);
    border-radius: var(--radius);
    filter: var(--drawn);
    pointer-events: none;
  }

  .Window_Bar {
    position: relative;
    display: flex;
    justify-content: center;
    padding: 0.625rem 1rem;
  }

  .Window_Bar::after {
    content: '';
    position: absolute;
    inset: auto -1px calc(-1 * var(--room));
    height: calc(var(--stroke) + 2 * var(--room));
    background: var(--rule);
    filter: var(--drawn);
  }

  .Window_Body {
    display: grid;
    gap: 0.625rem;
    padding: 1.125rem 1.25rem 1.25rem;
  }

  .Window_Heading {
    font-size: 1.25rem;
    font-weight: 800;
  }

  .Window_List {
    display: grid;
    gap: 0.375rem;
  }

  .Window_List li {
    padding: 0.5rem 0.875rem;
    background: var(--bg);
  }

  .Window_On {
    color: var(--accent);
    font-weight: 700;
  }

  /* The body, when it holds the live app instead of a drawing: a browser's
     viewport, so the frame fills it edge to edge with no inset. */
  .Window_Body-frame {
    padding: 0;
  }

  /* Match the embedded app's background while it loads. */
  .Window_Frame {
    display: block;
    width: 100%;
    height: 26rem;
    border: 0;
    background: var(--preview);
  }

  /* A page of plain prose — help, and the legal pages: the same column and
     voice, nothing boxed. Prose dresses the elements you did NOT name; a
     list that carries a component class keeps its component. They are read
     on a phone more often than not, so nothing is wider than the column and
     a long link breaks rather than scrolls. */
  .Prose {
    display: grid;
    gap: 2rem;
    overflow-wrap: break-word;
  }

  /* Nothing in a document is wider than the column it is in. A grid item is
     as wide as its longest unbreakable word unless it is told it may be
     narrower, and one URL in one paragraph was enough to push a phone's whole
     page sideways — the opposite of what break-word above is for. What must
     not shrink says so itself: a code block scrolls (.Docs pre). */
  .Prose :where(*) {
    min-width: 0;
  }

  .Prose_Head {
    display: grid;
    gap: var(--half-gap);
  }

  .Prose_When {
    color: var(--muted);
    font-size: var(--small);
  }

  .Prose section {
    display: grid;
    gap: 0.75rem;
  }

  .Prose h2 {
    font-size: 1.25rem;
    font-weight: 800;
    text-wrap: balance;
  }

  .Prose p,
  .Prose li {
    color: var(--muted);
    text-wrap: pretty;
  }

  .Prose ul:not([class]) {
    display: grid;
    gap: var(--half-gap);
    padding-inline-start: 1.25rem;
    list-style: disc;
  }

  .Prose a {
    color: var(--accent);
  }

  .Prose address {
    font-style: normal;
    color: var(--muted);
  }

  .Prose code {
    padding: 0.1rem 0.4rem;
    background: var(--card);
    font-family: var(--mono);
    font-size: var(--small);
  }
}

@layer sections {
  /* The frame: how wide this page is, from the header down to the footer.
     A page says what it wants once, by re-pointing --measure, --side and
     --aside on its own <body> (the page kinds below do exactly that), and
     the three pieces of furniture that span the page all read the same three
     numbers. That is the whole rule: the header sits above the document at
     the document's own width, whatever the document asked for. */
  .Top,
  .Page,
  .Foot {
    width: min(
      100% - 2 * var(--gap),
      calc(var(--measure) + var(--side) + var(--aside))
    );
    margin-inline: auto;
  }

  /* The header: the mark and the name, and the four places worth going.
     The name IS "home" — it carries the label — so the nav names
     the other four and nothing else.

     Centred and stacked on a phone, and only spread apart once there is room
     for both on one line. */
  .Top {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    justify-content: center;
    gap: var(--half-gap) var(--gap);
    padding: 1.25rem 0;
  }

  @media (min-width: 40rem) {
    .Top {
      justify-content: space-between;
    }
  }

  .Top_Name {
    display: inline-flex;
    align-items: center;
    gap: var(--half-gap);
    color: var(--text);
    font-weight: 800;
    font-size: var(--lead);
    text-decoration: none;
  }

  /* The nav itself: quiet words, not buttons — a row of links that wraps
     rather than scrolls, since a phone is the first screen this is read on.
     The page you are already on goes to full ink; nothing else marks it. */
  .Nav {
    display: flex;
    flex-wrap: wrap;
    justify-content: center;
    gap: var(--half-gap) var(--gap);
    font-size: var(--small);
    font-weight: 700;
  }

  .Nav a {
    color: var(--muted);
    text-decoration: none;
  }

  .Nav a:hover,
  .Nav a[aria-current='page'] {
    color: var(--text);
  }

  /* A person signed in reads "Open yaks.app" where "Sign in" is (signed.ts sets
     data-signed on the root before the page paints). */
  .Nav_Open,
  :root[data-signed] .Nav_SignIn {
    display: none;
  }

  :root[data-signed] .Nav_Open {
    display: revert;
  }

  /* The reading column, and the two slots beside it. The column says how
     WIDE, never how far apart: what fills it — .Home, .Pricing, .Guide — owns
     its own rhythm, and says so by re-pointing --rhythm. A page that names
     none keeps the default, so a page of two sections (the gallery and its
     invitation under it) never draws one against the other. The gap is the
     Page's, not its content's: .Prose on a Page is spaced by the rhythm,
     which overrides the gap it would keep elsewhere.

     Three columns are always here and the outer two are nothing wide, so a
     page that names no slot is the single column it has always been. A page
     that wants more structure re-points --side (a sidebar before the reading
     column) or --aside (a gutter after it, for asides and annotations), and
     the frame grows by exactly that much — nothing else moves. Whatever a
     page drops in lands in the reading column; .Page_Side and .Page_Aside are
     how a child opts into a slot, whether it is a nav, a note beside a
     paragraph, or a pull quote. The slots carry their own gutter as padding,
     so the rhythm is rows only: a column gap would come out of the very
     width the page asked for. */
  .Page {
    display: grid;
    grid-template-columns:
      [side] var(--side)
      [body] minmax(0, 1fr)
      [aside] var(--aside);
    row-gap: var(--rhythm);
    padding-block: var(--wide-gap) 3rem;
  }

  /* Zero specificity, so a slot class below always wins however it is
     ordered. */
  :where(.Page) > * {
    grid-column: body;
  }

  /* Both gutters sit in the first row, so the reading column starts level
     with them rather than below them. That is also why a page that uses a
     slot wraps its reading column in one .Page_Body: the row is as tall as
     what is in it. */
  .Page_Side {
    grid-column: side;
    grid-row: 1;
    align-self: start;
    padding-inline-end: var(--wide-gap);
  }

  .Page_Body {
    grid-column: body;
  }

  .Page_Aside {
    grid-column: aside;
    grid-row: 1;
    align-self: start;
    padding-inline-start: var(--wide-gap);
    color: var(--muted);
    font-size: var(--small);
  }

  /* Not room enough for a gutter: an aside reads above what it annotates,
     and the sidebar runs down beside both rows rather than making the first
     one as tall as itself. The gutter closes in the TEMPLATE, not in
     --aside: the page's asked-for width is what the header and footer read,
     and below this breakpoint the viewport is the narrower of the two
     anyway. */
  @media (max-width: 1000px) {
    .Page {
      grid-template-columns:
        [side] var(--side)
        [body] minmax(0, 1fr)
        [aside] 0;
    }

    .Page_Side {
      grid-row: 1 / span 2;
    }

    .Page_Aside {
      grid-column: body;
      grid-row: 1;
      padding-inline-start: 0;
    }

    .Page_Body {
      grid-row: 2;
    }
  }

  /* A phone: one column — and what the reader came for first. A sidebar of
     every page is two screens of somewhere else to be, so it goes to the
     foot, under the document, where it reads as where to go next. */
  @media (max-width: 700px) {
    .Page {
      grid-template-columns: minmax(0, 1fr);
    }

    .Page_Side,
    .Page_Body,
    .Page_Aside {
      grid-column: 1;
      grid-row: auto;
    }

    .Page_Aside {
      order: 1;
    }

    .Page_Body {
      order: 2;
    }

    .Page_Side {
      order: 3;
      padding-inline-end: 0;
    }
  }

  /* The home page (index.html), a page kind on its <body>: wider grids than
     a letter, and the loose rhythm a landing page reads in. Prose pages name
     no kind at all and keep the reading width. */
  .Home {
    --measure: var(--wide-measure);
    --rhythm: clamp(3rem, 6vw, 5rem);
  }

  .Hello {
    display: grid;
    gap: 1.25rem;
    text-align: center;
  }

  .Home .Hello {
    gap: 2.5rem;
    align-items: center;
    text-align: start;
  }

  .Hello_Copy {
    display: grid;
    gap: var(--gap);
    max-width: 36rem;
  }

  /* The kicker is underlined twice by hand. */
  .Hello_Kicker {
    position: relative;
    width: fit-content;
    padding-bottom: 0.4rem;
    color: var(--accent);
    font-size: var(--small);
    font-weight: 800;
    letter-spacing: 0.04em;
  }

  .Hello_Kicker::after {
    content: '';
    position: absolute;
    inset: auto -0.4rem 0 -0.15rem;
    height: 0.55rem;
    background: currentColor;
    mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 200 10' preserveAspectRatio='none'%3E%3Cg fill='none' stroke='%23000' stroke-linecap='round'%3E%3Cpath d='M2 5.5C40 3.6 95 3.2 198 4.2' stroke-width='2' vector-effect='non-scaling-stroke'/%3E%3Cpath d='M14 8.2C70 6.4 130 6.2 188 6.9' stroke-width='1.2' stroke-opacity='.7' vector-effect='non-scaling-stroke'/%3E%3C/g%3E%3C/svg%3E")
      0 0 / 100% 100% no-repeat;
  }

  /* The yak is the logo (wander.js): a square frame with air around him,
     reaching left by that much so his figure lines up with the words. */
  .Hello_Yak {
    width: 6rem;
    aspect-ratio: 1;
    margin-left: -1.15rem;
  }

  .Hello_Yak img,
  .Wander img {
    display: block;
    width: 100%;
    height: 100%;
  }

  /* The yak out in the margin is placed on the page (body is not
     positioned, so this is the document's corner), scrolling with it, above
     its words and never in the way of a click. Each of his pictures is a layer: the one
     marked data-on shows, and a strip of frames shows one frame at a time. */
  .Wander {
    position: relative;
    width: 100%;
    height: 100%;
  }

  .Wander-out {
    position: absolute;
    top: 0;
    left: 0;
    z-index: 1;
    pointer-events: none;
    will-change: transform;
  }

  .Wander > * {
    position: absolute;
    inset: 0;
    visibility: hidden;
  }

  .Wander > [data-on] {
    visibility: visible;
  }

  .Wander_Strip {
    overflow: hidden;
  }

  .Wander_Strip img {
    width: 600%;
    max-width: none;
  }

  .Home .Title-hero {
    --title-size: clamp(2rem, 4vw + 1rem, 2.75rem);
  }

  /* The box an idea is typed in, with its button under it at the right. */
  .Hello_Ask {
    display: grid;
    gap: 0.75rem;
    max-width: 36rem;
  }

  .Hello_Ask textarea.Field {
    width: 100%;
    min-height: 6.5rem;
    font-size: var(--size);
    line-height: 1.5;
  }

  .Hello_Ask .Button {
    justify-self: end;
  }

  /* A phone: the yak sits beside the kicker rather than over it, the heading
     is the box's label, and the box opens three lines tall, so the box and
     its button are on the first screen even under an in-app browser's
     bars. */
  @media (max-width: 40rem) {
    .Hello_Copy {
      grid-template-columns: auto minmax(0, 1fr);
      align-items: end;
    }

    .Hello_Copy > :not(.Hello_Yak, .Hello_Kicker) {
      grid-column: 1 / -1;
    }

    .Hello_Yak {
      width: 4.5rem;
      margin-left: -0.85rem;
    }

    .Hello_Ask textarea.Field {
      min-height: 4.5rem;
    }
  }

  .Demo {
    display: grid;
    gap: var(--gap);
    min-width: 0;
  }

  .Demo_Title {
    font-size: var(--size);
    font-weight: 700;
  }

  /* The examples, one card at a time: a row that scrolls sideways and stops
     on each card, by swipe, by keys or by itself (carousel.js). The room
     around it keeps the cards' pencil lines and focus rings inside the
     scroll box, which clips them. */
  .Demo_Slides {
    --room-around: 4px;
    display: grid;
    grid-auto-flow: column;
    grid-auto-columns: 100%;
    gap: var(--gap);
    margin: calc(-1 * var(--room-around));
    padding: var(--room-around);
    list-style: none;
    overflow-x: auto;
    scroll-snap-type: x mandatory;
    scroll-padding-inline: var(--room-around);
    scrollbar-width: none;
  }

  .Demo_Slides::-webkit-scrollbar {
    display: none;
  }

  .Demo_Slides > li {
    scroll-snap-align: start;
  }

  @media (prefers-reduced-motion: no-preference) {
    .Demo_Slides {
      scroll-behavior: smooth;
    }
  }

  .Demo_Controls {
    --control-height: 2rem;
    --control-pad-inline: .7rem;
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: var(--half-gap);
  }

  .Demo_Controls[hidden] {
    display: none;
  }

  .Demo_Pause {
    margin-inline-start: auto;
    font-size: var(--fine);
  }

  .Demo_Dots {
    display: flex;
    flex-wrap: wrap;
  }

  /* A dot is small, but the button around it is nearly a fingertip wide, and
     the row of them leaves room for Pause on a phone's line. */
  .Demo_Dot {
    display: grid;
    place-items: center;
    width: 1.375rem;
    height: 2rem;
    padding: 0;
    border: 0;
    background: none;
    cursor: pointer;
  }

  .Demo_Dot::before {
    content: '';
    width: .55rem;
    height: .55rem;
    border: var(--stroke) solid var(--graphite);
    border-radius: 50%;
  }

  .Demo_Dot[aria-current='true']::before {
    border-color: var(--accent);
    background: var(--accent);
  }

  @media (min-width: 60rem) {
    .Home .Hello {
      grid-template-columns: minmax(0, 0.9fr) minmax(0, 1.1fr);
      gap: clamp(2rem, 5vw, 4rem);
    }

    .Hello_Copy {
      gap: 1.25rem;
    }

    .Hello_Yak {
      width: 8rem;
      margin-left: -1.5rem;
    }

    .Hello .Title-hero {
      --title-size: 3rem;
    }
  }

  .For,
  .How,
  .Path {
    display: grid;
    gap: 1.5rem;
  }

  /* Who it's for: a card each for work, side projects and home, with one
     app from it to open or copy. Side by side on a laptop, stacked on a
     phone. */
  .For_List {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(min(100%, 16rem), 1fr));
    gap: var(--gap);
    margin: 0;
    padding: 0;
    list-style: none;
  }

  .For_Doors {
    display: flex;
    flex-wrap: wrap;
    gap: var(--half-gap) var(--gap);
    font-weight: 700;
  }

  .Step_Name {
    color: var(--accent);
    font-size: var(--lead);
    font-weight: 700;
  }

  /* Keep setup order in an ordered list, including without styles. */
  .Steps {
    display: grid;
    gap: var(--wide-gap);
    margin: 0;
    padding: 0;
    counter-reset: step;
  }

  .Steps li {
    position: relative;
    display: grid;
    grid-template-columns: 2rem 1fr;
    align-content: start;
    gap: var(--quarter-gap) 0.875rem;
    counter-increment: step;
  }

  /* Each step's number, circled by hand. */
  .Steps li::before {
    content: counter(step);
    grid-row: span 2;
    display: grid;
    place-items: center;
    width: 2rem;
    height: 2rem;
    color: var(--accent);
    font-size: var(--lead);
    font-weight: 800;
  }

  .Steps li::after {
    content: '';
    position: absolute;
    inset: -0.35rem auto auto -0.4rem;
    width: 2.8rem;
    height: 2.7rem;
    background: var(--accent);
    mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 44 42'%3E%3Cpath d='M29.5 6.5C20 3 7.5 7.5 5.2 19.5 3.2 30 11.5 37.5 22 37 32.5 36.4 39.5 28.5 38.6 18.8 37.8 10.5 30 4.8 20.5 5.2 16.5 5.4 13.2 6.6 10.8 8.6' fill='none' stroke='%23000' stroke-width='1.7' stroke-linecap='round'/%3E%3C/svg%3E")
      0 0 / 100% 100% no-repeat;
  }

  /* The plans, on the home page and the pricing page: narrower than the
     examples, since there are only three. */
  .Cost {
    display: grid;
    gap: 1.25rem;
    width: min(100%, 52rem);
    justify-self: center;
  }

  /* The gallery (gallery.ts), a page kind on its <body>: a grid of cards
     as wide as the home page's, so as many columns fit as the screen has
     room for. */
  .Gallery {
    --measure: var(--wide-measure);
  }

  .Make {
    display: grid;
    gap: 1.25rem;
  }

  .Make_Intro {
    display: grid;
    gap: var(--half-gap);
  }

  .Make_List {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(min(100%, 18rem), 1fr));
    gap: var(--gap);
  }

  /* A gallery entry (gallery.ts) is a card: its head the app's name and the
     copy it offers, then its picture. The app's own share card where it has
     one, and the platform tile where it does not; a picture from somebody
     else's app is any shape it likes, so the box is what fixes the row:
     cropped to fill, never stretched. */
  .Make_Shot {
    display: block;
    aspect-ratio: 1200 / 630;
    overflow: hidden;
    background: var(--bg);
  }

  /* On a card, the picture runs to the card's edges, so it is as large as
     the card is wide; last on the card, it closes the card's foot too. */
  .Card > .Make_Shot {
    margin-inline: calc(-1 * var(--pad-inline));
  }

  .Card > .Make_Shot:last-child {
    margin-bottom: calc(-1 * var(--pad-block));
    border-radius: 0 0 var(--radius) var(--radius);
  }

  .Make_Shot img {
    display: block;
    width: 100%;
    height: 100%;
    object-fit: cover;
  }

  .Make_Shot .Make_Shot-none {
    object-fit: contain;
    padding: var(--half-gap);
  }

  /* A published app's own page (app-page.ts): its name, what it is and
     where it was made, its picture, then its two doors, opening it first. */
  .Listing {
    display: grid;
    gap: var(--gap);
    width: min(100%, 44rem);
  }

  .Listing_Head {
    display: grid;
    gap: var(--half-gap);
  }

  .Listing_Doors {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: var(--gap);
  }

  .Listing_Doors form {
    display: contents;
  }

  .Listing_Made {
    margin-top: var(--gap);
  }

  /* The integration directory (integrations.ts): a card a service, its head
     the service and the way to add it, then what it is, where its key goes
     and how to get one. */
  .Services {
    display: grid;
    gap: 1.25rem;
  }

  .Services_Intro {
    display: grid;
    gap: var(--half-gap);
    max-width: 40rem;
  }

  .Services_List {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(min(100%, 20rem), 1fr));
    gap: var(--gap);
    margin: 0;
    padding: 0;
    list-style: none;
  }

  /* Ruled off above and below in pencil. */
  .Yours {
    position: relative;
    display: grid;
    gap: 1.5rem;
    padding-block: 2rem;
  }

  .Yours::before,
  .Yours::after {
    content: '';
    position: absolute;
    inset: calc(-1 * var(--room)) 0 auto;
    height: calc(var(--stroke) + 2 * var(--room));
    background: var(--rule);
    filter: var(--drawn);
  }

  .Yours::after {
    inset: auto 0 calc(-1 * var(--room));
  }

  .Yours_List {
    display: grid;
    gap: var(--wide-gap);
    margin: 0;
  }

  .Yours_List dt {
    color: var(--accent);
    font-weight: 700;
  }

  .Yours_List dd {
    margin: var(--quarter-gap) 0 0;
    color: var(--muted);
    text-wrap: pretty;
  }

  @media (min-width: 48rem) {
    .Home .Yours_List,
    .Steps {
      grid-template-columns: repeat(3, minmax(0, 1fr));
      gap: 2rem;
    }
  }

  .Join {
    display: grid;
    gap: var(--gap);
    text-align: center;
    width: min(100%, 52rem);
    justify-self: center;
    justify-items: center;
  }

  .Join > .Note {
    max-width: 40rem;
  }

  .Join_Doors {
    margin-top: var(--quarter-gap);
  }

  /* The pricing page (pricing.html): three plans side by side on a
     laptop, stacked on a phone. A wider column than a letter, because
     columns of numbers are the one thing here that is not prose — and no
     wider than three of them need. */
  .Pricing {
    --measure: 52rem;
    --rhythm: 3rem;
  }

  /* Plans set side by side, on the home page and the pricing page. A card's
     four parts, its price, note, list and button, sit on four rows the
     cards share, so every plan's list starts on one line and every button
     sits on one line, however long each list runs. */
  .Plans {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(min(100%, 15rem), 1fr));
    grid-auto-rows: auto auto 1fr auto;
    gap: var(--gap);
  }

  /* The paid one is drawn in the accent. It is a variant of a section,
     not of the Card component: what is emphasised on this page is this
     page's business. */
  .Plan {
    grid-row: span 4;
    grid-template-rows: subgrid;
    text-align: left;
  }

  .Plan-plus,
  .Plan-organization {
    --pencil: var(--accent);
  }

  .Plan_Price {
    color: var(--text);
    font-size: 2rem;
    font-weight: 800;
    line-height: 1.1;
  }

  .Plan_Per {
    color: var(--muted);
    font-size: var(--size);
    font-weight: 400;
  }

  .Plan_List {
    display: grid;
    gap: 0.5rem;
    margin: 0;
    padding-inline-start: 1.25rem;
    color: var(--muted);
    list-style: '–  ';
    text-wrap: pretty;
  }

  .Plan_List li::marker {
    color: var(--accent);
  }

  /* Every limit, a row each and a plan a column. Each row's name says what
     it counts underneath it, so the numbers stay one short column apiece;
     on a phone the table scrolls sideways rather than squeezing them. */
  .Limits {
    display: grid;
    gap: var(--wide-gap);
  }

  .Limits_Table {
    overflow-x: auto;
  }

  .Limits table {
    width: 100%;
    min-width: 32rem;
    border-collapse: collapse;
  }

  .Limits :is(th, td) {
    padding: var(--half-gap);
    border-bottom: 1px solid var(--border);
    text-align: left;
    vertical-align: top;
  }

  .Limits thead th {
    color: var(--accent);
  }

  .Limits tbody th {
    width: 50%;
  }

  .Limits small {
    display: block;
    margin-top: var(--quarter-gap);
    color: var(--muted);
    font-size: var(--fine);
    font-weight: 400;
    text-wrap: pretty;
  }

  .Limits td {
    font-variant-numeric: tabular-nums;
    white-space: nowrap;
  }

  .Foot {
    display: grid;
    gap: 0.75rem;
    padding-block: var(--wide-gap) 3rem;
    color: var(--muted);
    font-size: var(--small);
    text-align: center;
    text-wrap: pretty;
  }

  .Foot_Links {
    display: flex;
    flex-wrap: wrap;
    justify-content: center;
    gap: var(--half-gap) 1.25rem;
  }

  .Foot_Links a {
    color: var(--muted);
  }

  /* The documentation (docs.ts): the guide's markdown drawn as a page. The
     renderer names no classes — it emits the plain elements the markdown
     asked for — so everything here dresses those, and .Prose above already
     dresses the rest. Each rendered block is its own grid so paragraphs sit
     closer together than sections do.

     It is the first page kind to use both .Page slots: the list of pages in
     the sidebar, what is on this page in the gutter, and the document itself
     at the reading width in between. Both are asked for on the <body>, so
     the header above the document spans the same frame it does. */
  .Docs {
    --side: 13rem;
    --aside: 14rem;
  }

  /* The sidebar leans against nothing here — the document beside it is not a
     panel — so it has no edge, and its current row is a closed pencil box. */
  .Docs_Nav {
    --nav-panel: transparent;
    --nav-edge: transparent;
    --nav-shut: var(--graphite);
  }

  .Docs_Contents {
    display: grid;
    gap: var(--half-gap);
    position: sticky;
    top: var(--gap);
  }

  .Docs_Label {
    color: var(--text);
    font-weight: 800;
  }

  .Docs_Contents ul {
    display: grid;
    gap: 0.35rem;
    margin: 0;
    padding: 0;
    list-style: none;
  }

  .Docs_Jump a {
    color: var(--muted);
    text-decoration: none;
  }

  .Docs_Jump a:hover {
    color: var(--text);
    text-decoration: underline;
  }

  .Docs_Jump-sub {
    padding-inline-start: var(--half-gap);
  }

  @media (max-width: 1000px) {
    /* Above the document, a contents list reads as a row of places. */
    .Docs_Contents {
      position: static;
    }

    .Docs_Contents ul {
      grid-template-columns: repeat(auto-fill, minmax(11rem, 1fr));
    }
  }

  .Docs .Body {
    display: grid;
    gap: 0.75rem;
  }

  .Docs h3 {
    margin-top: 0.75rem;
    font-size: 1.05rem;
    font-weight: 800;
  }

  .Docs ol:not([class]) {
    display: grid;
    gap: var(--half-gap);
    padding-inline-start: 1.4rem;
    list-style: decimal;
  }

  /* Code blocks are the one thing wider than the column, and they scroll
     rather than push the page sideways. */
  .Docs pre {
    margin: 0;
    padding: var(--half-gap) 0.75rem;
    background: var(--card);
    overflow-x: auto;
  }

  .Docs pre code {
    padding: 0;
    background: none;
    font-size: var(--small);
  }

  .Docs blockquote {
    margin: 0;
    padding-inline-start: 0.75rem;
    border-inline-start: 2px solid var(--border);
    color: var(--muted);
  }

  .Docs_Pages {
    display: grid;
    gap: 0.75rem;
    padding: var(--gap);
    background: var(--card);
  }

  .Docs_Pages ul {
    display: grid;
    gap: var(--half-gap);
    margin: 0;
    padding-inline-start: 1.25rem;
    list-style: disc;
  }

  .Docs_Pages li {
    color: var(--muted);
  }

  .Docs_Back {
    color: var(--muted);
    font-size: var(--small);
  }

  /* The style guide itself (style-guide.html): a wider column, because a
     row of swatches is the one thing here that is not a letter. */
  .Guide {
    --measure: 52rem;
    --rhythm: 3rem;
  }

  .Guide_Part {
    display: grid;
    gap: var(--gap);
  }

  .Guide_Rules {
    display: grid;
    gap: 0.75rem;
    padding-inline-start: 1.25rem;
    color: var(--muted);
    list-style: disc;
    text-wrap: pretty;
  }

  .Guide_SideNav {
    display: grid;
    grid-template-columns: 10rem minmax(0, 1fr);
    background: var(--card);
  }
  .Guide_SideNav .SideNav {
    align-self: start;
  }
  .Guide_SidePanel {
    padding: 1rem;
  }
  .Guide_Choices {
    display: grid;
    gap: .25rem;
    margin: .75rem 0;
    padding: .75rem;
  }
  @media (max-width: 700px) {
    .Guide_SideNav {
      display: block;
    }
  }

  /* A specimen's frame: a card in a light dashed line, so what it holds
     reads as the thing shown. */
  .Guide_Demo {
    --pencil: var(--border);
    --pencil-style: dashed;
    display: grid;
    gap: 0.75rem;
    padding: 1.25rem;
    background: none;
  }

  .Guide_Name {
    color: var(--muted);
    font-family: var(--mono);
    font-size: var(--small);
    font-weight: 400;
  }

  .Guide_Swatches {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(12rem, 1fr));
    gap: 0.75rem;
  }

  .Guide_Swatch {
    display: grid;
    grid-template-columns: auto 1fr;
    align-items: center;
    gap: 0 0.75rem;
  }

  .Guide_Chip {
    grid-row: span 2;
    width: 2.5rem;
    height: 2.5rem;
    border: 1px solid var(--border);
    background: var(--swatch);
  }

  .Guide_Value {
    color: var(--muted);
    font-family: var(--mono);
    font-size: 0.8125rem;
  }

  .Guide_Sizes {
    display: grid;
    gap: 0.5rem;
    overflow-x: auto; /* --measure is wider than a phone, on purpose */
  }

  .Guide_Size {
    display: grid;
    grid-template-columns: 12rem auto;
    align-items: center;
    gap: 0.75rem;
  }

  .Guide_Bar {
    height: 0.75rem;
    width: var(--bar);
    background: var(--accent);
  }
}
