/* ============================================================
   retnd docs palette and base page styles.

   # The palette, and why it is this one

   Most of what this site shows is screenshots of the application,
   so the site takes its colours from the application rather than
   choosing its own. ui/shared/src/design-system/tokens.css sets
   --platform-accent to oklch(0.52 0.09 255), which is the slate
   blue #446b9c, and docs/assets/logo-light.svg already draws the
   product mark in exactly that. Anything else here would make
   every picture on the page look like it came from a different
   product.

   So: slate blue for links and rules, a deep navy for the hero, and
   the application's own near-neutral warm greys for surfaces and
   text (--text #191a19 and --text-2 #5b5d5b are lifted straight out
   of tokens.css). The primary is pulled a little darker than the
   application's accent, to #3a628f, because the app renders it on
   its own white cards while this page renders it as body-copy links
   on an off-white ground and that needs the extra contrast.

   The one hue that is not the application's is --accent, a muted
   teal. It marks the "what this entry actually does" annotations on
   the tutorial, and those have to be distinguishable at a glance
   from a link, a warning and a piece of chrome. Teal against slate
   is a cool analogous pair, which is the point: it reads as
   infrastructure and it cannot be mistaken for a status colour.

   Warning and danger are the application's --warn and --danger,
   flattened out of oklch, so a caution on this page is the same
   colour as the caution in the screenshot beside it.

   # Both themes are load-bearing

   Every colour is declared as a custom property in both blocks
   below. Nothing anywhere else in this site may write a literal
   colour, because a literal survives the theme switch and then one
   element is wrong in exactly one theme, which is the failure mode
   nobody notices until a reader reports it.
   ============================================================ */

:root, [data-theme="light"] {
  --primary: #3a628f;
  /* The hero bar is dark in both themes, and topbar.css paints its
     own text with var(--white). It is a literal, not a surface. */
  --white: #ffffff;
  --primary-dark: #21384f;
  --accent: #2c6f63;
  --bg: #f4f4f2;
  --text: #191a19;
  --text-light: #5b5d5b;
  --text-faint: #8b8d8a;
  --code-bg: #ececea;
  /* An output block is not a thing you type, so it does not look like
     one. White against the typed block's grey, and the highlight inside
     it is tuned against THIS panel rather than against the page. */
  --code-bg-out: #ffffff;
  --hl-bg: #b2e2c4;
  --border: #dedcd8;
  --border-strong: #c8c7c3;
  --hero-bg: #16283a;
  /* Raised surfaces: cards, callouts, the screenshot mat. */
  --surface: #ffffff;
  --table-header-bg: #ececea;

  --ok: #2c6e49;
  --ok-bg: #e9f2ec;
  --warn: #8a5d0c;
  --warn-bg: #fbf1de;
  --danger: #a03823;
  --danger-bg: #fbeae6;

  --max-width: 900px;
}

[data-theme="dark"] {
  --primary: #7fa8d6;
  --primary-dark: #a9c6e6;
  --accent: #63bdab;
  --bg: #121312;
  --text: #eceeeb;
  --text-light: #a3a6a2;
  --text-faint: #767976;
  --code-bg: #1e201e;
  /* Inverted relationship on purpose: in the dark scheme the output
     panel goes DEEPER than the typed one rather than lighter, because
     there is nothing above white to move to. Same intent, opposite
     direction, and the highlight is re-tuned for it. */
  --code-bg-out: #0d0f0d;
  --hl-bg: #22513a;
  --border: #313331;
  --border-strong: #454745;
  --hero-bg: #0d1720;
  --surface: #1b1d1b;
  --table-header-bg: #1e201e;

  --ok: #6cbf95;
  --ok-bg: #17261e;
  --warn: #d9a340;
  --warn-bg: #2a2113;
  --danger: #e08772;
  --danger-bg: #2c1a16;
}

* { margin: 0; padding: 0; box-sizing: border-box; }

body {
  /* IBM Plex, the same pair ui/shared/index.html loads, so the prose
     around a screenshot is set in the face the screenshot is set in. */
  font-family: "IBM Plex Sans", -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;
  color: var(--text);
  background: var(--bg);
  line-height: 1.65;
  -webkit-font-smoothing: antialiased;
  overflow-anchor: none;
}

main {
  max-width: var(--max-width);
  margin: 0 auto;
  padding: 2.5rem 1.5rem 4rem;
}

section { margin-bottom: 2.75rem; }

h2 {
  font-size: 1.4rem;
  font-weight: 700;
  color: var(--primary-dark);
  margin-bottom: 0.75rem;
  padding-bottom: 0.35rem;
  border-bottom: 2px solid var(--border);
  scroll-margin-top: calc(var(--topbar-collapsed-height) + 1rem);
}

h3 {
  font-size: 1.08rem;
  font-weight: 600;
  color: var(--text);
  margin: 1.75rem 0 0.5rem;
  scroll-margin-top: calc(var(--topbar-collapsed-height) + 1rem);
}

h4 {
  font-size: 0.95rem;
  font-weight: 600;
  color: var(--text);
  margin: 1.25rem 0 0.35rem;
}

p { margin-bottom: 0.75rem; color: var(--text-light); }
p strong, li strong { color: var(--text); }

a { color: var(--primary); }
a:hover { color: var(--primary-dark); }

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

ul li {
  position: relative;
  padding: 0.3rem 0 0.3rem 1.4rem;
  color: var(--text-light);
}

ul li::before {
  content: "\25B8";
  position: absolute;
  left: 0;
  color: var(--primary);
  font-weight: bold;
}

ol { counter-reset: step; }

ol li {
  position: relative;
  padding: 0.3rem 0 0.3rem 1.8rem;
  color: var(--text-light);
  counter-increment: step;
}

ol li::before {
  content: counter(step) ".";
  position: absolute;
  left: 0;
  color: var(--primary);
  font-weight: 600;
  font-family: "IBM Plex Mono", ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
  font-size: 0.85em;
}

table {
  width: 100%;
  border-collapse: collapse;
  margin-bottom: 0.75rem;
  font-size: 0.9rem;
}

th, td {
  text-align: left;
  padding: 0.55rem 0.75rem;
  border-bottom: 1px solid var(--border);
  vertical-align: top;
}

th {
  font-weight: 600;
  color: var(--primary-dark);
  background: var(--table-header-bg);
}

td { color: var(--text-light); }
td strong { color: var(--text); }

/* A short identifier in a first column is a label, not prose: letting
   it wrap turns "monthly" into "month / ly" and costs more width than
   keeping it whole ever would. Later columns still wrap freely. */
.scroll-x table td:first-child code { white-space: nowrap; }

code {
  font-family: "IBM Plex Mono", ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
  font-size: 0.88em;
}

:not(pre) > code {
  background: var(--code-bg);
  padding: 0.1rem 0.35rem;
  border-radius: 3px;
  word-break: break-word;
}

pre {
  background: var(--code-bg);
  color: var(--text);
  border: 1px solid var(--border);
  border-radius: 6px;
  padding: 1rem 1.25rem;
  overflow-x: auto;
  font-size: 0.85rem;
  line-height: 1.55;
  margin-bottom: 0.75rem;
}

pre code { background: none; padding: 0; }

/* Minimal YAML/shell tinting. Same class names the rest of the site
   uses, so a future page can highlight without inventing a scheme. */
.cm { color: var(--text-faint); font-style: italic; }
.key { color: var(--primary); }
.str { color: var(--ok); }
.num { color: var(--warn); }

/* ---------------------------------------------------------------
   Callouts. Three tones, each one carrying a word as well as a
   colour, because the product's own UI rule (§ status is never
   colour alone) is a reasonable rule for its documentation too.
   --------------------------------------------------------------- */
.note {
  border: 1px solid var(--border-strong);
  border-left: 4px solid var(--primary);
  border-radius: 0 6px 6px 0;
  background: var(--surface);
  padding: 0.9rem 1.1rem;
  margin: 1rem 0 1.25rem;
}

.note.warn   { border-left-color: var(--warn);   background: var(--warn-bg); }
.note.danger { border-left-color: var(--danger); background: var(--danger-bg); }
.note.ok     { border-left-color: var(--ok);     background: var(--ok-bg); }

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

.note-label {
  display: block;
  font-family: "IBM Plex Mono", ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
  font-size: 0.72rem;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  font-weight: 600;
  margin-bottom: 0.3rem;
  color: var(--primary);
}

.note.warn   .note-label { color: var(--warn); }
.note.danger .note-label { color: var(--danger); }
.note.ok     .note-label { color: var(--ok); }

/* ---------------------------------------------------------------
   Screenshots. A figure, a caption, and a hard rule that the
   caption says where the picture came from.
   --------------------------------------------------------------- */
figure {
  margin: 1.25rem 0 1.75rem;
}

figure img {
  display: block;
  width: 100%;
  height: auto;
  border: 1px solid var(--border-strong);
  border-radius: 8px;
  background: var(--surface);
}

figcaption {
  margin-top: 0.5rem;
  font-size: 0.82rem;
  color: var(--text-faint);
  line-height: 1.5;
}

/* A figure allowed out of the text column. The moving pictures are
   1100px wide because that is the width at which 13px application text
   downsamples into something a reader can still read; squeezing one into
   a 900px measure throws that away for nothing. Clamped to the viewport
   so it never puts a horizontal scrollbar on the page. */
figure.wide {
  width: min(1100px, calc(100vw - 2.5rem));
  margin-left: 50%;
  transform: translateX(-50%);
}

/* A clip is a picture that moves, and a reader deserves to be told which
   ones do before they scroll past a still frame waiting for something to
   happen. */
.clip-tag {
  display: inline-block;
  font-family: "IBM Plex Mono", ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
  font-size: 0.68rem;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  font-weight: 600;
  color: var(--accent);
  border: 1px solid var(--border-strong);
  border-radius: 3px;
  padding: 0.05rem 0.4rem;
  margin-right: 0.45rem;
  vertical-align: 0.05em;
}

/* Two or three short cards side by side, for a page that opens with a
   list of what is on it. Collapses to one column on a phone. */
.cards {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(240px, 1fr));
  gap: 1rem;
  margin: 1.25rem 0 1.75rem;
}

.cards .clipping { margin: 0; }

/* ---------------------------------------------------------------
   The per-field tables that carry most of the tutorial. "What it
   does" is the column that matters, so it gets the room.
   --------------------------------------------------------------- */
.fields { margin: 1rem 0 1.25rem; }
.fields th:nth-child(1), .fields td:nth-child(1) { width: 21%; }
.fields th:nth-child(2), .fields td:nth-child(2) { width: 26%; }
.fields td:nth-child(2) { font-family: "IBM Plex Mono", ui-monospace, SFMono-Regular, Menlo, Consolas, monospace; font-size: 0.82rem; word-break: break-word; }

.does {
  color: var(--accent);
  font-weight: 600;
}

/* Wide content scrolls inside itself rather than widening the page. */
.scroll-x { overflow-x: auto; }

/* ---------------------------------------------------------------
   Step headers on the tutorial.
   --------------------------------------------------------------- */
.step-eyebrow {
  display: inline-block;
  font-family: "IBM Plex Mono", ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
  font-size: 0.72rem;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--text-faint);
  margin-bottom: 0.15rem;
}

/* ---------------------------------------------------------------
   Home page teaser card, the shape the reference site used for its
   benchmark clipping.
   --------------------------------------------------------------- */
.clipping {
  display: block;
  margin: 0 0 2.5rem;
  padding: 1.4rem 1.6rem 1.15rem;
  background: var(--surface);
  border: 1px solid var(--border);
  border-left: 4px solid var(--primary);
  border-radius: 0 6px 6px 0;
  box-shadow: 0 2px 8px rgba(0,0,0,0.06);
  text-decoration: none;
  transition: box-shadow 0.2s, transform 0.2s;
}

.clipping:hover { box-shadow: 0 4px 16px rgba(0,0,0,0.12); transform: translateY(-1px); }

.clipping-tag {
  display: inline-block;
  font-family: "IBM Plex Mono", ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
  font-size: 0.7rem;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--primary);
  margin-bottom: 0.4rem;
}

.clipping p { color: var(--text-light); margin-bottom: 0.6rem; }
.clipping-read { font-size: 0.85rem; font-weight: 600; color: var(--primary); }

/* ---------------------------------------------------------------
   Table of contents on the tutorial.
   --------------------------------------------------------------- */
.toc {
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: 8px;
  padding: 1rem 1.25rem;
  margin-bottom: 2rem;
}

.toc ol { columns: 2; column-gap: 2rem; }
.toc li { padding: 0.22rem 0 0.22rem 1.8rem; break-inside: avoid; }

@media (max-width: 640px) {
  .toc ol { columns: 1; }
  .fields th:nth-child(1), .fields td:nth-child(1),
  .fields th:nth-child(2), .fields td:nth-child(2) { width: auto; }
}

footer {
  border-top: 1px solid var(--border);
  padding: 1.75rem 1.5rem 2.5rem;
  text-align: center;
  font-size: 0.85rem;
  color: var(--text-faint);
}

footer p { color: var(--text-faint); margin-bottom: 0.3rem; }

/* -------------------------------------------------------------------
   Command output, and an attention marker inside it.

   A code block on this site is a thing you type. An output block is what
   came back, and the two look identical without a label, so every output
   block carries one.

   The marker exists because a reader who has just run the install has
   exactly one question, and it is about one string on the screen. The
   bubble has to sit OUTSIDE the <pre>: pre is overflow-x: auto, and an
   absolutely-positioned child of a scroll container is clipped by it, so
   a bubble inside would be cut off at the first line it exceeded. It is
   a sibling instead, positioned against .io, and :has() is what lets
   hovering something inside the pre reveal something outside it.
   ------------------------------------------------------------------- */
.io-label {
  margin: 0 0 0.3rem;
  font-family: "IBM Plex Mono", ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
  font-size: 0.7rem;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--text-3, var(--text-2));
}
/* The bubble hangs BELOW the block, not over it. Anchored inside, it
   covered the line it was describing: you hovered the link, the bubble
   opened on top of it, and the thing you were pointing at disappeared
   under the explanation of itself. */
/* What came back, not what you type. The border is doing as much of the
   separating as the fill: two panels a shade apart read as one surface
   without it. */
pre.io-out {
  background: var(--code-bg-out);
  border-color: var(--border-strong);
}

/* The one line in an output block a reader has to act on, and by some
   distance the longest: a URL with a 32-character token in it, indented
   inside an epilog. These blocks scroll sideways rather than wrap, which
   left the only clickable thing on the page off the right edge, and
   scrolling to it took the start of every other line off the left. So
   that one line wraps, which is what the terminal it was copied from
   would have done with it anyway. */
.io-out .io-wrap {
  white-space: pre-wrap;
  overflow-wrap: break-word;
}
/* The URL is not wrapped with the sentence around it. Chromium breaks a
   long one after its slashes, and half a one-time link on each of two
   lines is a thing a reader retypes wrong. Left whole, the line breaks
   before it instead. */
.io-out .io-wrap .tip-term { white-space: nowrap; }

.io { position: relative; }

.tip-term {
  background: var(--hl-bg);
  border-bottom: 1px dashed var(--ok);
  border-radius: 3px;
  padding: 0 0.15em;
  color: inherit;
  text-decoration: none;
}
.tip-term:hover, .tip-term:focus { background: var(--ok); color: #fff; }
.tip-term::after {
  content: " \2139";           /* an information source, not an emoji */
  font-style: normal;
  color: var(--ok);
}
.tip-term:hover::after, .tip-term:focus::after { color: #fff; }
.tip-token { font-weight: 600; }

.tip-bubble {
  display: none;
  position: absolute;
  z-index: 5;
  left: 0;
  right: 0;
  top: calc(100% + 0.35rem);
  max-width: 46rem;
  padding: 0.8rem 2.1rem 0.8rem 1rem;
  border: 1px solid var(--ok);
  border-left-width: 4px;
  border-radius: 6px;
  background: var(--surface, #fff);
  box-shadow: 0 6px 20px rgba(0, 0, 0, 0.18);
  font-size: 0.85rem;
  line-height: 1.5;
}
.tip-bubble p { margin: 0 0 0.5rem; }
.tip-bubble p:last-child { margin-bottom: 0; }
.tip-bubble .tip-heading {
  display: block;
  margin-bottom: 0.35rem;
  font-family: "IBM Plex Mono", ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
  font-size: 0.7rem;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--ok);
}

/* Dismissible, so it needs a way to dismiss it. Sized to the 24px
   minimum a pointer target wants rather than to the glyph. */
.tip-close {
  position: absolute;
  top: 0.3rem;
  right: 0.35rem;
  width: 1.5rem;
  height: 1.5rem;
  padding: 0;
  border: 0;
  border-radius: 4px;
  background: none;
  color: var(--text-2);
  font-size: 1rem;
  line-height: 1;
  cursor: pointer;
}
.tip-close:hover, .tip-close:focus { background: var(--ok-bg); color: var(--text); }

/* With JavaScript, is-open is the ONLY thing that opens this, and that
   is not tidiness. While CSS also opened it on :hover/:focus, the two
   owners disagreed: the close control returns focus to the term so a
   keyboard user is not dropped at the top of the document, the CSS focus
   rule saw that focus, and the note reopened the instant it was
   dismissed. Escape failed the same way. One owner, no argument.
   
   tooltip.js sets .tip-js on <html> before first paint, so the rules
   below are what a reader with JavaScript off still gets: revealed on
   hover and focus, just not sticky. */
html:not(.tip-js) .io:has(.tip-term:hover) .tip-bubble,
html:not(.tip-js) .io:has(.tip-term:focus) .tip-bubble,
html:not(.tip-js) .io:has(.tip-bubble:hover) .tip-bubble,
.tip-bubble.is-open { display: block; }

/* Without :has() the bubble can never be revealed, so it stops being a
   bubble and becomes a note under the block. Worse placement, same
   information, and nobody is left with a marker that does nothing. */
@supports not selector(:has(*)) {
  .tip-bubble {
    display: block;
    position: static;
    margin: 0 0 0.75rem;
    box-shadow: none;
  }
}

/* -------------------------------------------------------------------
   The install section, given the weight of the thing it is.

   It is the first section on the page and above the tutorial and
   reference cards, because somebody arriving here wants to install this
   before they want to read about it. A plain <section> in that position
   still read as the first of several: the panel and the accent are what
   say "this is the command", so the eye lands on it before the prose.
   ------------------------------------------------------------------- */
.install-hero {
  margin: 0 0 2rem;
  padding: 1.4rem 1.5rem 1.1rem;
  border: 1px solid var(--border-strong);
  border-left: 5px solid var(--primary);
  border-radius: 10px;
  /* --bg, not --surface, and the output block is why. On a white panel
     the white output block had nothing to stand against and the typed
     and returned blocks stopped reading as two things. Against --bg
     there are three distinct steps in both schemes:

       light   panel #f4f4f2  typed #ececea  output #ffffff
       dark    panel #121312  typed #1e201e  output #0d0f0d

     The panel is identified by its border and accent rather than by its
     fill, which is what lets the fill do this job instead. */
  background: var(--bg);
}
.install-hero > h2 {
  margin-top: 0;
  border-bottom: 0;
  font-size: 1.55rem;
}
.install-hero > h2::before {
  content: "Start here";
  display: block;
  margin-bottom: 0.35rem;
  font-family: "IBM Plex Mono", ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
  font-size: 0.68rem;
  font-weight: 600;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--primary);
}
/* The two commands themselves, which are the point of the section. */
/* Named rather than positional: copy.js wraps each <pre>, so it stops
   being a child of the section and :first-of-type stops matching. */
.install-hero .cmd-primary {
  border-color: var(--primary);
  font-size: 0.92rem;
}
@media (max-width: 640px) {
  .install-hero { padding: 1.1rem 1rem 0.9rem; }
  .install-hero > h2 { font-size: 1.3rem; }
}

/* -------------------------------------------------------------------
   The copy control on a command block. Injected by copy.js, so the
   wrapper below never appears in the markup: every rule here has to be
   written as if the <pre> gained a parent at runtime, which it did.
   ------------------------------------------------------------------- */
.code-wrap {
  position: relative;
  margin-bottom: 0.75rem;
}
/* The margin moved to the wrapper, or every block would carry both. */
.code-wrap > pre { margin-bottom: 0; }

.copy-btn {
  position: absolute;
  top: 0.45rem;
  right: 0.45rem;
  z-index: 2;
  padding: 0.28rem 0.55rem;
  border: 1px solid var(--border-strong);
  border-radius: 5px;
  background: var(--surface);
  color: var(--text-2);
  font-family: "IBM Plex Mono", ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
  font-size: 0.72rem;
  line-height: 1.2;
  cursor: pointer;
  opacity: 0;
  transition: opacity 0.15s ease, background 0.15s ease, color 0.15s ease;
}
/* Revealed on hover like the reference, and ALWAYS on a keyboard focus
   or once it has been used: a control that only exists while a pointer
   is over it does not exist for somebody tabbing through the page. */
.code-wrap:hover .copy-btn,
.copy-btn:focus,
.copy-btn.is-copied { opacity: 1; }

.copy-btn:hover { background: var(--primary); color: #fff; border-color: var(--primary); }
.copy-btn.is-copied { background: var(--ok); color: #fff; border-color: var(--ok); }

/* Touch has no hover, so there is nothing to reveal it with. */
@media (hover: none) {
  .copy-btn { opacity: 1; }
}
