/* Render the header logo image as a circle. */
.md-header__button.md-logo img {
  border-radius: 50%;
  object-fit: cover;
}

/* Center figures (images that stand alone in a paragraph, optionally
   wrapped in a link to make them clickable) and give them a light border.
   The :only-child selectors keep inline images such as emoji, which appear
   alongside text, out of scope. */
.md-typeset p > img:only-child:not(.twemoji),
.md-typeset p > a:only-child > img:only-child:not(.twemoji) {
  display: block;
  box-sizing: border-box;
  margin-inline: auto;
  max-width: 100%;
  height: auto;
  border: 1px solid var(--md-default-fg-color--lighter);
  border-radius: 0.1rem;
}

/* The link wrapping such an image needs to be centered as a block itself,
   since the img inside it no longer touches the paragraph directly. */
.md-typeset p > a:only-child:has(> img:only-child:not(.twemoji)) {
  display: block;
  width: fit-content;
  max-width: 100%;
  margin-inline: auto;
}

/* Lay several figures out in one row: a paragraph of nothing but images,
   marked "{ .figure-row }". Tall portrait shots (phone screenshots) eat a
   lot of vertical space stacked, and side by side they also read as a set.
   The images shrink to share the row rather than wrapping, so they stay
   side by side on narrow screens too — which is the whole point. */
.md-typeset p.figure-row {
  display: flex;
  gap: 0.8rem;
  align-items: flex-start;
  justify-content: center;
}

/* These images are not :only-child, so the rule above doesn't reach them. */
.md-typeset p.figure-row > img:not(.twemoji) {
  box-sizing: border-box;
  min-width: 0;
  height: auto;
  border: 1px solid var(--md-default-fg-color--lighter);
  border-radius: 0.1rem;
}

/* Scope this to the main content only. The footer's .md-footer-meta also
   carries md-typeset, so anchoring on .md-typeset would mark the Zensical
   link in the copyright line as well. A link that's only a figure image
   skips the icon — the image itself is the affordance, and the icon would
   otherwise land oddly below it since it follows a block-level img. */
.md-content__inner a[href^="http"][target="_blank"]:not(:has(> img:only-child))::after {
  content: "";
  display: inline-block;
  width: 0.7em;
  height: 0.7em;
  margin-left: 0.25em;
  vertical-align: middle;
  background-color: currentColor;
  -webkit-mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2.5' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6'/%3E%3Cpolyline points='15 3 21 3 21 9'/%3E%3Cline x1='10' y1='14' x2='21' y2='3'/%3E%3C/svg%3E");
          mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2.5' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6'/%3E%3Cpolyline points='15 3 21 3 21 9'/%3E%3Cline x1='10' y1='14' x2='21' y2='3'/%3E%3C/svg%3E");
  -webkit-mask-size: contain;
          mask-size: contain;
  -webkit-mask-repeat: no-repeat;
          mask-repeat: no-repeat;
}

/* Responsive wrapper for embedded videos. The iframe fills a 16:9 box so the
   embed scales with the content column instead of overflowing it on narrow
   screens. */
.md-typeset .video {
  aspect-ratio: 16 / 9;
  margin: 1em 0;
  border: 1px solid var(--md-default-fg-color--lighter);
  border-radius: 0.1rem;
  overflow: hidden;
}

.md-typeset .video iframe {
  display: block;
  width: 100%;
  height: 100%;
  border: 0;
}

/* The embedded X post draws its own 1px card border a couple pixels inside
   the iframe's edge, in a light gray that X doesn't reliably swap for dark
   mode — visible as a hairline (and, at the rounded corners, a bit of the
   iframe's own white background peeking past the card's own rounding).
   That's rendered inside cross-origin content, so it can't be recolored
   directly. Instead, scale the iframe up by a hair so its edge — border
   included — lands just outside the wrapper's unscaled clip box. */
.md-typeset .x-post .twitter-tweet {
  overflow: hidden;
  border: 1px solid var(--md-default-fg-color--lighter);
  border-radius: 12px;
}

.md-typeset .x-post iframe {
  transform: scale(1.015);
}

/* Add breathing room above a paragraph marked "{ .impression }" — used for
   personal commentary that follows a talk's metadata list (登壇者・発表資料・
   …), so it doesn't run together with the list above it. Scoped to this
   class rather than to "list item followed by a paragraph" in general,
   since that broader shape also occurs in unrelated content (e.g. a field
   description followed by its citation in the Wi-Fi drafts). */
.md-typeset p.impression {
  margin-top: 1.5em;
}

/* Enlarge an opening line marked "{ .lead }" — the landing page greeting.
   2em matches the hero line on tiangolo.com, which wraps its greeting in a
   div at that size. Relative to the body text, so it follows the theme's
   font size across breakpoints instead of pinning a pixel value. */
.md-typeset p.lead {
  font-size: 2em;
}

/* Center the landing page. Scoped with :has() to a page whose h1 carries
   "{ .landing }", so every other article is left alone — the theme offers
   no per-page class to hook onto. */
.md-content__inner:has(> h1.landing) {
  text-align: center;
}

/* On that page the greeting introduces the site, which makes the heading
   above it redundant on screen. Hide it visually, but keep it in the
   accessibility tree and the document outline rather than using
   "display: none", which would drop it from both. */
.md-typeset h1.landing {
  position: absolute;
  width: 1px;
  height: 1px;
  margin: -1px;
  padding: 0;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
}

/* An image marked "{ .avatar }" is a portrait, not a figure: round it off
   and drop the frame the figure rule above draws. That rule and this one
   have the same specificity, so this has to stay below it to win. */
.md-typeset p > img.avatar:only-child {
  width: 14rem;
  border: 0;
  border-radius: 50%;
}

/* The last-updated line each article carries above its h1, marked
   "{ .page-updated data-search-exclude }". Pushed to the right so it reads
   as a stamp on the title rather than as an opening sentence; the color and
   size match the theme's own .md-source-file__fact, which is what Zensical
   uses for the same kind of metadata. The date is maintained by hand, so
   data-search-exclude keeps "Last Update" out of the search index — without
   it every page matches that phrase. */
.md-typeset p.page-updated {
  display: flex;
  justify-content: flex-end;
  align-items: center;
  gap: 0.3rem;
  margin: 0 0 0.4em;
  color: var(--md-default-fg-color--light);
  font-size: 0.68rem;
}

/* The clock is an inlined lucide/clock, drawn as a mask rather than an
   image so "background-color: currentColor" tints it — that way it follows
   the text color into dark mode with no second asset to ship. */
.md-typeset p.page-updated::before {
  content: "";
  width: 0.9rem;
  height: 0.9rem;
  background-color: currentColor;
  -webkit-mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Ccircle cx='12' cy='12' r='10'/%3E%3Cpolyline points='12 6 12 12 16 14'/%3E%3C/svg%3E");
          mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Ccircle cx='12' cy='12' r='10'/%3E%3Cpolyline points='12 6 12 12 16 14'/%3E%3C/svg%3E");
  -webkit-mask-size: contain;
          mask-size: contain;
  -webkit-mask-repeat: no-repeat;
          mask-repeat: no-repeat;
}
