/*
  File tool — Notion-flavoured attachment block. Calm, neutral, generous: a
  rounded card with a grey file-type tile, medium-weight filename, quiet
  size meta, and a circular download affordance with a neutral hover. Only
  the upload progress fill carries the blue accent. The empty/upload state is
  the shared media uploader (see media-empty.css +
  components/utils/media-empty-state.ts). Scoped to [data-blok-tool="file"];
  all colour + radius via palette tokens.
*/

[data-blok-tool="file"] {
  --file-tile-size: 40px;
  --file-action-size: 32px;
  margin: var(--blok-space-2-5) 0;
}

/* ─── Rendered: download card ─────────────────────────────────────── */

/*
  The card body and the download affordance are siblings inside the wrapper:
  the body (a button when previewable, else a download anchor) carries the
  card chrome and stretches; the download link sits on the trailing edge.
*/
[data-blok-tool="file"] .blok-file-card-wrapper {
  position: relative;
  display: flex;
  align-items: center;
}

[data-blok-tool="file"] .blok-file-card {
  flex: 1 1 auto;
  display: flex;
  align-items: center;
  gap: var(--blok-space-3-5);
  width: 100%;
  padding: var(--blok-space-3) var(--blok-space-3-5);
  padding-inline-end: calc(var(--file-action-size) + var(--blok-space-3-5) + var(--blok-space-3));
  border: 1px solid var(--blok-border-subtle);
  border-radius: var(--blok-radius-xl);
  background: var(--blok-bg-primary);
  box-shadow: var(--blok-image-shadow-resting);
  font: inherit;
  text-align: start;
  color: inherit;
  text-decoration: none;
  cursor: pointer;
  appearance: none;
  transition:
    border-color var(--blok-duration-base) var(--blok-ease-standard),
    background-color var(--blok-duration-base) var(--blok-ease-standard);
}
[data-blok-tool="file"] .blok-file-card:hover {
  border-color: var(--blok-border-strong);
  background: var(--blok-bg-hover);
}

/* neutral file-type tile — Notion reads the document glyph in greys */
[data-blok-tool="file"] .blok-file-icon {
  flex: 0 0 auto;
  display: flex;
  align-items: center;
  justify-content: center;
  width: var(--file-tile-size);
  height: var(--file-tile-size);
  border-radius: var(--blok-radius-md);
  background: var(--blok-bg-secondary);
  color: var(--blok-text-secondary);
}
[data-blok-tool="file"] .blok-file-icon svg {
  width: 20px;
  height: 20px;
}

/* Subtle per-type tint: the glyph carries the category hue, the tile shows a
 * faint wash of it. color-mix against the neutral tile keeps both light and
 * dark themes legible. text/generic keep the neutral default above. */
[data-blok-tool="file"] .blok-file-icon[data-file-category="pdf"] {
  color: var(--blok-file-icon-pdf);
  background: color-mix(in srgb, var(--blok-file-icon-pdf) 12%, var(--blok-bg-secondary));
}
[data-blok-tool="file"] .blok-file-icon[data-file-category="document"] {
  color: var(--blok-file-icon-document);
  background: color-mix(in srgb, var(--blok-file-icon-document) 12%, var(--blok-bg-secondary));
}
[data-blok-tool="file"] .blok-file-icon[data-file-category="spreadsheet"] {
  color: var(--blok-file-icon-spreadsheet);
  background: color-mix(in srgb, var(--blok-file-icon-spreadsheet) 12%, var(--blok-bg-secondary));
}
[data-blok-tool="file"] .blok-file-icon[data-file-category="presentation"] {
  color: var(--blok-file-icon-presentation);
  background: color-mix(in srgb, var(--blok-file-icon-presentation) 12%, var(--blok-bg-secondary));
}
[data-blok-tool="file"] .blok-file-icon[data-file-category="archive"] {
  color: var(--blok-file-icon-archive);
  background: color-mix(in srgb, var(--blok-file-icon-archive) 12%, var(--blok-bg-secondary));
}
[data-blok-tool="file"] .blok-file-icon[data-file-category="audio"] {
  color: var(--blok-file-icon-audio);
  background: color-mix(in srgb, var(--blok-file-icon-audio) 12%, var(--blok-bg-secondary));
}
[data-blok-tool="file"] .blok-file-icon[data-file-category="video"] {
  color: var(--blok-file-icon-video);
  background: color-mix(in srgb, var(--blok-file-icon-video) 12%, var(--blok-bg-secondary));
}
[data-blok-tool="file"] .blok-file-icon[data-file-category="image"] {
  color: var(--blok-file-icon-image);
  background: color-mix(in srgb, var(--blok-file-icon-image) 12%, var(--blok-bg-secondary));
}
[data-blok-tool="file"] .blok-file-icon[data-file-category="code"] {
  color: var(--blok-file-icon-code);
  background: color-mix(in srgb, var(--blok-file-icon-code) 12%, var(--blok-bg-secondary));
}

[data-blok-tool="file"] .blok-file-meta {
  display: flex;
  flex-direction: column;
  flex: 1 1 auto;
  min-width: 0;
  gap: var(--blok-space-0-5);
}
[data-blok-tool="file"] .blok-file-name {
  font-size: var(--blok-font-size-body);
  font-weight: var(--blok-font-weight-medium);
  line-height: var(--blok-line-height-option);
  color: var(--blok-text-primary);
  /* Shrink to the title text instead of stretching across the flex column, so
   * the (editable) field is exactly as wide as the filename, capped at the row. */
  align-self: flex-start;
  max-width: 100%;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
/* Editable filename: text caret on hover so it reads as an edit target. */
[data-blok-tool="file"] .blok-file-name[contenteditable="true"]:hover {
  cursor: text;
}
[data-blok-tool="file"] .blok-file-size {
  font-size: var(--blok-font-size-ui-compact);
  line-height: var(--blok-line-height-tight);
  color: var(--blok-text-secondary);
}

/* circular download button — pinned to the trailing edge, neutral hover */
[data-blok-tool="file"] .blok-file-download {
  position: absolute;
  inset-inline-end: var(--blok-space-3);
  top: 50%;
  transform: translateY(-50%);
  flex: 0 0 auto;
  display: flex;
  align-items: center;
  justify-content: center;
  width: var(--file-action-size);
  height: var(--file-action-size);
  border-radius: var(--blok-radius-pill);
  color: var(--blok-text-secondary);
  text-decoration: none;
  /* translateY(-50%) keeps it vertically centred; scale composes onto it */
  transition:
    color var(--blok-duration-base) var(--blok-ease-standard),
    background-color var(--blok-duration-base) var(--blok-ease-standard),
    transform var(--blok-duration-standard) var(--blok-ease-spring);
}
[data-blok-tool="file"] .blok-file-download svg {
  width: 18px;
  height: 18px;
  transition: transform var(--blok-duration-standard) var(--blok-ease-spring);
}
[data-blok-tool="file"] .blok-file-download:hover {
  color: var(--blok-text-primary);
  background: var(--blok-bg-hover);
  transform: translateY(-50%) scale(1.04);
}
/* arrow dips down on hover — a small "download" cue */
[data-blok-tool="file"] .blok-file-download:hover svg {
  transform: translateY(1px);
}
[data-blok-tool="file"] .blok-file-download:active {
  transform: translateY(-50%) scale(0.97);
  transition-duration: var(--blok-duration-fast);
}

/* Honour reduced-motion: keep the colour cues, drop the movement. */
@media (prefers-reduced-motion: reduce) {
  [data-blok-tool="file"] .blok-file-download:hover,
  [data-blok-tool="file"] .blok-file-download:active {
    transform: translateY(-50%);
  }
  [data-blok-tool="file"] .blok-file-download:hover svg {
    transform: none;
  }
}

/* ─── Caption ─────────────────────────────────────────────────────── */

[data-blok-tool="file"] .blok-file-caption-row {
  margin-top: var(--blok-space-2);
  padding-inline: var(--blok-space-1);
}
[data-blok-tool="file"] .blok-file-caption {
  font-size: var(--blok-file-caption-font-size, var(--blok-font-size-ui-label));
  line-height: var(--blok-line-height-body);
  color: var(--blok-text-secondary);
  outline: none;
}
[data-blok-tool="file"] .blok-file-caption:empty::before {
  content: attr(data-placeholder);
  color: var(--blok-text-tertiary);
}


/* ─── Uploading ───────────────────────────────────────────────────── */

[data-blok-tool="file"] .blok-file-uploading {
  display: flex;
  align-items: center;
  gap: var(--blok-space-3);
  padding: var(--blok-space-3) var(--blok-space-3-5);
  border: 1px solid var(--blok-border-subtle);
  border-radius: var(--blok-radius-xl);
  background: var(--blok-bg-primary);
  box-shadow: var(--blok-image-shadow-resting);
}
[data-blok-tool="file"] .blok-file-uploading-label {
  flex: 0 1 auto;
  min-width: 0;
  font-size: var(--blok-font-size-ui-label);
  color: var(--blok-text-secondary);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
[data-blok-tool="file"] .blok-file-bar {
  flex: 1 1 auto;
  height: 6px;
  border-radius: var(--blok-radius-pill);
  background: var(--blok-bg-hover);
  overflow: hidden;
}
[data-blok-tool="file"] .blok-file-bar-fill {
  position: relative;
  height: 100%;
  border-radius: var(--blok-radius-pill);
  background: var(--blok-color-accent);
  overflow: hidden;
  transition: width var(--blok-duration-standard) var(--blok-ease-standard);
}
/* A highlight band sweeps across the filled portion on a loop, so the bar
   reads as "still working" even when the width sits at a value between
   progress updates. */
[data-blok-tool="file"] .blok-file-bar-fill::after {
  content: "";
  position: absolute;
  inset: 0;
  background: linear-gradient(
    90deg,
    transparent 0%,
    var(--blok-overlay-shimmer) 50%,
    transparent 100%
  );
  transform: translateX(-100%);
  animation: blok-file-bar-sheen 1.15s var(--blok-ease-standard) infinite;
}
@keyframes blok-file-bar-sheen {
  from { transform: translateX(-100%); }
  to   { transform: translateX(100%); }
}
@media (prefers-reduced-motion: reduce) {
  [data-blok-tool="file"] .blok-file-bar-fill::after { animation: none; }
}
[data-blok-tool="file"] .blok-file-cancel {
  flex: 0 0 auto;
  padding: var(--blok-space-1-5) var(--blok-space-3);
  border: 0;
  border-radius: var(--blok-radius-pill);
  background: transparent;
  font-size: var(--blok-font-size-ui-label);
  font-weight: var(--blok-font-weight-medium);
  color: var(--blok-text-secondary);
  cursor: pointer;
  transition: background-color var(--blok-duration-base) var(--blok-ease-standard);
}
[data-blok-tool="file"] .blok-file-cancel:hover {
  background: var(--blok-bg-hover);
  color: var(--blok-text-primary);
}

/* ─── Error ───────────────────────────────────────────────────────── */

[data-blok-tool="file"] .blok-file-error-state {
  display: flex;
  align-items: center;
  gap: var(--blok-space-3);
  padding: var(--blok-space-3) var(--blok-space-3-5);
  border: 1px solid var(--blok-border-subtle);
  border-radius: var(--blok-radius-xl);
  background: var(--blok-item-destructive-hover-bg);
  font-size: var(--blok-font-size-ui-label);
  color: var(--blok-item-destructive-text);
}
[data-blok-tool="file"] .blok-file-error-state span {
  flex: 1 1 auto;
  min-width: 0;
}
[data-blok-tool="file"] .blok-file-retry {
  flex: 0 0 auto;
  padding: var(--blok-space-1-5) var(--blok-space-3);
  border: 0;
  border-radius: var(--blok-radius-pill);
  background: var(--blok-bg-primary);
  font-size: var(--blok-font-size-ui-label);
  font-weight: var(--blok-font-weight-semibold);
  color: var(--blok-text-primary);
  cursor: pointer;
}

/* ─── Preview modal ───────────────────────────────────────────────────
   Mounted on document.body (outside the tool scope), so these selectors
   are intentionally global rather than nested under [data-blok-tool]. */

.blok-file-preview-backdrop {
  position: fixed;
  inset: 0;
  z-index: var(--blok-z-drawer);
  /* border-box so 100vh sizing keeps the padding inside the viewport — with
     content-box the padding adds to 100vh, overflowing and offsetting the
     vertically-centred dialog. */
  box-sizing: border-box;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: var(--blok-space-6);
  background: var(--blok-overlay-dark);
  /* Soft frost behind the dialog so the page recedes; the opacity keyframe
     fades the scrim and the blur in together. */
  backdrop-filter: blur(6px);
  -webkit-backdrop-filter: blur(6px);
  animation: blok-file-preview-backdrop-in 200ms ease;
}
/* Exit: fade the scrim out, then JS detaches on animationend. */
.blok-file-preview-backdrop[data-blok-closing],
.blok-file-preview-backdrop[data-blok-closing][data-blok-top-layer][popover] {
  animation: blok-file-preview-backdrop-out 180ms ease forwards;
  pointer-events: none;
}
@keyframes blok-file-preview-backdrop-in {
  from { opacity: 0; }
  to { opacity: 1; }
}
@keyframes blok-file-preview-backdrop-out {
  from { opacity: 1; }
  to { opacity: 0; }
}
/*
  Re-assert viewport coverage + padding when promoted to the Top Layer. The
  `[data-blok-top-layer][popover]` reset in main.css (specificity 0,2,0) sets
  `inset: auto; padding: 0` which would otherwise outrank the class rule above
  (0,1,0) and collapse the backdrop to its content.
*/
.blok-file-preview-backdrop[data-blok-top-layer][popover] {
  inset: 0;
  width: 100vw;
  height: 100vh;
  max-width: 100vw;
  max-height: 100vh;
  padding: var(--blok-space-6);
}

.blok-file-preview {
  display: flex;
  flex-direction: column;
  width: min(960px, 100%);
  height: min(90vh, 100%);
  overflow: hidden;
  border-radius: var(--blok-radius-xl);
  background: var(--blok-bg-primary);
  box-shadow: var(--blok-image-shadow-resting);
  transform-origin: center bottom;
  /* Springy ease (gentle overshoot) so the dialog "settles" in rather than
     stopping flat — reads more alive than a plain decel curve. */
  animation: blok-file-preview-dialog-in 360ms cubic-bezier(0.34, 1.56, 0.64, 1);
}
.blok-file-preview-backdrop[data-blok-closing] .blok-file-preview {
  animation: blok-file-preview-dialog-out 180ms cubic-bezier(0.4, 0, 1, 1) forwards;
}
@keyframes blok-file-preview-dialog-in {
  0% { opacity: 0; transform: translateY(20px) scale(0.92); }
  55% { opacity: 1; }
  100% { opacity: 1; transform: none; }
}
@keyframes blok-file-preview-dialog-out {
  from { opacity: 1; transform: none; }
  to { opacity: 0; transform: translateY(6px) scale(0.985); }
}
@media (prefers-reduced-motion: reduce) {
  .blok-file-preview-backdrop,
  .blok-file-preview-backdrop[data-blok-top-layer][popover],
  .blok-file-preview-backdrop[data-blok-closing],
  .blok-file-preview,
  .blok-file-preview-backdrop[data-blok-closing] .blok-file-preview {
    animation: none;
  }
}

/* Title · Rendered/Raw toggle · close — a 3-column grid. The flanking 1fr
   tracks keep the centre slot (the toggle, present only for markdown)
   optically centred; the title truncates and the close button sits flush
   right. Kinds without a toggle just leave the centre slot empty. */
.blok-file-preview-header {
  display: grid;
  grid-template-columns: 1fr auto 1fr;
  align-items: center;
  gap: var(--blok-space-3);
  padding: var(--blok-space-2) var(--blok-space-4);
  border-bottom: 1px solid var(--blok-border-subtle);
}

/* Icon + filename read as one "document chip": the glyph anchors the title to
   the left edge and balances the close button's icon on the right, so the bar's
   three zones share one visual weight. Only the text track truncates. */
.blok-file-preview-title {
  grid-column: 1;
  grid-row: 1;
  min-width: 0;
  display: inline-flex;
  align-items: center;
  gap: var(--blok-space-2);
}

.blok-file-preview-title-icon {
  flex: 0 0 auto;
  display: inline-flex;
  color: var(--blok-text-secondary);
}
.blok-file-preview-title-icon svg {
  width: 18px;
  height: 18px;
}

.blok-file-preview-title-text {
  min-width: 0;
  font-size: var(--blok-font-size-body);
  font-weight: var(--blok-font-weight-medium);
  color: var(--blok-text-primary);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.blok-file-preview-actions {
  grid-column: 3;
  grid-row: 1;
  justify-self: end;
  display: inline-flex;
  align-items: center;
  gap: var(--blok-space-1);
}

.blok-file-preview-open,
.blok-file-preview-close {
  display: flex;
  align-items: center;
  justify-content: center;
  width: var(--file-action-size, 32px);
  height: var(--file-action-size, 32px);
  border: 0;
  border-radius: var(--blok-radius-pill);
  background: transparent;
  color: var(--blok-text-secondary);
  font: inherit;
  text-decoration: none;
  cursor: pointer;
  appearance: none;
  transition:
    background-color var(--blok-duration-base) var(--blok-ease-standard),
    color var(--blok-duration-base) var(--blok-ease-standard);
}
.blok-file-preview-open svg,
.blok-file-preview-close svg {
  width: 18px;
  height: 18px;
}
.blok-file-preview-open:hover,
.blok-file-preview-close:hover {
  background: var(--blok-bg-hover);
  color: var(--blok-text-primary);
}

.blok-file-preview-body {
  position: relative;
  flex: 1 1 auto;
  min-height: 0;
  display: flex;
  flex-direction: column;
  /* Matches the view surface (bg-primary). The markdown views slide in on a
     small translateX; if the body were a different tone, that offset would
     flash a strip of the wrong colour along the edge mid-slide. The views
     always fully cover the body, so this is invisible except during that
     animation. */
  background: var(--blok-bg-primary);
}

/* Scroll haze: gradient strips pinned to the body edges, faded in (by JS) only
   while the active view has hidden content past that edge. `--blok-haze-color`
   is set inline to the scrolling surface's own background so the haze melts into
   paper, desk, or editor alike; the fallback covers the first paint. */
.blok-file-preview-haze {
  position: absolute;
  z-index: 2;
  pointer-events: none;
  opacity: 0;
  transition: opacity 150ms ease;
}

.blok-file-preview-haze[data-blok-haze-visible] {
  opacity: 1;
}

@media (prefers-reduced-motion: reduce) {
  .blok-file-preview-haze {
    transition: none;
  }
}

.blok-file-preview-haze[data-blok-haze='top'],
.blok-file-preview-haze[data-blok-haze='bottom'] {
  left: 0;
  right: 0;
  height: var(--blok-space-6);
}

.blok-file-preview-haze[data-blok-haze='left'],
.blok-file-preview-haze[data-blok-haze='right'] {
  top: 0;
  bottom: 0;
  width: var(--blok-space-6);
}

.blok-file-preview-haze[data-blok-haze='top'] {
  top: 0;
  background: linear-gradient(to bottom, var(--blok-haze-color, var(--blok-bg-primary)), transparent);
}

.blok-file-preview-haze[data-blok-haze='bottom'] {
  bottom: 0;
  background: linear-gradient(to top, var(--blok-haze-color, var(--blok-bg-primary)), transparent);
}

.blok-file-preview-haze[data-blok-haze='left'] {
  left: 0;
  background: linear-gradient(to right, var(--blok-haze-color, var(--blok-bg-primary)), transparent);
}

.blok-file-preview-haze[data-blok-haze='right'] {
  right: 0;
  background: linear-gradient(to left, var(--blok-haze-color, var(--blok-bg-primary)), transparent);
}

.blok-file-preview-frame {
  flex: 1 1 auto;
  min-height: 0;
  width: 100%;
  border: 0;
}

.blok-file-preview-loading {
  display: flex;
  align-items: center;
  justify-content: center;
  flex: 1 1 auto;
  min-height: 0;
  color: var(--blok-text-secondary);
  font-size: 0.875rem;
}

.blok-file-preview-pre,
.blok-file-preview-md {
  flex: 1 1 auto;
  min-height: 0;
  margin: 0;
  overflow: auto;
}

/* Preview scroll containers reserve the scrollbar's layout space; the styled
   ::-webkit-scrollbar keeps it classic (space-taking) instead of an overlay
   scrollbar painting over the content. */
.blok-file-preview-pre,
.blok-file-preview-md,
.blok-file-preview-office {
  scrollbar-gutter: stable both-edges;
}
.blok-file-preview-pre::-webkit-scrollbar,
.blok-file-preview-md::-webkit-scrollbar,
.blok-file-preview-office::-webkit-scrollbar {
  width: 10px;
  height: 10px;
}
.blok-file-preview-pre::-webkit-scrollbar-track,
.blok-file-preview-md::-webkit-scrollbar-track,
.blok-file-preview-office::-webkit-scrollbar-track {
  background: transparent;
}
/* Thumb hidden at rest (system auto-hide behavior), revealed on hover. */
.blok-file-preview-pre::-webkit-scrollbar-thumb,
.blok-file-preview-md::-webkit-scrollbar-thumb,
.blok-file-preview-office::-webkit-scrollbar-thumb {
  background: transparent;
  border-radius: var(--blok-space-1);
}
.blok-file-preview-pre:hover::-webkit-scrollbar-thumb,
.blok-file-preview-md:hover::-webkit-scrollbar-thumb,
.blok-file-preview-office:hover::-webkit-scrollbar-thumb {
  background: color-mix(in srgb, currentColor 15%, transparent);
}
.blok-file-preview-pre::-webkit-scrollbar-thumb:hover,
.blok-file-preview-md::-webkit-scrollbar-thumb:hover,
.blok-file-preview-office::-webkit-scrollbar-thumb:hover {
  background: color-mix(in srgb, currentColor 25%, transparent);
}

/* Source pane — shared by the markdown raw view, code-file previews, and
   plain-text previews. Reads like a code editor: comfortable monospace,
   generous gutters, small tab stops. Code/text keep `pre` so columns stay
   intact and overflow scrolls horizontally. */
.blok-file-preview-pre {
  padding: var(--blok-space-5) var(--blok-space-6);
  font-size: 0.875rem;
  line-height: 1.7;
  tab-size: 2;
  white-space: pre;
  font-family: var(--blok-font-mono, ui-monospace, monospace);
  color: var(--blok-text-primary);
  background: var(--blok-bg-primary);
}

/* Markdown source is prose, not code: soft-wrap it so long lines stop
   clipping off the right edge, and centre it in the same reading column
   as the rendered view so toggling Rendered ⇄ Raw feels continuous. */
.blok-file-preview-pre[data-role="file-preview-md-raw"] {
  white-space: pre-wrap;
  word-break: break-word;
  animation: blok-file-preview-view-in-right 260ms var(--blok-ease-popover) backwards;
}

.blok-file-preview-pre[data-role="file-preview-md-raw"] code {
  display: block;
  max-width: 50rem;
  margin-inline: auto;
}

/* ─── Rendered markdown document ──────────────────────────────────────
   The render view holds arbitrary block HTML (headings, tables, code,
   quotes). It reads like a document: a centred reading column with
   editorial vertical rhythm. Heading sizes scale in `em` off the column
   font-size; spacing routes through tokens, and colours through palette
   vars so the whole thing tracks light/dark automatically.

   Vertical rhythm: block elements share one bottom-margin rule (the
   grouped selector below). Per-element rules add only what's unique to
   them — never another bottom margin — so the rhythm stays a single
   source of truth (and avoids repeated length literals). */
.blok-file-preview-md {
  padding-block: var(--blok-space-6);
  padding-inline: max(var(--blok-space-5), calc((100% - 46rem) / 2));
  font-size: 0.9375rem;
  line-height: 1.7;
  color: var(--blok-text-primary);
  background: var(--blok-bg-primary);
  white-space: normal;
  word-break: break-word;
  animation: blok-file-preview-view-in-left 260ms var(--blok-ease-popover) backwards;
}

/* Crossfade Rendered ⇄ Raw: the outgoing view is display:none'd (which resets
   its animation), so the incoming view replays its slide on every toggle. Each
   view slides in from the side its segment sits on — Rendered (left button)
   from the left, Raw (right button) from the right — so the content tracks the
   pill. Expo-out easing decelerates into place for a soft landing.

   The slide runs at full opacity — no fade. Fading would blink: the outgoing
   view is display:none'd instantly while a fading-in view is briefly
   transparent, so the eye catches an empty frame between them. An opaque slide
   has no transparent state, so the swap reads as one continuous motion. The
   `backwards` fill applies the offset before the first frame so it never pops
   in un-slid. */
@keyframes blok-file-preview-view-in-left {
  from { transform: translate3d(-14px, 0, 0); }
  to { transform: none; }
}
@keyframes blok-file-preview-view-in-right {
  from { transform: translate3d(14px, 0, 0); }
  to { transform: none; }
}
@media (prefers-reduced-motion: reduce) {
  .blok-file-preview-pre[data-role="file-preview-md-raw"],
  .blok-file-preview-md {
    animation: none;
  }
  .blok-file-preview-toggle-indicator {
    transition: none;
  }
}

.blok-file-preview-md p,
.blok-file-preview-md ul,
.blok-file-preview-md ol,
.blok-file-preview-md blockquote,
.blok-file-preview-md pre,
.blok-file-preview-md table,
.blok-file-preview-md .blok-md-alert {
  margin: 0 0 1em;
}

.blok-file-preview-md > :first-child {
  margin-top: 0;
}

.blok-file-preview-md > :last-child {
  margin-bottom: 0;
}

.blok-file-preview-md h1,
.blok-file-preview-md h2,
.blok-file-preview-md h3,
.blok-file-preview-md h4,
.blok-file-preview-md h5,
.blok-file-preview-md h6 {
  margin: 1.6em 0 0.5em;
  font-weight: var(--blok-font-weight-semibold);
  line-height: var(--blok-line-height-tight);
  color: var(--blok-text-primary);
}

.blok-file-preview-md h1 {
  font-size: 1.9em;
  letter-spacing: -0.02em;
}

.blok-file-preview-md h2 {
  font-size: 1.45em;
  letter-spacing: -0.015em;
  padding-bottom: 0.3em;
  border-bottom: 1px solid var(--blok-border-subtle);
}

.blok-file-preview-md h3 {
  font-size: 1.2em;
}

.blok-file-preview-md h4 {
  font-size: 1.05em;
}

.blok-file-preview-md h5,
.blok-file-preview-md h6 {
  font-size: 0.95em;
  color: var(--blok-text-secondary);
}

.blok-file-preview-md a {
  color: var(--blok-color-accent);
  text-decoration: underline;
  text-underline-offset: 2px;
  text-decoration-thickness: 1px;
}

.blok-file-preview-md a:hover {
  text-decoration-thickness: 2px;
}

.blok-file-preview-md ul,
.blok-file-preview-md ol {
  padding-left: 1.5em;
}

.blok-file-preview-md li {
  margin: 0.35em 0;
}

.blok-file-preview-md li > ul,
.blok-file-preview-md li > ol {
  margin-block: 0;
}

.blok-file-preview-md blockquote {
  padding-block: var(--blok-space-1);
  padding-left: var(--blok-space-4);
  border-left: 3px solid var(--blok-border-strong);
  color: var(--blok-text-secondary);
}

.blok-file-preview-md hr {
  margin: 1.75em 0;
  border: 0;
  border-top: 1px solid var(--blok-border-subtle);
}

.blok-file-preview-md code {
  font-family: var(--blok-font-mono, ui-monospace, monospace);
  font-size: 0.875em;
  background: var(--blok-bg-tertiary);
  padding: var(--blok-space-0-5) var(--blok-space-1);
  border-radius: var(--blok-radius-sm);
}

.blok-file-preview-md pre {
  padding: var(--blok-space-3) var(--blok-space-4);
  background: var(--blok-bg-tertiary);
  border: 1px solid var(--blok-border-subtle);
  border-radius: var(--blok-radius-md);
  overflow-x: auto;
  font-size: 0.8125rem;
  line-height: 1.6;
}

.blok-file-preview-md pre code {
  padding: 0;
  background: none;
  font-size: inherit;
}

.blok-file-preview-md img {
  max-width: 100%;
  height: auto;
  border-radius: var(--blok-radius-md);
}

.blok-file-preview-md table {
  width: 100%;
  border-collapse: collapse;
  font-size: 0.9em;
}

.blok-file-preview-md th,
.blok-file-preview-md td {
  padding: var(--blok-space-2) var(--blok-space-3);
  border: 1px solid var(--blok-border-subtle);
  text-align: left;
  vertical-align: top;
}

.blok-file-preview-md th {
  background: var(--blok-bg-tertiary);
  font-weight: var(--blok-font-weight-semibold);
}

/* Segmented Rendered / Raw switch — a pill track in the header's centre
   slot, with the active segment lifted onto the primary surface. */
.blok-file-preview-toggle {
  position: relative;
  grid-column: 2;
  grid-row: 1;
  display: inline-flex;
  gap: var(--blok-space-0-5);
  padding: var(--blok-space-0-5);
  background: var(--blok-bg-tertiary);
  border: 1px solid var(--blok-border-subtle);
  border-radius: var(--blok-radius-pill);
}

/* The lifted pill, glided under the active segment by JS (it sets width +
   translateX from the live button geometry). Painted behind the labels. */
.blok-file-preview-toggle-indicator {
  position: absolute;
  top: var(--blok-space-0-5);
  bottom: var(--blok-space-0-5);
  left: 0;
  width: 0;
  border-radius: var(--blok-radius-pill);
  background: var(--blok-bg-primary);
  box-shadow: 0 1px 2px var(--blok-checklist-shadow);
  transition:
    transform var(--blok-duration-standard) var(--blok-ease-popover),
    width var(--blok-duration-standard) var(--blok-ease-popover);
  pointer-events: none;
}

.blok-file-preview-toggle button {
  position: relative;
  z-index: 1;
  border: 0;
  background: transparent;
  padding: var(--blok-space-1) var(--blok-space-3);
  border-radius: var(--blok-radius-pill);
  font-size: var(--blok-font-size-ui-small);
  font-weight: var(--blok-font-weight-medium);
  color: var(--blok-text-secondary);
  cursor: pointer;
  transition: color var(--blok-duration-base) var(--blok-ease-standard);
}

.blok-file-preview-toggle button:hover {
  color: var(--blok-text-primary);
}

.blok-file-preview-toggle button[aria-pressed="true"] {
  color: var(--blok-text-primary);
}

.blok-file-preview-error {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: var(--blok-space-3);
  flex: 1 1 auto;
  min-height: 0;
  color: var(--blok-text-secondary);
}

.blok-file-preview-download {
  color: var(--blok-text-primary);
  text-decoration: underline;
}

.blok-md-task {
  display: flex;
  align-items: flex-start;
  gap: var(--blok-space-2);
  list-style: none;
}

/* GitHub-style alerts: a tinted callout with a coloured left rule and a
   semantic title. Kind colours come from the shared palette tokens so they
   adapt to light/dark automatically. */
.blok-md-alert {
  padding: var(--blok-space-3) var(--blok-space-4);
  border-left: 3px solid var(--blok-color-blue-text);
  border-radius: var(--blok-radius-sm);
  background: var(--blok-color-blue-bg);
}

.blok-md-alert > :last-child {
  margin-bottom: 0;
}

.blok-md-alert-title {
  margin: 0 0 var(--blok-space-1);
  font-weight: var(--blok-font-weight-semibold);
  color: var(--blok-color-blue-text);
}

.blok-md-alert-tip {
  border-left-color: var(--blok-color-green-text);
  background: var(--blok-color-green-bg);
}

.blok-md-alert-tip .blok-md-alert-title {
  color: var(--blok-color-green-text);
}

.blok-md-alert-important {
  border-left-color: var(--blok-color-purple-text);
  background: var(--blok-color-purple-bg);
}

.blok-md-alert-important .blok-md-alert-title {
  color: var(--blok-color-purple-text);
}

.blok-md-alert-warning {
  border-left-color: var(--blok-color-yellow-text);
  background: var(--blok-color-yellow-bg);
}

.blok-md-alert-warning .blok-md-alert-title {
  color: var(--blok-color-yellow-text);
}

.blok-md-alert-caution {
  border-left-color: var(--blok-color-red-text);
  background: var(--blok-color-red-bg);
}

.blok-md-alert-caution .blok-md-alert-title {
  color: var(--blok-color-red-text);
}

/* Footnotes trailer: a quieter, smaller list anchored at the document foot. */
.blok-md-footnotes {
  margin-top: 2em;
  font-size: 0.85em;
  color: var(--blok-text-secondary);
}

.blok-md-footnotes ol {
  padding-left: 1.25em;
}

.blok-md-fnref a,
.blok-md-fnback {
  color: var(--blok-color-accent);
  text-decoration: none;
}

.blok-md-fnback {
  margin-left: var(--blok-space-1);
}

/* Office previews (docx/xlsx/pptx) render into this scroll container inside the
   modal body. Each format reads like a document on a desk: a soft neutral
   canvas behind crisp, lightly-shadowed "paper". The renderers build their own
   DOM inside; per-kind rules below dress that DOM with our tokens. */
.blok-file-preview-office {
  flex: 1 1 auto;
  min-height: 0;
  overflow: auto;
  color: var(--blok-text-primary);
  background: var(--blok-bg-secondary);
}

/* --- docx: paper pages centred on the desk -------------------------------- */
/* docx-preview emits a .blok-docx-wrapper (its own grey desk) wrapping one
   section.blok-docx per page. Our two-class selectors out-specify the library's
   single-class injected styles, so we reclaim the desk tone and page chrome. */
.blok-file-preview-docx {
  padding: 0;
}

.blok-file-preview-docx .blok-docx-wrapper {
  background: transparent;
  padding: clamp(var(--blok-space-5), 4vw, var(--blok-space-10)) var(--blok-space-5);
}

.blok-file-preview-docx .blok-docx {
  border: 1px solid var(--blok-border-subtle);
  border-radius: var(--blok-radius-lg);
  box-shadow: var(--blok-image-shadow-resting);
}

/* --- xlsx: a single crisp data card, centred on the desk ------------------ */
/* A small sheet centres in the modal instead of stranding in the top-left; the
   `safe` keyword makes a sheet larger than the viewport fall back to start
   alignment (scrollable) rather than clipping its first rows/columns. */
.blok-file-preview-xlsx {
  display: flex;
  align-items: safe center;
  justify-content: safe center;
  padding: var(--blok-space-6);
}

.blok-file-preview-xlsx-table {
  border-collapse: separate;
  border-spacing: 0;
  font-size: 0.8125rem;
  line-height: var(--blok-line-height-tight);
  background: var(--blok-bg-primary);
  border: 1px solid var(--blok-border-subtle);
  border-radius: var(--blok-radius-md);
  box-shadow: var(--blok-image-shadow-resting);
  overflow: hidden;
}

.blok-file-preview-xlsx-table td {
  min-width: 3rem;
  padding: var(--blok-space-2) var(--blok-space-3);
  border-right: 1px solid var(--blok-border-subtle);
  border-bottom: 1px solid var(--blok-border-subtle);
  white-space: pre;
}

/* Numbers right-align with tabular figures so columns read like a spreadsheet. */
.blok-file-preview-xlsx-table td.blok-file-preview-xlsx-num {
  text-align: right;
  font-variant-numeric: tabular-nums;
}

.blok-file-preview-xlsx-table td:last-child {
  border-right: 0;
}

.blok-file-preview-xlsx-table tr:last-child td {
  border-bottom: 0;
}

/* First row reads as the header band; alternating rows aid horizontal scanning. */
.blok-file-preview-xlsx-table tr:first-child td {
  font-weight: 600;
  color: var(--blok-text-primary);
  background: var(--blok-bg-secondary);
}

.blok-file-preview-xlsx-table tr:nth-child(even) td {
  background: var(--blok-bg-secondary);
}

/* --- pptx: stacked slide cards -------------------------------------------- */
/* With fitMode: 'contain' the renderer scales each slide to the container width
   and patches its wrapper's height to match. We stack those wrappers down the
   desk with vertical breathing room; the sides stay flush because the renderer
   already centres each slide via its own inline `margin: 0 auto`. */
.blok-file-preview-pptx {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: var(--blok-space-6);
  padding: var(--blok-space-6) 0;
}

/* flex-shrink: 0 is load-bearing — a tall deck overflows the modal, and without
   it the flex column would compress each slide wrapper below its real height,
   then `overflow: hidden` (for the rounded corners) would clip the slide body
   down to just its title band. The shadow + radius carry the card framing. */
.blok-file-preview-pptx > * {
  flex-shrink: 0;
  border-radius: var(--blok-radius-lg);
  box-shadow: var(--blok-image-shadow-resting);
  overflow: hidden;
}
