/*  rkroll default theme.
 *
 *  Photo-friendly: prose stays narrow for readability; figures break
 *  out of the prose column to fill the wider content area. Drives the
 *  custom-property surface documented in docs/theming.md; layered on
 *  top of base.css (which carries a11y + overflow primitives).
 */

:root {
  /* color tokens */
  --rkr-bg: #fdfdfb;
  --rkr-text: #1a1a1a;
  --rkr-muted: #707070;
  --rkr-rule: #e5e5e2;
  --rkr-link: #1a4f7f;
  --rkr-link-hover: #0d2c4d;
  --rkr-danger: #cf222e;
  --rkr-shadow: rgba(0, 0, 0, 0.08);

  /* layout tokens */
  --rkr-content: 64rem;     /* outer column for figures + galleries */
  --rkr-prose: 38rem;       /* inner column for prose */
  --rkr-gap: 1.25rem;
  --rkr-radius: 4px;

  /* type tokens */
  --rkr-prose-font: ui-serif, Georgia, "Times New Roman", Times, serif;
  --rkr-display-font: -apple-system, BlinkMacSystemFont, "Segoe UI",
    Roboto, "Helvetica Neue", Arial, sans-serif;
  --rkr-mono-font: ui-monospace, "SF Mono", Menlo, Consolas, monospace;
  --rkr-base-size: 1.0625rem; /* 17px */
  --rkr-line-height: 1.6;
}

@media (prefers-color-scheme: dark) {
  :root {
    --rkr-bg: #14140e;
    --rkr-text: #ebeae4;
    --rkr-muted: #9c9c95;
    --rkr-rule: #2a2a25;
    --rkr-link: #8fb3da;
    --rkr-link-hover: #b9d1eb;
    --rkr-shadow: rgba(0, 0, 0, 0.4);
  }
}

/* Theme-owned body typography. base.css covers margin reset +
   overflow-clip; everything visual (font, line height, colors)
   belongs to the theme. */
body {
  font-family: var(--rkr-prose-font);
  line-height: var(--rkr-line-height);
  color: var(--rkr-text);
  background: var(--rkr-bg);
}

/* ---- site chrome -------------------------------------------------- */

.rkr-site-head {
  border-bottom: 1px solid var(--rkr-rule);
  padding: 1.5rem 1.5rem 1rem;
}
.rkr-site-head .rkr-site-head-inner {
  max-width: var(--rkr-content);
  margin: 0 auto;
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 1rem;
  flex-wrap: wrap;
}
.rkr-site-title {
  font-family: var(--rkr-display-font);
  font-size: 1.25rem;
  font-weight: 700;
  letter-spacing: -0.01em;
  margin: 0;
}
.rkr-site-title a {
  color: inherit;
  text-decoration: none;
}
/* The header admin strip (New post / Posts / Settings / Edit /
   Logout) was replaced by per-page FABs (.rkr-fab) and a footer
   Login/Logout switch. The .rkr-admin-strip rules are gone with it. */
.rkr-site-tagline {
  color: var(--rkr-muted);
  font-size: 0.9rem;
}

/* ---- 404 (/not-found) -------------------------------------------- */
.rkr-notfound {
  max-width: var(--rkr-prose);
  margin: 4rem auto;
  padding: 0 1.25rem;
  text-align: center;
}
.rkr-notfound h1 {
  font-family: var(--rkr-display-font);
  font-size: 2.25rem;
  letter-spacing: -0.01em;
  margin: 0 0 0.75rem;
}
.rkr-notfound p {
  color: var(--rkr-muted);
  margin: 0 0 1.25rem;
}
.rkr-notfound a {
  color: var(--rkr-link);
  text-decoration: none;
  border-bottom: 1px solid currentColor;
}
.rkr-notfound a:hover { color: var(--rkr-link-hover); }

/* ---- login (/admin/login) ---------------------------------------- */
.rkr-login {
  max-width: 24rem;
  margin: 2rem auto;
}
.rkr-login h1 {
  font-family: var(--rkr-display-font);
  font-size: 1.5rem;
  margin: 0 0 1.5rem;
}
.rkr-login hr {
  border: 0;
  border-top: 1px solid var(--rkr-rule);
  margin: 2rem 0;
}
.rkr-login-google {
  display: inline-block;
  padding: 0.5rem 1rem;
  border: 1px solid var(--rkr-rule);
  border-radius: var(--rkr-radius);
  text-decoration: none;
  color: var(--rkr-text);
}
.rkr-login-google:hover { color: var(--rkr-link); }
.rkr-login-form {
  display: flex;
  flex-direction: column;
  gap: 0.75rem;
}
.rkr-login-form label {
  display: flex;
  flex-direction: column;
  gap: 0.25rem;
  font-size: 0.9rem;
}
.rkr-login-form input {
  padding: 0.5rem;
  font: inherit;
  border: 1px solid var(--rkr-rule);
  border-radius: var(--rkr-radius);
  background: var(--rkr-bg);
  color: var(--rkr-text);
}
.rkr-login-submit {
  padding: 0.5rem 1rem;
  font: inherit;
  background: var(--rkr-link);
  color: var(--rkr-bg);
  border: 1px solid var(--rkr-link);
  border-radius: var(--rkr-radius);
  cursor: pointer;
}
.rkr-login-submit:hover { background: var(--rkr-link-hover); border-color: var(--rkr-link-hover); }
.rkr-login-hint { color: var(--rkr-muted); font-size: 0.9rem; }

/* ---- admin posts list (admin-only /admin/posts) ----------------- */
.rkr-admin-posts-heading {
  font-family: var(--rkr-display-font);
  font-size: 1.5rem;
  margin: 0 0 1rem;
}
/* Horizontal-scroll container for the admin posts table on narrow
   viewports. Without this, the table widens the body past the
   viewport and iOS Safari anchors fixed-position FABs to the body's
   right edge — shoving the + and gear buttons off-screen. The
   wrapper absorbs the overflow so the body stays viewport-width. */
.rkr-admin-posts-scroll {
  overflow-x: auto;
  -webkit-overflow-scrolling: touch;
  margin: 0 -0.5rem;
  padding: 0 0.5rem;
}
.rkr-admin-posts {
  width: 100%;
  border-collapse: collapse;
  font-size: 0.95rem;
  /* Don't let cell wrap on narrow viewports — the scroll container
     above provides the horizontal escape. Specific cells (title)
     can opt into wrapping locally. */
  white-space: nowrap;
}
.rkr-admin-posts td:first-child,
.rkr-admin-posts th:first-child { white-space: normal; }
.rkr-admin-posts th, .rkr-admin-posts td {
  text-align: left;
  padding: 0.5rem 0.75rem;
  border-bottom: 1px solid var(--rkr-rule);
  /* Mixed content per row — text, a <select>, a <button>, a <time>.
     Baseline alignment would shift each by its own font metrics; pin
     everything to the row's vertical centre so columns read as a real
     table. */
  vertical-align: middle;
}
.rkr-admin-posts th {
  font-size: 0.8rem;
  text-transform: uppercase;
  letter-spacing: 0.05em;
  color: var(--rkr-muted);
  font-weight: 500;
}
.rkr-admin-posts td a {
  color: var(--rkr-text);
  text-decoration: none;
}
.rkr-admin-posts td a:hover { color: var(--rkr-link); text-decoration: underline; }
.rkr-admin-posts-status {
  font-size: 0.75rem;
  text-transform: uppercase;
  letter-spacing: 0.04em;
  padding: 0.1rem 0.5rem;
  border-radius: 999px;
  border: 1px solid var(--rkr-rule);
  background: transparent;
  color: var(--rkr-muted);
  cursor: pointer;
  font: inherit; font-size: 0.75rem;
}
.rkr-admin-posts-status.is-published {
  border-color: color-mix(in srgb, var(--rkr-link) 40%, transparent);
  color: var(--rkr-link);
}
.rkr-admin-posts-status-form { display: inline; margin: 0; }
/* Each action lives in its own column so the controls stack on a
   vertical line across rows. `width:1%` lets the browser shrink-wrap
   the column to the widest cell content; the title cell soaks up the
   remaining width. white-space:nowrap stops the column from collapsing
   onto multiple lines under tight viewports. */
.rkr-admin-posts-action {
  width: 1%;
  white-space: nowrap;
  text-align: right;
}
/* WCAG-compliant visually-hidden label for the per-row status select. */
.rkr-vh {
  position: absolute; width: 1px; height: 1px;
  margin: -1px; padding: 0; overflow: hidden;
  clip: rect(0, 0, 0, 0); white-space: nowrap; border: 0;
}
.rkr-admin-posts-del { display: inline; margin: 0; }
.rkr-admin-posts-del-btn,
.rkr-admin-posts-pin {
  background: none; border: 0; padding: .2rem; cursor: pointer;
  color: var(--rkr-muted); display: inline-flex; align-items: center;
  vertical-align: middle; line-height: 1;
}
/* Destructive: muted at rest, red on hover/focus. Same pattern
   used for every trash button in the admin (figure delete, cell
   delete, posts-list delete) — see --rkr-danger token + the
   admin-styles.ts rules. */
.rkr-admin-posts-del-btn:hover,
.rkr-admin-posts-del-btn:focus-visible { color: var(--rkr-danger); }
.rkr-admin-posts-pin:hover:not(:disabled) { color: var(--rkr-link); }
.rkr-admin-posts-pin:disabled { cursor: progress; opacity: 0.6; }
/* Pin icon shows CURRENT STATE, not the click action: when pinned,
   the pin is the active accent colour; when not, it's muted (same
   default as the rest button). The icon swap (pin vs pin-off) in
   posts-list.ts reinforces it visually. */
.rkr-admin-posts-pin[aria-pressed="true"] { color: var(--rkr-link); }
.rkr-admin-posts-empty {
  color: var(--rkr-muted);
  text-align: center;
  padding: 2rem;
  font-style: italic;
}
.rkr-admin-posts-empty a { color: var(--rkr-link); }

/* Settings page: a vertical two-column grid mirroring the editor's
   meta panel (label on the left, input on the right). */
.rkr-admin-settings-heading { font-size: 1.5rem; margin: 1rem 0; }
.rkr-admin-settings {
  display: grid;
  grid-template-columns: max-content 1fr;
  gap: 0.5rem 0.75rem;
  align-items: center;
  max-width: 40rem;
  margin: 1rem 0;
}
.rkr-admin-settings label { color: var(--rkr-muted); }
.rkr-admin-settings input,
.rkr-admin-settings select {
  padding: 0.35rem 0.5rem;
  font: inherit;
  min-width: 0; /* let inputs shrink inside the 1fr column on narrow viewports */
}
/* Number knobs hold 1–4 digits; let them sit as a narrow chip on the
   left of the column instead of stretching to fill the 1fr track. */
.rkr-admin-settings input[type="number"] {
  width: 7rem;
  justify-self: start;
}
.rkr-admin-settings-hint {
  grid-column: 1 / -1;
  margin: 0.25rem 0;
  color: var(--rkr-muted);
  font-size: 0.85rem;
}
.rkr-admin-settings-section {
  grid-column: 1 / -1;
  font-size: 1.15rem;
  margin: 1.5rem 0 0.25rem;
  padding-top: 1rem;
  border-top: 1px solid var(--rkr-rule);
}
.rkr-admin-settings-hint code {
  background: color-mix(in srgb, var(--rkr-text) 8%, transparent);
  padding: 0 0.25rem;
  border-radius: 3px;
}
.rkr-admin-settings-submit {
  grid-column: 1 / -1;
  justify-self: start;
  padding: 0.4rem 0.9rem;
  cursor: pointer;
}
/* Build chip at the bottom of /admin/settings — muted footer hint
   so the operator can confirm which deploy is live. The short
   hash (12 chars) is the click-friendly form; the full sha lives
   in the <code title=…> tooltip for copy/paste verification. */
.rkr-admin-settings-build {
  margin: 2rem 0 0;
  color: var(--rkr-muted);
  font-size: 0.85rem;
}
.rkr-admin-settings-build code {
  background: color-mix(in srgb, var(--rkr-text) 6%, transparent);
  padding: 0 0.25rem;
  border-radius: 3px;
}
.rkr-admin-settings-flash {
  padding: 0.5rem 0.75rem;
  border: 1px solid var(--rkr-rule);
  border-radius: 4px;
  max-width: 40rem;
}
.rkr-admin-settings-flash.is-ok {
  border-color: color-mix(in srgb, var(--rkr-link) 40%, transparent);
  color: var(--rkr-link);
}
.rkr-admin-settings-flash.is-error {
  border-color: #cf222e;
  color: #cf222e;
}

.rkr-site-foot {
  border-top: 1px solid var(--rkr-rule);
  margin-top: 4rem;
  padding: 1.5rem;
  font-size: 0.85rem;
  color: var(--rkr-muted);
  text-align: center;
}
.rkr-site-foot-sep { margin: 0 0.4rem; }
.rkr-site-foot-admin {
  color: inherit; text-decoration: none;
  background: none; border: 0; padding: 0; cursor: pointer;
  font: inherit;
}
.rkr-site-foot-admin:hover { color: var(--rkr-link); text-decoration: underline; }
.rkr-site-foot-logout-form { display: inline; margin: 0; }

/* Floating action buttons (FABs) — replaced the old admin chrome
   strip. Circular icon buttons fixed to the bottom-right corner of
   the viewport. Slots stack upward: --slot-1 is the lowest, --slot-2
   sits above it, and so on. Page templates emit FABs only when
   isAdmin so anonymous visitors see clean pages. */
.rkr-fab {
  position: fixed;
  right: 1.25rem;
  z-index: 50;
  width: 3rem; height: 3rem;
  display: inline-flex; align-items: center; justify-content: center;
  border-radius: 999px;
  border: 1px solid var(--rkr-rule);
  background: var(--rkr-bg);
  color: var(--rkr-link);
  text-decoration: none;
  box-shadow: 0 2px 8px rgba(0, 0, 0, 0.18);
  transition: transform 80ms ease, box-shadow 80ms ease;
}
.rkr-fab:hover {
  transform: translateY(-1px);
  box-shadow: 0 4px 12px rgba(0, 0, 0, 0.22);
}
.rkr-fab:focus-visible { outline: 2px solid var(--rkr-link); outline-offset: 2px; }
.rkr-fab--slot-1 { bottom: 1.25rem; }
.rkr-fab--slot-2 { bottom: 5rem; }
.rkr-fab--slot-3 { bottom: 8.75rem; }

/* ---- main column -------------------------------------------------- */

main {
  max-width: var(--rkr-content);
  margin: 0 auto;
  padding: 2rem 1.5rem;
}

/* ---- prose -------------------------------------------------------- */

article {
  max-width: var(--rkr-prose);
  margin: 0 auto;
}

article > header {
  margin-bottom: 2rem;
}
article > header h1 {
  font-family: var(--rkr-display-font);
  font-size: 2rem;
  line-height: 1.15;
  letter-spacing: -0.02em;
  margin: 0 0 .5rem;
}
/* Copy-link icon sitting flush after the post title. Inherits the
   title's font-size-down to keep it visually balanced; padding lets
   the click target meet the WCAG 24x24 minimum. The data-state
   attribute is set by /static/site/copy-link.js for ~1.5s after a
   click — green for a successful copy, red for a clipboard error;
   matches the editor's rkr-copy-link affordance so the gesture is
   the same wherever the author lives. */
.rkr-post-copylink {
  appearance: none;
  background: transparent;
  border: 1px solid transparent;
  border-radius: var(--rkr-radius);
  color: var(--rkr-muted);
  padding: 0.25rem 0.4rem;
  margin-left: 0.5rem;
  vertical-align: middle;
  cursor: pointer;
  transition: color 0.15s, border-color 0.15s, background 0.15s;
}
.rkr-post-copylink:hover,
.rkr-post-copylink:focus-visible {
  color: var(--rkr-link);
  border-color: var(--rkr-rule);
}
.rkr-post-copylink[data-state='copied'] {
  color: #2ea44f;
  border-color: color-mix(in srgb, #2ea44f 30%, transparent);
}
.rkr-post-copylink[data-state='error'] {
  color: #cf222e;
  border-color: color-mix(in srgb, #cf222e 30%, transparent);
}

/* Subtitle: under the h1, muted, slightly larger than body so it
   reads as a deck head rather than a stray paragraph. */
.rkr-post-subtitle {
  font-family: var(--rkr-display-font);
  font-size: 1.1rem;
  font-weight: 400;
  color: var(--rkr-muted);
  margin: 0 0 .5rem;
  line-height: 1.35;
}
article > header time {
  display: block;
  color: var(--rkr-muted);
  font-size: 0.9rem;
  font-family: var(--rkr-display-font);
}

article p,
article ul,
article ol,
article blockquote {
  margin: 1.1em 0;
}
article h2,
article h3,
article h4 {
  font-family: var(--rkr-display-font);
  letter-spacing: -0.015em;
  line-height: 1.25;
  margin: 2.4em 0 .6em;
}
article h2 { font-size: 1.5rem; }
article h3 { font-size: 1.2rem; }
article h4 { font-size: 1rem; text-transform: uppercase; letter-spacing: 0.05em; }

article a {
  color: var(--rkr-link);
  text-decoration: underline;
  text-underline-offset: 2px;
  text-decoration-thickness: 1px;
}
article a:hover { color: var(--rkr-link-hover); }

article blockquote {
  border-left: 3px solid var(--rkr-rule);
  padding-left: 1rem;
  color: var(--rkr-muted);
  font-style: italic;
}

article code {
  font-family: var(--rkr-mono-font);
  font-size: 0.92em;
  background: var(--rkr-rule);
  padding: 0.1em 0.35em;
  border-radius: var(--rkr-radius);
}
article pre {
  font-family: var(--rkr-mono-font);
  background: var(--rkr-rule);
  padding: 1rem;
  border-radius: var(--rkr-radius);
  overflow-x: auto;
  font-size: 0.9rem;
  line-height: 1.45;
}
article pre code {
  background: transparent;
  padding: 0;
}

article hr {
  border: 0;
  border-top: 1px solid var(--rkr-rule);
  margin: 3rem auto;
  width: 8ch;
}

/* ---- ::figure widget (unified, spec.md §9) ----------------------- */
/* The only image directive (legacy widgets removed). Grid mode for
   uniform NxM layouts; flow modes for justified / masonry; carousel
   mode kicks in when len(ids) exceeds matrix capacity. Per-cell styles
   live below; figure-level shell + caption styling here. */

.rkr-figure {
  display: block;
  margin: 2rem auto;
}
.rkr-figure-grid {
  display: grid;
  gap: var(--rkr-gap);
  width: 100%;
}
.rkr-figure-cell {
  display: block;
  /* Reserve aspect-ratio per cell. Defaults to the figure-level
     --rkr-cell-aspect (set on the <figure>); cells override with their
     own --rkr-image-aspect when no explicit aspect is given on the
     directive. */
  aspect-ratio: var(--rkr-cell-aspect, var(--rkr-image-aspect, 1));
  overflow: hidden;
  border-radius: var(--rkr-radius);
  background: var(--rkr-rule);
}
.rkr-figure-cell picture,
.rkr-figure-cell img {
  display: block;
  width: 100%;
  height: 100%;
  border-radius: 0;
  box-shadow: none;
}
.rkr-fit-cover .rkr-figure-cell img { object-fit: cover; }
.rkr-fit-contain .rkr-figure-cell img { object-fit: contain; }

/* Block placement (mirrors rkr-pos-* but renamed per spec). */
.rkr-justify-center {
  width: 100%;
  max-width: var(--rkr-content);
  margin-left: auto;
  margin-right: auto;
}
.rkr-justify-left {
  float: left;
  width: 40%;
  margin: 0.5rem 1rem 0.5rem 0;
  shape-margin: 0.5rem;
}
.rkr-justify-right {
  float: right;
  width: 40%;
  margin: 0.5rem 0 0.5rem 1rem;
  shape-margin: 0.5rem;
}
@media (max-width: 600px) {
  .rkr-justify-left,
  .rkr-justify-right { float: none; width: 100%; margin: 1rem 0; }
}
.rkr-justify-full {
  width: 100%;
  max-width: var(--rkr-content);
  margin-left: auto;
  margin-right: auto;
}
.rkr-justify-bleed {
  /* Break out of the containing column to span the full viewport. */
  width: 100vw;
  margin-left: calc(50% - 50vw);
  margin-right: calc(50% - 50vw);
  max-width: none;
}
/* Inline mode wraps the picture in a <span> rather than <figure>; styling
   matches the legacy rkr-pos-inline so authors get identical behaviour. */
span.rkr-justify-inline {
  display: inline-block;
  margin: 0 0.25em;
  vertical-align: text-bottom;
}
span.rkr-justify-inline img {
  display: inline-block;
  height: 1.5em;
  width: auto;
  border-radius: 0;
  box-shadow: none;
}

.rkr-figure > figcaption {
  margin-top: 0.5rem;
  font-family: var(--rkr-display-font);
  font-size: 0.875rem;
  color: var(--rkr-muted);
  text-align: center;
}

/* ---- ::figure flow layouts (justified, masonry) ------------------- */
/* Both modes are CSS-only. Each image keeps its native aspect;
   `aspect` / `fit` are ignored at the directive level. */

.rkr-figure-justified .rkr-figure-flow {
  display: flex;
  flex-wrap: wrap;
  gap: var(--rkr-gap);
}
.rkr-figure-justified .rkr-figure-cell {
  /* Each cell is a fixed-height row item; aspect-ratio drives intrinsic
     width. flex-grow with a basis of auto makes rows fill the container
     by stretching items proportionally — the standard CSS flex-justified
     trick. The visual compromise is that the LAST row also stretches
     (Flickr's original behaviour leaves it un-stretched); pure CSS
     can't distinguish "last incomplete row" without JS. Acceptable
     trade-off for now. */
  height: var(--rkr-row-height, 240px);
  flex: 1 1 auto;
  aspect-ratio: var(--rkr-image-aspect, 1.5);
  /* Override the grid-mode defaults that would force a fixed cell
     aspect from --rkr-cell-aspect. */
  background: transparent;
  overflow: hidden;
  border-radius: var(--rkr-radius);
}
.rkr-figure-justified .rkr-figure-cell picture,
.rkr-figure-justified .rkr-figure-cell img {
  width: 100%;
  height: 100%;
  object-fit: cover; /* fill the row-height box; aspect mismatch is rare */
}

.rkr-figure-masonry .rkr-figure-flow {
  /* Multi-column layout with the column count from --rkr-cols. Modern
     browsers (Firefox 110+, Chrome 119+, Safari 18+) also support
     `grid-template-rows: masonry` — when adoption is broad enough we
     can switch for a more Pinterest-faithful "shortest column" layout.
     `column-count` flows top-to-bottom which is visually similar. */
  column-count: var(--rkr-cols, 3);
  column-gap: var(--rkr-gap);
  display: block;
}
.rkr-figure-masonry .rkr-figure-cell {
  display: block;
  break-inside: avoid;
  margin: 0 0 var(--rkr-gap) 0;
  /* Override grid-mode aspect-ratio so each masonry cell's height
     follows its image's native aspect. */
  aspect-ratio: var(--rkr-image-aspect, 1);
  background: transparent;
  overflow: hidden;
  border-radius: var(--rkr-radius);
}
.rkr-figure-masonry .rkr-figure-cell picture,
.rkr-figure-masonry .rkr-figure-cell img {
  width: 100%;
  height: 100%;
  object-fit: cover;
}

/* ---- carousel widget ---------------------------------------------- */
/* Scroll-snap drives the actual slide motion: native touch swipe works
   for free, no JS swipe handler needed. Buttons + dots are wired by
   src/site/carousel.ts. */

.rkr-carousel {
  position: relative;
  display: block;
  width: 100%;
  max-width: var(--rkr-content);
  margin: 2.5rem auto;
  outline: none;
}
.rkr-carousel:focus-visible {
  box-shadow: 0 0 0 3px var(--rkr-link);
  border-radius: var(--rkr-radius);
}
.rkr-carousel > figcaption {
  margin-top: .75rem;
  text-align: center;
  color: var(--rkr-muted);
  font-size: 0.9rem;
  font-style: italic;
  max-width: var(--rkr-prose);
  margin-left: auto;
  margin-right: auto;
}

.rkr-carousel-track {
  display: flex;
  overflow-x: auto;
  scroll-snap-type: x mandatory;
  scroll-behavior: smooth;
  scrollbar-width: none;             /* Firefox */
  -webkit-overflow-scrolling: touch; /* iOS momentum */
  border-radius: var(--rkr-radius);
}
.rkr-carousel-track::-webkit-scrollbar { display: none; }
/* WCAG 2.3.3: respect prefers-reduced-motion. Auto-scroll instead of
   smooth keeps the carousel functional without animating motion the
   user explicitly opted out of. */
@media (prefers-reduced-motion: reduce) {
  .rkr-carousel-track { scroll-behavior: auto; }
}

.rkr-carousel-slide {
  flex: 0 0 100%;
  scroll-snap-align: start;
  margin: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  /* Reserve height from --aspect set by the renderer. */
  aspect-ratio: var(--aspect, 1.5);
  background: var(--rkr-rule);
}
.rkr-carousel-slide picture,
.rkr-carousel-slide img {
  display: block;
  width: 100%;
  height: 100%;
  object-fit: contain;
}

/* ---- ::figure carousel (multi-cell pages) ------------------------- */
/* When a figure overflows its matrix, each "slide" is a page containing
   `matrix.rows × matrix.cols` cells. Pages compose with the legacy
   .rkr-carousel-* CSS for the track + nav + dots; only the page contents
   differ (a grid instead of a single centered image). */

.rkr-figure-page {
  /* Override the single-image-slide assumptions inherited from
     .rkr-carousel-slide. Pages are grids; the inline `style` from the
     widget sets grid-template-rows/columns to the matrix shape. */
  display: grid;
  align-items: stretch;
  justify-content: stretch;
  aspect-ratio: auto;
  background: transparent;
  gap: var(--rkr-gap);
  padding: 0;
}
.rkr-figure-page .rkr-figure-cell {
  /* Each cell behaves the same as in the non-carousel grid path. */
  aspect-ratio: var(--rkr-cell-aspect, var(--rkr-image-aspect, 1));
}
/* Object-fit on the cell image itself is determined by the figure's
   rkr-fit-* class; the picture/img inside the page stretches to the cell. */
.rkr-figure-page picture,
.rkr-figure-page img {
  width: 100%;
  height: 100%;
}

/* Nav row sits below the track; on hover, prev/next overlay the image. */
.rkr-carousel-nav {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: .5rem;
  margin-top: .5rem;
}
.rkr-carousel-prev,
.rkr-carousel-next,
.rkr-carousel-play {
  background: transparent;
  border: 1px solid var(--rkr-rule);
  color: var(--rkr-text);
  border-radius: 999px;
  width: 2rem;
  height: 2rem;
  font-size: 1rem;
  line-height: 1;
  cursor: pointer;
  display: inline-flex;
  align-items: center;
  justify-content: center;
}
.rkr-carousel-prev:hover,
.rkr-carousel-next:hover,
.rkr-carousel-play:hover {
  background: var(--rkr-rule);
}

.rkr-carousel-dots {
  display: inline-flex;
  gap: .25rem;
  align-items: center;
}
/* WCAG 2.5.8 (AA, 2.2): 24x24px hit area. The visible dot stays small
   for design; padding + box-shadow make the dot itself, but the
   button is sized for the touch/click target. */
.rkr-carousel-dot {
  width: 24px;
  height: 24px;
  padding: 0;
  border-radius: 50%;
  border: none;
  background: transparent;
  cursor: pointer;
  display: inline-flex;
  align-items: center;
  justify-content: center;
}
.rkr-carousel-dot::after {
  content: '';
  display: block;
  width: .55rem;
  height: .55rem;
  border-radius: 50%;
  border: 1px solid var(--rkr-muted);
  background: transparent;
}
.rkr-carousel-dot.is-active::after {
  background: var(--rkr-text);
  border-color: var(--rkr-text);
}

/* ---- index page --------------------------------------------------- */

/* Visually-hidden but accessible — the index has site chrome that already
   shows the title, but every page needs a document-level <h1>. */
.rkr-index-heading {
  position: absolute;
  width: 1px; height: 1px;
  padding: 0; margin: -1px;
  overflow: hidden; clip-path: inset(50%);
  white-space: nowrap; border: 0;
}

.post-list {
  list-style: none;
  padding: 0;
  max-width: var(--rkr-prose);
  margin: 0 auto;
}
.post-list li {
  display: grid;
  grid-template-columns: max-content 1fr;
  gap: 1.25rem;
  align-items: baseline;
  padding: 1rem 0;
  border-bottom: 1px solid var(--rkr-rule);
}
.post-list li:last-child {
  border-bottom: 0;
}
.post-list time {
  color: var(--rkr-muted);
  font-size: 0.85rem;
  font-family: var(--rkr-display-font);
  white-space: nowrap;
}
.post-list a {
  font-family: var(--rkr-display-font);
  color: var(--rkr-text);
  text-decoration: none;
  font-size: 1.05rem;
  font-weight: 500;
}
.post-list a:hover {
  color: var(--rkr-link);
}

/* pager */
nav[aria-label="pagination"] {
  margin: 2.5rem auto;
  text-align: center;
  font-size: 0.9rem;
  color: var(--rkr-muted);
}
nav[aria-label="pagination"] a {
  color: var(--rkr-link);
  margin: 0 .75rem;
  text-decoration: none;
}

/* ---- mobile ------------------------------------------------------- */

@media (max-width: 640px) {
  html { font-size: 16px; }
  main { padding: 1.25rem 1rem; }
  .rkr-site-head { padding: 1rem 1rem 0.75rem; }
  article > header h1 { font-size: 1.6rem; }
  .post-list li {
    grid-template-columns: 1fr;
    gap: 0.25rem;
  }
  /* Wrap-positioned figures stack at mobile widths — wrapping prose
     around tiny images on narrow screens is unreadable. */
  .rkr-justify-left,
  .rkr-justify-right {
    float: none;
    width: 100%;
    max-width: var(--rkr-prose);
    margin: 1.5rem auto;
  }
  /* Full-bleed clamps to viewport (already 100vw); keep as-is. */

  /* Masonry shrinks to two columns on narrow screens. */
  .rkr-figure-masonry .rkr-figure-flow { column-count: 2; }
  /* Justified: shorter rows for narrower viewports. */
  .rkr-figure-justified .rkr-figure-cell { height: 140px; }

  /* Carousel: keep slides full-width; shrink nav buttons. */
  .rkr-carousel-prev,
  .rkr-carousel-next,
  .rkr-carousel-play {
    width: 1.75rem;
    height: 1.75rem;
    font-size: 0.9rem;
  }
}

@media (max-width: 400px) {
  .rkr-figure-masonry .rkr-figure-flow { column-count: 1; }
}
