/* ExtraDrive's built-in viewers — the look of a rendered file, wherever it is
   rendered (DESIGN.md §6.2).

   Two callers, one stylesheet: the UI drops a rendered element into a modal and
   only needs the `.xd-*` rules; the serve shell is a whole page and uses
   `.xd-page` as well. Absent a host telling it otherwise, a viewer follows the
   reader's own colour scheme — it is embedded in properties whose palettes we
   do not know, so it dresses itself. A host that DOES know its own mode (Extra,
   framing an item) says so with `[data-mode]` on this document's `<html>`
   (`viewer-shell.js`), which then wins over `prefers-color-scheme` — the same
   attribute Extra itself toggles on its own `<html>`, so a dark item does not
   sit in a light Extra or the reverse.

   Phone-first, per the house convention: the base is the narrow layout and the
   only enhancement is a wider measure at 720px. */

:root {
  --xd-bg: #ffffff;
  --xd-ink: #17161b;
  --xd-dim: #6b6875;
  --xd-line: rgba(23, 22, 27, 0.14);
  --xd-fill: rgba(23, 22, 27, 0.05);
  --xd-accent: #2f49d1;
}
@media (prefers-color-scheme: dark) {
  :root:not([data-mode]) {
    --xd-bg: #16161b;
    --xd-ink: #f2f0ea;
    --xd-dim: #9c98a6;
    --xd-line: rgba(242, 240, 234, 0.16);
    --xd-fill: rgba(242, 240, 234, 0.07);
    --xd-accent: #8fa0ff;
  }
}
:root[data-mode="dark"] {
  --xd-bg: #16161b;
  --xd-ink: #f2f0ea;
  --xd-dim: #9c98a6;
  --xd-line: rgba(242, 240, 234, 0.16);
  --xd-fill: rgba(242, 240, 234, 0.07);
  --xd-accent: #8fa0ff;
}

/* ---- the standalone page (serve host only) ---- */

.xd-page {
  margin: 0;
  background: var(--xd-bg);
  color: var(--xd-ink);
  font: 16px/1.6 -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
  -webkit-text-size-adjust: 100%;
}
.xd-bar {
  position: sticky; top: 0; z-index: 2;
  display: flex; align-items: center; gap: 10px;
  padding: 8px 14px; min-height: 44px;
  background: var(--xd-bg); border-bottom: 1px solid var(--xd-line);
  font-size: 12.5px; color: var(--xd-dim);
}
.xd-bar .xd-name {
  flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
  direction: rtl; text-align: left;
}
.xd-bar a, .xd-bar button {
  flex-shrink: 0; font: inherit; color: var(--xd-dim); background: none; border: 0;
  border-radius: 8px; padding: 8px 6px; min-height: 32px; cursor: pointer; text-decoration: none;
}
.xd-bar a:hover, .xd-bar button:hover { color: var(--xd-accent); }
.xd-body { padding: 18px 16px 48px; }
.xd-body > .xd-md, .xd-body > .xd-json { max-width: 46rem; }
/* Media and pages take the whole frame; a document takes a column. */
.xd-body.xd-fill { padding: 0; height: calc(100dvh - 45px); display: flex; flex-direction: column; }
.xd-body.xd-fill > * { margin: auto; max-width: 100%; max-height: 100%; }
.xd-body.xd-fill > audio { width: min(560px, 92%); }
/* Takes over the centering/sizing `> *` above gave the media element
   directly, so pins/chips have a box to position against that matches what
   a person actually sees — letterboxing included — rather than the frame's
   own box, which is wrong the moment an image's aspect ratio does not match
   it. See `item-comments-contract.md` §15 and `viewer-shell.js`'s image/
   video/audio branch. */
.xd-media-wrap { position: relative; display: inline-flex; max-width: 100%; max-height: 100%; }
.xd-media-wrap > img, .xd-media-wrap > video { display: block; max-width: 100%; max-height: 100%; }
.xd-media-wrap > audio { width: min(560px, 92%); }
.xd-pinlayer { position: absolute; inset: 0; pointer-events: none; }
.xd-anchor-pin {
  position: absolute; transform: translate(-50%, -50%); pointer-events: auto; cursor: pointer;
  width: 22px; height: 22px; border-radius: 50%; border: 2px solid #fff;
  background: rgba(255, 199, 0, .92); color: #1a1a1a; font: 700 11px/18px ui-monospace, monospace;
  text-align: center; box-shadow: 0 1px 3px rgba(0,0,0,.4);
}
.xd-timechips { display: flex; flex-wrap: wrap; gap: 6px; justify-content: center; padding: 8px 0 0; }
.xd-timechip, .xd-pin-moment {
  border: 1px solid var(--xd-line); border-radius: 999px; padding: .2rem .7rem; font-size: .85em;
  background: var(--xd-fill); cursor: pointer; color: var(--xd-ink);
}
.xd-timechip:hover, .xd-pin-moment:hover { background: rgba(255, 199, 0, .35); }
.xd-pin-moment { align-self: center; margin: 0 0 6px; font-weight: 600; }
/* A CSV cell or JSON node with a comment, drawn by adding a class rather
   than wrapping a node — both are already discrete elements. */
.xd-anchor-cell { background: rgba(255, 199, 0, .35); cursor: pointer; }

@media (min-width: 721px) {
  .xd-page { font-size: 15px; }
  .xd-body { padding: 22px 24px 60px; }
}

/* ---- the renderers ---- */

.xd-md { line-height: 1.6; overflow-wrap: break-word; }
.xd-md h1, .xd-md h2, .xd-md h3, .xd-md h4 { margin: 1.4em 0 .5em; line-height: 1.25; }
.xd-md h1 { font-size: 1.7em; }
.xd-md h2 { font-size: 1.35em; }
.xd-md h3 { font-size: 1.12em; }
.xd-md > :first-child { margin-top: 0; }
.xd-md p, .xd-md ul, .xd-md ol { margin: .7em 0; }
.xd-md li { margin: .25em 0; }
.xd-md li input { margin-right: .5em; }
.xd-md pre {
  background: var(--xd-fill); padding: .8rem 1rem; border-radius: 8px;
  overflow-x: auto; font-size: .85em; line-height: 1.5;
}
.xd-md code {
  background: var(--xd-fill); padding: .12em .38em; border-radius: 5px; font-size: .88em;
  font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
}
.xd-md pre code { background: none; padding: 0; }
.xd-md blockquote {
  border-left: 3px solid var(--xd-line); margin: .8em 0; padding: .1em 0 .1em 1rem; color: var(--xd-dim);
}
.xd-md img { max-width: 100%; height: auto; border-radius: 8px; }
.xd-md a { color: var(--xd-accent); text-decoration: underline; }
.xd-md hr { border: none; border-top: 1px solid var(--xd-line); margin: 1.6em 0; }

.xd-table { border-collapse: collapse; font-size: .9em; }
.xd-table th, .xd-table td {
  border: 1px solid var(--xd-line); padding: .35rem .6rem; text-align: left; vertical-align: top;
}
.xd-table th { background: var(--xd-fill); font-weight: 650; }
/* A table is the one thing that may scroll sideways inside its own box; the
   page itself never does. */
.xd-md .xd-table { display: block; overflow-x: auto; max-width: 100%; }
.xd-csv-wrap { overflow: auto; max-width: 100%; }
.xd-csv th, .xd-csv td { white-space: nowrap; }
.xd-csv th { position: sticky; top: 0; background: var(--xd-bg); }

.xd-raw {
  margin: 0; white-space: pre; overflow-x: auto; tab-size: 2;
  font: 12.5px/1.55 ui-monospace, SFMono-Regular, Menlo, monospace;
}
/* A text anchor, drawn by the shell itself over its own `<pre>` — never by
   the host, which cannot see inside this frame at all. See
   `item-comments-contract.md` §12 and `viewer-shell.js`'s `drawAnchors`. */
.xd-anchor {
  background: rgba(96, 165, 250, .35); cursor: pointer; border-radius: 2px;
}
.xd-anchor:hover { background: rgba(96, 165, 250, .6); }
/* The thread selected in the rail — darker still than hover, so the two
   states stay visually distinct even though hovering the active mark itself
   is the common case. */
.xd-anchor.on { background: rgba(37, 99, 235, .7); }
/* The floating button any selection offers while the rail is open — never a
   mode entered first. `position: fixed`, appended to the real
   `document.body` rather than this page's own content div, so the
   `getBoundingClientRect()` coordinates `viewer-shell.js` sets on it line up
   regardless of scrolling inside that div. */
.xd-add-comment {
  position: fixed; transform: translate(-50%, -100%) translateY(-8px); z-index: 1000;
  border: none; border-radius: 6px; padding: .4rem .75rem; font-size: .85em; font-weight: 600;
  background: #1a1a1a; color: #fff; cursor: pointer; box-shadow: 0 2px 8px rgba(0,0,0,.3);
  white-space: nowrap;
}
.xd-add-comment:hover { background: #333; }
/* Selection starts on the first line, no room to place the button above it
   (`viewer-shell.js`'s `onSelect`, `BTN_SPACE`) — render it below the
   selection instead, so it lands somewhere clickable rather than off the top
   edge of this frame's own viewport. */
.xd-add-comment.xd-add-comment-below { transform: translate(-50%, 0); }
.xd-json { font: 12.5px/1.55 ui-monospace, SFMono-Regular, Menlo, monospace; }
.xd-json details { padding-left: 1rem; }
.xd-json summary { cursor: pointer; color: var(--xd-dim); min-height: 22px; }
.xd-json-leaf { padding-left: 1rem; }
.xd-json-string { color: #4f9d5b; }
.xd-json-number { color: #b8813c; }
.xd-json-boolean { color: #9a63c8; }
@media (prefers-color-scheme: dark) {
  :root:not([data-mode]) .xd-json-string { color: #7aa869; }
  :root:not([data-mode]) .xd-json-number { color: #c08c4a; }
  :root:not([data-mode]) .xd-json-boolean { color: #b07acc; }
}
:root[data-mode="dark"] .xd-json-string { color: #7aa869; }
:root[data-mode="dark"] .xd-json-number { color: #c08c4a; }
:root[data-mode="dark"] .xd-json-boolean { color: #b07acc; }

.xd-note, .xd-empty { color: var(--xd-dim); font-size: 12.5px; padding: 10px 2px; }
.xd-none { text-align: center; color: var(--xd-dim); padding: 40px 18px; }
.xd-none .xd-t { color: var(--xd-ink); font-size: 15px; margin-bottom: 6px; word-break: break-all; }
.xd-none a {
  display: inline-block; margin-top: 14px; padding: 10px 16px; min-height: 44px;
  border: 1px solid var(--xd-line); border-radius: 9px; color: var(--xd-ink); text-decoration: none;
}
