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

@import url('controls.css');

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