:root {
  /* Brand palette (raw values). */
  --color-edgj-light-blue: rgb(0, 92, 151);
  --color-edgj-navy: rgb(14, 23, 38);
  --color-overlay-bg: rgba(59, 68, 75, 0.5);
  --color-text-light: #ffffff;

  /* Semantic tokens. Each resolves via light-dark() against the active
     color-scheme, so the whole palette flips with no JavaScript. */
  --color-bg: light-dark(#ffffff, #14181d);
  --color-text: light-dark(#1c1e21, #d7dade);
  --color-muted: light-dark(#555555, #9aa1a9);
  --color-accent: light-dark(var(--color-edgj-light-blue), rgb(125, 180, 226));
  --color-border: var(--color-accent);
  --color-surface: light-dark(#f3f5f7, #1e242b);

  --font-mono: ui-monospace, "SF Mono", Menlo, Consolas, monospace;

  color-scheme: light dark;
  interpolate-size: allow-keywords;
}

/* The header checkbox (no JavaScript) forces the scheme *opposite* to the
   system preference; unchecked means "follow the system". light-dark()
   tokens and form controls all flip with it. State is per-page: a static
   site has nowhere to persist it without JS or a server-set cookie. */
@media (prefers-color-scheme: light) {
  html:has(.theme-toggle-input:checked) {
    color-scheme: dark;
  }
}
@media (prefers-color-scheme: dark) {
  html:has(.theme-toggle-input:checked) {
    color-scheme: light;
  }
}

body {
  font-family: "IBM Plex Sans", Verdana, Geneva, Tahoma, sans-serif;
  line-height: 1.6;
  max-width: 90ch;
  margin-inline: auto;
  padding-inline: 1rem;
  background-color: var(--color-bg);
  color: var(--color-text);
}

a {
  color: var(--color-accent);
}

main {
  margin-inline: 5%;
}

article {
  text-align: start;
}

article header p {
  font-size: smaller;
}

body > header {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  justify-content: space-between;
  gap: 0.4rem 1.2rem;
  margin-block: 1.5rem;
  margin-inline: 5%;
  border-block-end: 1px solid var(--color-border);
}

.site-title {
  margin: 0;
  font-size: 1.3rem;
}

/* The site-title emoji doubles as the dark-mode toggle: a label for the
   visually-hidden checkbox at the top of <header>. */
.theme-toggle {
  cursor: pointer;
}

.theme-toggle-input {
  position: absolute;
  width: 1px;
  height: 1px;
  margin: -1px;
  padding: 0;
  border: 0;
  clip-path: inset(50%);
  overflow: hidden;
  white-space: nowrap;
}

.theme-toggle-input:focus-visible ~ .site-title .theme-toggle {
  outline: 2px solid var(--color-accent);
  outline-offset: 2px;
}

/* Show the circle matching the page's *current* scheme: ⚪ when light is
   active, ⚫ when dark is active (mirrors the color-scheme rules above). */
.theme-toggle-emoji::before {
  content: "⚪";
}
@media (prefers-color-scheme: light) {
  html:has(.theme-toggle-input:checked) .theme-toggle-emoji::before {
    content: "⚫";
  }
}
@media (prefers-color-scheme: dark) {
  html:not(:has(.theme-toggle-input:checked)) .theme-toggle-emoji::before {
    content: "⚫";
  }
}

nav ul {
  display: flex;
  list-style: none;
  padding: 0;
  flex-wrap: wrap;
  margin: 0;
  font-size: 1.3rem;
  gap: 0.4rem 1.2rem;
}

footer {
  font-size: smaller;
  text-align: center;
  margin-block: 1.5rem;
  margin-inline: 5%;
  padding-block-start: 0.5rem;
  border-block-start: 1px solid var(--color-border);
}

footer ul {
  display: flex;
  list-style: none;
  justify-content: center;
  padding: 0;
  flex-wrap: wrap;
  font-size: 1.3rem;
  column-gap: 1.875rem;
}

footer a {
  text-decoration: none;
}

/* The CC and RSS icons are monochrome SVGs loaded via <img>, so they render
   in their own document context where currentColor resolves to black. Invert
   them when the effective scheme is dark so they stay legible. Mastodon and
   Signal logos are intentionally untouched — they're brand-coloured. */
@media (prefers-color-scheme: dark) {
  html:not(:has(.theme-toggle-input:checked)) footer img[src^="/icons/cc"],
  html:not(:has(.theme-toggle-input:checked)) footer img[src="/icons/rss.svg"] {
    filter: invert(1);
  }
}
@media (prefers-color-scheme: light) {
  html:has(.theme-toggle-input:checked) footer img[src^="/icons/cc"],
  html:has(.theme-toggle-input:checked) footer img[src="/icons/rss.svg"] {
    filter: invert(1);
  }
}

.build-info {
  max-inline-size: 32rem;
  margin: 1.75rem auto 0;
  text-align: start;
  border: 1px solid var(--color-accent);
  border-radius: 4px;
}

.build-info > summary {
  cursor: pointer;
  font-weight: bold;
  color: var(--color-accent);
  width: max-content;
  margin: -0.75em auto 0;
  padding: 0 0.6rem;
  background: var(--color-bg);
  list-style: none;
}

.build-info > summary::-webkit-details-marker,
.build-info > summary::marker {
  display: none;
  content: "";
}

.build-info::details-content {
  block-size: 0;
  opacity: 0;
  overflow: clip;
  transition: content-visibility 1s ease allow-discrete,
              block-size 1s ease,
              opacity 0.8s ease;
}

.build-info[open]::details-content {
  block-size: auto;
  opacity: 1;
}

@media (prefers-reduced-motion: reduce) {
  .build-info::details-content {
    transition: none;
  }
}

.build-info-card {
  margin-block-start: 0.5rem;
  font-family: var(--font-mono);
  font-size: 0.85em;
}

.build-info-card section {
  padding: 0.6rem 1rem;
  border-block-end: 1px dashed color-mix(in srgb, var(--color-accent) 30%, transparent);
}

.build-info-card section:last-child {
  border-block-end: none;
}

.build-info-card h2 {
  margin: 0 0 0.3rem;
  font-size: 0.75em;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.08em;
  color: var(--color-accent);
  opacity: 0.75;
}

.build-info-card dl {
  display: grid;
  grid-template-columns: max-content 1fr;
  gap: 0.2rem 1.25rem;
  margin: 0;
}

.build-info-card dt {
  font-weight: 600;
  color: var(--color-accent);
}

.build-info-card dd {
  margin: 0;
  word-break: break-word;
}

.build-info-card .session-info {
  display: block;
  inline-size: 100%;
  max-inline-size: 21rem;
  height: auto;
  margin-block-start: 0.1rem;
}

.build-info-card .build-verify {
  background: color-mix(in srgb, var(--color-accent) 6%, transparent);
}

.build-info-card .build-verify > details > summary {
  cursor: pointer;
  margin: 0 0 0.3rem;
  font-size: 0.75em;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.08em;
  color: var(--color-accent);
  opacity: 0.75;
  list-style: revert;
}

.build-info-card .build-verify > details::details-content {
  block-size: 0;
  opacity: 0;
  overflow: clip;
  transition: content-visibility 1s ease allow-discrete,
              block-size 1s ease,
              opacity 0.8s ease;
}

.build-info-card .build-verify > details[open]::details-content {
  block-size: auto;
  opacity: 1;
}

@media (prefers-reduced-motion: reduce) {
  .build-info-card .build-verify > details::details-content {
    transition: none;
  }
}

.build-info-card .build-verify p {
  margin: 0 0 0.4rem;
}

.build-info-card .build-verify pre {
  margin: 0;
  padding: 0.5rem 0.6rem;
  background: var(--color-edgj-navy);
  color: var(--color-text-light);
  border-radius: 3px;
  overflow-x: auto;
  font-size: 0.95em;
  line-height: 1.4;
}

main a[href^='http']::after {
  content: "";
  display: inline-block;
  width: 0.8em;
  height: 0.8em;
  margin-inline-start: 0.3em;
  vertical-align: middle;
  background-color: currentColor;
  /* SVG for the mask - paths will default to black, forming the shape */
  -webkit-mask-image: url("data:image/svg+xml,%3Csvg viewBox='0 0 16 16' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath d='M13.5 2h-3a.5.5 0 0 0 0 1h1.8L7.65 7.65a.5.5 0 0 0 .7.7L13 3.7v1.8a.5.5 0 0 0 1 0v-3a.5.5 0 0 0-.5-.5Z'/%3E%3Cpath d='M12 11a.5.5 0 0 0-.5.5v1.5H4V5h1.5a.5.5 0 0 0 0-1H3.5A.5.5 0 0 0 3 4.5v9a.5.5 0 0 0 .5.5h9a.5.5 0 0 0 .5-.5V11.5A.5.5 0 0 0 12 11Z'/%3E%3C/svg%3E");
  mask-image: url("data:image/svg+xml,%3Csvg viewBox='0 0 16 16' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath d='M13.5 2h-3a.5.5 0 0 0 0 1h1.8L7.65 7.65a.5.5 0 0 0 .7.7L13 3.7v1.8a.5.5 0 0 0 1 0v-3a.5.5 0 0 0-.5-.5Z'/%3E%3Cpath d='M12 11a.5.5 0 0 0-.5.5v1.5H4V5h1.5a.5.5 0 0 0 0-1H3.5A.5.5 0 0 0 3 4.5v9a.5.5 0 0 0 .5.5h9a.5.5 0 0 0 .5-.5V11.5A.5.5 0 0 0 12 11Z'/%3E%3C/svg%3E");
  -webkit-mask-size: contain;
  mask-size: contain;
  -webkit-mask-repeat: no-repeat;
  mask-repeat: no-repeat;
}

/* Link that wraps a clickable image (navigates to the full-screen photo page). */
.photo-trigger {
  display: block;
  cursor: zoom-in;
}
.photo-trigger:focus-visible {
  outline: 2px solid var(--color-accent);
  outline-offset: 2px;
}

img,
video,
iframe {
  max-inline-size: 100%;
  block-size: auto;
}

@font-face {
  font-display: swap;
  font-family: "IBM Plex Sans";
  font-weight: 400;
  src: url("/fonts/ibm-plex-sans-v14-latin-regular.woff2") format("woff2");
}

h1 {
  text-align: center;
  margin-block: 0.67em;
  font-size: 2em;
}

.post-metadata {
  opacity: 0.4;
  text-align: center;
  font-style: italic;
}

.content p {
  text-align: start;
}

ol.posts-toc-index {
  list-style-type: square;
}

ol.posts-toc {
  list-style-type: none;
}

/* || Photo Overlay */

.photo-container {
  position: relative;
  display: inline-block;
}

.photo-container img {
  display: block;
  max-width: 100%;
  height: auto;
}

.photo-caption-overlay {
  position: absolute;
  bottom: 0;
  left: 0;
  right: 0;
  max-height: 60%;
  overflow-y: auto;
  background-color: rgba(0, 0, 0, 0.7);
  color: white;
  padding: 0.5em 1em;
  text-align: center;
  font-size: 0.9em;
  opacity: 0;
  visibility: hidden;
  transition:
    opacity 0.3s ease-in-out,
    visibility 0.3s ease-in-out;
}
.photo-caption-overlay a {
  color: white;
  text-decoration: none;
}
.photo-caption-overlay a:hover {
  text-decoration: underline;
}
/* Only hover-capable devices reveal overlays on hover/focus. (Gating focus-within to
   these devices also prevents the overlays re-appearing on touch when focus returns to
   the trigger button after the lightbox closes.) */
@media (hover: hover) {
  .photo-container:hover .photo-caption-overlay,
  .photo-container:focus-within .photo-caption-overlay {
    opacity: 1;
    visibility: visible;
  }
}

.photo-caption-below {
  padding: 0.5em 0;
  font-size: 0.9em;
  color: var(--color-muted);
  text-align: center;
}
.photo-caption-below a {
  color: inherit;
}

.photo-exif-overlay {
  position: absolute;
  top: 10px;
  left: 10px;
  max-width: calc(100% - 20px);
  max-height: calc(100% - 20px);
  overflow-y: auto;
  overflow-wrap: anywhere;
  background-color: rgba(0, 0, 0, 0.6);
  color: white;
  padding: 0.5em;
  font-size: 0.8em;
  border-radius: 3px;
  opacity: 0;
  visibility: hidden;
  transition:
    opacity 0.3s ease-in-out,
    visibility 0.3s ease-in-out;
}
@media (hover: hover) {
  .photo-container:hover .photo-exif-overlay,
  .photo-container:focus-within .photo-exif-overlay {
    opacity: 1;
    visibility: visible;
  }
}

/* Tap-to-toggle for touch devices: a hidden checkbox, flipped by the info button, reveals
   the overlays. Visually hidden but kept focusable so the toggle is keyboard-operable. */
.photo-details-toggle,
.photo-details-srlabel {
  position: absolute;
  width: 1px;
  height: 1px;
  margin: -1px;
  padding: 0;
  border: 0;
  clip-path: inset(50%);
  overflow: hidden;
  white-space: nowrap;
}

.photo-details-toggle:checked ~ .photo-exif-overlay,
.photo-details-toggle:checked ~ .photo-caption-overlay {
  opacity: 1;
  visibility: visible;
}

/* The info button is only needed where hover isn't available. */
.photo-details-btn {
  display: none;
}

/* On hover-capable devices the overlays reveal on hover, so the toggle is unused; remove it
   from the layout and a11y tree (otherwise the visually-hidden checkbox stays focusable). */
@media (hover: hover) {
  .photo-details-toggle {
    display: none;
  }
}

.photo-details-toggle:focus-visible ~ .photo-details-btn {
  outline: 2px solid var(--color-accent);
  outline-offset: 2px;
}

@media (hover: none) {
  /* On touch the overlays are revealed over the image by the info button (tap-to-toggle).
     They're size-capped (max-width/max-height above) and scroll internally so they can't
     cover the whole photo. Keep the EXIF box clear of the top-right button. */
  .photo-exif-overlay {
    max-width: calc(100% - 60px);
  }

  /* The info button sits in the image's top-right corner, drawn as a white info-circle SVG
     (recoloured via the mask + background-color) with a drop-shadow so it stays legible
     over light photos. */
  .photo-details-btn {
    display: block;
    position: absolute;
    top: 8px;
    right: 8px;
    width: 1.75rem;
    height: 1.75rem;
    cursor: pointer;
    z-index: 2;
    background-color: #fff;
    filter: drop-shadow(0 1px 2px rgba(0, 0, 0, 0.6));
    -webkit-mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'%3E%3Cpath d='M8 16A8 8 0 1 1 8 0a8 8 0 0 1 0 16zM8 4a1 1 0 1 0 0 2 1 1 0 0 0 0-2zm1 3H7v6h2z'/%3E%3C/svg%3E")
      center / contain no-repeat;
    mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'%3E%3Cpath d='M8 16A8 8 0 1 1 8 0a8 8 0 0 1 0 16zM8 4a1 1 0 1 0 0 2 1 1 0 0 0 0-2zm1 3H7v6h2z'/%3E%3C/svg%3E")
      center / contain no-repeat;
  }
  .photo-details-btn::before {
    content: none;
  }
}

@media (prefers-reduced-motion: reduce) {
  .photo-caption-overlay,
  .photo-exif-overlay {
    transition: none;
  }
}

/* Styling for items within the EXIF overlay (from exif.html) */
.exif-details .exif-item {
  margin-bottom: 0.3em;
}
.exif-details .exif-item:last-child {
  margin-bottom: 0;
}

/* Year groups on the posts list are <h2> for a correct document outline
   (h1 -> h2), but keep the visual size of the <h3> they used to be. */
.posts-year {
  font-size: 1.17em;
  margin-block: 1em;
}

/* tables */

.data-table {
  overflow-x: auto;
}

table {
  table-layout: auto;
  width: 100%;
  border-collapse: collapse;
}

th,
td {
  padding: 1.25rem;
}

th {
  letter-spacing: 2px;
}

td {
  letter-spacing: 1px;
}

tbody td {
  text-align: center;
}

tfoot th {
  text-align: right;
}


.anchor{
  text-decoration: none;
  margin-left: 0.25em; /* Adjust spacing as needed */
  font-weight: normal;
  opacity: 0.25;

  &:hover {
    opacity: 0.8;
    text-decoration: underline;
  }
}

#page-title .anchor {
  visibility: hidden;
}

/* || Photo Page (full-screen view, one HTML page per image) */

.photo-page {
  /* Escape the 90ch body cap so the image can use the whole viewport. The
     negative margin trick pulls the panel back to the viewport edges from
     within the constrained <body> + <main>. */
  width: 100vw;
  margin-inline: calc(50% - 50vw);
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 1rem;
  padding: 1rem clamp(1rem, 3vw, 3rem);
  box-sizing: border-box;
}

.photo-page-nav {
  align-self: flex-start;
  font-size: 0.95em;
}

.photo-page-back {
  text-decoration: none;
}
.photo-page-back:hover,
.photo-page-back:focus-visible {
  text-decoration: underline;
}

.photo-page-figure {
  margin: 0;
  max-width: 100%;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 0.75rem;
}

.photo-page-figure img {
  display: block;
  max-width: 100%;
  max-height: calc(100vh - 8rem);
  height: auto;
  width: auto;
  object-fit: contain;
}

.photo-page-caption {
  max-width: 70ch;
  text-align: center;
  font-size: 0.95em;
  color: var(--color-muted);
}

.photo-page-caption-text {
  margin: 0 0 0.5em;
}

.photo-page-exif {
  font-size: 0.85em;
  opacity: 0.85;
}

code[data-lang=pwsh] {
    text-wrap: wrap;
}

pre {
  overflow-x: auto;
}
