/* intelektas.ai stylesheet. Self-hosted fonts, no external requests, no JS. */

@font-face {
  font-family: "Inter";
  font-style: normal;
  font-weight: 400 600;
  font-display: swap;
  src: url("/assets/fonts/inter-latin.woff2") format("woff2");
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
@font-face {
  font-family: "Inter";
  font-style: normal;
  font-weight: 400 600;
  font-display: swap;
  src: url("/assets/fonts/inter-latin-ext.woff2") format("woff2");
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}
@font-face {
  font-family: "Montserrat";
  font-style: normal;
  font-weight: 700;
  font-display: swap;
  src: url("/assets/fonts/montserrat-700-latin.woff2") format("woff2");
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
@font-face {
  font-family: "Montserrat";
  font-style: normal;
  font-weight: 700;
  font-display: swap;
  src: url("/assets/fonts/montserrat-700-latin-ext.woff2") format("woff2");
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}

:root {
  --surface: #ffffff;
  --surface-alt: #f4f6f9;
  --surface-dark: #0b1020;
  --ink: #14181f;
  --ink-muted: #5b6472;
  --ink-on-dark: #ffffff;
  --rule: #e6e9ee;
  --accent: #29b6e8;
  --accent-text: #0b7ba5;
  --accent-2: #5a43d6;

  --font-display: "Montserrat", system-ui, -apple-system, "Segoe UI", sans-serif;
  --font-body: "Inter", system-ui, -apple-system, "Segoe UI", sans-serif;
  --font-mono: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;

  --pad: clamp(1.25rem, 3.5vw, 3.5rem);
  --measure: 720px;
  --wide: 1600px;
  --radius: 8px;

  /* Motion. One easing curve and three durations for the whole site. */
  --ease: cubic-bezier(0.2, 0.7, 0.2, 1);
  --dur-fast: 200ms;
  --dur: 300ms;
  --dur-slow: 420ms;

  /* Shadows. The only place a raw colour is allowed to appear. */
  --shadow-card: 0 1px 2px rgba(11, 16, 32, 0.04);
  --shadow-card-hover: 0 8px 22px rgba(11, 16, 32, 0.12);
  --shadow-header: 0 2px 14px rgba(11, 16, 32, 0.22);
  --tint-accent: rgba(41, 182, 232, 0.14);
  --tint-on-dark: rgba(255, 255, 255, 0.4);
  --ink-on-dark-soft: rgba(255, 255, 255, 0.86);
}

* {
  box-sizing: border-box;
}

html {
  -webkit-text-size-adjust: 100%;
}

body {
  margin: 0;
  background: var(--surface);
  color: var(--ink);
  font-family: var(--font-body);
  font-size: 18px;
  line-height: 1.65;
  -webkit-font-smoothing: antialiased;
  display: flex;
  flex-direction: column;
  min-height: 100vh;
}

main {
  flex: 1 0 auto;
}

h1,
h2,
h3 {
  font-family: var(--font-display);
  font-weight: 700;
  line-height: 1.18;
  letter-spacing: -0.01em;
  margin: 0 0 0.6rem;
  text-wrap: balance;
}

h1 {
  font-size: clamp(1.9rem, 4vw, 2.6rem);
}

p {
  margin: 0 0 1rem;
  text-wrap: pretty;
}

a {
  color: var(--accent-text);
  text-underline-offset: 0.15em;
}

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

/* Text links in running copy: the underline is drawn as a background layer so
   it can thicken on hover instead of blinking on and off. */
.prose a,
.talk-title a,
.home-all a,
.site-footer a {
  text-decoration: none;
  background-image: linear-gradient(currentColor, currentColor);
  background-repeat: no-repeat;
  background-position: 0 100%;
  background-size: 100% 1px;
  padding-bottom: 0.06em;
}

.prose a:hover,
.talk-title a:hover,
.home-all a:hover,
.site-footer a:hover {
  background-size: 100% 2px;
}

/* The footer wordmark is a mark, not a link in running text. */
.site-footer .wordmark {
  background-image: none;
  padding-bottom: 0;
}

:focus-visible {
  outline: 3px solid var(--accent);
  outline-offset: 2px;
}

.skip-link {
  position: absolute;
  left: -9999px;
  top: 0;
}

.skip-link:focus {
  left: 0.75rem;
  top: 0.75rem;
  z-index: 20;
  background: var(--surface);
  color: var(--ink);
  padding: 0.5rem 1rem;
  border: 2px solid var(--accent);
}

/* The heading is typeset into the cover image, so the real h1 stays in the
   document for the outline and for anything that does not load images. */
.visually-hidden {
  position: absolute;
  width: 1px;
  height: 1px;
  margin: -1px;
  padding: 0;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
  border: 0;
}

/* Header band */

.site-header {
  background: var(--surface-dark);
  color: var(--ink-on-dark);
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: 0.75rem 2rem;
  padding: 1.1rem var(--pad);
  position: sticky;
  top: 0;
  z-index: 10;
}

/* Shadow once the page has moved under the header. Scroll-driven animation
   where it exists, a class from site.js everywhere else. */
.site-header.is-scrolled {
  box-shadow: var(--shadow-header);
}

@supports (animation-timeline: scroll()) {
  .site-header {
    animation: header-lift linear both;
    animation-timeline: scroll();
    animation-range: 0 80px;
  }
}

@keyframes header-lift {
  from {
    box-shadow: 0 0 0 rgba(0, 0, 0, 0);
  }
  to {
    box-shadow: var(--shadow-header);
  }
}

.wordmark {
  font-family: var(--font-display);
  font-weight: 700;
  font-size: 1.2rem;
  letter-spacing: -0.02em;
  color: var(--ink-on-dark);
  text-decoration: none;
}

.wordmark .dot {
  color: var(--accent);
  display: inline-block;
  transform-origin: 50% 80%;
}

.site-nav ul {
  list-style: none;
  margin: 0;
  padding: 0;
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0.35rem 1.4rem;
}

.site-nav a {
  color: var(--ink-on-dark-soft);
  text-decoration: none;
  font-size: 0.98rem;
  padding: 0.15rem 0;
  position: relative;
}

/* The rule under a nav item is a pseudo-element so it can slide out from the
   left rather than appear all at once. */
.site-nav a::after {
  content: "";
  position: absolute;
  left: 0;
  right: 0;
  bottom: -2px;
  height: 2px;
  background: var(--tint-on-dark);
  transform: scaleX(0);
  transform-origin: left center;
}

.site-nav a:hover {
  color: var(--ink-on-dark);
}

.site-nav a:hover::after {
  transform: scaleX(1);
}

.site-nav a.is-current {
  color: var(--ink-on-dark);
}

.site-nav a.is-current::after {
  background: var(--accent);
  transform: scaleX(1);
}

.nav-langs {
  display: flex;
  align-items: center;
  gap: 0.35rem;
  font-size: 0.9rem;
}

.nav-langs .sep,
.footer-langs .sep {
  color: var(--ink-muted);
  margin: 0 0.15rem;
}

/* Footer */

.site-footer {
  background: var(--surface-alt);
  border-top: 1px solid var(--rule);
  padding: 2rem var(--pad);
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0.4rem 2rem;
  font-size: 0.95rem;
  color: var(--ink-muted);
}

.site-footer .wordmark {
  color: var(--ink);
  font-size: 1rem;
}

.site-footer p {
  margin: 0;
}

/* Cover banner: home, section index pages, pranešimai, apie. The cover already
   carries the heading, typeset into the light illustration, so this is only a
   frame: the alt surface behind it, a hairline so the near-white canvas has an
   edge, and the same 8px radius as every other image on the site. */

.cover-banner {
  background: var(--surface-alt);
  border-bottom: 1px solid var(--rule);
}

.cover-banner-inner {
  max-width: var(--wide);
  padding: clamp(1rem, 2.5vw, 2rem) var(--pad);
}

/* The build wraps every asset image in a <picture> so it can serve WebP with a
   PNG fallback. display: contents takes the wrapper out of the layout entirely,
   so every rule below still applies to the img as if it were a direct child of
   its figure, banner or card. */
picture {
  display: contents;
}

/* Capped rather than full bleed: at 7:4 an uncapped cover fills a laptop
   screen on its own and pushes every card below the fold. 920px wide and
   cropped to the Open Graph ratio (the same slice off the top and the bottom
   that lib/covers.js takes for the OG card, so nothing typeset is lost) keeps
   the title large and leaves the first row of cards visible on a laptop. */
.cover-img {
  display: block;
  width: 100%;
  max-width: 920px;
  height: auto;
  aspect-ratio: 1200 / 630;
  object-fit: cover;
  object-position: center;
  margin: 0 auto;
  border: 1px solid var(--rule);
  border-radius: var(--radius);
  background: var(--surface-alt);
}

/* Home */

.home {
  max-width: var(--wide);
  padding: clamp(2rem, 5vw, 3.5rem) var(--pad) 4rem;
}

.home.has-banner,
.section-page.has-banner,
.page-about.has-banner {
  padding-top: clamp(1.75rem, 3.5vw, 2.75rem);
}

.promise {
  font-family: var(--font-display);
  font-weight: 700;
  font-size: clamp(1.4rem, 2.8vw, 2.1rem);
  line-height: 1.25;
  letter-spacing: -0.015em;
  margin: 0 0 clamp(2rem, 4vw, 3rem);
  max-width: 30ch;
}

.home-grid {
  display: grid;
  grid-template-columns: 1fr;
  gap: 2.5rem 2.5rem;
}

.home-section h2 {
  font-size: 1.05rem;
  letter-spacing: 0.01em;
  border-top: 2px solid var(--ink);
  padding-top: 0.6rem;
  margin-bottom: 0.4rem;
}

.home-section h2 a {
  color: var(--ink);
  text-decoration: none;
}

.home-section h2 a:hover {
  color: var(--accent-text);
}

.home-all {
  margin: 0.75rem 0 0;
  font-size: 0.9rem;
}

/* One muted line for a first-time reader, between the cover and the posts. */
.home-hook {
  color: var(--ink-muted);
  margin: 0 0 clamp(1.5rem, 3vw, 2.25rem);
  font-size: 0.95rem;
}

/* The home page is three stacked blocks now (Naujausi, Rėmai, Vaizdais), each
   one the full width with its cards flowing inside it, so the grid stays a
   single column at every size and only the gap grows. */
@media (min-width: 860px) {
  .home-grid {
    gap: 3.5rem;
  }
}

/* Entry cards. Date, title, description and a thumbnail. The whole card is
   clickable through a pseudo-element on the title link, so the accessible name
   stays the title and there is still exactly one link per card. */

.entry-list {
  list-style: none;
  margin: 0;
  padding: 0;
  display: grid;
  gap: 0.9rem;
}

.entry {
  position: relative;
  display: grid;
  gap: 0.65rem;
  padding: 0.85rem 0.95rem;
  background: var(--surface);
  border: 1px solid var(--rule);
  border-radius: var(--radius);
  box-shadow: var(--shadow-card);
}

/* The stream filter hides cards with the hidden attribute, which the display
   above would otherwise win against. */
.entry[hidden] {
  display: none;
}

.entry-body {
  display: grid;
  gap: 0.15rem;
  align-content: start;
  min-width: 0;
}

/* The covers are drawn on a near-white canvas, so the thumbnail needs a
   hairline of its own or it bleeds into the card. */
.entry-thumb {
  display: block;
  overflow: hidden;
  border: 1px solid var(--rule);
  border-radius: calc(var(--radius) - 2px);
  background: var(--surface-alt);
}

.entry-thumb img {
  display: block;
  width: 100%;
  height: auto;
  aspect-ratio: 16 / 9;
  object-fit: cover;
}

.entry-date {
  color: var(--ink-muted);
  font-size: 0.85rem;
  font-variant-numeric: tabular-nums;
}

.entry-title {
  font-family: var(--font-display);
  font-weight: 700;
  font-size: 1.02rem;
  line-height: 1.28;
  letter-spacing: -0.01em;
  color: var(--ink);
  text-decoration: none;
  text-wrap: balance;
}

/* Cover the card. Keeps the link target large without nesting links. */
.entry-title::after {
  content: "";
  position: absolute;
  inset: 0;
  border-radius: var(--radius);
}

.entry:hover,
.entry:focus-within {
  box-shadow: var(--shadow-card-hover);
  border-color: var(--accent);
}

.entry:hover .entry-title,
.entry:focus-within .entry-title {
  color: var(--accent-text);
}

.entry:focus-within {
  outline: 3px solid var(--accent);
  outline-offset: 2px;
}

.entry-title:focus-visible {
  outline: none;
}

.entry-desc {
  color: var(--ink-muted);
  font-size: 0.95rem;
  line-height: 1.5;
}

/* Home blocks: small thumbnail beside the text so three entries stay compact.
   On a phone the text column would be too narrow, so it stacks instead. */
@media (min-width: 480px) {
  .entry-compact.has-thumb {
    grid-template-columns: 200px minmax(0, 1fr);
    gap: 1rem;
    align-items: start;
  }
}

.entry-compact .entry-desc {
  font-size: 0.9rem;
}

/* Section index: full width, cards flowing into as many columns as fit. */
@media (min-width: 720px) {
  /* Tracks have a ceiling so a section with a single post keeps a card-sized
     card instead of stretching one entry across the whole viewport. */
  .entry-list-wide {
    grid-template-columns: repeat(auto-fill, minmax(300px, 400px));
    justify-content: start;
    gap: 1.5rem 1.5rem;
  }

  .entry-list-wide .entry {
    padding: 1rem 1.1rem 1.2rem;
  }

  .entry-list-wide .entry-title {
    font-size: 1.12rem;
  }
}

/* The home blocks that are a row of covers rather than a column of titles:
   the frameworks, which are a fixed set of reference pages, and the comics,
   which are read as pictures. */
@media (min-width: 720px) {
  .entry-list-row {
    grid-template-columns: repeat(auto-fill, minmax(min(100%, 15rem), 1fr));
    gap: 1.5rem;
  }
}

/* Section and talk pages */

.section-page {
  max-width: var(--wide);
  padding: clamp(2rem, 5vw, 3.5rem) var(--pad) 4rem;
}

.section-intro {
  color: var(--ink-muted);
  max-width: 60ch;
  margin-bottom: 2rem;
}

.soon {
  color: var(--ink-muted);
}

/* The topic chips: "Visi" for the whole stream, then every section, on the
   stream page and on each section index. One row that wraps, every chip a
   plain link to a page that exists, and the current one filled so a reader
   always knows which slice of the site they are looking at. */
.section-chips {
  margin: -1rem 0 2.25rem;
  font-size: 0.9rem;
}

.section-chips ul {
  list-style: none;
  display: flex;
  flex-wrap: wrap;
  gap: 0.4rem;
  margin: 0;
  padding: 0;
}

.section-chips a {
  display: inline-block;
  padding: 0.2rem 0.7rem;
  border: 1px solid var(--rule);
  border-radius: 999px;
  background: var(--surface);
  color: var(--ink);
  text-decoration: none;
  transition: border-color var(--dur-fast) var(--ease), color var(--dur-fast) var(--ease),
    background-color var(--dur-fast) var(--ease);
}

.section-chips a:hover,
.section-chips a:focus-visible {
  border-color: var(--accent);
  color: var(--accent-text);
}

.section-chips a.is-current {
  background: var(--ink);
  border-color: var(--ink);
  color: var(--surface);
}

/* The bench: the sidebar and the cards on the stream page and on every section
   index. Two columns from 900px, the sidebar sticky under the header, the
   cards in two columns beside it. Below 900px the sidebar folds into a
   <details> above the list. Everything that needs the script is hidden until
   site.js adds the .js class, so a reader without it never meets a control
   that does nothing. */

.bench {
  max-width: var(--wide);
  padding: clamp(1.5rem, 4vw, 2.5rem) var(--pad) 0;
  display: grid;
  gap: 1.5rem;
  align-items: start;
}

.bench-foot {
  max-width: var(--wide);
  padding: 0 var(--pad) 4rem;
}

@media (min-width: 900px) {
  .bench {
    grid-template-columns: 300px minmax(0, 1fr);
    gap: 2.5rem 3rem;
  }

  .bench-side {
    position: sticky;
    top: 5.5rem;
  }
}

.bench-title {
  font-size: clamp(1.6rem, 3vw, 2.1rem);
  margin-bottom: 0.35rem;
}

.bench-intro {
  color: var(--ink-muted);
  font-size: 0.95rem;
  margin-bottom: 1.1rem;
}

/* The summary is the phone control only: from 900px the panel is simply open
   and the word "Filtrai" would be a label over nothing. */
.bench-filters summary {
  cursor: pointer;
  font-family: var(--font-display);
  font-weight: 700;
  font-size: 0.8rem;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  padding: 0.55rem 0;
  border-top: 1px solid var(--rule);
  border-bottom: 1px solid var(--rule);
}

@media (min-width: 900px) {
  .bench-filters summary {
    display: none;
  }
}

.bench-search {
  margin: 1rem 0 1.4rem;
}

.bench-search input {
  width: 100%;
  font: inherit;
  font-size: 0.95rem;
  padding: 0.4rem 0.7rem;
  color: var(--ink);
  background: var(--surface);
  border: 1px solid var(--rule);
  border-radius: var(--radius);
}

.bench-search input:hover {
  border-color: var(--accent);
}

.bench-group {
  margin: 0 0 1.5rem;
}

.bench-label {
  font-size: 0.72rem;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--ink-muted);
  margin: 0 0 0.35rem;
}

.bench-lines {
  list-style: none;
  margin: 0;
  padding: 0;
}

.bench-lines a,
.bench-lines button {
  display: flex;
  justify-content: space-between;
  align-items: baseline;
  gap: 0.75rem;
  width: 100%;
  font: inherit;
  font-size: 0.95rem;
  text-align: left;
  padding: 0.2rem 0 0.2rem 0.55rem;
  color: var(--ink);
  text-decoration: none;
  background: none;
  border: 0;
  border-radius: 2px;
  cursor: pointer;
}

.bench-lines a:hover,
.bench-lines button:hover {
  color: var(--accent-text);
}

/* The current topic and the pressed toggles: bold, with a cyan rule down the
   left so the state survives being read in grey. */
.bench-lines a.is-current,
.bench-lines button[aria-pressed="true"] {
  font-weight: 600;
  box-shadow: inset 2px 0 var(--accent);
}

.bench-lines button[aria-pressed="true"]::after {
  content: "\2713";
  color: var(--accent-text);
  font-size: 0.85rem;
}

.bench-count {
  color: var(--ink-muted);
  font-size: 0.85rem;
  font-variant-numeric: tabular-nums;
}

/* Search, length, sort, the view switch and the reveal button all need the
   script. Hidden until it says so. */
.bench-js,
.bench-search {
  display: none;
}

.js .bench-js,
.js .bench-search {
  display: block;
}

.bench-bar {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 1rem;
  margin: 0 0 1.1rem;
  padding-bottom: 0.5rem;
  border-bottom: 1px solid var(--rule);
}

.bench-showing {
  margin: 0;
  color: var(--ink-muted);
  font-size: 0.9rem;
}

.js .bench-view {
  display: flex;
  align-items: baseline;
  gap: 0.4rem;
  flex: none;
}

.bench-view button {
  font: inherit;
  font-size: 0.9rem;
  color: var(--ink-muted);
  background: none;
  border: 0;
  padding: 0;
  cursor: pointer;
}

.bench-view button:hover {
  color: var(--accent-text);
}

.bench-view button[aria-pressed="true"] {
  color: var(--ink);
  font-weight: 600;
}

.bench-view-sep {
  color: var(--rule);
}

.bench-list {
  gap: 1.25rem;
}

@media (min-width: 900px) {
  .bench-list {
    grid-template-columns: repeat(2, minmax(0, 1fr));
    gap: 1.5rem;
  }
}

/* A middle dot between the parts of the meta line, drawn rather than typed, so
   the markup stays date, section, minutes. */
.bench .entry-meta > * + *::before {
  content: "\00b7";
  color: var(--ink-muted);
  margin-right: 0.5rem;
}

/* List mode: no thumbnail, no blurb, one row per post with the meta and the
   title side by side once the column can hold both. */
.bench-list.is-list {
  grid-template-columns: 1fr;
  gap: 0;
}

.bench-list.is-list .entry {
  grid-template-columns: 1fr;
  padding: 0.7rem 0.2rem;
  border-width: 0 0 1px;
  border-radius: 0;
  box-shadow: none;
}

.bench-list.is-list .entry-thumb,
.bench-list.is-list .entry-desc {
  display: none;
}

@media (min-width: 720px) {
  .bench-list.is-list .entry-body {
    display: flex;
    align-items: baseline;
    gap: 0.9rem;
  }

  .bench-list.is-list .entry-meta {
    flex: none;
  }
}

.bench-more {
  display: block;
  margin: 1.5rem 0 0;
  font: inherit;
  font-size: 0.95rem;
  padding: 0.45rem 1.1rem;
  color: var(--ink);
  background: var(--surface);
  border: 1px solid var(--rule);
  border-radius: 999px;
  cursor: pointer;
}

.bench-more:hover {
  border-color: var(--accent);
  color: var(--accent-text);
}

.bench-more[hidden],
.bench-empty[hidden] {
  display: none;
}

.bench-empty {
  margin: 1.5rem 0 0;
  color: var(--ink-muted);
}

.bench-clear {
  font: inherit;
  color: var(--accent-text);
  background: none;
  border: 0;
  padding: 0;
  cursor: pointer;
  text-decoration: underline;
}

/* What to read after a post: exactly two entries, the rest of its own section
   first, then the newest of everything else. Same entry card as everywhere
   else, side by side once the prose column can hold two of them. */
.read-next {
  max-width: var(--measure);
  margin: 3.5rem 0 0;
  padding-top: 2rem;
  border-top: 1px solid var(--rule);
}

@media (min-width: 720px) {
  .entry-list-related {
    grid-template-columns: repeat(2, minmax(0, 1fr));
    gap: 1.2rem;
  }
}

.read-next h2 {
  font-size: 1rem;
  letter-spacing: 0.02em;
  text-transform: uppercase;
  color: var(--ink-muted);
  margin: 0 0 1.1rem;
}

.talk-list {
  list-style: none;
  margin: 0;
  padding: 0;
  display: grid;
  gap: 1.75rem;
}

@media (min-width: 900px) {
  .talk-list {
    grid-template-columns: repeat(2, minmax(0, 1fr));
    gap: 2rem 3rem;
  }
}

@media (min-width: 1440px) {
  .talk-list {
    grid-template-columns: repeat(3, minmax(0, 1fr));
  }
}

.talk {
  border-top: 2px solid var(--ink);
  padding-top: 0.7rem;
}

.talk-event {
  color: var(--ink-muted);
  font-size: 0.85rem;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  margin-bottom: 0.3rem;
}

.talk-title {
  font-size: 1.15rem;
  margin-bottom: 0.4rem;
}

.talk-line {
  margin-bottom: 0.3rem;
}

.talk-note {
  color: var(--ink-muted);
  font-size: 0.9rem;
  margin: 0;
}

/* Article and plain pages */

.post,
.page {
  max-width: calc(var(--measure) + 2 * var(--pad));
  margin: 0 auto;
  padding: clamp(2rem, 5vw, 3.5rem) var(--pad) 4rem;
}

.post-section {
  margin-bottom: 0.5rem;
  font-size: 0.85rem;
  letter-spacing: 0.04em;
  text-transform: uppercase;
}

.post-meta {
  color: var(--ink-muted);
  font-size: 0.9rem;
  margin-bottom: 2rem;
}

.post-read,
.post-updated {
  margin-left: 1rem;
}

/* The cover sits above the heading, article width, no caption: the title is
   already typeset into it. */
.post-cover {
  display: block;
  width: 100%;
  height: auto;
  margin: 0 0 1.75rem;
  border: 1px solid var(--rule);
  border-radius: var(--radius);
  background: var(--surface-alt);
}

.prose {
  max-width: var(--measure);
}

.prose > :first-child {
  margin-top: 0;
}

.prose h2 {
  font-size: 1.5rem;
  margin-top: 3.1rem;
}

.prose h3 {
  font-size: 1.2rem;
  margin-top: 2.2rem;
}

.prose ul,
.prose ol {
  padding-left: 1.3rem;
  margin: 0 0 1.2rem;
}

.prose li {
  margin-bottom: 0.4rem;
}

.prose a {
  color: var(--accent-text);
}

.prose blockquote {
  margin: 1.5rem 0;
  padding: 0.25rem 0 0.25rem 1.1rem;
  border-left: 3px solid var(--accent);
  color: var(--ink-muted);
}

.prose code {
  font-family: var(--font-mono);
  font-size: 0.9em;
  background: var(--surface-alt);
  padding: 0.1em 0.35em;
  border-radius: 3px;
}

.prose pre {
  background: var(--surface-alt);
  border: 1px solid var(--rule);
  padding: 1rem;
  overflow-x: auto;
}

.prose pre code {
  background: none;
  padding: 0;
}

.prose img {
  max-width: 100%;
  height: auto;
}

.prose figure {
  margin: 0 0 2rem;
}

.prose figure img {
  display: block;
  width: 100%;
  background: var(--surface-alt);
  border: 1px solid var(--rule);
  border-radius: var(--radius);
}

.prose figcaption {
  color: var(--ink-muted);
  font-size: 0.9rem;
  margin-top: 0.6rem;
}

.table-scroll {
  overflow-x: auto;
  margin: 1.5rem 0;
}

.prose table {
  border-collapse: collapse;
  width: 100%;
  font-size: 0.95rem;
}

.prose th,
.prose td {
  text-align: left;
  padding: 0.5rem 0.75rem;
  border-bottom: 1px solid var(--rule);
}

.prose th {
  font-weight: 600;
}

.summary-box {
  background: var(--surface-alt);
  border-left: 4px solid var(--accent);
  border-radius: 0 var(--radius) var(--radius) 0;
  padding: 1.2rem 1.4rem;
  margin: 2.5rem 0;
}

.summary-box > :first-child {
  margin-top: 0;
}

.summary-box > :last-child {
  margin-bottom: 0;
}

.summary-box h3 {
  margin-top: 0;
  font-size: 1.05rem;
}

.callout {
  background: var(--surface-alt);
  border: 1px solid var(--rule);
  border-radius: var(--radius);
  padding: 1.2rem 1.4rem;
  margin: 2.5rem 0;
}

.callout > :first-child {
  margin-top: 0;
}

.callout > :last-child {
  margin-bottom: 0;
}

/* Pull quote: one liftable line, cyan rule on the left. */
.pull-quote {
  font-family: var(--font-display);
  font-weight: 700;
  font-size: clamp(1.25rem, 2.4vw, 1.6rem);
  line-height: 1.3;
  letter-spacing: -0.015em;
  color: var(--ink);
  border-left: 4px solid var(--accent);
  padding: 0.15rem 0 0.15rem 1.2rem;
  margin: 2.5rem 0;
  text-wrap: balance;
}

.pull-quote cite {
  display: block;
  font-family: var(--font-body);
  font-weight: 400;
  font-style: normal;
  font-size: 1rem;
  color: var(--ink-muted);
  margin-top: 0.5rem;
}

/* Key number: one statistic, big figure over a short label. */
.key-number {
  margin: 2.5rem 0;
}

.key-number .num {
  display: block;
  font-family: var(--font-display);
  font-weight: 700;
  font-size: clamp(2.4rem, 6vw, 3.4rem);
  line-height: 1;
  letter-spacing: -0.03em;
  color: var(--accent-text);
  font-variant-numeric: tabular-nums;
}

.key-number .label {
  display: block;
  color: var(--ink-muted);
  font-size: 0.95rem;
  margin-top: 0.45rem;
  max-width: 40ch;
}

.key-number-row {
  display: grid;
  gap: 1.5rem;
  margin: 2.5rem 0;
}

.key-number-row .key-number {
  margin: 0;
}

@media (min-width: 620px) {
  .key-number-row {
    grid-template-columns: repeat(2, minmax(0, 1fr));
  }
}

/* Aside note: a short remark that must not interrupt the argument. */
.aside-note {
  color: var(--ink-muted);
  font-size: 0.92rem;
  line-height: 1.55;
  border-left: 2px solid var(--rule);
  padding-left: 0.9rem;
  margin: 1.75rem 0;
}

@media (min-width: 1180px) {
  .aside-note {
    width: 15rem;
    float: right;
    margin: 0.4rem -17rem 1.25rem 1.5rem;
    border-left: 2px solid var(--accent);
  }
}

/* Steps: numbered instructions with cyan numerals. */
.steps {
  list-style: none;
  counter-reset: step;
  padding-left: 0;
  margin: 1.75rem 0 2rem;
}

.steps > li {
  position: relative;
  counter-increment: step;
  padding-left: 2.6rem;
  margin-bottom: 0.9rem;
}

.steps > li::before {
  content: counter(step);
  position: absolute;
  left: 0;
  top: -0.05em;
  width: 1.8rem;
  text-align: center;
  font-family: var(--font-display);
  font-weight: 700;
  font-size: 1.05rem;
  color: var(--accent-text);
}

/* Monday line: what to do first thing on Monday. Chip, not a heading. */
.monday {
  display: inline-flex;
  align-items: baseline;
  gap: 0.55rem;
  background: var(--surface-alt);
  border-radius: 999px;
  padding: 0.35rem 0.95rem 0.4rem;
  font-size: 0.95rem;
  margin: 1.5rem 0 0.75rem;
}

.monday::before {
  content: "";
  flex: none;
  width: 0.55rem;
  height: 0.55rem;
  border-radius: 50%;
  background: var(--accent-2);
  transform: translateY(-0.1em);
}

/* Tool table: comparison grids that have to survive a phone. */
.tool-table {
  border-collapse: collapse;
  width: 100%;
  min-width: 34rem;
  font-size: 0.95rem;
}

.tool-table th,
.tool-table td {
  text-align: left;
  padding: 0.6rem 0.85rem;
  border-bottom: 1px solid var(--rule);
  vertical-align: top;
}

.tool-table thead th {
  font-family: var(--font-display);
  font-size: 0.85rem;
  letter-spacing: 0.03em;
  text-transform: uppercase;
  color: var(--ink-muted);
  border-bottom: 2px solid var(--ink);
}

.tool-table tbody tr:nth-child(even) {
  background: var(--surface-alt);
}

.tool-table td:first-child {
  font-weight: 600;
}

/* Printable checklist inside a post. Boxes are drawn, not input elements,
   so the page stays readable and printable with no JS. */

.checklist {
  border: 2px solid var(--ink);
  padding: 1.2rem 1.4rem;
  margin: 2rem 0;
}

.checklist > :first-child {
  margin-top: 0;
}

.checklist > :last-child {
  margin-bottom: 0;
}

.checklist h3 {
  margin-top: 0;
  font-size: 1.1rem;
}

.checklist ul {
  list-style: none;
  padding-left: 0;
  margin: 0 0 1rem;
}

.checklist li {
  position: relative;
  padding-left: 2rem;
  margin-bottom: 0.55rem;
}

.checklist li::before {
  content: "";
  position: absolute;
  left: 0;
  top: 0.4em;
  width: 1.05rem;
  height: 1.05rem;
  border: 2px solid var(--ink-muted);
}

.checklist-note {
  font-size: 0.9rem;
  color: var(--ink-muted);
  margin-bottom: 0;
}

/* Shown only on paper. */
.print-only {
  display: none;
}

.disclaimer {
  color: var(--ink-muted);
}

.contact {
  margin-top: 2rem;
}

/* Motion.

   Everything below is inside prefers-reduced-motion: no-preference, so a reader
   who has asked for less movement gets the same page with none of it. The
   reveal-on-scroll hidden state is also gated on the .js class that site.js adds
   to <html>, so with JavaScript off or broken nothing is ever hidden. */

@media (prefers-reduced-motion: no-preference) {
  html {
    scroll-behavior: smooth;
  }

  .site-nav a::after {
    transition: transform var(--dur-fast) var(--ease);
  }

  .wordmark .dot {
    transition: transform var(--dur) var(--ease);
  }

  .wordmark:hover .dot {
    transform: scale(1.35);
  }

  .prose a,
  .talk-title a,
  .home-all a,
  .site-footer a {
    transition: background-size var(--dur-fast) var(--ease), color var(--dur-fast) var(--ease);
  }

  .entry {
    transition: transform var(--dur-fast) var(--ease), box-shadow var(--dur-fast) var(--ease),
      border-color var(--dur-fast) var(--ease);
  }

  .entry:hover {
    transform: translateY(-2px);
  }

  .entry-thumb img {
    transition: transform var(--dur-slow) var(--ease);
  }

  .entry:hover .entry-thumb img {
    transform: scale(1.03);
  }

  /* First paint: entry cards fade and rise, staggered, done inside 600 ms. */
  .entry-list > .entry {
    animation: rise var(--dur-slow) var(--ease) both;
  }

  .entry-list > .entry:nth-child(1) {
    animation-delay: 40ms;
  }
  .entry-list > .entry:nth-child(2) {
    animation-delay: 110ms;
  }
  .entry-list > .entry:nth-child(3) {
    animation-delay: 180ms;
  }
  .entry-list > .entry:nth-child(4) {
    animation-delay: 250ms;
  }
  .entry-list > .entry:nth-child(5) {
    animation-delay: 320ms;
  }
  .entry-list > .entry:nth-child(6) {
    animation-delay: 390ms;
  }
  .entry-list > .entry:nth-child(7) {
    animation-delay: 460ms;
  }
  .entry-list > .entry:nth-child(n + 8) {
    animation-delay: 520ms;
  }

  /* Reveal on scroll. Only ever hidden when site.js is running. The list sits
     inside :where() so it adds no specificity and the is-visible rule below
     always wins, whatever the element happens to be. */
  .js
    :where(
      .prose figure,
      .summary-box,
      .setup-card,
      .callout,
      .checklist,
      .pull-quote,
      .key-number,
      .table-scroll,
      .reveal
    ) {
    opacity: 0;
    transform: translateY(14px);
    transition: opacity var(--dur-slow) var(--ease), transform var(--dur-slow) var(--ease);
  }

  .js .is-visible {
    opacity: 1;
    transform: none;
  }

  /* Images settle in once they have loaded. */
  .js .fx-img {
    opacity: 0;
    transform: translateY(6px);
  }

  .js .fx-img.is-loaded {
    opacity: 1;
    transform: none;
    transition: opacity var(--dur) var(--ease), transform var(--dur) var(--ease);
  }
}

@keyframes rise {
  from {
    opacity: 0;
    transform: translateY(10px);
  }
  to {
    opacity: 1;
    transform: none;
  }
}

/* Print: article only */

@media print {
  .site-header,
  .site-footer,
  .site-nav,
  .skip-link {
    display: none;
  }

  body {
    font-size: 12pt;
    color: #000;
  }

  /* Paper never animates, and nothing may stay hidden on it. */
  *,
  *::before,
  *::after {
    animation: none !important;
    transition: none !important;
    opacity: 1 !important;
    transform: none !important;
  }

  .post,
  .page {
    max-width: none;
    padding: 0;
  }

  .cover-banner,
  .post-cover,
  .entry-thumb {
    display: none;
  }

  .prose a {
    color: #000;
  }

  .print-only {
    display: block;
  }

  .checklist {
    border-color: #000;
    break-inside: avoid;
    page-break-inside: avoid;
  }

  .checklist li::before {
    border-color: #000;
  }

  .summary-box,
  .callout {
    background: none;
    border: 1px solid #000;
    break-inside: avoid;
    page-break-inside: avoid;
  }
}

/* ===== BEGIN: screenshot figure + reveal box (eksperimentas post) ===== */

/* Real screenshots inside an article. The base .prose figure img already draws
   the hairline border and the 8px radius, so this only adds the lift and makes
   sure the corners clip whatever sits inside. */
.prose figure.screenshot {
  border-radius: var(--radius);
  box-shadow: var(--shadow-card-hover);
  overflow: hidden;
  margin-bottom: 2.25rem;
}

.prose figure.screenshot img {
  display: block;
  width: 100%;
  height: auto;
  border: 1px solid var(--rule);
  border-radius: var(--radius);
}

.prose figure.screenshot figcaption {
  padding: 0 0.1rem 0.75rem;
}

/* Answer that stays hidden until the reader asks for it. Pure <details>, so it
   works with no JavaScript at all. */
.prose .reveal-box {
  border: 1px solid var(--rule);
  border-radius: var(--radius);
  background: var(--surface-alt);
  padding: 1rem 1.25rem;
  margin: 1.75rem 0 2rem;
}

.prose .reveal-box > summary {
  cursor: pointer;
  display: inline-block;
  list-style: none;
  font-family: var(--font-display);
  font-size: 0.95rem;
  color: var(--accent-text);
  background: var(--surface);
  border: 1px solid var(--ink);
  border-radius: 999px;
  padding: 0.5rem 1.1rem;
  transition: background var(--dur-fast) var(--ease), color var(--dur-fast) var(--ease);
}

.prose .reveal-box > summary::-webkit-details-marker {
  display: none;
}

.prose .reveal-box > summary::before {
  content: "+ ";
}

.prose .reveal-box[open] > summary::before {
  content: "- ";
}

.prose .reveal-box > summary:hover {
  background: var(--tint-accent);
}

.prose .reveal-box > summary:focus-visible {
  outline: 3px solid var(--accent);
  outline-offset: 2px;
}

.prose .reveal-box > *:not(summary) {
  margin-bottom: 0;
}

.prose .reveal-box > summary + * {
  margin-top: 1.1rem;
}

.prose .reveal-box p + p {
  margin-top: 0.9rem;
}

@media (prefers-reduced-motion: reduce) {
  .prose .reveal-box > summary {
    transition: none;
  }
}

/* ===== END: screenshot figure + reveal box (eksperimentas post) ===== */

/* ==========================================================================
   Doodles: inline concept illustrations inside posts.
   Appended block, keep it last.
   ========================================================================== */

.prose figure.doodle {
  margin: 2.5rem auto;
  max-width: 560px;
  text-align: center;
}

.prose figure.doodle img {
  display: block;
  width: 100%;
  height: auto;
  margin: 0 auto;
  background: transparent;
  border: 0;
  border-radius: 0;
}

.prose figure.doodle figcaption {
  color: var(--ink-muted);
  font-size: 0.875rem;
  line-height: 1.5;
  margin-top: 0.6rem;
  text-align: center;
}

/* ========================================================================== */

/* ==== fun components: memes and interactive pieces ==== start ====
   Appended as one block on purpose. Everything here is either an image the
   build generates (lib/memes.js) or progressive enhancement layered on top of
   markup that already reads without JavaScript. See docs/components.md. */

/* Meme panel. The only thing on the site allowed to be centred inside the
   prose column: a meme that is not centred stops reading as a meme. The
   selectors are .prose-scoped so they outrank the generic .prose figure rules
   above rather than fighting them. */
.prose .meme {
  max-width: 620px;
  margin: 2.5rem auto;
}

.prose .meme img {
  display: block;
  width: 100%;
  height: auto;
  border: 1px solid var(--rule);
  border-radius: var(--radius);
  background: var(--surface-alt);
}

.prose .meme figcaption {
  text-align: center;
}

/* "Ar galima klijuoti?" checker. With no JavaScript this is a plain form:
   the three questions still read, and the noscript line points at the
   checklist that answers them. */
.checker {
  border: 2px solid var(--ink);
  border-radius: var(--radius);
  padding: 1.2rem 1.4rem;
  margin: 2.5rem 0;
}

.checker h3 {
  margin-top: 0;
  font-size: 1.1rem;
}

.checker fieldset {
  border: 0;
  padding: 0;
  margin: 0 0 1.1rem;
}

.checker legend {
  padding: 0;
  font-size: 0.98rem;
  font-weight: 600;
  margin-bottom: 0.35rem;
}

.checker-answers {
  display: flex;
  flex-wrap: wrap;
  gap: 0.4rem 1.4rem;
}

.checker-answers label {
  display: inline-flex;
  align-items: center;
  gap: 0.45rem;
  font-size: 0.95rem;
  cursor: pointer;
}

.checker-answers input {
  margin: 0;
  accent-color: var(--accent-2);
}

/* The result line is in the document from the first paint and keeps its
   height, so enhancing it swaps words without moving anything below. */
.checker-result {
  display: flex;
  align-items: baseline;
  gap: 0.55rem;
  min-height: 2.4rem;
  margin: 0;
  padding-top: 0.9rem;
  border-top: 1px solid var(--rule);
  font-family: var(--font-display);
  font-weight: 700;
  font-size: 1.05rem;
  color: var(--ink-muted);
}

.checker-result::before {
  content: "";
  flex: none;
  width: 0.6rem;
  height: 0.6rem;
  border-radius: 50%;
  background: var(--rule);
  transform: translateY(-0.05em);
}

.checker-result.is-ok,
.checker-result.is-stop {
  color: var(--ink);
}

.checker-result.is-ok::before {
  background: var(--accent);
}

.checker-result.is-stop::before {
  background: var(--accent-2);
}

.checker noscript {
  display: block;
  font-size: 0.9rem;
  color: var(--ink-muted);
  margin-top: 0.6rem;
}

/* Filter chips above a comparison table. With no JavaScript every row is
   shown, which is the whole table, so nothing is hidden from anyone. */
.chips {
  display: flex;
  flex-wrap: wrap;
  gap: 0.5rem;
  margin: 1.75rem 0 0.5rem;
}

.chip {
  font: inherit;
  font-size: 0.9rem;
  line-height: 1.4;
  color: var(--ink);
  background: var(--surface-alt);
  border: 1px solid var(--rule);
  border-radius: 999px;
  padding: 0.35rem 0.95rem;
  cursor: pointer;
}

.chip:hover {
  border-color: var(--accent);
}

.chip[aria-pressed="true"] {
  background: var(--accent);
  border-color: var(--accent);
  font-weight: 600;
}

.prose tr[hidden] {
  display: none;
}

/* The Monday lines, once site JS has turned them into a checklist. The
   checkbox takes the place of the violet dot, so the chip keeps its size. */
.monday-counter {
  font-size: 0.9rem;
  color: var(--ink-muted);
  font-variant-numeric: tabular-nums;
  min-height: 1.6rem;
  margin: 1.5rem 0 0.5rem;
}

.monday.is-checkable::before {
  display: none;
}

.monday.is-checkable label {
  display: inline-flex;
  align-items: baseline;
  gap: 0.55rem;
  cursor: pointer;
}

.monday.is-checkable input {
  flex: none;
  width: 0.95rem;
  height: 0.95rem;
  margin: 0;
  accent-color: var(--accent-2);
  transform: translateY(0.1em);
}

.monday.is-done {
  color: var(--ink-muted);
}

.monday.is-done label span {
  text-decoration: line-through;
}

@media (prefers-reduced-motion: no-preference) {
  .prose .meme img {
    transition: transform var(--dur) var(--ease);
  }

  .prose .meme:hover img {
    transform: rotate(-0.6deg) scale(1.01);
  }

  .chip {
    transition: background-color var(--dur-fast) var(--ease),
      border-color var(--dur-fast) var(--ease);
  }

  .checker-result {
    transition: color var(--dur) var(--ease);
  }

  .checker-result::before {
    transition: background-color var(--dur) var(--ease);
  }
}

@media print {
  .chips,
  .monday-counter {
    display: none;
  }

  .prose tr[hidden] {
    display: table-row;
  }
}

/* ==== fun components ==== end ==== */

/* ==== post spec components ==== start ====
   The pieces docs/post-spec.md asks every post to carry: the setup card, the
   prompt block, the status line, and the signup form under a post. Appended as
   one block, same as everything above. See docs/components.md. */

/* Bandymo kortelė: what was run, on what, when, and at what it cost. A plain
   definition list, so with no CSS at all it still reads label, value, label,
   value, top to bottom. */
.prose .setup-card {
  display: grid;
  grid-template-columns: 1fr;
  gap: 0.9rem 2rem;
  background: var(--surface-alt);
  border: 1px solid var(--rule);
  border-radius: var(--radius);
  padding: 1.1rem 1.3rem;
  margin: 2rem 0 2.5rem;
}

.prose .setup-card > div {
  min-width: 0;
}

.prose .setup-card dt {
  font-family: var(--font-display);
  font-weight: 700;
  font-size: 0.74rem;
  letter-spacing: 0.07em;
  text-transform: uppercase;
  color: var(--ink-muted);
  margin-bottom: 0.1rem;
}

.prose .setup-card dd {
  margin: 0;
  color: var(--ink);
  font-size: 0.98rem;
  line-height: 1.45;
}

/* Two columns once the prose column is wide enough to hold two labels and two
   values without either wrapping mid word. A card written as bare dt/dd pairs
   with no <div> around each pair gets a narrow label column and the value
   beside it instead, so both ways of writing the card still line up. */
@media (min-width: 720px) {
  .prose .setup-card {
    grid-template-columns: repeat(2, minmax(0, 1fr));
  }

  .prose .setup-card:not(:has(> div)) {
    grid-template-columns: minmax(6rem, 11rem) minmax(0, 1fr);
    gap: 0.7rem 1.5rem;
  }

  .prose .setup-card:not(:has(> div)) > dt {
    margin-bottom: 0;
    padding-top: 0.15em;
  }
}

/* Prompt block: the exact words that were sent, the model and date they were
   sent with, and a collapsed line on why it works. The copy button is added by
   interactive.js; the corner it sits in is reserved here, so the page does not
   move when the script lands. */
.prose figure.prompt {
  position: relative;
  margin: 2rem 0 2.5rem;
}

.prose figure.prompt pre {
  margin: 0;
  padding: 1.1rem 1.2rem;
  /* Room for the copy button, held whether or not the script ever runs. */
  padding-right: 7rem;
  background: var(--surface-alt);
  border: 1px solid var(--rule);
  border-radius: var(--radius);
  overflow-x: visible;
}

.prose figure.prompt code {
  display: block;
  background: none;
  padding: 0;
  font-family: var(--font-mono);
  font-size: 0.88rem;
  line-height: 1.6;
  /* A prompt is prose with line breaks in it, not code that must not wrap. */
  white-space: pre-wrap;
  overflow-wrap: break-word;
}

.prompt-copy {
  position: absolute;
  top: 0.7rem;
  right: 0.7rem;
  font: inherit;
  font-size: 0.85rem;
  line-height: 1.3;
  color: var(--ink);
  background: var(--surface);
  border: 1px solid var(--rule);
  border-radius: 999px;
  padding: 0.3rem 0.85rem;
  cursor: pointer;
}

.prompt-copy:hover {
  border-color: var(--accent);
  color: var(--accent-text);
}

.prompt-copy.is-done {
  background: var(--tint-accent);
  border-color: var(--accent);
  color: var(--ink);
}

.prose figure.prompt figcaption {
  display: flex;
  flex-wrap: wrap;
  gap: 0.4rem 0.6rem;
  align-items: baseline;
  color: var(--ink-muted);
  font-size: 0.85rem;
  margin-top: 0.55rem;
}

/* The collapsed "kodėl veikia" line. Same shape as .reveal-box, one size down,
   so the two never compete inside one post. */
.prose .prompt-why {
  margin-top: 0.9rem;
}

.prose .prompt-why > summary {
  cursor: pointer;
  display: inline-block;
  list-style: none;
  font-family: var(--font-display);
  font-size: 0.88rem;
  color: var(--accent-text);
  background: var(--surface);
  border: 1px solid var(--ink);
  border-radius: 999px;
  padding: 0.35rem 0.9rem;
}

.prose .prompt-why > summary::-webkit-details-marker {
  display: none;
}

.prose .prompt-why > summary::before {
  content: "+ ";
}

.prose .prompt-why[open] > summary::before {
  content: "- ";
}

.prose .prompt-why > summary:hover {
  background: var(--tint-accent);
}

.prose .prompt-why > summary + * {
  margin-top: 0.8rem;
}

.prose .prompt-why > *:not(summary) {
  font-size: 0.95rem;
  color: var(--ink-muted);
  margin-bottom: 0;
}

/* Status line: one muted sentence under the title that says what kind of thing
   this is. "Vienas bandymas su savo užduotimi, ne tyrimas." It sits right under
   the date line, so the date line gives up its own bottom margin when one is
   there. Without :has the two just sit further apart, which is not a defect. */
.status {
  color: var(--ink-muted);
  font-size: 0.9rem;
  max-width: var(--measure);
  margin: 0 0 2rem;
}

.post-meta:has(+ .status) {
  margin-bottom: 0.35rem;
}

/* Newsletter signup. A plain form posting to /subscribe on this server, no
   third party script, no popup, no tracking pixel. It reads and answers with
   JavaScript off; site.js only upgrades it in place. */
.subscribe {
  max-width: var(--measure);
  background: var(--surface-alt);
  border: 1px solid var(--rule);
  border-radius: var(--radius);
  padding: 1.2rem 1.3rem;
  margin: 3rem 0 0;
}

.section-page .subscribe {
  margin-top: 3.5rem;
}

.home .subscribe {
  margin: 3.5rem auto 0;
}

.subscribe h2 {
  margin: 0 0 0.4rem;
  font-size: 1.25rem;
  line-height: 1.25;
}

.subscribe-lead {
  margin: 0 0 0.9rem;
  font-size: 0.98rem;
}

/* The honeypot. Off the page rather than display:none, so a bot that checks
   for hidden fields still fills it in. */
.subscribe-trap {
  position: absolute;
  width: 1px;
  height: 1px;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
  margin: 0;
}

.subscribe-gdpr {
  margin: 0.9rem 0 0;
  font-size: 0.85rem;
  line-height: 1.5;
  color: var(--ink-muted);
}

.subscribe-status,
.subscribe-error {
  margin: 0.75rem 0 0;
  font-size: 0.9rem;
  line-height: 1.5;
  color: var(--ink-muted);
}

.subscribe-error {
  color: var(--accent-text);
}

/* Success state. site.js fills the panel, hides the form and the lead, and
   the ring and the tick draw themselves in when motion is allowed. */
.subscribe.is-done .subscribe-lead,
.subscribe.is-done .subscribe-form,
.subscribe.is-done .subscribe-gdpr {
  display: none;
}

.subscribe-done {
  display: flex;
  gap: 1rem;
  align-items: flex-start;
  outline: none;
}

.subscribe-done[hidden] {
  display: none;
}

.subscribe-check {
  flex: 0 0 auto;
  width: 3.25rem;
  height: 3.25rem;
}

.subscribe-check-ring {
  stroke: var(--accent);
}

.subscribe-check-mark {
  stroke: var(--ink);
}

.subscribe-done-heading {
  margin: 0.15rem 0 0.35rem;
  font-family: var(--font-display, inherit);
  font-weight: 700;
  font-size: 1.1rem;
  line-height: 1.3;
}

.subscribe-done-text {
  margin: 0;
  font-size: 0.95rem;
  line-height: 1.55;
  color: var(--ink-muted);
}

@media (prefers-reduced-motion: no-preference) {
  .subscribe.is-sending button {
    animation: subscribe-pulse 1.1s ease-in-out infinite;
  }

  .subscribe.is-done .subscribe-done {
    animation: subscribe-in var(--dur-slow) var(--ease) both;
  }

  .subscribe.is-done .subscribe-check-ring {
    stroke-dasharray: 183;
    stroke-dashoffset: 183;
    animation: subscribe-draw 600ms var(--ease) 100ms forwards;
  }

  .subscribe.is-done .subscribe-check-mark {
    stroke-dasharray: 40;
    stroke-dashoffset: 40;
    animation: subscribe-draw 380ms var(--ease) 560ms forwards;
  }

  @keyframes subscribe-draw {
    to {
      stroke-dashoffset: 0;
    }
  }

  @keyframes subscribe-in {
    from {
      opacity: 0;
      transform: translateY(6px);
    }
    to {
      opacity: 1;
      transform: none;
    }
  }

  @keyframes subscribe-pulse {
    50% {
      opacity: 0.55;
    }
  }
}

.subscribe input:focus-visible,
.subscribe button:focus-visible {
  outline: 2px solid var(--accent-text);
  outline-offset: 2px;
}

.subscribe button[disabled] {
  opacity: 0.6;
  cursor: default;
}

.subscribe-field {
  display: grid;
  gap: 0.35rem;
  align-items: end;
}

.subscribe-field label {
  font-size: 0.85rem;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  color: var(--ink-muted);
  font-family: var(--font-display);
  font-weight: 700;
}

.subscribe input {
  font: inherit;
  font-size: 1rem;
  color: var(--ink);
  background: var(--surface);
  border: 1px solid var(--rule);
  border-radius: var(--radius);
  padding: 0.55rem 0.75rem;
  width: 100%;
  min-width: 0;
}

.subscribe input:hover {
  border-color: var(--accent);
}

.subscribe button {
  font: inherit;
  font-family: var(--font-display);
  font-weight: 700;
  font-size: 0.95rem;
  color: var(--ink-on-dark);
  background: var(--surface-dark);
  border: 1px solid var(--surface-dark);
  border-radius: var(--radius);
  padding: 0.6rem 1.2rem;
  cursor: pointer;
}

.subscribe button:hover {
  background: var(--accent-text);
  border-color: var(--accent-text);
}

@media (min-width: 560px) {
  .subscribe-field {
    grid-template-columns: minmax(0, 1fr) auto;
    grid-template-areas:
      "label label"
      "input button";
    gap: 0.35rem 0.6rem;
  }

  .subscribe-field label {
    grid-area: label;
  }

  .subscribe-field input {
    grid-area: input;
  }

  .subscribe-field button {
    grid-area: button;
  }
}

/* The small trust links in the footer: start here, how DI is used here, and the
   corrections log. */
.footer-trust {
  display: flex;
  flex-wrap: wrap;
  gap: 0.3rem 1.2rem;
  margin: 0;
}

@media (prefers-reduced-motion: no-preference) {
  .prompt-copy,
  .prose .prompt-why > summary,
  .subscribe input,
  .subscribe button {
    transition: background-color var(--dur-fast) var(--ease),
      border-color var(--dur-fast) var(--ease), color var(--dur-fast) var(--ease);
  }
}

@media print {
  .prompt-copy,
  .subscribe {
    display: none;
  }

  .prose .prompt-why[open],
  .prose .prompt-why {
    display: block;
  }

  .prose .setup-card {
    background: none;
    border: 1px solid #000;
    break-inside: avoid;
    page-break-inside: avoid;
  }
}

/* ==== post spec components ==== end ==== */


/* ---- About portrait ---- */
.about-grid {
  display: grid;
  gap: 1.5rem;
  align-items: start;
}

/* The blocks under the bio: past talks, then where the site keeps its
   promises. Each one starts on a rule, the same way a talk or a home block
   does, so the page reads as sections rather than as one long column. */
.about-block {
  margin-top: clamp(2.5rem, 5vw, 3.5rem);
  padding-top: 1.75rem;
  border-top: 1px solid var(--rule);
}

.about-block > h2 {
  font-size: 1.05rem;
  letter-spacing: 0.01em;
  margin-bottom: 1.25rem;
}

.about-links {
  list-style: none;
  margin: 0;
  padding: 0;
  display: flex;
  flex-wrap: wrap;
  gap: 0.5rem 1.5rem;
}

.about-links a {
  color: var(--ink);
  text-decoration: none;
  background-image: linear-gradient(currentColor, currentColor);
  background-repeat: no-repeat;
  background-position: 0 100%;
  background-size: 100% 1px;
  padding-bottom: 0.06em;
}

.about-links a:hover {
  color: var(--accent-text);
  background-size: 100% 2px;
}
.portrait {
  width: 120px;
  height: 120px;
  border-radius: 50%;
  object-fit: cover;
  border: 1px solid var(--rule);
  background: var(--surface-alt);
}
@media (min-width: 720px) {
  .about-grid {
    grid-template-columns: 160px minmax(0, var(--measure));
    gap: 2rem;
  }
  .portrait {
    width: 160px;
    height: 160px;
    margin-top: 0.4rem;
  }
}

/* ==========================================================================
   Vaizdais: the picture-post format. A sequence of panels, one line of caption
   under each, and as little prose as the idea will bear. Appended block, keep
   it last. See docs/components.md.
   ========================================================================== */

/* The panels are the article, so the article widens to fit them. 720px is a
   reading measure; a drawing at 720px is a thumbnail with ambitions. */
.post-visual {
  max-width: calc(880px + 2 * var(--pad));
}

.visual-post {
  max-width: 880px;
}

/* Prose inside a picture post stays at the reading measure. Only the panels
   get the extra width, so the optional intro and the closing box still read
   like text rather than like a banner. */
.visual-post > p,
.visual-post > ul,
.visual-post > ol,
.visual-post > .summary-box,
.visual-post > .callout,
.visual-post > .checklist {
  max-width: var(--measure);
}

/* One panel. Generous air below it, because the gap between two panels is what
   tells the reader they are two separate beats and not one wide picture. */
.visual-post .panel {
  counter-increment: panel;
  max-width: none;
  margin: 0 0 3.25rem;
  /* The header sticks, so a panel stepped to from the keyboard has to stop
     below it rather than under it. */
  scroll-margin-top: 5rem;
}

.visual-post .panel:last-of-type {
  margin-bottom: 2.5rem;
}

.visual-post .panel img {
  display: block;
  width: 100%;
  height: auto;
  border: 1px solid var(--rule);
  border-radius: var(--radius);
  background: var(--surface-alt);
}

/* The caption and the counter share one line, the caption left and "3 / 9"
   pinned to the bottom right. The counter is generated, so it cannot drift out
   of step with the panels the way a hand-typed number would. */
.visual-post .panel figcaption {
  display: flex;
  align-items: flex-end;
  justify-content: space-between;
  gap: 1.5rem;
  margin-top: 0.85rem;
  color: var(--ink-muted);
  font-size: 1rem;
  line-height: 1.5;
  text-align: left;
}

.visual-post .panel figcaption::after {
  content: counter(panel) " / " counter(panel-total);
  flex: none;
  font-family: var(--font-display);
  font-size: 0.78rem;
  letter-spacing: 0.06em;
  font-variant-numeric: tabular-nums;
  color: var(--ink-muted);
}

/* Panels take focus from the keyboard stepping in interactive.js. They are not
   in the tab order (tabindex="-1"), so this ring only ever shows when a step
   put it there. */
.visual-post .panel:focus {
  outline: none;
}

.visual-post .panel:focus-visible {
  outline: 3px solid var(--accent);
  outline-offset: 6px;
  border-radius: var(--radius);
}

/* On a phone the caption and the counter stop fitting on one line together. */
@media (max-width: 480px) {
  .visual-post .panel figcaption {
    display: block;
  }

  .visual-post .panel figcaption::after {
    display: block;
    margin-top: 0.35rem;
    text-align: right;
  }
}

/* The format chip on an entry card. Hairline and a cyan dot, no fill: it has
   to label the card without competing with the title. */
.entry-meta {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 0.55rem;
}

.chip-format {
  display: inline-flex;
  align-items: center;
  gap: 0.35rem;
  padding: 0.05rem 0.5rem 0.1rem;
  border: 1px solid var(--rule);
  border-radius: 999px;
  font-family: var(--font-display);
  font-size: 0.68rem;
  letter-spacing: 0.07em;
  text-transform: uppercase;
  white-space: nowrap;
  color: var(--ink-muted);
}

/* The section a card came from, on the cards that can come from anywhere. It
   is a real link inside a card whose title link already covers the whole card
   through a pseudo-element, so it has to be lifted above that overlay. */
.chip-section {
  position: relative;
  z-index: 1;
  display: inline-block;
  padding: 0.05rem 0.5rem 0.1rem;
  border: 1px solid var(--rule);
  border-radius: 999px;
  font-family: var(--font-display);
  font-size: 0.68rem;
  letter-spacing: 0.07em;
  text-transform: uppercase;
  white-space: nowrap;
  color: var(--ink-muted);
  text-decoration: none;
  transition: border-color var(--dur-fast) var(--ease), color var(--dur-fast) var(--ease);
}

.chip-section:hover,
.chip-section:focus-visible {
  border-color: var(--accent);
  color: var(--accent-text);
}

.chip-format::before {
  content: "";
  flex: none;
  width: 0.38rem;
  height: 0.38rem;
  border-radius: 50%;
  background: var(--accent);
}

/* ==========================================================================
   Komiksas: the comic format. One story told in drawn panels whose words are
   already typeset into the artwork by lib/comics.js, laid out as a comic page
   rather than as a column of illustrations. Appended block, keep it last.
   See docs/components.md.
   ========================================================================== */

/* Wider than a picture post, because two panels sit side by side and the text
   inside a panel is part of the artwork: it cannot reflow, so the only way to
   keep a bubble readable is to give the panel room. */
.post-comic {
  max-width: calc(1180px + 2 * var(--pad));
}

.comic-post {
  max-width: 1180px;
}

/* The comic page. Tight gutters on purpose: a comic reads as one page with
   panels next to each other, not as separate figures with air between them. */
.comic {
  display: grid;
  grid-template-columns: 1fr;
  gap: 12px;
  margin: 0 0 2.75rem;
}

@media (min-width: 720px) {
  .comic {
    grid-template-columns: 1fr 1fr;
  }

  /* The lesson panel, and any other beat that has to land on its own. */
  .comic .panel[data-wide] {
    grid-column: 1 / -1;
  }
}

/* No caption, no counter, no margin: the panel is the beat and the words are
   already inside it. These override the vaizdais rules the wrapper also
   carries, since a comic post is a picture post too. */
.comic-post .comic .panel {
  margin: 0;
  counter-increment: none;
  scroll-margin-top: 5rem;
}

/* A 2px ink frame is what makes a grid of pictures read as a comic. */
.comic-post .comic .panel img {
  display: block;
  width: 100%;
  height: auto;
  border: 2px solid var(--ink);
  border-radius: 4px;
  background: var(--surface-alt);
}

/* Same keyboard stepping as a picture post, so the ring has to show here too. */
.comic-post .comic .panel:focus {
  outline: none;
}

.comic-post .comic .panel:focus-visible {
  outline: 3px solid var(--accent);
  outline-offset: 4px;
  border-radius: 4px;
}

/* ==== home hero, rows, article furniture ==== start ====
   The home page opens with live text rather than the typeset cover (the cover
   is still generated and is still the Open Graph card), and the article page
   gained a breadcrumb, a table of contents and a FAQ block. Everything here
   follows the same tokens as the rest of the file. */

/* The hero. One column on a phone, text and picture side by side once there is
   room for both. The picture is the text-free drawing the cover is built on,
   so the title is not painted into it twice. */
.hero {
  display: grid;
  gap: 1.5rem;
  align-items: center;
  margin: 0 0 clamp(1.5rem, 3vw, 2.25rem);
}

@media (min-width: 860px) {
  .hero {
    grid-template-columns: minmax(0, 1fr) minmax(0, 0.85fr);
    gap: clamp(2rem, 4vw, 3.5rem);
  }
}

.hero-title {
  font-size: clamp(1.6rem, 3.2vw, 2.35rem);
  line-height: 1.2;
  margin: 0 0 0.6rem;
  max-width: 22ch;
}

.hero-sub {
  color: var(--ink-muted);
  margin: 0 0 1.6rem;
  max-width: 46ch;
}

/* The newest post, as the one thing to read right now. The rule above it is
   the same 2px ink rule every home block heading carries. */
.hero-featured {
  border-top: 2px solid var(--ink);
  padding-top: 0.9rem;
}

.hero-featured-meta {
  margin: 0 0 0.35rem;
  font-size: 0.85rem;
  color: var(--ink-muted);
  font-variant-numeric: tabular-nums;
}

.hero-featured-meta a {
  color: var(--ink-muted);
}

.hero-featured-meta .sep {
  margin: 0 0.15rem;
  color: var(--rule);
}

.hero-featured-title {
  font-size: clamp(1.25rem, 2.4vw, 1.6rem);
  margin: 0 0 0.5rem;
}

.hero-featured-title a {
  color: var(--ink);
  text-decoration: none;
}

.hero-featured-title a:hover,
.hero-featured-title a:focus-visible {
  color: var(--accent-text);
}

.hero-featured-desc {
  color: var(--ink-muted);
  margin: 0 0 1rem;
  max-width: 52ch;
}

.hero-cta {
  margin: 0;
}

/* The one dark button on the site. */
.button {
  display: inline-block;
  background: var(--surface-dark);
  color: var(--ink-on-dark);
  border-radius: var(--radius);
  padding: 0.55rem 1.1rem;
  font-family: var(--font-display);
  font-weight: 700;
  font-size: 0.95rem;
  text-decoration: none;
  border: 1px solid var(--surface-dark);
}

.button:hover,
.button:focus-visible {
  background: var(--ink);
  color: var(--ink-on-dark);
  border-color: var(--ink);
}

.hero-art img {
  display: block;
  width: 100%;
  height: auto;
  border: 1px solid var(--rule);
  border-radius: var(--radius);
  background: var(--surface-alt);
}

/* The number of posts behind a topic chip. */
.chip-count {
  color: var(--ink-muted);
  font-variant-numeric: tabular-nums;
  font-size: 0.85em;
}

.section-chips a.is-current .chip-count {
  color: var(--tint-on-dark);
}

/* The home chip row sits under the hook line rather than under a page intro,
   so it does not need the negative top margin the section pages use. */
.home .section-chips {
  margin-top: 0;
}

/* Nuo ko pradėti: three fixed entries, title and one meta line, no thumbnail.
   Deliberately lighter than an entry card, because these are a route rather
   than news. */
.starter-list {
  list-style: none;
  margin: 0;
  padding: 0;
  display: grid;
  gap: 0.9rem;
}

@media (min-width: 720px) {
  .starter-list {
    grid-template-columns: repeat(auto-fit, minmax(min(100%, 16rem), 1fr));
    gap: 1.2rem;
  }
}

.starter {
  display: grid;
  gap: 0.3rem;
  align-content: start;
  border-top: 1px solid var(--rule);
  padding-top: 0.7rem;
}

.starter-title {
  font-family: var(--font-display);
  font-weight: 700;
  font-size: 1rem;
  line-height: 1.3;
  color: var(--ink);
  text-decoration: none;
  text-wrap: balance;
}

.starter-title:hover,
.starter-title:focus-visible {
  color: var(--accent-text);
}

.starter-meta {
  color: var(--ink-muted);
  font-size: 0.85rem;
}

.starter-meta .sep {
  margin: 0 0.15rem;
  color: var(--rule);
}

/* How long a card takes to read, beside the date and the section. */
.entry-read {
  color: var(--ink-muted);
  font-size: 0.85rem;
  font-variant-numeric: tabular-nums;
}

/* Two lines of blurb and no more, so a row of cards keeps one height whatever
   the descriptions do. */
.entry-desc {
  display: -webkit-box;
  -webkit-box-orient: vertical;
  -webkit-line-clamp: 2;
  line-clamp: 2;
  overflow: hidden;
}

/* Iš laboratorijos. The tiles link into /lab, which is a different service
   behind the same domain, so the thumbnails come from there and not from
   /assets. */
.lab-list {
  list-style: none;
  margin: 0;
  padding: 0;
  display: grid;
  gap: 1rem;
}

@media (min-width: 560px) {
  .lab-list {
    grid-template-columns: repeat(auto-fit, minmax(min(100%, 13rem), 1fr));
    gap: 1.2rem;
  }
}

.lab-link {
  display: grid;
  gap: 0.3rem;
  text-decoration: none;
  color: var(--ink);
  height: 100%;
}

.lab-link img {
  display: block;
  width: 100%;
  height: auto;
  aspect-ratio: 16 / 10;
  object-fit: cover;
  object-position: top center;
  border: 1px solid var(--rule);
  border-radius: var(--radius);
  background: var(--surface-alt);
  margin-bottom: 0.35rem;
}

.lab-link:hover img,
.lab-link:focus-visible img {
  border-color: var(--accent);
}

.lab-name {
  font-family: var(--font-display);
  font-weight: 700;
  font-size: 0.98rem;
  line-height: 1.3;
}

.lab-link:hover .lab-name,
.lab-link:focus-visible .lab-name {
  color: var(--accent-text);
}

.lab-what {
  color: var(--ink-muted);
  font-size: 0.88rem;
  line-height: 1.45;
}

/* Breadcrumb above the article title: the stream, the section, this post. The
   last step is not a link, because it is the page the reader is on. */
.breadcrumb {
  margin: 0 0 0.6rem;
  font-size: 0.85rem;
  color: var(--ink-muted);
}

.breadcrumb ol {
  list-style: none;
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: 0.15rem 0.4rem;
  margin: 0;
  padding: 0;
}

.breadcrumb li + li::before {
  content: "\203A";
  margin-right: 0.4rem;
  color: var(--rule);
}

.breadcrumb a {
  color: var(--ink-muted);
  text-decoration: none;
}

.breadcrumb a:hover,
.breadcrumb a:focus-visible {
  color: var(--accent-text);
  text-decoration: underline;
}

/* The article meta line: who wrote it, when, and how long it takes. */
.post-meta > * + *::before {
  content: "\00B7";
  margin-right: 0.5rem;
  color: var(--ink-muted);
}

.post-read,
.post-updated,
.post-meta time {
  margin-left: 0.5rem;
}

/* The article aside: the table of contents and a compact signup. Hidden below
   1180px, where the article has no room for a second column and the wide
   signup under the text is the one that shows. */
.post-aside {
  display: none;
}

.toc-label {
  margin: 0 0 0.5rem;
  font-family: var(--font-display);
  font-weight: 700;
  font-size: 0.8rem;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--ink-muted);
}

.toc ol {
  list-style: none;
  margin: 0;
  padding: 0;
  display: grid;
  gap: 0.5rem;
  counter-reset: toc;
}

.toc li {
  counter-increment: toc;
  font-size: 0.92rem;
  line-height: 1.35;
  border-left: 2px solid var(--rule);
  padding-left: 0.7rem;
}

.toc a {
  color: var(--ink-muted);
  text-decoration: none;
}

.toc a:hover,
.toc a:focus-visible {
  color: var(--accent-text);
}

@media (min-width: 1180px) {
  .post.has-aside {
    display: grid;
    grid-template-columns: minmax(0, var(--measure)) 16rem;
    column-gap: 3rem;
    max-width: calc(var(--measure) + 16rem + 3rem + 2 * var(--pad));
  }

  /* The cover img is wrapped in a <picture> that is display: contents, which
     would make the img itself the grid item and drop it out of the column
     below. Inside the two-column article the wrapper is a block again. */
  .post.has-aside > picture {
    display: block;
  }

  .post.has-aside > *:not(.post-aside) {
    grid-column: 1;
    min-width: 0;
  }

  .post.has-aside > .post-aside {
    display: block;
    grid-column: 2;
    /* Spanning every row is what gives the sticky aside the whole article to
       travel down. The explicit grid has one row, so the span is written out
       rather than left to -1. */
    grid-row: 1 / span 99;
    align-self: start;
    position: sticky;
    /* Clear of the sticky header. */
    top: 5rem;
  }

  /* Only one signup box is ever visible: the compact one in the aside here,
     the wide one under the article everywhere else. */
  .post.has-aside > .subscribe {
    display: none;
  }

  .post-aside .subscribe {
    margin: 0;
    padding: 1rem 1.05rem;
  }

  .post-aside .subscribe h2 {
    font-size: 1.05rem;
  }

  .post-aside .subscribe-lead,
  .post-aside .subscribe-gdpr {
    font-size: 0.85rem;
  }

  .post-aside .toc {
    margin-bottom: 1.5rem;
  }

  /* The field goes two up at 560px of viewport, which says nothing about a
     16rem column: in the aside the input and the button stay stacked. */
  .post-aside .subscribe-field {
    grid-template-columns: minmax(0, 1fr);
    grid-template-areas:
      "label"
      "input"
      "button";
  }
}

/* One line out to the rest of the section, under the read-next cards. */
.read-next-all {
  margin: 1.2rem 0 0;
  font-size: 0.9rem;
}

/* Dažni klausimai. A rule between items, a plus sign that turns into a minus
   when the answer is open, and nothing that stops working with JavaScript off:
   it is <details> and only <details>. */
.faq {
  margin: 2.5rem 0;
  border-top: 2px solid var(--ink);
  padding-top: 0.8rem;
}

.faq > h2 {
  font-size: 1.15rem;
  margin: 0 0 0.4rem;
}

.faq details {
  border-bottom: 1px solid var(--rule);
}

.faq summary {
  list-style: none;
  cursor: pointer;
  display: flex;
  gap: 0.9rem;
  align-items: baseline;
  justify-content: space-between;
  padding: 0.85rem 0;
  font-family: var(--font-display);
  font-weight: 700;
  font-size: 1rem;
  line-height: 1.35;
}

.faq summary::-webkit-details-marker {
  display: none;
}

.faq summary::after {
  content: "+";
  flex: none;
  font-size: 1.3rem;
  line-height: 1;
  color: var(--accent-text);
}

.faq details[open] > summary::after {
  content: "\2212";
}

.faq summary:hover,
.faq details[open] > summary {
  color: var(--accent-text);
}

.faq summary:focus-visible {
  outline: 3px solid var(--accent);
  outline-offset: 2px;
}

.faq details > *:not(summary) {
  margin: 0 0 0.9rem;
  color: var(--ink-muted);
  font-size: 0.98rem;
}

@media (prefers-reduced-motion: no-preference) {
  .faq summary::after {
    transition: transform var(--dur-fast) var(--ease), color var(--dur-fast) var(--ease);
  }

  .faq details[open] > summary::after {
    transform: rotate(180deg);
  }

  .lab-link img,
  .hero-art img {
    transition: border-color var(--dur-fast) var(--ease);
  }
}

/* ==== home hero, rows, article furniture ==== end ==== */
