/* ==========================================================================
   DINKOMART — the documentation assistant

   Styling for docs/askbot.js. Loaded by all five guides, the help-centre
   landing page and Atlas. One stylesheet for both assistants: the public one
   and the internal one differ in what they search, never in how they look.

   ---------------------------------------------------------------------------
   THE CONTRACT

   1. NOTHING HERE HIDES DOCUMENTATION. Every selector below addresses an
      element askbot.js created. Delete this file and the guides render exactly
      as they did; the assistant just looks unstyled. That is the six-blank-
      sections rule (CLAUDE.md) honoured by construction rather than by care.

   2. SEMANTIC TOKENS ONLY. Not one `--bone-*`, `--loam-*` or `--forest-*`.
      The documentation set has its own theme key and its own dark mode, and a
      cream tint authored in light mode would paint cream across every dark
      guide. Everything here resolves through `--surface`, `--fg`, `--brand`
      and friends, so the panel flips with the page.

   3. IT MUST SURVIVE 320px. The whole tree was audited to 320 on 2026-09-02
      (KNOWN_ISSUES §F) and reports zero bleed. A floating panel is the easiest
      way to put that back, so below 860px this is a bottom sheet pinned to
      both edges — it cannot be wider than the viewport because it never has a
      width of its own.

   ---------------------------------------------------------------------------
   WHY A DOCKED PANEL AND NOT A FULL-PAGE SEARCH

   Because the answer is almost never the whole of what the reader wanted. They
   ask, they read two sentences, they look back at the chapter they were
   already in, they ask again. A page navigation throws that away every time.
   The panel sits beside the guide so the guide is still there.
   ========================================================================== */

.askbot {
  --ab-w: 400px;
  --ab-radius: 18px;
  /* Above the sticky topbar (--z-nav, 40) and the off-canvas rail
     (--z-overlay, 100); below the skip link, which must always win. */
  --ab-z: 200;
  font-family: inherit;
}

/* Screen-reader-only. `.visually-hidden` exists in the shop's stylesheets but
   not reliably in every shell this mounts on — Atlas has its own. Local. */
.ab-vh {
  position: absolute !important; width: 1px; height: 1px;
  padding: 0; margin: -1px; overflow: hidden;
  clip: rect(0 0 0 0); white-space: nowrap; border: 0;
}


/* ==========================================================================
   1. THE LAUNCHER

   A pill rather than the usual circle, because a bare circular glyph in the
   corner of a documentation site reads as a chat widget from a vendor, and
   this is not that. The label says what it does; the kbd says how to skip it.
   ========================================================================== */
.ab-fab {
  position: fixed;
  right: clamp(12px, 3vw, 28px);
  bottom: clamp(12px, 3vw, 28px);
  z-index: var(--ab-z);

  display: inline-flex; align-items: center; gap: .55rem;
  max-width: calc(100vw - 24px);
  padding: 10px 14px 10px 12px;
  border: 1px solid var(--border-strong);
  border-radius: var(--r-pill, 999px);
  background: var(--surface);
  color: var(--fg);
  font-size: var(--t-sm); font-weight: 600;
  line-height: 1;
  box-shadow: var(--shadow-md);
  cursor: pointer;
  transition: transform var(--dur-2, .18s) var(--ease-out, ease),
              box-shadow var(--dur-2, .18s) var(--ease-out, ease),
              border-color var(--dur-2, .18s) var(--ease-out, ease);
}
.ab-fab:hover {
  transform: translateY(-2px);
  border-color: var(--brand);
  box-shadow: var(--shadow-lg);
}
.ab-fab:focus-visible {
  outline: 2px solid var(--border-focus);
  outline-offset: 3px;
}

.ab-fab-ico {
  width: 20px; height: 20px; flex: none;
  color: var(--brand);
  fill: none; stroke: currentColor; stroke-width: 1.7;
  stroke-linecap: round; stroke-linejoin: round;
}
.ab-fab-label { white-space: nowrap; }

.ab-fab-kbd {
  flex: none;
  padding: 3px 6px;
  border: 1px solid var(--border);
  border-radius: 6px;
  background: var(--surface-2);
  color: var(--fg-faint);
  font: inherit; font-size: var(--t-2xs); font-weight: 600;
  letter-spacing: .02em;
}

/* The launcher stays put while the panel is open on desktop — closing is the
   X, or Escape — but on a phone the sheet covers it, so it is pushed out of
   the way rather than left underneath to be tapped by accident. */
.askbot.is-open .ab-fab { opacity: 0; pointer-events: none; }
@media (min-width: 861px) {
  .askbot.is-open .ab-fab { opacity: 1; pointer-events: auto; }
}


/* ==========================================================================
   2. THE PANEL
   ========================================================================== */
.ab-panel {
  position: fixed;
  right: clamp(12px, 3vw, 28px);
  bottom: calc(clamp(12px, 3vw, 28px) + 58px);
  z-index: var(--ab-z);

  /* `min()` against the viewport, not a bare 400px. A fixed width wider than
     the screen is the exact defect the 2026-09-02 audit cleared out of this
     tree; a floating element is the easiest place to reintroduce it. */
  width: min(var(--ab-w), calc(100vw - 24px));
  max-height: min(620px, calc(100vh - 130px));

  display: flex; flex-direction: column;
  overflow: hidden;
  border: 1px solid var(--border-strong);
  border-radius: var(--ab-radius);
  background: var(--surface);
  color: var(--fg);
  box-shadow: var(--shadow-xl);

  transform-origin: 100% 100%;

  /* NO `both`, AND THAT IS THE POINT.
     `animation: ab-in … both` with `from { opacity: 0 }` means the panel's
     resting state is invisible and only an animation makes it appear — which
     is the six-blank-sections rule (CLAUDE.md) with a keyframe instead of a
     class. Anything that stops the animation running (a renderer that does
     not advance them, an extension, a stalled paint) leaves an open panel
     nobody can see. Without a fill mode the base style IS the visible one and
     the keyframes are decoration on top of it. */
  animation: ab-in var(--dur-3, .24s) var(--ease-spring, cubic-bezier(.2,.9,.3,1.2));
}
@keyframes ab-in {
  from { opacity: 0; transform: translateY(10px) scale(.97); }
  to   { opacity: 1; transform: none; }
}

/* `[hidden]` on a normal element is beaten by any class that sets a display —
   and `.ab-panel` sets `display: flex`. Without this the panel is visible
   before it is ever opened. (Same failure family as the SVG note in
   CLAUDE.md, different cause: specificity, not namespacing.) */
.ab-panel[hidden] { display: none !important; }

.ab-scrim {
  position: fixed; inset: 0;
  z-index: calc(var(--ab-z) - 1);
  background: rgba(6, 21, 13, .38);
  animation: ab-fade var(--dur-2, .18s) ease;
}
@keyframes ab-fade { from { opacity: 0 } to { opacity: 1 } }
/* Desktop keeps the guide readable and clickable behind the panel — there is
   nothing modal about looking something up. The scrim is for the phone sheet. */
@media (min-width: 861px) { .ab-scrim { display: none; } }


/* -------------------------------------------------------------- the header */
.ab-head {
  display: flex; align-items: center; gap: .7rem;
  flex: none;
  padding: 13px 12px 13px 15px;
  border-bottom: 1px solid var(--border);
  background: var(--surface-2);
}
.ab-head-ico {
  display: grid; place-items: center;
  width: 32px; height: 32px; flex: none;
  border-radius: 10px;
  background: var(--brand-soft);
  color: var(--brand-ink);
}
.ab-head-ico .ico {
  width: 18px; height: 18px;
  fill: none; stroke: currentColor; stroke-width: 1.7;
  stroke-linecap: round; stroke-linejoin: round;
}
.ab-head-txt {
  display: flex; flex-direction: column; gap: 1px;
  min-width: 0;                       /* or the title cannot ellipsis */
  flex: 1 1 auto;
}
.ab-head-txt b {
  font-size: var(--t-sm); font-weight: 700; line-height: 1.2;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.ab-head-txt small {
  font-size: var(--t-2xs); color: var(--fg-faint);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}

.ab-x {
  display: grid; place-items: center;
  width: 32px; height: 32px; flex: none;
  border: 1px solid transparent; border-radius: 9px;
  background: none; color: var(--fg-subtle); cursor: pointer;
  transition: background var(--dur-1, .12s) ease, color var(--dur-1, .12s) ease;
}
.ab-x:hover { background: var(--surface-sunk); color: var(--fg); }
.ab-x:focus-visible { outline: 2px solid var(--border-focus); outline-offset: 1px; }
.ab-x .ico {
  width: 16px; height: 16px;
  fill: none; stroke: currentColor; stroke-width: 1.9; stroke-linecap: round;
}


/* ------------------------------------------------------------- the scopes
   Internal assistant only. Four guides is exactly the number where "which
   one holds this?" stops being obvious and "search them all" stops being
   precise enough, so both are offered. */
.ab-scopes {
  display: flex; gap: 6px; flex: none;
  padding: 9px 12px;
  border-bottom: 1px solid var(--border);
  overflow-x: auto;
  scrollbar-width: none;
}
.ab-scopes::-webkit-scrollbar { height: 0; }

.ab-scope {
  flex: 0 0 auto;
  padding: 5px 10px;
  border: 1px solid var(--border);
  border-radius: var(--r-pill, 999px);
  background: var(--surface);
  color: var(--fg-subtle);
  font-size: var(--t-2xs); font-weight: 600;
  white-space: nowrap; cursor: pointer;
  transition: background var(--dur-1, .12s) ease, color var(--dur-1, .12s) ease,
              border-color var(--dur-1, .12s) ease;
}
.ab-scope:hover { border-color: var(--border-strong); color: var(--fg); }
.ab-scope.is-on {
  background: var(--brand); border-color: var(--brand); color: var(--brand-fg);
}
.ab-scope:focus-visible { outline: 2px solid var(--border-focus); outline-offset: 2px; }


/* ----------------------------------------------------------------- the log */
.ab-log {
  flex: 1 1 auto;
  min-height: 0;                      /* the scroll container's real fix */
  overflow-y: auto;
  overscroll-behavior: contain;       /* stop the guide scrolling behind it */
  padding: 14px;
  display: flex; flex-direction: column; gap: 12px;
  scrollbar-width: thin;
}
.ab-log:focus-visible { outline: none; }
.ab-log::-webkit-scrollbar { width: 8px; }
.ab-log::-webkit-scrollbar-thumb {
  background: var(--border-strong); border-radius: 4px;
}

/* Again no fill mode: a turn's resting state must be the readable one, or a
   halted animation leaves an answer in the log that cannot be read. */
.ab-turn { animation: ab-turn-in var(--dur-2, .2s) var(--ease-out, ease); }
@keyframes ab-turn-in {
  from { opacity: 0; transform: translateY(6px); }
  to   { opacity: 1; transform: none; }
}

/* --- what the reader asked ------------------------------------------------ */
.ab-you {
  align-self: flex-end;
  max-width: 88%;
  padding: 8px 12px;
  border-radius: 14px 14px 4px 14px;
  background: var(--brand);
  color: var(--brand-fg);
  font-size: var(--t-sm); line-height: var(--lh-snug, 1.4);
}
.ab-you p { margin: 0; }

/* --- what the guides said ------------------------------------------------- */
.ab-bot { max-width: 100%; }
.ab-bot > :first-child { margin-top: 0; }
.ab-bot > :last-child { margin-bottom: 0; }

.ab-intro,
.ab-dead {
  margin: 0 0 10px;
  padding: 11px 13px;
  border: 1px solid var(--border);
  border-left: 3px solid var(--brand);
  border-radius: 4px 12px 12px 4px;
  background: var(--surface-2);
  color: var(--fg-muted);
  font-size: var(--t-xs); line-height: var(--lh-copy, 1.6);
}
.ab-dead { border-left-color: var(--accent); }

.ab-lead {
  margin: 0 0 10px;
  font-size: var(--t-sm);
  line-height: var(--lh-copy, 1.62);
  color: var(--fg);
}
.ab-lead mark {
  padding: 0 2px;
  border-radius: 3px;
  background: var(--accent-soft);
  color: inherit;
  font-weight: 600;
}

.ab-note {
  margin: 0; font-size: var(--t-2xs); color: var(--fg-faint);
}
.ab-note.is-bad { color: var(--danger); }

.ab-link { color: var(--brand-ink); text-decoration: underline; }


/* ------------------------------------------------------------- a hit card
   The source is ABOVE the title, not below it. A reader scanning three
   results is deciding which GUIDE to trust before they read the heading —
   putting the provenance last means re-reading every card. */
.ab-hit {
  display: flex; flex-direction: column; gap: 3px;
  padding: 10px 12px;
  border: 1px solid var(--border);
  border-radius: 12px;
  background: var(--surface);
  color: inherit; text-decoration: none;
  transition: border-color var(--dur-1, .12s) ease,
              background var(--dur-1, .12s) ease,
              transform var(--dur-1, .12s) ease;
}
.ab-hit + .ab-hit { margin-top: 7px; }
.ab-hit:hover {
  border-color: var(--brand);
  background: var(--surface-2);
  transform: translateX(2px);
}
.ab-hit:focus-visible { outline: 2px solid var(--border-focus); outline-offset: 2px; }

.ab-hit.is-primary {
  border-color: var(--border-strong);
  box-shadow: var(--shadow-sm);
}

.ab-hit-top {
  display: flex; align-items: center; gap: 6px;
  min-width: 0;
}
.ab-hit-where {
  min-width: 0; flex: 1 1 auto;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
  font-size: var(--t-2xs); font-weight: 600;
  letter-spacing: .04em; text-transform: uppercase;
  color: var(--fg-faint);
}
.ab-tag {
  flex: 0 0 auto;
  padding: 2px 7px;
  border-radius: var(--r-pill, 999px);
  background: var(--accent-soft);
  color: var(--accent-ink);
  font-size: var(--t-2xs); font-weight: 700;
  letter-spacing: .02em;
}

.ab-hit-title {
  font-size: var(--t-sm); font-weight: 650;
  line-height: var(--lh-snug, 1.35);
  color: var(--fg);
}
.ab-hit-go {
  display: inline-flex; align-items: center; gap: 3px;
  margin-top: 3px;
  font-size: var(--t-2xs); font-weight: 600;
  color: var(--brand-ink);
}
.ab-hit-go .ico {
  width: 13px; height: 13px;
  fill: none; stroke: currentColor; stroke-width: 2;
  stroke-linecap: round; stroke-linejoin: round;
  transition: transform var(--dur-1, .12s) ease;
}
.ab-hit:hover .ab-hit-go .ico { transform: translateX(2px); }

.ab-also {
  margin: 13px 0 6px;
  font-size: var(--t-2xs); font-weight: 700;
  letter-spacing: .05em; text-transform: uppercase;
  color: var(--fg-faint);
}


/* ------------------------------------------------------- catalogue answers
   Public assistant only. Prices are read from the live catalogue at answer
   time, so this block is showing the same number the product card shows. */
.ab-cat {
  margin: 0 0 11px;
  border: 1px solid var(--border);
  border-radius: 12px;
  overflow: hidden;
}
.ab-cat-row {
  display: flex; align-items: baseline; justify-content: space-between; gap: 10px;
  padding: 9px 12px;
  color: inherit; text-decoration: none;
  background: var(--surface);
  transition: background var(--dur-1, .12s) ease;
}
.ab-cat-row + .ab-cat-row { border-top: 1px solid var(--border); }
.ab-cat-row:hover { background: var(--surface-2); }
.ab-cat-name {
  min-width: 0; flex: 1 1 auto;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
  font-size: var(--t-sm); font-weight: 600;
}
.ab-cat-price {
  flex: 0 0 auto;
  font-size: var(--t-xs); font-weight: 700; color: var(--brand-ink);
}
.ab-cat-foot {
  margin: 0; padding: 7px 12px;
  border-top: 1px solid var(--border);
  background: var(--surface-2);
  font-size: var(--t-2xs); color: var(--fg-faint);
}


/* ------------------------------------------------------------------- seeds */
.ab-seed-label {
  margin: 10px 0 6px;
  font-size: var(--t-2xs); font-weight: 700;
  letter-spacing: .05em; text-transform: uppercase;
  color: var(--fg-faint);
}
.ab-seeds { display: flex; flex-wrap: wrap; gap: 6px; }
.ab-seed {
  padding: 6px 11px;
  border: 1px solid var(--border);
  border-radius: var(--r-pill, 999px);
  background: var(--surface);
  color: var(--fg-muted);
  font-size: var(--t-2xs); font-weight: 600;
  text-align: left; cursor: pointer;
  transition: border-color var(--dur-1, .12s) ease, color var(--dur-1, .12s) ease,
              background var(--dur-1, .12s) ease;
}
.ab-seed:hover {
  border-color: var(--brand); color: var(--brand-ink); background: var(--brand-soft);
}
.ab-seed:focus-visible { outline: 2px solid var(--border-focus); outline-offset: 2px; }

.ab-bot.is-quiet .ab-seed { border-style: dashed; }


/* --------------------------------------------------------------- the input */
.ab-ask {
  display: flex; align-items: center; gap: 8px;
  flex: none;
  padding: 11px 12px;
  border-top: 1px solid var(--border);
  background: var(--surface-2);
}
.ab-input {
  flex: 1 1 auto;
  min-width: 0;                       /* flex children do not shrink without it */
  padding: 9px 12px;
  border: 1px solid var(--border-strong);
  border-radius: var(--r-pill, 999px);
  background: var(--surface);
  color: var(--fg);
  font: inherit; font-size: var(--t-sm);
}
.ab-input::placeholder { color: var(--fg-faint); }
.ab-input:focus {
  outline: none;
  border-color: var(--brand);
  box-shadow: 0 0 0 3px color-mix(in srgb, var(--brand) 18%, transparent);
}
.ab-send {
  display: grid; place-items: center;
  width: 36px; height: 36px; flex: none;
  border: none; border-radius: 50%;
  background: var(--brand); color: var(--brand-fg);
  cursor: pointer;
  transition: background var(--dur-1, .12s) ease, transform var(--dur-1, .12s) ease;
}
.ab-send:hover { background: var(--brand-hover); transform: scale(1.06); }
.ab-send:focus-visible { outline: 2px solid var(--border-focus); outline-offset: 2px; }
.ab-send .ico {
  width: 18px; height: 18px;
  fill: none; stroke: currentColor; stroke-width: 2;
  stroke-linecap: round; stroke-linejoin: round;
}


/* ==========================================================================
   2b. THE RAIL SEARCH'S DEAD END

   Sits in the guide's sidebar, under the title filter, and appears only when
   that filter has matched nothing. It is injected by askbot.js — no guide's
   markup contains it — so the "nothing hidden waiting for a script" rule
   holds: before this file runs there is no element here to hide.
   ========================================================================== */
/* This class lands on guide.js's own `.rail-none` paragraph, so it overrides
   rather than replaces — and it must not fight `[hidden]`, which guide.js
   uses to show and hide it. */
.ab-rail-none.rail-none {
  display: block;
  margin: 2px 0 10px;
  padding: 10px 11px;
  border: 1px dashed var(--border-strong);
  border-radius: 12px;
  background: var(--surface-2);
}
.ab-rail-none.rail-none[hidden] { display: none !important; }

.ab-rail-none-p {
  display: block;
  margin: 0 0 8px;
  font-size: var(--t-xs); line-height: var(--lh-snug, 1.45);
  color: var(--fg-subtle);
}

.ab-rail-none-go {
  display: inline-flex; align-items: center; gap: 6px;
  width: 100%;
  padding: 7px 10px;
  border: 1px solid var(--brand);
  border-radius: var(--r-pill, 999px);
  background: var(--brand); color: var(--brand-fg);
  font-size: var(--t-2xs); font-weight: 700;
  cursor: pointer; text-align: left;
  transition: background var(--dur-1, .12s) ease;
}
.ab-rail-none-go:hover { background: var(--brand-hover); }
.ab-rail-none-go:focus-visible { outline: 2px solid var(--border-focus); outline-offset: 2px; }
.ab-rail-none-go .ico {
  width: 15px; height: 15px; flex: none;
  fill: none; stroke: currentColor; stroke-width: 1.7;
  stroke-linecap: round; stroke-linejoin: round;
}


/* Appended into docs/demo.js's own "nothing matched" paragraph on the help
   centre landing page. Block, and on its own line, because it follows a
   sentence of prose. */
.ab-inline-go {
  /* `flex`, not `inline-flex`, and a fitted width. It is appended INTO a
     <p> of prose, so an inline box would sit on the end of that sentence,
     run under the launcher in the corner and read as part of the paragraph.
     A flex box is block-level, so it takes its own line. */
  display: flex; width: fit-content;
  align-items: center; gap: 6px;
  margin-top: 10px;
  padding: 8px 14px;
  border: 1px solid var(--brand);
  border-radius: var(--r-pill, 999px);
  background: var(--brand); color: var(--brand-fg);
  font-size: var(--t-xs); font-weight: 700;
  cursor: pointer;
  transition: background var(--dur-1, .12s) ease;
}
.ab-inline-go:hover { background: var(--brand-hover); }
.ab-inline-go:focus-visible { outline: 2px solid var(--border-focus); outline-offset: 2px; }
.ab-inline-go .ico {
  width: 15px; height: 15px; flex: none;
  fill: none; stroke: currentColor; stroke-width: 1.7;
  stroke-linecap: round; stroke-linejoin: round;
}


/* ==========================================================================
   3. THE JUMP TARGET

   When an answer sends the reader into a chapter, the chapter says so. A hash
   jump on a long page lands you at a heading with no indication which of the
   nine paragraphs below it you were sent for.

   `outline` rather than `background`, and no layout properties at all — this
   lands on documentation elements this file does not own, so it must not be
   able to move one.
   ========================================================================== */
.ab-flash {
  /* `forwards`, not `both`. `both` would apply the 0% frame BEFORE the
     animation starts, so a halted animation pins the ring on permanently. */
  animation: ab-flash 2.4s var(--ease-out, ease) forwards;
  border-radius: 6px;
}
@keyframes ab-flash {
  0%   { outline: 2px solid var(--brand); outline-offset: 6px;
         background: color-mix(in srgb, var(--brand) 12%, transparent); }
  70%  { outline: 2px solid var(--brand); outline-offset: 4px;
         background: color-mix(in srgb, var(--brand) 8%, transparent); }
  100% { outline: 2px solid transparent; outline-offset: 4px;
         background: transparent; }
}


/* ==========================================================================
   4. THE PHONE

   Below 860px the panel becomes a bottom sheet pinned to both edges. Note
   what it does NOT have any more: a width. It cannot overflow a viewport it
   is not measured against, which is the cheapest possible way to keep the
   320px result from KNOWN_ISSUES §F true.
   ========================================================================== */
@media (max-width: 860px) {
  .ab-panel {
    right: 0; left: 0; bottom: 0;
    width: auto;
    max-height: 86vh;
    max-height: 86dvh;               /* the URL bar, on iOS */
    border-radius: var(--ab-radius) var(--ab-radius) 0 0;
    border-left: none; border-right: none; border-bottom: none;
    animation-name: ab-sheet-in;   /* still no fill mode — see .ab-panel */
  }
  @keyframes ab-sheet-in {
    from { opacity: 0; transform: translateY(22px); }
    to   { opacity: 1; transform: none; }
  }
  .ab-log { padding-bottom: 18px; }
  /* Thumb-sized targets, and a bar that clears the home indicator. */
  .ab-ask { padding-bottom: max(11px, env(safe-area-inset-bottom)); }
}

@media (max-width: 640px) {
  /* The label and the shortcut both go: a phone has no Ctrl key, and the
     pill would otherwise take a third of the screen width. */
  .ab-fab-label, .ab-fab-kbd { display: none; }
  .ab-fab {
    width: 48px; height: 48px;
    padding: 0; justify-content: center;
    border-radius: 50%;
  }
  .ab-fab-ico { width: 22px; height: 22px; }
}

@media (max-width: 360px) {
  .ab-log { padding: 11px; }
  .ab-head { padding-left: 12px; }
  .ab-you { max-width: 94%; }
}


/* ==========================================================================
   5. MOTION, PRINT, AND THE COARSE POINTER
   ========================================================================== */
@media (prefers-reduced-motion: reduce) {
  .ab-panel, .ab-turn, .ab-scrim { animation: none; }
  .ab-fab:hover, .ab-hit:hover, .ab-send:hover { transform: none; }
  .ab-flash { animation-duration: .01ms; outline: 2px solid var(--brand); }
}

/* A tap has no hover to reveal anything, and a 13px chip is not a target. */
@media (pointer: coarse) {
  .ab-seed, .ab-scope { padding-top: 8px; padding-bottom: 8px; }
}

/* ==========================================================================
   THE BUTTON RESERVES THE SPACE IT OCCUPIES

   `.ab-fab` is `position: fixed` in the bottom-right corner, so at the very
   bottom of a page it lands on top of whatever the footer put there. On the
   guides that is the right-hand column of `.sitefoot-base` — measured at
   1400px: the button occupies 1159..1357 x 2630..2672 and the footer line
   sits at 1066..1343, an overlap of 184 x 38px. It reads as text that has
   been cut off, which is what it was reported as.

   Measured rather than guessed: the button is 42px tall and sits at
   `bottom: clamp(12px, 3vw, 28px)`, so it claims up to 70px from the bottom
   of the viewport. 56px on top of the footer's existing 32px clears it with
   room to spare.

   THIS LIVES HERE, NOT IN guide.css, AND THAT IS THE POINT. A floating
   element owns the space it takes; putting the reservation in the footer's
   own stylesheet would apply it on `dev/index.php` too, which has the same
   footer and no assistant. This file is loaded by exactly the seven pages
   that have the button. */
.sitefoot { padding-bottom: calc(var(--s-7) + 56px); }

/* The assistant is a tool for reading the page, not part of it. */
@media print {
  .askbot { display: none !important; }
  .ab-flash { animation: none; outline: none; background: none; }
  /* nothing floats on paper, so the footer takes its normal space back */
  .sitefoot { padding-bottom: var(--s-7); }
}
