/**
 * root Design System - documentation styles: token specimens
 *
 * The layout every copyable specimen sits in - a color ramp, a token row, a glyph cell, the
 * legend that explains them. Linked by `scripts/_docs-shell.mjs` on the ten foundation pages
 * and on the brand page, which shares the ramp and the swatch, and nowhere else: sixty of the
 * seventy-one pages were carrying it in `index.css` for nothing (ADR-047).
 *
 * Not split any finer, and the reason is in the rules: `[data-part="shades"]` and
 * `[data-part="tokens"]` are one declaration, `[data-part="shade"]` and
 * `[data-part="token-row"]` another. Cutting the brand's half out would mean cutting those
 * rules in half, which is a change to them and not a move. Same constraints as the rest of the shell: zero CSS
 * classes - element, `[data-part]` and attribute selectors only - zero inline styles, and
 * every value a root foundation token.
 */

/* ---------------------------------------------------------------------------
   Foundation pages

   Generated by `scripts/_foundations-docs.mjs`: one page per token family, each
   specimen driven by a rule in the generated `foundations.css` (no inline
   styles). What is styled here is the layout those specimens sit in.
   --------------------------------------------------------------------------- */

[data-part="legend"] {
  display: flex;
  flex-direction: column;
  gap: var(--root-s--xs);

  /* Off the lead paragraph above it, which is the page's own sentence and not part of
     the legend: at the paragraph's own bottom margin the two read as one block. */
  margin-block: var(--root-s--xl) var(--root-s--lg);
  padding: var(--root-s--sm);

  color: var(--docs-muted);
  background: var(--docs-elevated);
  border: 1px solid var(--docs-border);
  border-radius: var(--root-r--md);

  /* One block per point, each opening with what it is about. `article p` paints every
     paragraph on the page in the text color, and these belong to the legend. */
  p {
    margin: 0;

    color: inherit;
  }

  /* The block opens with what it is about, and that opening has to read as a title: bold
     alone, in the muted color of the sentence continuing on the same line, it read as an
     emphasised clause. On its own line and in the page's text color, it is the thing the
     eye lands on when picking which block to read. */
  p > strong:first-child {
    display: block;

    margin-block-end: var(--root-s--5xs);

    color: var(--docs-text);
    letter-spacing: 0.01em;
  }
}

[data-part="ramp"] {
  margin-block-end: var(--root-s--xl);
}

[data-part="shades"],
[data-part="tokens"],
/* The column is sized by the longest name in the font, not by a column count: the
   name is the thing being looked up, so it is never cut and never wrapped, and how
   many columns fit is whatever the width allows. 29rem is `align-center-horizontal-
   simple` at the mono `sm` step (26.3rem) plus the cell's own padding - measured, not
   guessed, so a longer name in a future export is the one thing that would need this
   raised. Below one column's worth of room the grid scrolls sideways rather than
   spilling the name over the card. */
[data-part="glyphs"] {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(29rem, 1fr));
  gap: var(--root-s--sm);

  margin: 0;
  padding: 0;
  overflow-x: auto;
}

/* The row - or the glyph cell - is a `button`, and the `li` around it is the grid item
   that gives it its box, so the button is stretched to the cell rather than sized by its
   own contents. */
[data-part="shades"] > li,
[data-part="tokens"] > li,
[data-part="glyphs"] > li {
  display: grid;
  /* Both boxes have to be allowed under their own min-content width, or the row sizes
     itself to the sum of its three columns and hangs out of the track it was placed in -
     which is what happened on Motion, where two rows share the width. As a grid item the
     row used to be stretched to the track and spill its contents inside it; nested, it
     grows the box itself unless the floor is taken off both. */
  min-inline-size: 0;
}

/* Swatch | token | value - one row per shade, the value column monospaced so the
   HSL triples line up down the ramp. The type, color and alignment a button brings
   with it are handed back to the page, and the cursor says the row is activatable. */
[data-part="shade"],
[data-part="token-row"] {
  display: grid;
  grid-template-columns: 12rem minmax(20rem, 1fr) minmax(14rem, auto);
  align-items: center;
  gap: var(--root-s--sm);

  margin: 0;
  padding: var(--root-s--2xs) var(--root-s--xs);

  min-inline-size: 0;

  font: inherit;
  color: inherit;
  text-align: start;
  cursor: pointer;
  background: var(--docs-surface);
  border: 1px solid var(--docs-border);
  border-radius: var(--root-r--md);

  &:hover {
    border-color: light-dark(var(--root-c--default-400--light), var(--root-c--default-300--dark));
  }

  /* The confirmation is on the row that was clicked, as it is on a glyph tile: a page is
     a hundred rows long and a message at the top of it is off-screen by the time it is
     read. The `root-toast` raised alongside says the same thing once, in its own live
     region and docked to the viewport. */
  &[data-copied] {
    background: var(--docs-accent-weak);
    border-color: light-dark(var(--root-c--default-400--light), var(--root-c--default-300--dark));
  }
}

/* One line under the lead, saying the specimens below are copyable. Quiet, because it
   is an instruction and not what the page is about. */
[data-part="copy-hint"] {
  margin-block-end: var(--root-s--md);

  font-size: var(--root-t--font-size--sm);
  color: var(--docs-muted);
}

[data-part="token-name"],
[data-part="token-value"] {
  font-family: var(--root-t--font-family--mono);
  font-size: var(--root-t--font-size--sm);
}

[data-part="token-value"] {
  color: var(--docs-muted);
  text-align: start;
  word-break: break-word;
}

/* Typography, Spacings and Radii read down one column. On those three the specimen is
   the point - a type step drawn at its size, a square, a rounded box - and two abreast
   the eye compares the wrong pair: the row on the right against the row on the left,
   instead of each step against the one below it. The scale is a sequence, so it is drawn
   as one. Their `Scale basis` cards above stay a row of three: those are the numbers the
   scale is generated from, not steps of it. */
[data-part="tokens"]:has(:is([data-part="type-sample"], [data-part="space-bar"], [data-part="radius-box"])) {
  grid-template-columns: minmax(0, 1fr);
}

/* A literal list is a table of names and values, and reads as one only in a single
   column: on the shared `auto-fill` grid its rows sat two abreast, so the reader went
   down one half of the list and then back up for the other. */
[data-part="tokens"][data-part-variant="literal"] {
  grid-template-columns: minmax(0, 1fr);

  /* A literal row has no specimen, so it is two cells and not three: name, then value, on
     one line. Left on the three-column grid the name sat in the 12rem specimen column and
     the value in the 20rem one, which is narrower than
     `var(--root-f--outline-width) var(--root-f--outline-style) var(--root-f--outline-color)` -
     the row wrapped onto three lines. Sized to the longest name, the value takes the rest
     of a full-width row and fits on its own line with no sideways scroll. */
  [data-part="token-row"] {
    grid-template-columns: minmax(0, max-content) minmax(0, 1fr);
    /* `--root-f--outline` is three var() references and does take two lines; on the
       centred default the name floated between them instead of starting beside the first. */
    align-items: baseline;
  }
}

[data-part="swatch"] {
  block-size: 4rem;

  border-radius: var(--root-r--md);

  /* Only the poles keep an outline: white, near-black and the two surfaces are the
     column's own ground, and without a border they are an invisible rectangle. A ramp
     step always differs from the ground it sits on, so it is drawn bare - a border there
     read as part of the color. */
  &[data-pole] {
    border: 1px solid var(--docs-text);
  }
}

/* ---------------------------------------------------------------------------
   The two fixed-scheme columns

   The palette, the elevations and the focus ring all document tokens that resolve
   per scheme, so each page shows both at once: one column per scheme, each standing
   on that scheme's own pole. `color-scheme` is what pins it - every `light-dark()`
   inside a column resolves to the column's scheme and not the reader's, which is the
   only way a token can be shown in the scheme it is not being read in. The docs
   tokens are re-pointed with it, because the row, its border and its value text
   belong to the column and not to the page. `[data-part="preview"]` takes the same
   pair of overrides, in `_live-preview.css`, for the same reason.
   --------------------------------------------------------------------------- */
[data-part="schemes"] {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(34rem, 1fr));
  gap: var(--root-s--lg);

  margin-block-end: var(--root-s--xl);
}

[data-part="scheme"] {
  padding: var(--root-s--md);

  color: var(--docs-text);
  background: var(--docs-bg);
  border: 1px solid var(--docs-border);
  border-radius: var(--root-r--md);

  &[data-scheme="light"] {
    color-scheme: light;

    --docs-text: var(--root-c--dark);
    --docs-bg: var(--root-c--light);
    --docs-surface: var(--root-c--light);
    --docs-elevated: var(--root-c--light);
    --docs-muted: var(--root-c--default-700--light);
    --docs-border: var(--root-c--neutral-300--light);
  }

  &[data-scheme="dark"] {
    color-scheme: dark;

    --docs-text: var(--root-c--light);
    --docs-bg: var(--root-c--dark);
    --docs-surface: var(--root-c--dark);
    --docs-elevated: var(--root-c--dark);
    --docs-muted: var(--root-c--neutral-200--dark);
    --docs-border: var(--root-c--neutral-700--dark);
  }

  /* Half the page's width, so the value goes under the token name instead of pushing
     the row into a horizontal scroll. The swatch spans both rows beside them. */
  :is([data-part="shade"], [data-part="token-row"]) {
    grid-template-columns: 6rem minmax(0, 1fr);
  }

  :is([data-part="shade"], [data-part="token-row"]) > :first-child {
    grid-row: span 2;
  }

  :is([data-part="shade"], [data-part="token-row"]) > :is([data-part="token-name"], [data-part="token-value"]) {
    grid-column: 2;
  }
}

/* Typography: each sample is drawn at the step it documents, so the column has to
   grow with it rather than clip. */
[data-part="type-sample"] {
  display: block;

  line-height: var(--root-t--line-height--base);
}

[data-part="tokens"]:has([data-part="type-sample"]) [data-part="token-row"] {
  grid-template-columns: 14rem minmax(20rem, 1fr) minmax(10rem, auto);
  align-items: baseline;
}

/* The widest bar is the 9xl step at ~149px, so the specimen column has to hold it:
   a narrower one would clip the top of the scale, which is the part worth seeing. */
[data-part="tokens"]:has([data-part="space-bar"]) [data-part="token-row"] {
  grid-template-columns: 16rem minmax(18rem, 1fr) minmax(10rem, auto);
}

/* Spacings: the square *is* the token, on both axes - a gap is that one length in
   whichever direction the layout spends it - so neither dimension is set here. Both
   come from the generated rule, off the same token. */
[data-part="space-bar"] {
  display: block;

  background: light-dark(var(--root-c--default-400--light), var(--root-c--default-300--dark));
  /* Square. The specimen is a length drawn as a square, and a rounded corner takes a
     bite out of exactly the thing being measured - the small steps lost a visible part
     of their own width to it. */
  border-radius: var(--root-r--none);
}

/* The specimen column, sized to the specimen: the shared row grid opens on 12rem, and a
   15rem box in a 12rem cell overflowed 17px onto the token name beside it. Same
   treatment the spacing bars get, for the same reason. */
[data-part="tokens"]:has([data-part="radius-box"]) [data-part="token-row"] {
  grid-template-columns: 16rem minmax(18rem, 1fr) minmax(10rem, auto);
}

/* Fifteen rem, from six: a radius clamps at half the box, and `6xl` is 3.81rem - so on
   the old 6rem box the top three steps drew the same circle and the page could not tell
   them apart. At this size every step keeps a flat edge, and the curve is big enough to
   compare against the one above it. */
[data-part="radius-box"] {
  display: block;
  block-size: 15rem;
  inline-size: 15rem;

  background: var(--docs-accent-weak);
  border: 2px solid light-dark(var(--root-c--default-400--light), var(--root-c--default-300--dark));
}

/* Doubled: a shadow is judged by how far it reaches off the card, and on a 6x10rem card
   the `lg` blur was wider than the card casting it. */
[data-part="elevation-card"] {
  display: block;
  block-size: 12rem;
  inline-size: 20rem;

  background: var(--docs-surface);
  border-radius: var(--root-r--md);
}

/* Room for the shadow, which is the thing being documented: `lg` blurs 60px in the
   light scheme and 80px in the dark one, and at the list's usual padding the softest
   part of it died against the row's own edge. */
[data-part="tokens"]:has([data-part="elevation-card"]) [data-part="token-row"] {
  padding: var(--root-s--lg) var(--root-s--md);
}

/* A row here holds three things - the card, the name, the value - in two columns, so the
   card takes both of the column's rows and the name and value stack beside it. Left to
   flow, the value wrapped onto the second row of the *first* column and was drawn over
   the card; given its own line beside the name it has the whole second column. */
[data-part="scheme"] [data-part="tokens"]:has([data-part="elevation-card"]) [data-part="token-row"] {
  grid-template-columns: 20rem minmax(0, 1fr);
  justify-items: start;
}

[data-part="scheme"] [data-part="tokens"]:has([data-part="elevation-card"]) [data-part="elevation-card"] {
  grid-row: span 2;
}

/* Motion: hovering the row runs the dot with that row's own duration token. */
[data-part="motion-track"] {
  position: relative;
  display: block;
  block-size: 1.6rem;
  inline-size: 100%;

  background: var(--docs-accent-weak);
  border-radius: var(--root-r--full);
}

[data-part="motion-dot"] {
  position: absolute;
  inset-block-start: 0;
  inset-inline-start: 0;
  display: block;
  block-size: 1.6rem;
  inline-size: 1.6rem;

  background: light-dark(var(--root-c--default-400--light), var(--root-c--default-300--dark));
  border-radius: var(--root-r--full);

  transition-property: translate;
  transition-timing-function: var(--root-m--ease-standard);
  transition-duration: inherit;
}

[data-part="token-row"]:hover [data-part="motion-dot"],
[data-part="token-row"]:focus-within [data-part="motion-dot"] {
  translate: calc(100cqi - 1.6rem) 0;
}

[data-part="motion-track"] {
  container-type: inline-size;
}

@media (prefers-reduced-motion: reduce) {
  [data-part="motion-dot"] {
    transition-property: none;
  }
}

/* Focus: the frame is padded enough to hold the ring at its offset - an outline is
   drawn outside the box and would otherwise sit under the column's edge. The dashed
   box stands in for the component; the ring itself comes from the generated rule, so
   the offset and width are the foundation's own tokens. */
[data-part="focus-frame"] {
  display: flex;
  place-content: center;
  place-items: center;

  margin: 0;
  padding: var(--root-s--xl);
}

[data-part="focus-ring"] {
  padding: var(--root-s--sm) var(--root-s--md);

  border: 1px dashed var(--docs-muted);
  border-radius: var(--root-r--md);
}

/* The tile is a `button` - it copies its own markup - so the type, color and
   alignment a button brings with it are handed back to the page, and the cursor says
   the tile is activatable. */
[data-part="glyph-cell"] {
  display: grid;
  justify-items: center;
  gap: var(--root-s--2xs);

  margin: 0;
  padding: var(--root-s--sm);

  font: inherit;
  color: inherit;
  text-align: center;
  cursor: pointer;
  background: var(--docs-surface);
  border: 1px solid var(--docs-border);
  border-radius: var(--root-r--md);

  &:hover {
    border-color: light-dark(var(--root-c--default-400--light), var(--root-c--default-300--dark));
  }

  /* The confirmation is on the tile that was clicked, because the grid is 201 tiles
     long and a message at the top of the page is off-screen by the time it is read. The
     `root-toast` raised alongside it says the same thing once, in its own live region
     and docked to the viewport, so it is read wherever the reader is on the page. */
  &[data-copied] {
    color: light-dark(var(--root-c--default-400--light), var(--root-c--default-300--dark));
    background: var(--docs-accent-weak);
    border-color: light-dark(var(--root-c--default-400--light), var(--root-c--default-300--dark));
  }

  /* One line, whole: a wrapped name makes its cell taller than the rest of the row and
     the grid stops reading as a grid, and an ellipsis would hide the one string the
     reader came for. Both are avoided by the column being wide enough for the longest
     name there is, above. */
  [data-part="token-name"] {
    white-space: nowrap;
  }
}

/* Two and a half times the drawing the `2xl` step gave (22.8px measured): the page is
   here to let someone recognise a glyph, and at that size a caret was being judged at
   the size of body text. The column is sized by the longest *name*, so the cell has room
   for a much larger drawing without the grid changing shape - checked at 5.6rem: no
   glyph overflows its cell, no name truncates, no row wraps. */
[data-part="glyph"] {
  font-size: var(--root-t--font-size--9xl);
}

/* ── The marks on the brand page ────────────────────────────────────────── */
/* `derive()` strips the intrinsic `width`/`height` so CSS can size these, and until now
   nothing did: each mark filled its canvas edge to edge, which drew the root mark at 671px
   tall - a logo shown at a size nobody will ever place it at, on the one page that is
   supposed to say how it is used.

   Sized as a share of the canvas rather than in rem, so the pair stays proportional to the
   frame at every column width: the lockup at 70% and the mark at half. The Webidoo wordmark
   keeps the full width - it is a long, short shape, and at 51px tall it was never the
   problem. */
svg[data-part="root-logo"] {
  inline-size: 70%;
}

svg[data-part="root-mark"] {
  inline-size: 50%;
}
