/* 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;

/* Shared interactive controls and surfaces. Both the public site and account
   pages load these components; /style-guide contains working examples. */
@layer tokens, base, components, sections;
/* Shared paints, semantic roles, spacing and material tokens. */

/* 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 {
    color-scheme: light;

    /* The paints. Nothing below this block writes a colour down. */
    --cream: #fffbf5; /* the lightest warm white */
    --linen: #fdf7ee; /* warm ground, a gold lean */
    --oat: #f1e6d8; /* pale warm, for words on a dark ground */
    --shell: #efe3d2; /* the hairline between things */
    --taupe: #c9b19c; /* oat, gone quiet */
    --clay: #785b47; /* coffee, gone quiet */
    --coffee: #523828; /* warm brown, never black */
    --bark: #4d3d34; /* the hairline, on a dark ground */
    --cocoa: #372c26; /* cards and bubbles, on a dark ground */
    --night: #2b231f; /* the dark ground itself */
    --soot: #1d1714; /* a shadow, on a dark ground */
    --meadow: #4c773e; /* readable on both light backgrounds */
    --moss: #a7c080; /* the accent, lit for the dark */
    --blush: #f8e0c8; /* what you said */
    --ember: #4e3b32; /* what you said, in the dark */
    --sky: #e5eef5; /* what it answered */
    --dusk: #34404a; /* what it answered, in the dark */
    --brick: #a8503f;
    --rose: #e67e80;
    --forest: #33493c; /* the recipe preview's background */

    /* The roles. Everything below uses these, never a paint. */
    --ground: var(--linen);
    --paper: var(--cream);
    --ink: var(--coffee);
    --soft-ink: var(--clay);
    --line: var(--shell);
    --accent: var(--meadow);
    --warn: var(--brick);
    --on-accent: var(--ground); /* words on an accent fill */
    --mine: var(--blush); /* the person's bubble */
    --theirs: var(--sky); /* the assistant's bubble */
    --preview: var(--forest); /* matches the embedded app in either theme */
    --well: color-mix(in srgb, var(--paper), var(--line) 45%); /* a field */
    --shade: color-mix(in srgb, var(--coffee) 24%, transparent);

    /* Pencil and paper. A part worth outlining is drawn: a graphite line
       around it with slightly rounded corners, given the paper's tooth by
       pencil.svg. 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. */
    --graphite: color-mix(in srgb, var(--ink) 88%, transparent);
    --stroke: 1.5px; /* the weight of a drawn line */
    --corner: 4px; /* how round a drawn box's corners are */
    --lift: 4px; /* how far what can be pressed sits off its hatch */
    --hollow: inset 0 2px 4px var(--shade); /* how deep a well sits */
    --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 tab not chosen: a sheet behind the one in front. */
    --behind: color-mix(in srgb, var(--ground), var(--line) 40%);
    --edge: color-mix(in srgb, var(--line), var(--soft-ink) 32%);

    /* Type. */
    --font: 'Nunito', system-ui, -apple-system, 'Segoe UI', Roboto, sans-serif;
    --mono: ui-monospace, SFMono-Regular, Menlo, monospace;
    --body: 1.0625rem;
    --lead: 1.125rem;
    --small: 0.9375rem;
    --fine: 0.875rem; /* what describes a thing: a hint, a status, a count */

    /* Space and shape. The gaps derive from one number, and the frame a page
       is drawn in — header to footer, style.css — is the five that open the
       list: 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. */
    --measure: 38rem; /* reading width */
    --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 */
    --gap: 1rem;
    --control-height: 2.25rem;
    --quarter-gap: calc(var(--gap) / 4);
    --half-gap: calc(var(--gap) / 2);
    --wide-gap: calc(var(--gap) * 1.5);
  }

  /* A theme re-points roles. The paints above stay exactly where they are. */
  @media (prefers-color-scheme: dark) {
    :root:not([data-theme='light']) {
      color-scheme: dark;
      --ground: var(--night);
      --paper: var(--cocoa);
      --ink: var(--oat);
      --soft-ink: var(--taupe);
      --line: var(--bark);
      --accent: var(--moss);
      --warn: var(--rose);
      --mine: var(--ember);
      --theirs: var(--dusk);
      --well: color-mix(in srgb, var(--paper), var(--ground) 65%);
      --shade: color-mix(in srgb, var(--soot) 70%, transparent);
    }
  }

  :root[data-theme='dark'] {
    color-scheme: dark;
    --ground: var(--night);
    --paper: var(--cocoa);
    --ink: var(--oat);
    --soft-ink: var(--taupe);
    --line: var(--bark);
    --accent: var(--moss);
    --warn: var(--rose);
    --mine: var(--ember);
    --theirs: var(--dusk);
    --well: color-mix(in srgb, var(--paper), var(--ground) 65%);
    --shade: color-mix(in srgb, var(--soot) 70%, transparent);
  }
}


@layer base {
  [hidden] {
    display: none !important;
  }

  /* The paper: one grain tile, speckled in ink and cream, laid over the
     whole page so cards, buttons and pictures share its tooth. It covers the
     document, not the window, so it scrolls with what is drawn on it. */
  html {
    position: relative;
    min-height: 100%;
  }
  html::after {
    content: '';
    position: absolute;
    inset: 0;
    z-index: 2147483647;
    background: url(paper.e48c5467b4.webp) 0 0 / 256px;
    opacity: .07;
    pointer-events: none;
  }
}

@layer components {
  .Button,
  .Field {
    box-sizing: border-box;
    height: var(--control-height);
    padding: 0 var(--control-pad-inline, .75rem);
    font: inherit;
    line-height: 1.25;
    vertical-align: middle;
  }
  /* What is drawn (tokens.css, Pencil and paper) wears its outline on
     ::after, in --pencil where a part asks for another colour and dashed
     where --pencil-style says so. Each part starts from a solid graphite
     line, so none takes the line of a box it sits in. A page's own surface
     is drawn by being a .Card. */
  .Button,
  .Card,
  a.Pill,
  .Empty,
  .Drop_Zone {
    --pencil: initial;
    --pencil-style: initial;
  }
  .Button::after,
  .Card::after,
  a.Pill::after,
  .Empty::after,
  .Drop_Zone::after {
    content: '';
    position: absolute;
    inset: -1px;
    border: var(--stroke) var(--pencil-style, solid)
      var(--pencil, var(--graphite));
    border-radius: var(--corner);
    filter: url(pencil.8a0c8518e4.svg#line);
    pointer-events: none;
  }

  /* A button is a flat fill on a hatch: the hatch is what an offset copy of
     it would show past its right and bottom edges. A hover lifts the button
     off it and a press slides the button onto it; the hatch stays put. */
  .Button {
    position: relative;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: .35rem;
    border: 1px solid transparent;
    border-radius: var(--corner);
    background: var(--button-fill, var(--accent));
    color: var(--button-ink, var(--on-accent));
    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(--corner);
    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(--accent)),
      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-quiet {
    --button-fill: var(--paper);
    --button-ink: var(--ink);
  }
  /* A button that steps back beside another: it reads as a link, with no
     fill, outline or hatch. */
  .Button-link,
  .Button-link:hover:not(:disabled, [aria-pressed='true']),
  .Button-link:active:not(:disabled) {
    --lift: 0px;
    padding: 0;
    background: none;
    color: var(--accent);
    font-weight: inherit;
    text-decoration: underline;
    transform: none;
  }
  .Button-link::before,
  .Button-link::after {
    content: none;
  }
  /* A field is a well: darker than the paper, a little hollow, its edge
     drawn in pencil. 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 {
    min-width: 0;
    max-width: 100%;
    border: var(--stroke) solid var(--graphite);
    border-radius: var(--corner);
    background: var(--well);
    box-shadow: var(--hollow);
    color: var(--ink);
    filter: url(pencil.8a0c8518e4.svg#line);
  }
  .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;
  }
  /* Pills: a chip, and a row of them that wraps like a handful of
     notes. The list is the same shape whether the chips are words (the home
     page) or links (the help page's questions). */
  .Pills {
    display: flex;
    flex-wrap: wrap;
    gap: 0.625rem;
  }

  .Pill {
    display: inline-block;
    padding: var(--pill-pad, .3rem .75rem);
    border: var(--pill-edge, 1px solid var(--line));
    border-radius: var(--corner);
    background: var(--pill-fill, var(--paper));
    color: var(--pill-ink, var(--ink));
    font-family: var(--pill-font, inherit);
    font-size: var(--pill-size, var(--small));
    font-weight: var(--pill-weight, 600);
    line-height: 1.4;
    vertical-align: middle;
    text-decoration: none;
  }

  a.Pill {
    --pill-ink: var(--accent);
    --pill-edge: 1px solid transparent;
    --pill-weight: 700;
    position: relative;
    text-decoration: underline;
    text-underline-offset: .18em;
  }
  a.Pill:hover {
    --pencil: var(--accent);
    --pill-fill: color-mix(in srgb, var(--accent) 7%, var(--paper));
  }
  a.Pill:active {
    transform: translate(1px, 1px);
  }
  a.Pill:focus-visible {
    outline: 3px solid var(--accent);
    outline-offset: 3px;
  }
  .Pill_Tag {
    margin-left: .5rem;
    color: var(--soft-ink);
    font-weight: 400;
    font-size: .85em;
  }

  /* A quiet label, such as the address in a window bar. */
  .Pill-quiet {
    --pill-fill: var(--ground);
    --pill-ink: var(--soft-ink);
    --pill-edge: 0;
    --pill-pad: 0.2rem 0.9rem;
    --pill-size: var(--small);
    --pill-weight: 600;
  }

  /* A URL somebody has to copy. */
  .Pill-code {
    --pill-pad: .2rem .5rem;
    --pill-fill: var(--ground);
    --pill-edge: 0;
    --pill-font: var(--mono);
    --pill-size: var(--small);
  }

  .Address {
    color: var(--soft-ink);
    font-weight: 400;
  }
  .Address_Name {
    color: var(--ink);
    font-weight: 800;
  }

  /* 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. */
  .Card {
    --pad-block: 1rem;
    --pad-inline: 1.25rem;
    position: relative;
    display: grid;
    align-content: start;
    gap: .75rem;
    min-width: 0;
    padding: var(--pad-block) var(--pad-inline);
    border: 1px solid transparent;
    border-radius: var(--corner);
    background: var(--paper);
    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: .7rem;
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: .5rem .75rem;
    min-height: 3rem;
    position: relative;
    margin: calc(-1 * var(--pad-block)) calc(-1 * var(--pad-inline)) 0;
    padding: .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: url(pencil.8a0c8518e4.svg#line);
  }
  .Card_Head:last-child {
    margin-bottom: calc(-1 * var(--pad-block));
  }
  .Card_Head:last-child::after {
    content: none;
  }
  .Card_Head:last-child::after {
    content: none;
  }
  .Card_Title {
    margin: 0;
    color: var(--ink);
    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: .5rem;
    margin: 0 0 0 auto;
  }
  .Card_Actions form {
    display: contents;
  }
  .Card_Actions .Button {
    font-size: var(--fine);
  }

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

  /* How something stands, as a word in its role's colour beside a dot:
     -good when it works, -warn when it needs the person. */
  .Status {
    display: inline-flex;
    align-items: center;
    gap: .35rem;
    color: var(--status, var(--soft-ink));
    font-size: var(--fine);
    font-weight: 700;
    line-height: 1.3;
  }
  .Status::before {
    content: '';
    flex: none;
    width: .5rem;
    height: .5rem;
    border-radius: 50%;
    background: currentColor;
  }
  .Status-good {
    --status: var(--accent);
  }
  .Status-warn {
    --status: var(--warn);
  }

  /* 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. In a card the
     rows run to its edges. */
  .Rows {
    display: grid;
    margin: 0;
    padding: 0;
    list-style: none;
  }
  .Rows_Item {
    --control-height: 2rem;
    --control-pad-inline: .7rem;
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: .5rem 1rem;
    padding: .75rem 0;
    border-top: 1px solid var(--line);
  }
  .Rows_Item:first-child {
    padding-top: 0;
    border-top: 0;
  }
  .Rows_Item:last-child {
    padding-bottom: 0;
  }
  .Card > .Rows {
    margin-inline: calc(-1 * var(--pad-inline));
  }
  .Card > .Rows > .Rows_Item {
    padding-inline: var(--pad-inline);
  }
  .Rows_Main {
    display: grid;
    flex: 1 1 12rem;
    gap: .15rem;
    min-width: 0;
    line-height: 1.45;
    overflow-wrap: anywhere;
  }
  .Rows_Name {
    color: var(--ink);
    font-weight: 700;
  }
  .Rows_Meta {
    color: var(--soft-ink);
    font-size: var(--fine);
  }
  .Rows_Actions {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: .5rem;
    margin: 0 0 0 auto;
  }
  .Rows_Actions form {
    display: contents;
  }
  .Rows_Actions .Button {
    font-size: var(--fine);
  }

  /* A heading over a run of cards that belong together. */
  .Group {
    margin: var(--gap) 0 0;
    color: var(--soft-ink);
    font-size: var(--small);
    font-weight: 700;
  }
  .Group:first-child {
    margin-top: 0;
  }

  /* A form: every field its label over its control over its hint, on one
     left edge and one width, and what sends it at the end. A field never
     trails a sentence: what explains it is its hint, under it. */
  .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(--ink);
    font-size: var(--small);
    font-weight: 700;
  }
  .Form_Optional {
    color: var(--soft-ink);
    font-weight: 400;
  }
  .Form_Field > .Field {
    width: 100%;
  }
  .Form_Hint {
    margin: 0;
    color: var(--soft-ink);
    font-size: var(--fine);
  }
  /* 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;
  }

  /* A field with a fixed ending beside it: the name an address takes. */
  .At {
    display: flex;
    align-items: center;
    gap: .35rem;
    min-width: 0;
  }
  .At > .Field {
    flex: 1 1 auto;
  }
  .At > span {
    flex: none;
    color: var(--soft-ink);
  }

  /* A drop zone: a dashed place to drop files on, which a press also opens
     the chooser from (a phone's picker on a phone), and under it what is
     chosen, each with its name, its size, a picture where it is one, and a
     way to take it back. The input is the form's own, unseen but kept in
     the tab order, so the zone wears its focus. public/drop.js draws the
     list and takes the drop. */
  .Drop {
    display: grid;
    gap: .5rem;
    min-width: 0;
  }
  .Drop_Zone {
    --pencil: var(--edge);
    --pencil-style: dashed;
    position: relative;
    display: grid;
    place-items: center;
    gap: .25rem;
    min-height: 6rem;
    padding: 1.25rem 1rem;
    border-radius: var(--corner);
    background: var(--ground);
    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(--paper);
  }
  .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(--ink);
  }
  .Drop_Choose {
    color: var(--accent);
    font-weight: 700;
    text-decoration: underline;
    text-underline-offset: .2em;
  }
  .Drop_Hint {
    color: var(--soft-ink);
    font-size: var(--fine);
  }
  .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(--corner);
    background: var(--well);
  }
  .Drop_Picture {
    flex: none;
    width: 2.5rem;
    height: 2.5rem;
    border-radius: var(--corner);
    object-fit: cover;
  }
  .Drop_Name {
    flex: 1 1 auto;
    min-width: 0;
    overflow: hidden;
    color: var(--ink);
    font-weight: 700;
    text-overflow: ellipsis;
    white-space: nowrap;
  }
  .Drop_Size {
    flex: none;
    color: var(--soft-ink);
    font-size: var(--fine);
  }
  .Drop_Item > .Button {
    flex: none;
    font-size: var(--fine);
  }

  /* What most people never need, folded under one line that says so. */
  .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;
  }
  /* Markdown someone wrote (theirs.ts), such as how to get a key, ends
     where the body does. */
  .More_Body > *,
  .More_Body > .Markdown > :last-child {
    margin: 0;
  }

  /* A line the page says back: what a press did, or why it did not. */
  .Say {
    margin: 0;
    color: var(--soft-ink);
    font-size: var(--small);
  }
  .Say:empty {
    display: none;
  }
  .Say-no {
    color: var(--warn);
  }

  /* Words to paste somewhere else, in a well, with the button that copies
     them beside it (pages.ts `copyable`). */
  .Copy {
    display: flex;
    align-items: center;
    gap: .5rem;
    min-width: 0;
  }
  .Pick {
    flex: 1;
    min-width: 0;
    min-height: var(--control-height);
    padding: .4rem .75rem;
    background: var(--ground);
    color: var(--ink);
    overflow-wrap: anywhere;
    user-select: all;
  }
  .Copy_Go {
    --button-fill: var(--paper);
    --button-ink: var(--accent);
    flex: none;
    font-size: var(--fine);
  }

  /* 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(--edge);
    --pencil-style: dashed;
    position: relative;
    display: grid;
    justify-items: center;
    gap: .5rem;
    padding: 2rem 1.25rem;
    border: 1px solid transparent;
    border-radius: var(--corner);
    color: var(--soft-ink);
    text-align: center;
  }
  .Empty > * {
    max-width: 30rem;
    margin: 0;
  }
  .Empty h2 {
    color: var(--ink);
    font-size: 1.05rem;
    font-weight: 800;
  }

  /* A report: a card whose head names what it counts and says the total
     where a card's actions would sit, then a bar a day and the short lists
     under it. */
  .Stats {
    gap: 1.25rem;
  }
  .Stats_Total {
    flex: none;
    margin: 0 0 0 auto;
    color: var(--ink);
    font-size: 1.25rem;
    font-weight: 800;
    font-variant-numeric: tabular-nums;
    line-height: 1.2;
  }
  .Stats_Unit {
    color: var(--soft-ink);
    font-size: var(--fine);
    font-weight: 400;
  }
  .Stats_Plot {
    display: grid;
    gap: .35rem;
    margin: 0;
  }
  /* A chart (@yaks/ui/chart): a line in pencil, ending in a dot on today, or
     a column a day. public/chart.js says the point a pointer, a finger or an
     arrow key is on, and lays a line through it at --at. */
  .Chart {
    position: relative;
    z-index: 1;
    touch-action: pan-y;
    cursor: crosshair;
  }
  .Chart:focus-visible {
    outline: 2px solid var(--accent);
    outline-offset: 2px;
  }
  .Chart[data-on]::after {
    content: '';
    position: absolute;
    top: 0;
    bottom: 0;
    left: var(--at);
    width: 1px;
    background: var(--soft-ink);
    pointer-events: none;
  }
  .Chart-line {
    display: inline-block;
    margin-left: .5rem;
    padding: .25rem 0;
    vertical-align: middle;
    line-height: 0;
  }
  .Chart-line .Chart_Plot {
    filter: url(pencil.8a0c8518e4.svg#line);
    overflow: visible;
  }
  .Chart-bars {
    display: block;
    height: 5rem;
    border-bottom: 1px solid var(--line);
  }
  .Chart-bars .Chart_Plot {
    display: block;
    width: 100%;
    height: 100%;
  }
  .Chart_Line {
    fill: none;
    stroke: var(--graphite);
    stroke-width: var(--stroke);
    stroke-linecap: round;
    stroke-linejoin: round;
  }
  .Chart_End,
  .Chart_Bar {
    fill: var(--accent);
  }
  .Chart_Tip {
    position: fixed;
    z-index: 10;
    padding: .15rem .5rem;
    border-radius: var(--corner);
    background: var(--ink);
    color: var(--paper);
    font-size: var(--fine);
    white-space: nowrap;
    pointer-events: none;
  }
  .Stats_Span {
    display: flex;
    justify-content: space-between;
    color: var(--soft-ink);
    font-size: var(--fine);
  }
  .Stats_Tops {
    display: grid;
    grid-template-columns: repeat(3, minmax(0, 1fr));
    gap: 1.5rem;
  }
  .Stats_Column h3 {
    margin: 0 0 .5rem;
    color: var(--soft-ink);
    font-size: var(--fine);
    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. */
  .Stats_List {
    display: grid;
    grid-template-columns: minmax(0, 1fr);
    gap: .4rem;
    margin: 0;
    padding: 0;
    list-style: none;
    font-size: var(--small);
  }
  .Stats_List li {
    display: flex;
    justify-content: space-between;
    gap: .75rem;
  }
  .Stats_List span {
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
  }
  .Stats_List b {
    flex: none;
    font-variant-numeric: tabular-nums;
    white-space: nowrap;
  }
  @media (max-width: 600px) {
    .Stats_Tops {
      grid-template-columns: minmax(0, 1fr);
      gap: 1rem;
    }
  }

  /* One row of physical tabs meets one sheet. Native radios own selection,
     including arrow keys, so the component works without JavaScript. Each
     tab is drawn in pencil on its top and sides; the panel's own top line is
     every tab's foot, and the selected tab covers it, so tab and panel are
     one sheet. */
  .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(--ink);
    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(--corner) var(--corner) 0 0;
    background: var(--behind);
    color: var(--soft-ink);
    font-size: .85rem;
    font-weight: 700;
    line-height: 1.25;
    text-align: center;
    cursor: pointer;
  }
  .Tabs_Tab::after {
    content: '';
    position: absolute;
    inset: -1px -1px 0;
    border: var(--stroke) solid var(--graphite);
    border-bottom: 0;
    border-radius: var(--corner) var(--corner) 0 0;
    filter: url(pencil.8a0c8518e4.svg#line);
    pointer-events: none;
  }
  @media (max-width: 480px) {
    .Tabs_Tab {
      padding-inline: .3rem;
      font-size: .8rem;
    }
  }
  .Tabs_Tab:hover {
    color: var(--ink);
  }
  .Tabs_Panel {
    order: 1;
    flex: 1 1 100%;
    min-width: 0;
    display: none;
    position: relative;
    margin: 0;
    text-align: left;
    z-index: 1;
  }
  .Tabs_Item > input:checked ~ .Tabs_Tab {
    margin-top: 0;
    padding-top: .9rem;
    background: var(--paper);
    color: var(--ink);
    z-index: 2;
  }
  /* The gap the selected 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_Item > input:checked ~ .Tabs_Tab::before {
    content: '';
    position: absolute;
    inset: auto 2px calc(-1.5 * var(--room));
    height: calc(3 * var(--room));
    background: var(--paper);
  }
  .Tabs_Item > input:checked ~ .Tabs_Panel {
    display: grid;
  }
  .Tabs_Item > input:focus-visible ~ .Tabs_Tab {
    outline: 3px solid var(--accent);
    outline-offset: -5px;
  }

  .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;
  }

  /* 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 (.Docs_Nav, and every nav on a phone). */
  .SideNav {
    --nav-panel: var(--paper);
    --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: url(pencil.8a0c8518e4.svg#line);
    pointer-events: none;
  }
  .SideNav a {
    position: relative;
    display: flex;
    align-items: center;
    gap: .65rem;
    padding: .6rem .8rem;
    border: 1px solid transparent;
    border-radius: var(--corner);
    color: var(--soft-ink);
    font-size: .95rem;
    text-decoration: none;
  }
  .SideNav a:hover {
    color: var(--ink);
  }
  .SideNav a[aria-current='page'] {
    background: var(--nav-panel);
    color: var(--ink);
    font-weight: 800;
    z-index: 1;
  }
  .SideNav a[aria-current='page']::after {
    content: '';
    position: absolute;
    inset: -1px 0 -1px -1px;
    border: var(--stroke) solid var(--graphite);
    border-right-color: var(--nav-shut);
    border-radius: var(--corner);
    filter: url(pencil.8a0c8518e4.svg#line);
    pointer-events: none;
  }
  /* The gap the current tab opens in the edge. */
  .SideNav a[aria-current='page']::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 hr {
    height: calc(var(--stroke) + 2 * var(--room));
    margin: calc(1rem - var(--room)) .8rem;
    border: 0;
    background: var(--rule);
    filter: url(pencil.8a0c8518e4.svg#line);
  }
  @media (max-width: 700px) {
    .SideNav {
      --nav-panel: transparent;
      --nav-edge: transparent;
      --nav-shut: var(--graphite);
      display: flex;
      flex-wrap: wrap;
    }
  }

  .Choice {
    display: inline-flex;
    align-items: center;
    gap: .5rem;
    min-height: var(--control-height);
    line-height: 1.4;
    cursor: pointer;
  }
  .Choice 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(--paper);
    cursor: inherit;
  }
  .Choice input[type='radio'] {
    border-radius: 50%;
  }
  .Choice input::before {
    content: '';
    width: .45rem;
    height: .45rem;
    transform: scale(0);
  }
  .Choice input[type='checkbox']::before {
    width: .3rem;
    height: .6rem;
    margin-top: -.15rem;
    border: solid var(--on-accent);
    border-width: 0 2px 2px 0;
    transform: rotate(45deg) scale(0);
  }
  .Choice input[type='radio']::before {
    border-radius: 50%;
    background: var(--on-accent);
  }
  .Choice input:checked {
    background: var(--accent);
    border-color: var(--accent);
  }
  .Choice input:checked::before {
    transform: scale(1);
  }
  .Choice input[type='checkbox']:checked::before {
    transform: rotate(45deg) scale(1);
  }
  .Choice:has(input:disabled) {
    opacity: .55;
    cursor: not-allowed;
  }
  .Choice input:focus-visible {
    outline: 3px solid var(--accent);
    outline-offset: 3px;
  }

  /* The agents a person connected, as rows (connected_ui.ts), or the ones
     with a web home as a line of links to open them. */
  .Agents-links {
    display: flex;
    flex-wrap: wrap;
    gap: .5rem 1.5rem;
    margin: 0;
    padding: 0;
    list-style: none;
  }
  .Agents_Open {
    display: inline-flex;
    align-items: center;
    gap: var(--quarter-gap);
    color: var(--accent);
    font-size: var(--small);
    font-weight: 700;
    text-underline-offset: .18em;
    white-space: nowrap;
  }

  /* An invitation not yet taken, in a person's row (render/held.ts). */
  .People_Waiting {
    color: var(--warn);
  }
}


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

  body {
    margin: 0;
    background: var(--ground);
    color: var(--ink);
    font-family: var(--font);
    font-size: var(--body);
    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;
  }

  .Yak-small {
    width: 2.25rem;
  }

  .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(--soft-ink);
    font-size: var(--note-size, inherit);
    text-wrap: pretty;
  }

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

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

  /* 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(--soft-ink);
    font-size: var(--small);
    font-weight: 700;
    text-align: var(--who-side, start);
  }

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

  .Chat_Bubble {
    --fill: var(--ground);
    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(--ink);
    -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(--corner);
    background: var(--paper);
  }

  .Window::after {
    content: '';
    position: absolute;
    inset: -1px;
    border: var(--stroke) solid var(--graphite);
    border-radius: var(--corner);
    filter: url(pencil.8a0c8518e4.svg#line);
    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: url(pencil.8a0c8518e4.svg#line);
  }

  .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(--ground);
  }

  .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(--soft-ink);
    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(--soft-ink);
    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(--soft-ink);
  }

  .Prose code {
    padding: 0.1rem 0.4rem;
    background: var(--paper);
    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(--ink);
    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(--soft-ink);
    text-decoration: none;
  }

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

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

  :root[data-signed] .Nav_Dashboard {
    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(--soft-ink);
    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;
  }

  .Hello_Yak {
    width: 4rem;
  }

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

  .Hello_Doors {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 1rem 1.5rem;
    font-weight: 700;
  }

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

  .Demo_Title {
    font-size: var(--body);
    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: 6rem;
    }

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

  .For,
  .How,
  .Path,
  .Made {
    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(--ground);
  }

  /* 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(--corner) var(--corner);
  }

  .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: url(pencil.8a0c8518e4.svg#line);
  }

  .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(--soft-ink);
    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 {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(min(100%, 15rem), 1fr));
    gap: var(--gap);
    align-items: start;
  }

  /* 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 {
    text-align: left;
  }

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

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

  .Plan_Per {
    color: var(--soft-ink);
    font-size: var(--body);
    font-weight: 400;
  }

  .Plan_List {
    display: grid;
    gap: 0.5rem;
    margin: 0;
    padding-inline-start: 1.25rem;
    color: var(--soft-ink);
    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(--line);
    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(--soft-ink);
    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(--soft-ink);
    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(--soft-ink);
  }

  /* 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(--ink);
    font-weight: 800;
  }

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

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

  .Docs_Jump a:hover {
    color: var(--ink);
    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 .Markdown {
    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(--paper);
    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(--line);
    color: var(--soft-ink);
  }

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

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

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

  .Docs_Back {
    color: var(--soft-ink);
    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(--soft-ink);
    list-style: disc;
    text-wrap: pretty;
  }

  .Guide_SideNav {
    display: grid;
    grid-template-columns: 10rem minmax(0, 1fr);
    background: var(--paper);
  }
  .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(--line);
    --pencil-style: dashed;
    display: grid;
    gap: 0.75rem;
    padding: 1.25rem;
    background: none;
  }

  .Guide_Name {
    color: var(--soft-ink);
    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(--line);
    background: var(--swatch);
  }

  .Guide_Value {
    color: var(--soft-ink);
    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(--size);
    background: var(--accent);
  }
}
