/* ssgtheme — reset, layout and components.
 *
 * The reset, .container, .prose and the header/card/footer components follow
 * the Tradik design system's own stylesheet, so the built site reads as the
 * same family: flat surfaces, hairline borders in --color-border-subtle,
 * underline-on-accent navigation, whole-card links that lift on hover, an
 * inverse code block, and a serif display face against a sans UI face.
 *
 * Nothing here hard-codes a colour, size or duration that a token names.
 */

/* Cache-bust marker. The edge pinned a 404 page under this file's previous
   content-addressed URL with a year-long immutable header, which no redeploy
   could correct; changing the bytes changes the URL, which is the only way past
   a poisoned immutable entry. Bump the date if it ever happens again.
   Last bust: 2026-08-07. */

@import url("tokens.372e90a5.css");

/* ── Reset ──────────────────────────────────────────────────────────────── */

*,
*::before,
*::after {
  box-sizing: border-box;
}

* {
  margin: 0;
}

html {
  -webkit-text-size-adjust: 100%;
  text-size-adjust: 100%;
  scroll-behavior: smooth;
  scroll-padding-top: var(--space-16);
  /* Safety net: nothing may widen the page past the viewport on phones. `clip`
   * (not `hidden`) because it does not create a scroll container, so the sticky
   * header keeps working. Individual wide elements (code, tables, diagrams)
   * scroll inside their own overflow-x: auto containers instead. */
  overflow-x: clip;
}

html,
body {
  height: 100%;
}

body {
  font-family: var(--font-family-sans);
  font-size: var(--font-size-base);
  line-height: var(--line-height-normal);
  color: var(--color-fg-primary);
  background: var(--color-bg-canvas);
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
}

img,
picture,
svg,
video {
  display: block;
  max-width: 100%;
}

input,
button,
textarea,
select {
  font: inherit;
  color: inherit;
}

button {
  background: none;
  border: 0;
  padding: 0;
  cursor: pointer;
}

a {
  color: var(--color-fg-link);
  text-decoration: underline;
  text-underline-offset: 0.2em;
}

a:hover {
  text-decoration-thickness: 2px;
}

:focus-visible {
  outline: 2px solid var(--color-border-focus);
  outline-offset: 2px;
  border-radius: var(--radius-sm);
}

::selection {
  background: var(--color-accent-bg);
  color: var(--color-accent-fg);
}

/* ── Layout ─────────────────────────────────────────────────────────────── */

.container {
  width: 100%;
  max-width: 72rem;
  margin-inline: auto;
  padding-inline: var(--space-4);
}

@media (min-width: 768px) {
  .container {
    padding-inline: var(--space-8);
  }
}

.prose {
  max-width: 44rem;
  /* Long unbreakable tokens (URLs, config keys) wrap instead of widening the
   * page past the viewport on phones. */
  overflow-wrap: break-word;
}

.skip-link {
  position: absolute;
  top: -40px;
  left: var(--space-4);
  background: var(--color-bg-inverse);
  color: var(--color-fg-onInverse);
  padding: var(--space-2) var(--space-3);
  border-radius: var(--radius-sm);
  text-decoration: none;
  z-index: 100;
}

.skip-link:focus {
  top: var(--space-2);
}

.eyebrow {
  text-transform: uppercase;
  letter-spacing: var(--letter-spacing-caps);
  font-size: var(--font-size-xs);
  color: var(--color-fg-muted);
  font-weight: var(--font-weight-medium);
}

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

/* ── Header ─────────────────────────────────────────────────────────────── */

.site-header {
  border-block-end: 1px solid var(--color-border-subtle);
  background: var(--color-bg-canvas);
  position: sticky;
  top: 0;
  z-index: 50;
  backdrop-filter: saturate(150%) blur(8px);
}

.header-inner {
  display: flex;
  flex-direction: column;
  gap: var(--space-3);
  padding-block: var(--space-3);
}

@media (min-width: 768px) {
  .header-inner {
    flex-direction: row;
    align-items: center;
    justify-content: space-between;
  }
}

.brand {
  display: inline-flex;
  align-items: center;
  gap: var(--space-2);
  color: var(--color-fg-primary);
  text-decoration: none;
}

/* The mark is sized by height so any aspect ratio fits the 40 px header band;
 * it carries its own transparency, so no plate or filter is applied and it
 * reads on both schemes. */
.brand-mark {
  height: 2.25rem;
  width: auto;
  flex: none;
}

.brand-mark--footer {
  height: 3rem;
}

.brand-text {
  display: inline-flex;
  flex-direction: column;
  line-height: 1;
}

.brand-name {
  font-family: var(--font-family-sans);
  font-weight: var(--font-weight-semibold);
  font-size: var(--font-size-lg);
  letter-spacing: var(--letter-spacing-tight);
}

.brand-sub {
  font-size: var(--font-size-xs);
  color: var(--color-fg-muted);
  margin-top: 2px;
}

.header-actions {
  display: flex;
  align-items: center;
  gap: var(--space-4);
}

.nav-list {
  list-style: none;
  padding: 0;
  margin: 0;
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-1) var(--space-4);
}

.nav-list a {
  color: var(--color-fg-secondary);
  text-decoration: none;
  font-size: var(--font-size-sm);
  padding-block: var(--space-1);
  border-block-end: 2px solid transparent;
}

.nav-list a:hover {
  color: var(--color-fg-primary);
}

.nav-list a[aria-current="page"] {
  color: var(--color-fg-primary);
  border-block-end-color: var(--color-accent-bg);
}

.stars {
  display: inline-flex;
  align-items: center;
  gap: var(--space-1);
  padding: var(--space-1) var(--space-3);
  border: 1px solid var(--color-border-default);
  border-radius: var(--radius-pill);
  color: var(--color-fg-secondary);
  font-size: var(--font-size-xs);
  font-variant-numeric: tabular-nums;
  text-decoration: none;
  white-space: nowrap;
}

.stars:hover {
  border-color: var(--color-border-strong);
  color: var(--color-fg-primary);
}

.version-note {
  color: var(--color-fg-muted);
  font-size: var(--font-size-xs);
  white-space: nowrap;
}

.version-note a {
  color: var(--color-fg-accent);
  text-decoration: none;
}

.version-note a:hover {
  text-decoration: underline;
}

@media (max-width: 1023px) {
  .version-note {
    display: none;
  }
}

.theme-toggle {
  color: var(--color-fg-muted);
  font-size: var(--font-size-sm);
  min-height: 2.5rem;
  min-width: 2.5rem;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  border-radius: var(--radius-sm);
}

.theme-toggle:hover {
  color: var(--color-fg-primary);
}

/* ── Hero ───────────────────────────────────────────────────────────────── */

.hero {
  margin-block-start: var(--space-12);
}

/* A photographic hero keeps the same type contrast as a plain one: the image
 * sits under a scrim built from the canvas colour, so --color-fg-primary still
 * measures 17.9:1 (light) / 16.9:1 (dark) over it. The gradient is part of the
 * same background shorthand, so it can never be missing. */
.hero--image {
  position: relative;
  margin-block-start: 0;
  margin-inline: calc(var(--space-4) * -1);
  padding: var(--space-16) var(--space-4) var(--space-12);
  border-radius: var(--radius-xl);
  background-image: var(--hero-scrim), var(--hero-image-sm);
  background-size: cover;
  background-position: center;
  overflow: hidden;
}

/* The copy occupies the left half; keeping it there is what lets the scrim
 * fade out over the photograph instead of covering all of it. */
.hero--image .hero-actions,
.hero--image h1,
.hero--image p {
  max-width: 34rem;
}

@media (min-width: 768px) {
  .hero--image {
    margin-inline: 0;
    padding-block: var(--space-20) var(--space-16);
    padding-inline: var(--space-10);
    min-height: 30rem;
    background-image: var(--hero-scrim), var(--hero-image);
  }
}

/* A hairline border disappears over a photograph; the secondary button needs a
 * visible edge to stay a button. */
.hero--image .btn--secondary {
  border-color: var(--color-border-strong);
  background: var(--color-bg-canvas);
}

.hero h1 {
  font-family: var(--font-family-display);
  font-size: var(--font-size-5xl);
  font-weight: var(--font-weight-semibold);
  line-height: var(--line-height-tight);
  letter-spacing: var(--letter-spacing-tight);
  margin-block: var(--space-3) var(--space-4);
  max-width: 18ch;
}

.hero p {
  color: var(--color-fg-secondary);
  font-size: var(--font-size-lg);
  line-height: var(--line-height-relaxed);
  max-width: 60ch;
}

.hero-actions {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-3);
  margin-block-start: var(--space-6);
}

/* ── Buttons ────────────────────────────────────────────────────────────── */

.btn {
  display: inline-flex;
  align-items: center;
  gap: var(--space-2);
  min-height: 2.5rem;
  padding-inline: var(--space-5);
  border-radius: var(--radius-md);
  border: 1px solid transparent;
  font-size: var(--font-size-sm);
  font-weight: var(--font-weight-medium);
  text-decoration: none;
  transition: background var(--motion-duration-fast) var(--motion-easing-standard),
    border-color var(--motion-duration-fast) var(--motion-easing-standard);
}

.btn--primary {
  background: var(--color-accent-bg);
  color: var(--color-accent-fg);
}

.btn--primary:hover {
  background: var(--color-accent-bgHover);
}

.btn--primary:active {
  background: var(--color-accent-bgActive);
}

.btn--secondary {
  border-color: var(--color-border-default);
  color: var(--color-fg-primary);
}

.btn--secondary:hover {
  border-color: var(--color-border-strong);
}

/* ── Sections and cards ─────────────────────────────────────────────────── */

.sections {
  margin-block-start: var(--space-12);
}

.section-title {
  font-family: var(--font-family-display);
  font-size: var(--font-size-2xl);
  font-weight: var(--font-weight-semibold);
  letter-spacing: var(--letter-spacing-tight);
  margin-block: var(--space-3) var(--space-2);
}

.section-lead {
  color: var(--color-fg-secondary);
  font-size: var(--font-size-sm);
  max-width: 60ch;
  margin-block-end: var(--space-6);
}

.cards {
  list-style: none;
  padding: 0;
  margin: 0;
  display: grid;
  gap: var(--space-4);
  grid-template-columns: 1fr;
}

@media (min-width: 640px) {
  .cards {
    grid-template-columns: repeat(2, 1fr);
  }
}

@media (min-width: 1024px) {
  .cards {
    grid-template-columns: repeat(3, 1fr);
  }
}

.card {
  display: block;
  padding: var(--space-5);
  border: 1px solid var(--color-border-subtle);
  border-radius: var(--radius-lg);
  background: var(--color-bg-subtle);
  color: inherit;
  text-decoration: none;
  transition: border-color var(--motion-duration-base) var(--motion-easing-standard),
    transform var(--motion-duration-base) var(--motion-easing-standard);
}

.card:hover {
  border-color: var(--color-border-strong);
  transform: translateY(-2px);
}

.card h3 {
  font-family: var(--font-family-display);
  font-size: var(--font-size-xl);
  font-weight: var(--font-weight-semibold);
  margin-block-end: var(--space-2);
}

.card p {
  color: var(--color-fg-secondary);
  font-size: var(--font-size-sm);
}

.card-meta {
  color: var(--color-fg-muted);
  font-size: var(--font-size-xs);
  margin-block-end: var(--space-2);
}

.badge {
  display: inline-block;
  padding: var(--space-1) var(--space-3);
  border: 1px solid var(--color-border-default);
  border-radius: var(--radius-pill);
  font-size: var(--font-size-xs);
  color: var(--color-fg-secondary);
  text-decoration: none;
}

.badge:hover {
  border-color: var(--color-border-strong);
  color: var(--color-fg-primary);
}

/* ── Article ────────────────────────────────────────────────────────────── */

.article {
  margin-block: var(--space-12) var(--space-16);
}

.article-meta {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-3);
  color: var(--color-fg-muted);
  font-size: var(--font-size-sm);
  margin-block-start: var(--space-3);
}

.prose h1,
.prose h2,
.prose h3,
.prose h4 {
  font-family: var(--font-family-display);
  letter-spacing: var(--letter-spacing-tight);
  line-height: var(--line-height-tight);
  margin-block: var(--space-8) var(--space-4);
}

.prose h1 {
  font-size: var(--font-size-4xl);
  font-weight: var(--font-weight-semibold);
  margin-block-start: 0;
}

.prose h2 {
  font-size: var(--font-size-2xl);
  font-weight: var(--font-weight-semibold);
}

.prose h3 {
  font-size: var(--font-size-xl);
  font-weight: var(--font-weight-semibold);
}

.prose h4 {
  font-size: var(--font-size-lg);
  font-weight: var(--font-weight-semibold);
}

.prose p,
.prose li {
  margin-block: var(--space-3);
}

.prose ul,
.prose ol {
  padding-inline-start: var(--space-6);
}

.prose blockquote {
  border-inline-start: 2px solid var(--color-border-strong);
  padding-inline-start: var(--space-4);
  color: var(--color-fg-secondary);
  margin-block: var(--space-4);
}

.prose code {
  font-family: var(--font-family-mono);
  font-size: 0.92em;
  background: var(--color-bg-sunken);
  padding: 0.15em 0.35em;
  border-radius: var(--radius-sm);
  /* Inline flags like `--check-images[=warn|strict]` have no spaces and are
   * wider than a phone viewport; let them break anywhere. A no-op inside
   * .prose pre, where white-space: pre keeps code lines intact and the block
   * scrolls instead. */
  overflow-wrap: anywhere;
}

.prose pre {
  font-family: var(--font-family-mono);
  background: var(--color-bg-inverse);
  color: var(--color-fg-onInverse);
  padding: var(--space-4);
  border-radius: var(--radius-md);
  overflow-x: auto;
  margin-block: var(--space-4);
}

.prose pre code {
  background: transparent;
  padding: 0;
  color: inherit;
}

.prose table {
  width: 100%;
  border-collapse: collapse;
  font-size: var(--font-size-sm);
  margin-block: var(--space-4);
  display: block;
  overflow-x: auto;
}

.prose th,
.prose td {
  border-block-end: 1px solid var(--color-border-default);
  padding: var(--space-2) var(--space-3);
  text-align: left;
}

.prose th {
  font-weight: var(--font-weight-semibold);
}

.prose hr {
  border: 0;
  border-block-start: 1px solid var(--color-border-subtle);
  margin-block: var(--space-8);
}

.pager {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-3);
  align-items: center;
  margin-block-start: var(--space-8);
  font-size: var(--font-size-sm);
}

/* ── Footer ─────────────────────────────────────────────────────────────── */

.site-footer {
  margin-block-start: var(--space-16);
  padding-block: var(--space-10) var(--space-6);
  border-block-start: 1px solid var(--color-border-subtle);
  background: var(--color-bg-subtle);
  color: var(--color-fg-secondary);
  font-size: var(--font-size-sm);
}

.footer-grid {
  display: grid;
  gap: var(--space-8);
  grid-template-columns: 1fr;
}

@media (min-width: 768px) {
  .footer-grid {
    grid-template-columns: 1fr 2fr;
    align-items: start;
  }
}

.brand-block {
  display: grid;
  gap: var(--space-2);
  align-content: start;
  max-width: 22rem;
}

.brand-block .brand-name {
  font-family: var(--font-family-display);
  font-size: var(--font-size-lg);
  font-weight: var(--font-weight-semibold);
  color: var(--color-fg-primary);
}

.brand-tag {
  color: var(--color-fg-muted);
}

.footer-nav {
  display: grid;
  gap: var(--space-6);
  grid-template-columns: repeat(2, 1fr);
}

@media (min-width: 1024px) {
  .footer-nav {
    grid-template-columns: repeat(4, 1fr);
  }
}

.col h2 {
  font-size: var(--font-size-xs);
  text-transform: uppercase;
  letter-spacing: var(--letter-spacing-caps);
  color: var(--color-fg-muted);
  font-weight: var(--font-weight-semibold);
  margin-block-end: var(--space-3);
}

.col ul {
  list-style: none;
  padding: 0;
  margin: 0;
  display: grid;
  gap: var(--space-2);
}

.col a {
  color: var(--color-fg-secondary);
  text-decoration: none;
  display: inline-block;
  min-height: 1.5rem;
}

.col a:hover {
  color: var(--color-fg-primary);
  text-decoration: underline;
  text-underline-offset: 0.2em;
}

.legal {
  margin-block-start: var(--space-8);
  padding-block-start: var(--space-4);
  border-block-start: 1px solid var(--color-border-subtle);
  color: var(--color-fg-muted);
  font-size: var(--font-size-xs);
  line-height: var(--line-height-relaxed);
  display: grid;
  gap: var(--space-2);
}

@media (prefers-reduced-motion: reduce) {
  *,
  *::before,
  *::after {
    animation-duration: 0.01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.01ms !important;
    scroll-behavior: auto !important;
  }
}

/* ── Marquee ────────────────────────────────────────────────────────────────
   A scrolling "deploys natively to" strip.

   The track is duplicated in the markup and the animation translates by exactly
   one track width, so the copy lands where the original started and the loop has
   no seam. That only holds if the two tracks sit flush: the leading gap belongs
   to each track's own padding, never to a gap on the viewport, or every lap
   jumps by the width of that gap.

   Motion is the reader's choice. Under prefers-reduced-motion the animation stops
   and an ordinary horizontally scrollable row remains, so nothing becomes
   unreachable (WCAG 2.2 2.3.3). It also pauses on hover and on keyboard focus,
   because a link moving under the pointer cannot be clicked.                    */

.marquee {
  /* No token names a duration this long — the motion tokens size
     micro-interactions. Exposed here so a site can tune the pace. */
  --marquee-duration: 32s;
  margin: var(--space-16) 0;
  text-align: center;
}

.marquee__title {
  margin-bottom: var(--space-6);
  font-size: var(--font-size-sm);
  font-weight: var(--font-weight-semibold);
  letter-spacing: var(--letter-spacing-caps);
  text-transform: uppercase;
  color: var(--color-fg-muted);
}

.marquee__viewport {
  display: flex;
  overflow: hidden;
  /* Fade the edges so entries arrive and leave instead of being cut mid-letter. */
  -webkit-mask-image: linear-gradient(90deg, transparent, #000 6%, #000 94%, transparent);
  mask-image: linear-gradient(90deg, transparent, #000 6%, #000 94%, transparent);
}

.marquee__track {
  display: flex;
  flex: 0 0 auto;
  align-items: center;
  gap: var(--space-16);
  /* The leading gap lives here rather than on the viewport — see the note above. */
  padding-left: var(--space-16);
  margin: 0;
  list-style: none;
  animation: marquee-scroll var(--marquee-duration) linear infinite;
}

.marquee__viewport:hover .marquee__track,
.marquee__viewport:focus-within .marquee__track {
  animation-play-state: paused;
}

.marquee__item {
  flex: 0 0 auto;
  color: var(--color-fg-secondary);
  transition: color var(--motion-duration-base) var(--motion-easing-standard);
}

.marquee__item:hover,
.marquee__item:focus-within {
  color: var(--color-fg-primary);
}

.marquee__item a,
.marquee__item > span {
  display: inline-flex;
  align-items: center;
  gap: var(--space-3);
  color: inherit;
  text-decoration: none;
}

/* Sized in em so the mark scales with its label rather than against it. */
.marquee__logo {
  width: 1.75em;
  height: 1.75em;
  flex: 0 0 auto;
}

.marquee__name {
  font-size: var(--font-size-base);
  font-weight: var(--font-weight-medium);
  white-space: nowrap;
}

@keyframes marquee-scroll {
  from {
    transform: translateX(0);
  }
  to {
    transform: translateX(-100%);
  }
}

@media (prefers-reduced-motion: reduce) {
  .marquee__viewport {
    overflow-x: auto;
    -webkit-mask-image: none;
    mask-image: none;
  }

  .marquee__track {
    animation: none;
  }

  /* The duplicate exists only to hide the seam; with the animation off it is
     redundant repetition in a plain scrollable row. */
  .marquee__track[aria-hidden="true"] {
    display: none;
  }
}

/* ── Pillars ─────────────────────────────────────────────────────────────────
   The three-column "why" row. Plain surfaces rather than cards: these are text
   to be read, not links to be clicked, and giving them card affordances would
   promise a click target that is not there — only the "more" line is a link.  */

.pillars {
  --pillar-rule: var(--color-border-subtle);
}

.pillar-list {
  list-style: none;
  padding: 0;
  margin: 0;
  display: grid;
  gap: var(--space-8);
  grid-template-columns: 1fr;
}

@media (min-width: 900px) {
  .pillar-list {
    grid-template-columns: repeat(3, 1fr);
    gap: var(--space-10);
  }
}

.pillar {
  /* A hairline rather than a box: it groups the column without implying a
     surface you can interact with. */
  border-top: 1px solid var(--pillar-rule);
  padding-top: var(--space-4);
}

.pillar h3 {
  margin-bottom: var(--space-3);
  font-size: var(--font-size-lg);
  line-height: 1.25;
}

.pillar p {
  color: var(--color-fg-secondary);
}

.pillar strong {
  color: var(--color-fg-primary);
  font-weight: var(--font-weight-semibold);
}

.pillar-more {
  margin-top: var(--space-3);
  font-size: var(--font-size-sm);
}

/* "See all" line under a card grid. A generous top margin keeps the button
 * clearly separated from the clickable cards above, so adjacent targets never
 * crowd each other (WCAG 2.2 §2.5.8 Target Size). */
.section-more {
  margin-block-start: var(--space-8);
  font-size: var(--font-size-sm);
  color: var(--color-fg-secondary);
}

/* The hero lead carries the sentence that used to be the H1, so it needs more
   weight than body copy without competing with the heading above it. */
.hero-lead {
  font-size: var(--font-size-lg);
  max-width: 46ch;
}

/* ── Docs layout ─────────────────────────────────────────────────────────────
   A guide beside the list of guides. The sidebar is a plain <nav> in source
   order before the article, so with no CSS — or on a narrow screen — it reads
   as a table of contents above the page rather than disappearing.            */

.docs-layout {
  display: grid;
  gap: var(--space-8);
  grid-template-columns: 1fr;
}

@media (min-width: 1000px) {
  .docs-layout {
    grid-template-columns: 16rem minmax(0, 1fr);
    gap: var(--space-12);
    align-items: start;
  }

  .docs-nav {
    position: sticky;
    /* Clears the fixed header, matching the anchor offset used site-wide. */
    top: var(--space-16);
    max-height: calc(100vh - var(--space-24));
    overflow-y: auto;
  }
}

.docs-nav__title {
  margin-bottom: var(--space-3);
  font-size: var(--font-size-sm);
  font-weight: var(--font-weight-semibold);
  letter-spacing: var(--letter-spacing-caps);
  text-transform: uppercase;
  color: var(--color-fg-muted);
}

.docs-nav__list {
  list-style: none;
  margin: 0;
  padding: 0;
  border-left: 1px solid var(--color-border-subtle);
}

.docs-nav__link {
  display: block;
  padding: var(--space-2) var(--space-4);
  /* Sits on the list's rule, so the current item thickens the line rather than
     shifting the text. */
  margin-left: -1px;
  border-left: 2px solid transparent;
  color: var(--color-fg-secondary);
  text-decoration: none;
  font-size: var(--font-size-sm);
  line-height: 1.4;
}

.docs-nav__link:hover {
  color: var(--color-fg-primary);
  border-left-color: var(--color-border-default);
}

.docs-nav__link.is-current {
  color: var(--color-fg-accent);
  font-weight: var(--font-weight-medium);
  border-left-color: var(--color-fg-accent);
}

/* ── Theme gallery ───────────────────────────────────────────────────────────
   The bundled themes as cards. The screenshot is the point, so it leads; the
   text underneath says what the theme is for.                                */

.theme-cards {
  list-style: none;
  margin: var(--space-8) 0;
  padding: 0;
  display: grid;
  gap: var(--space-6);
  grid-template-columns: 1fr;
}

@media (min-width: 720px) {
  .theme-cards {
    grid-template-columns: repeat(2, minmax(0, 1fr));
  }
}

.theme-card {
  border: 1px solid var(--color-border-subtle);
  border-radius: var(--radius-lg);
  overflow: hidden;
  background: var(--color-bg-subtle);
  display: flex;
  flex-direction: column;
}

.theme-card img {
  display: block;
  width: 100%;
  height: auto;
  /* A consistent crop keeps the row tidy when themes have different heights;
     top alignment keeps each header and hero in frame. */
  aspect-ratio: 16 / 10;
  object-fit: cover;
  object-position: top center;
  border-bottom: 1px solid var(--color-border-subtle);
}

.theme-card__body {
  padding: var(--space-4) var(--space-5) var(--space-5);
}

.theme-card__body h3 {
  margin-bottom: var(--space-2);
  font-size: var(--font-size-lg);
}

.theme-card__body p {
  margin: 0;
  color: var(--color-fg-secondary);
  font-size: var(--font-size-sm);
}

.theme-card__tag {
  display: inline-block;
  margin-top: var(--space-3);
  font-size: var(--font-size-sm);
  color: var(--color-fg-muted);
}
