.fact-row {
  display: flex; flex-wrap: wrap; gap: 1rem 2.5rem;
  border-block: 1px solid var(--border-subtle);
  margin: 1.5rem 0 2rem; padding: 1rem 0;
}
.fact { margin: 0; }
.fact dt {
  font: .72rem var(--font-mono); letter-spacing: .1em;
  text-transform: uppercase; color: var(--text-muted);
}
.fact dd { margin: .15rem 0 0; font-weight: 600; }

.feature-grid {
  display: grid; grid-template-columns: repeat(auto-fit, minmax(230px, 1fr));
  gap: 1.25rem 1.75rem; list-style: none; padding: 0; margin: 0 0 2.5rem;
  max-width: 900px;
}
.feature-grid li { border-top: 1px solid var(--border-subtle); padding-top: .8rem; }
.feature-grid h3 { font-size: 1rem; margin-bottom: .3rem; }
.feature-grid p { font-size: .92rem; color: var(--text-muted); margin: 0; }

.download-row { display: flex; flex-wrap: wrap; gap: .75rem; margin-bottom: 1rem; }
.download-row .btn { min-width: 12rem; text-align: center; }
.platform-note { margin-bottom: 2rem; }

/* Comparison copy on tool pages: reading measure, not a wall of text. */
.why-copy { max-width: 72ch; }
.why-copy p { margin: 0 0 1rem; }

.faq { max-width: 70ch; }
.faq details { border-top: 1px solid var(--border-subtle); padding: .9rem 0; }
.faq summary { cursor: pointer; font-weight: 600; }
.faq details > *:not(summary) { margin-top: .6rem; }
.faq ul { padding-left: 1.25rem; }

.callout {
  border-left: 3px solid var(--status-ok);
  padding: .2rem 0 .2rem .9rem; margin-bottom: 1.5rem;
  color: var(--text-muted);
}

/* Clearly-labeled stand-in for a video that does not exist yet. Never a
   broken embed: the box holds its 16:9 space and says what will go here. */
.video-placeholder {
  aspect-ratio: 16 / 9;
  display: flex;
  align-items: center;
  justify-content: center;
  background: var(--surface-card);
  border: 1px solid var(--border-subtle);
  border-radius: 12px;
  color: var(--text-muted);
  font-family: var(--font-mono);
  font-size: 0.85rem;
  /* Keeps the box a modest note rather than a full-width band. */
  max-width: 640px;
  margin-bottom: 2rem;
}

.steps { padding-left: 1.3rem; max-width: 62ch; }
.steps li { margin-bottom: .5rem; }

.changelog { padding-left: 1.3rem; max-width: 68ch; }
.changelog li { margin-bottom: .45rem; }

/* ===== Screenshot carousel (static/js/shots.js) =====
   Scroll-snap does the layout, the swipe and the keyboard geometry. The script
   only adds the buttons, the counter and a quiet auto-advance, so with no
   JS at all this is still a scrollable strip of screenshots. */
.shots { margin-bottom: 2.5rem; }
.shots__controls { display: flex; align-items: center; gap: .5rem; margin-bottom: .6rem; flex-wrap: wrap; }
.shots__btn {
  padding: .35rem .85rem; font: 600 .9rem var(--font-sans);
  border: 1px solid var(--border-subtle); border-radius: 8px;
  background: var(--surface-card); color: var(--text-primary); cursor: pointer;
}
.shots__btn:hover { background: var(--surface-hover); }
.shots__btn[aria-pressed="false"] { outline: 2px solid var(--accent-interactive); outline-offset: 1px; }
.shots__count {
  margin-left: auto; font: .78rem var(--font-mono); color: var(--text-muted);
}
.shots__hint { font: .8rem var(--font-mono); color: var(--text-muted); margin: 0 0 .85rem; }
.shots__track {
  display: flex; gap: 1rem; margin: 0; padding: 0 0 .6rem;
  list-style: none;
  overflow-x: auto; overscroll-behavior-x: contain;
  scroll-snap-type: x mandatory;
  scrollbar-width: thin;
}
/* One aspect for all twelve slides, so the 774px and 810px sources share
   pixel-identical outer dimensions. Images letterbox inside with contain. */
.shots__slide {
  flex: 0 0 min(92%, 900px); margin: 0; scroll-snap-align: center;
  aspect-ratio: 16 / 9;
}
.shots__slide img {
  display: block; width: 100%; height: 100%; object-fit: contain;
  border: 1px solid var(--border-subtle); border-radius: 12px;
  background: #101418;
}
.shots__cap { margin: .55rem 0 0; font: .8rem var(--font-mono); color: var(--text-muted); }

/* Taller slides where there is room: dense app screenshots stay readable. */
@media (min-width: 1024px) {
  .shots__slide { flex-basis: min(92%, 900px); height: min(64vh, 620px); aspect-ratio: auto; }
}
@media (min-width: 641px) and (max-width: 1023px) {
  .shots__slide { height: 52vh; aspect-ratio: auto; }
}
@media (max-width: 640px) {
  .shots__slide { height: min(60vh, 420px); aspect-ratio: auto; }
}

/* An empty ad slot reserves no space and shows no label: a labelled empty
   box reads as broken, so the frame only exists when there is an ad. */
.ad-slot:empty { display: none; }
.ad-slot:not(:has(ins, iframe, .adblock-notice, .ad-status)) .ad-slot__label { display: none; }
.ad-slot:not(:has(ins, iframe, .adblock-notice, .ad-status)) { padding: 0; border: 0; margin: 0; min-height: 0; }

/* Footer-only sections used by the community guide page. */
.reputation { max-width: 68ch; }
.reputation li { margin-bottom: .5rem; }
.reputation--good li {
  border-left: 3px solid var(--status-ok);
  padding-left: .8rem;
}
.reputation--bad li {
  border-left: 3px solid var(--status-danger);
  padding-left: .8rem;
}

@media (max-width: 640px) {
  .download-row .btn { flex: 1 1 100%; min-width: 0; }
}

/* ===== Portfolio: stack line, featured project, case study ===== */
.stack-line, .contact-line { margin: 0 0 .6rem; font-size: .95rem; }
.contact-line { font-weight: 600; margin-bottom: 1rem; }
/* One rhythm for every portfolio section. Each block owns its top margin, so
   a section can never sit flush against whatever precedes it, whether that is
   a grid of cards, a boxed case study or the hero. */
.featured-section, .case-study, .projects-section, .writing-section {
  margin-top: clamp(3rem, 7vw, 4.75rem);
}
.featured-section .project-card--full { max-width: 1000px; }
@media (min-width: 900px) {
  .featured-section .project-card--full { grid-template-columns: .85fr 1.15fr; }
  /* The picture fills the text column's height instead of holding 16:9. It is
     a dedicated crop of the screenshot (image_card in portfolio.yaml) centred
     on the app's title with the queue sidebar trimmed, so filling a tall
     column scales it only a little. */
  .featured-section .project-card--full .project-card__media {
    position: relative; aspect-ratio: auto; align-self: stretch;
    border-bottom: 0; border-right: 1px solid var(--border-subtle);
  }
  .featured-section .project-card--full .project-card__media picture { display: contents; }
  .featured-section .project-card--full .project-card__media img {
    position: absolute; inset: 0; object-fit: cover; object-position: 50% 50%;
  }
  .featured-section .project-card--full .project-card__body { padding: 1.4rem; }
}
.formerly { margin: .8rem 0 0; font-size: .9rem; color: var(--text-muted); }
.case-study {
  max-width: 1000px; padding: 1.6rem 1.6rem 1.2rem;
  background: var(--surface-card);
  border: 1px solid var(--border-subtle);
  border-left: 6px solid var(--accent-brand);
  border-radius: var(--radius);
}
.case-study h2 { margin: 0 0 .8rem; font-size: 1.5rem; }
.case-study__kicker {
  margin: 0 0 .3rem; font: .75rem var(--font-mono);
  letter-spacing: .08em; text-transform: uppercase; color: var(--text-muted);
}
.case-study__body { max-width: 68ch; }
.case-study__link { margin: .4rem 0 0; font-weight: 600; }
.writing-section { padding-bottom: 1rem; }
.writing-intro { max-width: 68ch; margin-bottom: 1.5rem; }
.writing-cards {
  display: grid; gap: 1.25rem;
  grid-template-columns: repeat(auto-fit, minmax(17rem, 1fr));
  max-width: 1000px;
}
.writing-card {
  display: grid; gap: .45rem; align-content: start; padding: 1.25rem 1.3rem;
  text-decoration: none; color: var(--text-primary);
  background: var(--surface-card);
  border: 1px solid var(--border-subtle); border-left: 4px solid var(--accent-brand);
  border-radius: var(--radius);
  transition: transform .25s var(--ease, ease), border-color .2s ease, box-shadow .25s ease;
}
.writing-card:hover {
  transform: translateY(-4px);
  border-color: var(--accent-brand);
  box-shadow: 0 16px 34px -20px rgba(0, 0, 0, .55);
  color: var(--text-primary);
}
.writing-card__kicker {
  font: .72rem var(--font-mono); letter-spacing: .1em;
  text-transform: uppercase; color: var(--text-muted);
}
.writing-card__title { font-size: 1.15rem; font-weight: 600; line-height: 1.3; }
.writing-card__go {
  display: inline-flex; align-items: center; gap: .4rem;
  font-weight: 600; color: var(--accent-interactive);
}
.writing-card__go .icon { transition: transform .25s var(--ease, ease); }
.writing-card:hover .writing-card__go .icon { transform: translateX(5px); }

/* Changelog entries quote identifiers with no break points; wrap them rather than widen the page. */
.changelog li { overflow-wrap: anywhere; }
/* Uniform grid: extra row height goes to the text, so image rows line up across cards. */
.portfolio-grid .project-card { grid-template-rows: auto 1fr; }

/* Demo video: a privacy-friendly YouTube embed that holds its 16:9 box, so
   the page does not jump when the frame loads. */
.video-embed {
  position: relative; aspect-ratio: 16 / 9; max-width: 860px; margin-bottom: 1rem;
  border: 1px solid var(--border-subtle); border-radius: 12px; overflow: hidden;
  background: var(--surface-card);
}
.video-embed iframe { position: absolute; inset: 0; width: 100%; height: 100%; border: 0; }

.release-headline { font-size: 1.1rem; font-weight: 600; margin-bottom: .4rem; }
.changelog-group { font-size: 1rem; margin: 1.4rem 0 .5rem; }

/* Buttons that carry an arrow: label and icon on one line, icon nudging the way it points. */
.shots__btn { display: inline-flex; align-items: center; gap: .45rem; }
.shots__btn[data-shots-prev]:hover .icon { transform: translateX(-3px); }
.shots__btn[data-shots-next]:hover .icon { transform: translateX(3px); }
.notes-jump .btn { gap: .5rem; }
.notes-jump .btn:hover .icon { transform: translateY(3px); }

/* Capability groups on the tool pages: a heading over each feature grid. */
.cap-group {
  font: 600 .95rem var(--font-sans);
  margin: 1.8rem 0 .9rem;
  padding-bottom: .4rem;
  border-bottom: 1px solid var(--border-subtle);
  max-width: 900px;
}
.cap-group:first-of-type { margin-top: 1rem; }
