/*
 * .SYNOPSIS
 * extras.css - maths, diagrams, the inline contents, the zoom overlay and
 * the button back to the top.
 *
 * .USAGE
 *   Loaded in this order by MarkstrataWebPart.ts, because later rules
 *   override earlier ones:
 *
 *     base, typography, code, syntax, callouts, tables-lists, extras,
 *     chrome, the three themes, modifiers, print
 *
 * .NOTES
 * Since:     0.0.6
 * Ships in:  the web part bundle
 * Requires:  nothing else in this project
 */

.strata-math-block {
  margin: 0 0 var(--strata-block-gap);
  padding: 8px 0;
  overflow-x: auto;
  text-align: center;
}

.strata-math-error,
.strata-math-error-inline {
  padding: 2px 6px;
  border-radius: var(--strata-radius-sm);
  background-color: rgba(var(--strata-color-red), 0.12);
  color: rgb(var(--strata-color-red));
  font-family: var(--strata-font-mono);
  font-size: 0.9em;
}

.strata-mermaid {
  position: relative;
  display: flex;
  /* Centred by an auto margin on the diagram rather than by justify-content:
     a centred flex item that overflows its container cannot be scrolled back
     to, so the left edge of a wide chart is lost. An auto margin centres what
     fits and collapses to nothing when it does not. */
  justify-content: flex-start;
  margin: 0 0 var(--strata-block-gap);
  padding: 16px;
  border: 1px solid var(--strata-border);
  border-radius: var(--strata-radius-md);
  background-color: var(--strata-mermaid-bg, var(--strata-bg-elevated));
  overflow-x: auto;
}

.strata-mermaid svg {
  max-width: 100%;
  height: auto;
  margin-inline: auto;
}

/* Scrolling a wide diagram means letting it keep its width: max-width would
   scale it back down, which is the thing the setting is there to avoid. Only
   the scroll mode wants this; fitting lays the diagram out to the column, and
   scaling is mermaid shrinking it on purpose. See utils/mermaidConfig.ts. */
.strata-mermaid[data-strata-diagram='scroll'] svg[aria-roledescription='gantt'] {
  max-width: none;
  flex: none;
}

/*
 * The copy button sits over the diagram rather than in a header of its own,
 * because a diagram has no header to put it in. It stays faint until the
 * diagram is hovered, so it does not compete with the drawing, and is always
 * visible to a keyboard once it has focus.
 */
.strata-diagram-tools {
  position: absolute;
  top: 8px;
  right: 8px;
  z-index: 1;
  display: flex;
  gap: 6px;
  opacity: 0;
  transition: opacity 0.12s ease-in-out;
}

.strata-mermaid:hover .strata-diagram-tools,
.strata-diagram-tools:focus-within {
  opacity: 1;
}

/* Kept apart from the rule above on purpose: a browser that does not know
   :has() throws out the whole rule it appears in, and the hover that reveals
   these buttons at all would go with it. */
.strata-diagram-tools:has(.strata-code-btn[data-state]) {
  opacity: 1;
}

/* Touch has no hover, so the buttons are simply there. */
@media (hover: none) {
  .strata-diagram-tools { opacity: 1; }
}

.strata-mermaid pre.mermaid {
  margin: 0;
  font-family: var(--strata-font-mono);
  font-size: var(--strata-code-font-size);
  color: var(--strata-text-muted);
  white-space: pre-wrap;
}

.strata-mermaid-error {
  border-color: rgb(var(--strata-color-red));
  background-color: rgba(var(--strata-color-red), 0.08);
}

.strata-mermaid-error pre {
  color: rgb(var(--strata-color-red));
}

/* Details / summary written directly in markdown (callouts style themselves). */
.strata-content details:not(.strata-callout) {
  margin: 0 0 var(--strata-block-gap);
  padding: 8px 12px;
  border: 1px solid var(--strata-border);
  border-radius: var(--strata-radius-md);
  background-color: var(--strata-bg-elevated);
}

.strata-content details:not(.strata-callout) > summary {
  cursor: pointer;
  font-weight: 600;
}

/* Keep KaTeX from inheriting the body line-height and clipping. */
.strata-content .katex {
  font-size: 1.05em;
  line-height: 1.2;
}

.strata-content .katex-display {
  margin: 0;
  padding: 4px 0;
}

/* Mermaid fallback: show the diagram source when rendering fails. */
.strata-mermaid-error {
  flex-direction: column;
  align-items: stretch;
  gap: 8px;
}

.strata-mermaid-message {
  color: rgb(var(--strata-color-red));
  font-size: 0.875em;
}

/*
 * An image that is a paragraph of its own, with its markdown title shown as a
 * caption rather than left as a tooltip a touch screen never sees and a
 * printed page loses.
 */
.strata-figure {
  margin: var(--strata-block-gap) 0;
  padding: 0;
}

/*
 * Where a picture sits in the column.
 *
 * Left by default, which is how markdown has always rendered a block image and
 * what GitHub and Obsidian both do. It is a setting rather than a fixed choice
 * because a page of screenshots usually reads better centred, and because
 * captioned images used to centre themselves while plain ones did not: the
 * figure rule set text-align and nothing else did, so whether a picture was
 * centred depended on whether its author had given it a title.
 *
 * A document can override the page for one picture by giving the image a
 * class, ![alt](x.png){.center}, which the attributes plugin already parses.
 */
.strata-root[data-strata-image-align='center'] .strata-image-block {
  text-align: center;
}

.strata-root[data-strata-image-align='right'] .strata-image-block {
  text-align: right;
}

.strata-image-block[data-strata-align='left'] { text-align: left; }
.strata-image-block[data-strata-align='center'] { text-align: center; }
.strata-image-block[data-strata-align='right'] { text-align: right; }

.strata-figure figcaption {
  margin-top: 8px;
  color: var(--strata-text-faint);
  font-size: 0.875em;
  line-height: 1.5;
}

/*
 * Screenshots are most of what documentation carries, and a SharePoint column
 * is narrow, so an image is usually shown well below its own size. Clicking it
 * opens it at full size.
 */
.strata-zoomable {
  cursor: zoom-in;
}

.strata-zoomable:focus-visible {
  outline: 2px solid var(--strata-link);
  outline-offset: 2px;
}

/*
 * Fixed rather than absolute: the overlay covers the window, not the web part,
 * which is a section of a page that may itself be scrolled.
 *
 * The top of that window is not the overlay's to use. The overlay is built
 * inside the web part's root so that what it shows is painted from the
 * reader's own theme, and a child of the web part cannot be raised above the
 * bars a SharePoint page keeps stuck across the top of it: those are in a
 * stacking context this one is not in, and no z-index here reaches them. They
 * covered the close button and the filename of an expanded code block, which
 * left the overlay openable and then neither readable nor dismissable except
 * with Escape.
 *
 * So the overlay still covers the window and lays out below that strip. The
 * close button and the panel are both measured from the same figure, because
 * padding does not move an absolutely positioned button: its offsets are
 * against the padding box, so padding alone would have pushed the content
 * clear and left the button exactly where it was.
 */
.strata-zoom {
  /* What a SharePoint page keeps for its suite bar and command bar. */
  --strata-zoom-chrome: 75px;
  --strata-zoom-close-size: 36px;
  position: fixed;
  inset: 0;
  z-index: 1000;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: calc(var(--strata-zoom-chrome) + var(--strata-zoom-close-size) + 16px)
    32px 32px;
  background-color: rgba(0, 0, 0, 0.82);
  cursor: zoom-out;
}

/*
 * A picture in the overlay: a window over it rather than the picture alone.
 *
 * The panel fills the room the overlay leaves, so a picture zoomed past the
 * window has somewhere to be panned to, and clips what hangs over the edge.
 * It is a dismiss target itself, which the overlay reads from the class rather
 * than from containment: with the panel filling the overlay there would
 * otherwise be nothing outside it left to click.
 */
.strata-zoom-picture {
  position: relative;
  display: flex;
  align-items: center;
  justify-content: center;
  width: 100%;
  height: 100%;
  overflow: hidden;
  /* The dark area around the picture still puts it away. */
  cursor: zoom-out;
  /* A pinch is ours to read; without this the browser zooms the page under
     the overlay instead. */
  touch-action: none;
}

.strata-zoom img {
  max-width: 100%;
  max-height: 100%;
  width: auto;
  /* The picture is the one thing in here that is not a dismiss target. */
  cursor: default;
  border-radius: var(--strata-radius-sm);
  box-shadow: 0 8px 40px rgba(0, 0, 0, 0.5);
}

/*
 * Scaled from the middle, so the maths that keeps the point under the pointer
 * still under it has one origin to reason about rather than one per picture
 * shape. No transition: a zoom that animates lags a wheel that is still
 * turning, and a drag has to track the finger exactly or it feels broken.
 */
.strata-zoom-picture img {
  transform-origin: center center;
  will-change: transform;
  /* The picture is what a drag grabs, so it is not the browser's to drag off
     as an image. */
  user-select: none;
  -webkit-user-drag: none;
}

.strata-zoom-picture[data-strata-zoomed='fit'] img {
  cursor: zoom-in;
}

.strata-zoom-picture[data-strata-zoomed='in'] img {
  cursor: grab;
}

.strata-zoom-picture[data-strata-zoomed='in'] img:active {
  cursor: grabbing;
}

/*
 * The buttons, bottom left, away from the close button in the opposite corner
 * so that reaching for one is never nearly the other.
 */
.strata-zoom-controls {
  position: absolute;
  left: 16px;
  bottom: 16px;
  display: inline-flex;
  border: 1px solid rgba(255, 255, 255, 0.35);
  border-radius: var(--strata-radius-sm);
  background-color: rgba(0, 0, 0, 0.5);
  overflow: hidden;
}

.strata-zoom-control {
  width: 36px;
  height: 36px;
  display: flex;
  align-items: center;
  justify-content: center;
  border: 0;
  background-color: transparent;
  color: rgba(255, 255, 255, 0.92);
  font-size: 16px;
  line-height: 1;
  cursor: pointer;
}

.strata-zoom-control + .strata-zoom-control {
  border-left: 1px solid rgba(255, 255, 255, 0.35);
}

.strata-zoom-control:hover {
  background-color: rgba(0, 0, 0, 0.75);
}

.strata-zoom-control:focus-visible {
  outline: 2px solid rgba(255, 255, 255, 0.9);
  outline-offset: -2px;
}

/*
 * A diagram in the overlay: its own ground under it, because the drawing has
 * none of its own and dark ink on the overlay's black is an empty rectangle.
 * The SVG keeps its viewBox and is given no size, so it grows to the panel and
 * stops at its own aspect ratio.
 */
.strata-zoom-diagram {
  display: flex;
  width: 100%;
  max-width: 100%;
  max-height: 100%;
  padding: 20px;
  border-radius: var(--strata-radius-md);
  background-color: var(--strata-mermaid-bg, var(--strata-bg-elevated));
  box-shadow: 0 8px 40px rgba(0, 0, 0, 0.5);
  cursor: default;
}

.strata-zoom-diagram svg {
  display: block;
  width: 100%;
  height: 100%;
}

/*
 * A code block in the overlay: the same block, with nothing capping it.
 *
 * It scrolls inside the panel rather than the panel growing past the window,
 * because a hundred line file opened full size is still a hundred lines. Its
 * own ground under it for the same reason the diagram has one: the overlay is
 * black and a light-theme block would otherwise be light text on it.
 */
.strata-zoom-code {
  width: 100%;
  max-width: 100%;
  max-height: 100%;
  overflow: auto;
  border-radius: var(--strata-radius-md);
  background-color: var(--strata-code-bg);
  box-shadow: 0 8px 40px rgba(0, 0, 0, 0.5);
  cursor: default;
}

/* The clone brought its own margin and rounding, which the panel now provides;
   two of each reads as a box inside a box. */
.strata-zoom-code .strata-code {
  margin: 0;
  border: 0;
  border-radius: 0;
}

/* Uncapped, whatever the block on the page was set to. */
.strata-zoom-code .strata-code-pre {
  max-height: none;
}

/* Under the chrome rather than behind it, in the room the padding above left
   for it, with the panel starting 8px below. */
.strata-zoom-close {
  position: absolute;
  top: calc(var(--strata-zoom-chrome) + 8px);
  right: 16px;
  width: var(--strata-zoom-close-size);
  height: var(--strata-zoom-close-size);
  display: flex;
  align-items: center;
  justify-content: center;
  border: 1px solid rgba(255, 255, 255, 0.35);
  border-radius: 50%;
  background-color: rgba(0, 0, 0, 0.5);
  color: rgba(255, 255, 255, 0.92);
  font-size: 15px;
  line-height: 1;
  cursor: pointer;
}

.strata-zoom-close:hover {
  background-color: rgba(0, 0, 0, 0.75);
}

.strata-zoom-close:focus-visible {
  outline: 2px solid rgba(255, 255, 255, 0.9);
  outline-offset: 2px;
}

/* Printing wants the document, not an overlay that happened to be open. */
@media print {
  .strata-zoom { display: none; }
}

/*
 * A wiki link, and one whose page was not found in the library.
 *
 * Marked rather than disabled: the link still goes where it said it would, and
 * an author following it is how a page gets created. Obsidian does the same.
 */
/* Scoped to the content, or `.strata-content a` wins on specificity and the
   link paints as an ordinary one while carrying the class that says it is not. */
.strata-content a.strata-wiki-link--missing {
  color: rgb(var(--strata-color-red));
  text-decoration-style: dotted;
  text-underline-offset: 2px;
}

.strata-content a.strata-wiki-link--missing::after {
  content: '?';
  margin-left: 1px;
  font-size: 0.85em;
  vertical-align: super;
  opacity: 0.8;
}

/*
 * A tag, `#recipe` or `#work/urgent`, which is how a note written in Obsidian
 * says what it is about. Shown as the pill it is there, in the accent colour
 * the links around it already use, and deliberately not as a link: this web
 * part cannot see the other documents in a library, so a tag that looked
 * clickable would be a promise it cannot keep.
 */
.strata-content .strata-tag {
  display: inline;
  padding: 0.1em 0.45em;
  border-radius: var(--strata-radius-lg);
  background-color: rgba(var(--strata-color-blue), 0.12);
  color: rgb(var(--strata-color-blue));
  font-size: 0.9em;
  white-space: nowrap;
}

/*
 * An embed of something that is not a picture: another document, a PDF, a
 * sound file. None of those can be put on the page while a string is being
 * rendered, since that would mean fetching them, so the document says what it
 * was asked to embed and links to it. The mark is what keeps that honest: the
 * reader can see that something was meant to sit here, rather than reading a
 * link that looks like any other.
 */
.strata-content a.strata-wiki-embed::before {
  content: '\29C9';
  margin-right: 0.3em;
  font-size: 0.9em;
  opacity: 0.75;
}

/*
 * Said to a screen reader and to nobody else. Not display:none, which would
 * take it out of the accessibility tree along with everything else.
 */
.strata-missing-note {
  position: absolute;
  width: 1px;
  height: 1px;
  margin: -1px;
  padding: 0;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
  border: 0;
}

/* ---------------------------------------------------------- office embeds */

/*
 * A Word, Excel or PowerPoint file named by an `![[embed]]`, shown as a card
 * rather than as a link to a download.
 *
 * Built so the card still reads correctly with no preview in it, because a
 * tenant can refuse the frame and there is no reliable way to find that out
 * from here. The name and the way into the editor are the card; the preview is
 * what fills the space under them when it can.
 */
.strata-office {
  margin: 1.2em 0;
  border: 1px solid var(--strata-border);
  border-radius: var(--strata-radius-sm);
  background-color: var(--strata-bg-elevated);
  overflow: hidden;
}

.strata-office-head {
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 8px 12px;
  border-bottom: 1px solid var(--strata-border);
  font-size: 0.875em;
}

.strata-office-name {
  font-weight: 600;
  color: var(--strata-text);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

/* Pushed to the end rather than floated, so a long file name shortens itself
   instead of pushing the way out of the card off the edge. */
.strata-office-open {
  margin-left: auto;
  flex: none;
  color: var(--strata-link);
}

.strata-office-preview {
  /* Roughly a page of A4 at the width a document column tends to be. Tall
     enough to read the top of the document, short enough that a card does not
     take the whole screen when several are on one page. */
  height: 460px;
}

/* No id came back, so there is no frame. The space goes with it: an empty box
   reads as a document with nothing in it, which is a different and wrong
   thing to say. */
.strata-office-preview[data-strata-no-preview='true'] {
  display: none;
}

.strata-office-frame {
  display: block;
  width: 100%;
  height: 100%;
  border: 0;
}

/* On paper a frame prints as an empty rectangle, so only the card's own line
   about which document it is survives. */
@media print {
  .strata-root .strata-office-preview { display: none; }
}
