/* =========================================================
   mbrd - the viewer, and the documents read inside it.
   ui/viewer.ts opens one item full-window; ui/documents.ts turns
   .docx/.odt/.pptx into elements inside it. Document rules share
   the viewer's Markdown measure and face.
   ========================================================= */

/* Fixed head, scrolling body. */
#viewer {
  width: min(1100px, calc(100vw - 32px));
  height: min(860px, calc(100dvh - 32px));
  max-width: none;
  max-height: none;
  padding: 0;
  border: var(--hairline) solid var(--rule-2);
  border-radius: var(--radius);
  background: var(--paper-card);
  box-shadow: var(--shadow-2);
  color: var(--ink);
  overflow: hidden;
  /* Top-layer <dialog> needs margin:auto for centring. */
  margin: auto;
  animation: ask-in var(--dur-base) var(--ease-back);
}
/* display:flex on [open] only — a flat flex outranks UA display:none. */
#viewer[open] { display: flex; flex-direction: column; }
#viewer::backdrop {
  background: color-mix(in srgb, var(--ink) 42%, transparent);
  -webkit-backdrop-filter: blur(2px);
  backdrop-filter: blur(2px);
}

#viewer-head {
  flex: none;
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 14px 16px 12px 20px;
  border-bottom: var(--hairline) solid var(--rule-2);
}
#viewer-names { min-width: 0; flex: 1 1 auto; }
#viewer-title {
  margin: 0;
  font-family: var(--font-display);
  font-size: var(--t-body);
  font-weight: 600;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
#viewer-meta {
  margin: 2px 0 0;
  color: var(--ink-3);
  font-size: var(--t-tiny);
  text-transform: uppercase;
  letter-spacing: 0.06em;
}
#viewer-meta:empty { display: none; }
#viewer-close {
  flex: none;
  display: grid;
  place-items: center;
  width: var(--icon-button); height: var(--icon-button);
  border: 0;
  border-radius: var(--leaf);
  background: none;
  color: var(--ink-2);
  cursor: pointer;
  transition: background var(--dur-fast) var(--ease), color var(--dur-fast) var(--ease);
}
@media (hover: hover) {
  #viewer-close:hover { background: var(--paper-2); color: var(--accent-deep); }
}
#viewer-close:active { background: var(--paper-3); }
#viewer-close:focus-visible { background: var(--paper-2); color: var(--accent-deep); }
#viewer-close svg { width: var(--icon-glyph); height: var(--icon-glyph); }

/* Grid centres a picture without stretching it; media caps at 100% and keeps
   aspect. Text overrides the centring (starts top-left). */
#viewer-body {
  flex: 1 1 auto;
  min-height: 0;
  overflow: auto;
  overscroll-behavior: contain;
  display: grid;
  place-items: center;
  padding: 16px 20px 20px;
  background: var(--paper-2);
}
#viewer-body:focus { outline: none; }

.viewer-media {
  max-width: 100%;
  max-height: 100%;
  object-fit: contain;
  border-radius: var(--leaf);
  background: var(--paper-3);
}
.viewer-cover {
  max-width: min(420px, 100%);
  border-radius: var(--leaf);
  box-shadow: var(--shadow-1);
}
.viewer-audio { width: min(640px, 100%); margin-top: 16px; }

/* ── The lightbox: what the viewer becomes for a picture or a clip ─────────
   A photo in a 1100px paper card on a wide monitor is too small for its room,
   but a full-window stage boxes the reader out of the board. data-media is a
   near-full inset card: a big near-black stage floating on the dimmed, blurred
   board, which stays visible around its edges. max-height: 100% works because
   the grid row is pinned to minmax(0, 1fr). */
#viewer[data-media] {
  /* Inset ~48px each side, not edge-to-edge — the board peeks around it. */
  width: calc(100vw - 96px);
  height: calc(100dvh - 96px);
  max-width: none;
  max-height: none;
  border: 0;
  border-radius: var(--radius);
  box-shadow: var(--shadow-2);
  /* Near-black, not the ink token — neutral ground for judging photos. */
  background: rgb(14 13 12 / 0.94);
  color: rgb(255 255 255 / 0.92);
}
/* Dims and blurs the board rather than hiding it, so the inset card reads as
   floating over the work, not a new full screen. */
#viewer[data-media]::backdrop {
  background: color-mix(in srgb, var(--ink) 58%, transparent);
  -webkit-backdrop-filter: blur(3px);
  backdrop-filter: blur(3px);
}
/* Head becomes a caption over the picture, not a bar. */
#viewer[data-media] #viewer-head {
  border-bottom: 0;
  background: none;
}
#viewer[data-media] #viewer-meta { color: rgb(255 255 255 / 0.55); }
/* A solid disc over the stage, not a bare icon that vanishes on a busy photo.
   Square at Harsh, as the other closes are: it is a close, not a circle with a meaning. */
#viewer[data-media] #viewer-close {
  border-radius: var(--radius-pill);
  background: rgb(14 13 12 / 0.55);
  border: var(--hairline) solid rgb(255 255 255 / 0.32);
  color: rgb(255 255 255 / 0.92);
}
#viewer[data-media] #viewer-close:hover {
  background: rgb(255 255 255 / 0.2);
  color: rgb(255 255 255 / 1);
}
#viewer[data-media] #viewer-close svg {
  width: calc(var(--icon-glyph) + 4px);
  height: calc(var(--icon-glyph) + 4px);
}
/* Definite row/column so max-height:100% resolves. No scroll — zoomed
   pictures are panned (attachZoomPan in ui/viewer.ts). */
#viewer[data-media] #viewer-body {
  overflow: hidden;
  background: none;
  padding: 0 16px 20px;
  grid-template-rows: minmax(0, 1fr);
  grid-template-columns: minmax(0, 1fr);
  touch-action: none;
}
#viewer[data-media] .viewer-media {
  border-radius: 0;
  background: none;
  transform-origin: center center;
  cursor: zoom-in;
  -webkit-user-select: none;
  user-select: none;
  -webkit-user-drag: none;
}
#viewer[data-media] .viewer-media.is-zoomed { cursor: grab; }
#viewer[data-media] .viewer-media.is-panning { cursor: grabbing; }
/* A clip keeps its controls — no zoom cursor, no drag claim. */
#viewer[data-media] video.viewer-media { cursor: default; }

/* Plain text: top-left, monospaced. */
#viewer-body:has(> .viewer-text),
#viewer-body:has(> .viewer-md) { place-items: start stretch; }
.viewer-text {
  margin: 0;
  max-width: 88ch;
  color: var(--ink);
  font-family: var(--font-mono);
  font-size: var(--t-small);
  line-height: 1.6;
  white-space: pre-wrap;
  word-break: break-word;
}

/* Rendered Markdown. Board's body face, comfortable measure. One selector per
   construct — the parser emits ordinary elements. */
.viewer-md {
  max-width: 74ch;
  color: var(--ink);
  font-size: var(--t-body);
  line-height: 1.65;
}
.viewer-md > :first-child { margin-top: 0; }
.viewer-md > :last-child { margin-bottom: 0; }
.viewer-md h1, .viewer-md h2, .viewer-md h3,
.viewer-md h4, .viewer-md h5, .viewer-md h6 {
  margin: 1.6em 0 0.5em;
  font-family: var(--font-display);
  font-weight: 600;
  line-height: 1.25;
}
.viewer-md h1 { font-size: 1.7em; }
.viewer-md h2 { font-size: 1.35em; }
.viewer-md h3 { font-size: 1.15em; }
.viewer-md h4, .viewer-md h5, .viewer-md h6 { font-size: 1em; }
/* Rule under h1/h2 only — h3+ would read as a ladder. */
.viewer-md h1, .viewer-md h2 {
  padding-bottom: 0.25em;
  border-bottom: var(--hairline) solid var(--rule-2);
}
.viewer-md p { margin: 0 0 1em; }
.viewer-md ul, .viewer-md ol { margin: 0 0 1em; padding-left: 1.6em; }
.viewer-md li { margin: 0.25em 0; }
.viewer-md li > ul, .viewer-md li > ol { margin: 0.25em 0 0; }
.viewer-md li.md-task { list-style: none; margin-left: -1.4em; }
.viewer-md li.md-task input { margin-right: 0.5em; accent-color: var(--accent-text); }
.viewer-md blockquote {
  margin: 0 0 1em;
  padding: 0.1em 0 0.1em 1em;
  border-left: 3px solid var(--rule);
  color: var(--ink-2);
}
.viewer-md hr {
  margin: 1.8em 0;
  border: 0;
  border-top: var(--hairline) solid var(--rule-2);
}
/* Radius from token so Harsh squares it off with everything else. */
.viewer-md code {
  padding: 0.12em 0.35em;
  border-radius: var(--radius-xs);
  background: var(--paper-3);
  font-family: var(--font-mono);
  font-size: 0.88em;
}
.viewer-md pre {
  margin: 0 0 1em;
  padding: 12px 14px;
  border-radius: var(--leaf);
  background: var(--paper-3);
  /* Code must not wrap — scrolls inside its own box. */
  overflow-x: auto;
}
.viewer-md pre code { padding: 0; border-radius: 0; background: none; }
.viewer-md a { color: var(--accent-deep); }
.viewer-md table {
  margin: 0 0 1em;
  border-collapse: collapse;
  font-size: 0.94em;
}
.viewer-md th, .viewer-md td {
  padding: 6px 10px;
  border: var(--hairline) solid var(--rule-2);
  text-align: left;
}
.viewer-md th { background: var(--paper-3); font-weight: 600; }
/* Image alt text — the image itself is not fetched (see ui/markdown.ts). */
.viewer-md .md-image {
  padding: 0.1em 0.45em;
  border: var(--hairline) dashed var(--rule);
  border-radius: var(--radius-xs);
  color: var(--ink-3);
  font-size: 0.9em;
}

/* ---------------------------------------------------------
   Documents in the viewer (ui/documents.ts)
   .docx, .odt and .pptx read into ordinary elements. Shares
   the viewer's Markdown measure and face. --------------- */

#viewer-body:has(> .doc-flow),
#viewer-body:has(> .doc-slide),
#viewer-body:has(> .doc-sheet),
#viewer-body:has(> .doc-table-wrap),
#viewer-body:has(> .doc-pages) { place-items: start stretch; }

.doc-flow {
  max-width: 74ch;
  color: var(--ink);
  font-size: var(--t-body);
  line-height: 1.65;
}
.doc-flow > :first-child { margin-top: 0; }
.doc-flow p { margin: 0 0 0.9em; }
.doc-flow h1, .doc-flow h2, .doc-flow h3,
.doc-flow h4, .doc-flow h5, .doc-flow h6 {
  margin: 1.4em 0 0.45em;
  font-family: var(--font-display);
  font-weight: 600;
  line-height: 1.25;
}
.doc-flow h1 { font-size: 1.6em; }
.doc-flow h2 { font-size: 1.3em; }
.doc-flow h3 { font-size: 1.12em; }
.doc-flow h4, .doc-flow h5, .doc-flow h6 { font-size: 1em; }
.doc-list { margin: 0 0 0.9em; padding-left: 1.5em; }
.doc-list li { margin: 0.2em 0; }
.doc-quote {
  padding-left: 1em;
  border-left: 3px solid var(--rule);
  color: var(--ink-2);
}
/* Links shown but not clickable — an address in a foreign file should not be
   one click away. */
.doc-link { text-decoration: underline; text-decoration-style: dotted; }
.doc-image {
  display: block;
  max-width: 100%;
  height: auto;
  margin: 0.8em 0;
  border-radius: var(--leaf);
}
.doc-missing { color: var(--ink-3); font-style: italic; }

/* Slides and sheets: named parts with a rule above the name. */
.doc-slide, .doc-sheet { margin: 0 0 28px; }
.doc-part {
  margin: 0 0 10px;
  padding-bottom: 6px;
  border-bottom: var(--hairline) solid var(--rule-2);
  color: var(--ink-3);
  font-family: var(--font-display);
  font-size: var(--t-small);
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.06em;
}

/* A spreadsheet scrolls inside its own box, not the whole dialog. */
.doc-table-wrap { max-width: 100%; overflow-x: auto; margin: 0 0 1em; }
.doc-table {
  border-collapse: collapse;
  font-size: var(--t-small);
  white-space: nowrap;
}
.doc-table th, .doc-table td {
  padding: 5px 10px;
  border: var(--hairline) solid var(--rule-2);
  text-align: left;
}
.doc-table th { background: var(--paper-3); font-weight: 600; }

/* Pages (comic, PDF) in one column. Canvas needs explicit height:auto. */
.doc-pages { display: flex; flex-direction: column; gap: 12px; align-items: center; }
.doc-page {
  max-width: 100%;
  height: auto;
  border-radius: var(--leaf);
  background: #fff;
  box-shadow: var(--shadow-1);
}

/* Load-more button, styled as a quiet continuation. */
.viewer-more {
  display: block;
  margin: 14px auto 0;
  padding: 8px 18px;
  border: var(--hairline) solid var(--rule-2);
  border-radius: var(--leaf);
  background: var(--paper-card);
  color: var(--ink-2);
  font-size: var(--t-small);
  cursor: pointer;
}
.viewer-more:hover { background: var(--paper-2); color: var(--accent-deep); }
.viewer-more:disabled { color: var(--ink-3); cursor: default; }

.doc-svg { display: grid; place-items: center; }
.doc-svg svg { max-width: 100%; max-height: 70dvh; height: auto; }

.viewer-note-sheet {
  width: min(520px, 100%);
  box-sizing: border-box;
  padding: 28px;
  border-radius: var(--leaf);
  background: var(--note-1);
  box-shadow: var(--shadow-1);
  font-size: var(--t-body);
  line-height: 1.5;
  white-space: pre-wrap;
  word-break: break-word;
}

.viewer-link {
  max-width: 100%;
  color: var(--accent-deep);
  font-size: var(--t-body);
  word-break: break-all;
  text-align: center;
}

/* An embeddable link (YouTube, Spotify) played inside the viewer. YouTube is
   16:9 and fills the width; Spotify's player is flat, so it takes a fixed
   height. The frame stops loading when the body is emptied on close. */
.viewer-embed {
  width: min(100%, 960px);
  margin: auto;
}
.viewer-embed[data-provider="youtube"] { aspect-ratio: 16 / 9; }
.viewer-embed[data-provider="spotify"] { height: min(560px, 80dvh); }
.viewer-embed .embed-frame {
  width: 100%;
  height: 100%;
  border: 0;
  border-radius: var(--leaf);
}

.viewer-note {
  margin: 12px 0 0;
  color: var(--ink-3);
  font-size: var(--t-small);
}

/* color-mix() fallback for WebKit < 16.2 — see tokens.css section 7. */
@supports not (color: color-mix(in srgb, red, blue)) {
  #viewer::backdrop { background: rgb(var(--ink-c) / 42%); }
}
