/* ---------------------------------------------------------------------------
   VENDORED FILE. DO NOT EDIT.

   Source:  aline-no/aline-design-system @ v5.0.0
   Synced:  2026-11-01 by scripts/sync-to-decks.mjs
   Fonts:   ./fonts/, copied in the same pass. Both travel together.

   Edit the design system and re-run the sync. Anything changed here is lost on
   the next one, and a value that exists only in this file is a value the rest
   of Aline does not have.
   --------------------------------------------------------------------------- */

/* =========================================================================
   slides.css
   The frame a deck is presented in, and the chrome drawn on every slide.

   Scope: the frame, the head bar and the progress bar, the three grounds, the
   controls, print, the type ladder, and every kind: its structure and its
   look. The look is the decks', measured from _shared/deck-styles.css and the
   Onwards 2026 deck, and the character limits in limits.js are measured
   against this ladder at the smallest frame. See DESIGN.md D26.

   The kind markup contract is the list of classes below, one block per kind.
   A deck writes it by hand, Aloud's Deck.tsx emits it, and both get the same
   slide. A class not in this file is a deck's own and lives in that deck's
   CSS.

   One frame, documented in stage.js, which is what sizes it: the frame takes
   the window's shape, never smaller than 1280 by 1080, and fills the screen
   with no bands. A deck behaves like a full-width site. There is no second,
   letterboxed mode, and a slide placed at coordinates is an SVG with a viewBox.

   --px is one screen pixel in the frame's own pixels, written on the deck by
   stage.js. Everything in the chrome is sized through it, so the bars hold
   their size on the screen while the slide's content scales with the frame. It is declared here as 1px so the frame still
   draws without the script, which is what a print and a crawler get.

   The chrome's numbers came over from Aloud as they are: an 11px line in a
   50px bar, 28px in from the edges, a 3px progress bar. Everywhere else in
   this package Aloud's values stop at its own repo and only the mechanism
   moves, but the bars are the one place where those values are the look
   rather than a layout decision a deck makes for itself.
   ========================================================================= */

/* -------------------------------------------------------------- the ladder */

/* Unregistered, a custom property is text, and its cqi is worked out where it
   is used, against the nearest container. Inside a side-by-side kind that is
   .slide-main, 200 frame pixels narrower than the stage, so every step there
   would come out smaller than the same step in the title above it. A length
   is worked out where it is declared. */
@property --slide-cover { syntax: "<length>"; inherits: true; initial-value: 0px; }
@property --slide-display { syntax: "<length>"; inherits: true; initial-value: 0px; }
@property --slide-title { syntax: "<length>"; inherits: true; initial-value: 0px; }
@property --slide-label { syntax: "<length>"; inherits: true; initial-value: 0px; }
@property --slide-quote { syntax: "<length>"; inherits: true; initial-value: 0px; }
@property --slide-lead { syntax: "<length>"; inherits: true; initial-value: 0px; }
@property --slide-body { syntax: "<length>"; inherits: true; initial-value: 0px; }
@property --slide-small { syntax: "<length>"; inherits: true; initial-value: 0px; }
@property --slide-figure { syntax: "<length>"; inherits: true; initial-value: 0px; }

/* ---------------------------------------------------------------- the deck */

.slide-deck {
  /* One screen pixel in frame pixels. stage.js overwrites it per frame. */
  --px: 1px;

  min-height: 100vh;
  /* The deck's ground is the slide's ground, not a well under it. The frame
     fills the window, so this shows only where the page does: overscroll, and
     anything a deck draws outside the deck. One ground, so no edge appears
     that nobody drew. */
  background: var(--background);
  color: var(--foreground);
  overflow: auto;
}

/* Before the script runs the slides stack in order at their authored size and
   the page scrolls. After it runs the deck is the window and the stage is the
   frame, centred and scaled from its middle. The stage is the container the
   ladder reads, so a size follows the frame's width in frame pixels, which
   is the window's shape and not its size. */
.slide-stage {
  width: 1920px;
  container-type: inline-size;
}

.slide-stage > .slide + .slide {
  margin-top: 32px;
}

.slide-deck[data-ready] {
  position: fixed;
  inset: 0;
  overflow: hidden;
}

/* Width, height and scale are written here by stage.js, which is why they are
   not in this rule. */
.slide-deck[data-ready] .slide-stage {
  position: absolute;
  top: 50%;
  left: 50%;
  transform-origin: center;
}

.slide-deck[data-ready] .slide {
  position: absolute;
  inset: 0;
  width: auto;
  height: auto;
  margin: 0;
}

/* ---------------------------------------------------------------- a slide */

.slide {
  /* The side padding, named because the head bar has to cancel it to reach
     both edges of the slide. */
  --slide-pad: 100px;

  /* The ladder, in frame pixels. Each step is the decks' size in a 1920 frame
     and runs down in a straight line to its size in a 1280 frame, which is
     where the decks themselves stepped down (Onwards: title 88 to 64, lead 44
     to 36). Between the two it follows the frame's width; past 1920 it holds.
     The slope and the offset are the two ends solved for: a step from S at
     1280 to L at 1920 is S - 2(L - S) plus 0.15625(L - S) of the frame.

       cover    128   96   the cover and the close
       display   96   72   a statement, a section, the access details
       title     88   64   every other kind's title
       label     56   44   a highlight word, a card's title
       quote     56   44
       lead      44   36   a line under a title, a step, a figure's caption
       body      34   28
       small     28   24   eyebrows, notes, captions. Nothing is set under 24
       figure   180  128   a number slide's figure

     Registered, so each step is worked out once on the slide against the
     stage and a kind that is its own container reads the same number. */
  --slide-cover: clamp(96px, 32px + 5cqi, 128px);
  --slide-display: clamp(72px, 24px + 3.75cqi, 96px);
  --slide-title: clamp(64px, 16px + 3.75cqi, 88px);
  --slide-label: clamp(44px, 20px + 1.875cqi, 56px);
  --slide-quote: clamp(44px, 20px + 1.875cqi, 56px);
  --slide-lead: clamp(36px, 20px + 1.25cqi, 44px);
  --slide-body: clamp(28px, 16px + 0.9375cqi, 34px);
  --slide-small: clamp(24px, 16px + 0.625cqi, 28px);
  --slide-figure: clamp(128px, 24px + 8.125cqi, 180px);

  position: relative;
  width: 1920px;
  height: 1080px;
  padding: 0 var(--slide-pad);
  box-sizing: border-box;
  display: flex;
  flex-direction: column;
  overflow: hidden;
  background: var(--background);
  color: var(--foreground);
  font-family: var(--font-sans);
  font-size: var(--slide-body);
  line-height: 1.35;
}

/* ----------------------------------------------------------------- grounds */

/* data-theme picks the ground. Dark and light are surfaces.css, which carries
   these selectors on its two blocks, so a slide gets the whole token set of
   its surface whatever the page around it is. Light lays the slide on the
   light surface's --sunken, a grey and never the page's near-white, which
   still holds a --surface block off it. Green is the light surface with the
   accent laid over it: the ground, and every text role in the accent
   foreground, because no grey reads on green and dark green text is not used.
   Dark for the first slide, the last and a chapter opening, light or green
   for the rest; the deck picks, the package only draws it. The extra class is
   for order, so these win over surfaces.css whichever of the two a page loads
   last. */
.slide[data-slide][data-theme="light"] {
  --background: var(--sunken);
}

.slide[data-slide][data-theme="green"] {
  --background: var(--accent);
  --foreground: var(--accent-foreground);
  --body: var(--accent-foreground);
  --muted-foreground: var(--accent-foreground);
  --tert: var(--accent-foreground);
  --ink: var(--accent-foreground);
}

.slide[hidden] {
  display: none;
}

/* A deck sets its own spacing inside a slide, so nothing in it arrives with a
   browser margin. */
.slide :where(h1, h2, h3, h4, p, ol, ul, figure, blockquote) {
  margin: 0;
}

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

/* The head is a bar along the top edge of every slide: the mark, the event and
   the deck on the left, where the slide sits in the deck on the right, over a
   rule the full width of the slide. Its text is the one line in a deck set
   under 24px, because it is for the presenter and not for the room, so it is
   set in the sans like the tool's own UI rather than as a label. */
.slide-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  flex-shrink: 0;
  height: calc(50 * var(--px));
  margin-inline: calc(-1 * var(--slide-pad));
  padding-inline: calc(28 * var(--px));
  border-bottom: var(--px) solid var(--hair);
  font-family: var(--font-sans);
  font-weight: var(--weight-normal);
  font-size: calc(11 * var(--px));
  font-variant-numeric: tabular-nums;
  color: var(--tert);
  /* nowrap rather than Aloud's pre. The bar is one line and has to stay one
     line, which both do, but pre also renders the newlines in the markup, so a
     credit written across three lines of HTML draws as three lines of text.
     Aloud never saw it because JSX drops that whitespace. */
  white-space: nowrap;
}

.slide-credit {
  display: flex;
  align-items: center;
  gap: calc(16 * var(--px));
  text-transform: uppercase;
  letter-spacing: var(--tracking-widest);
}

.slide-count {
  word-spacing: calc(2 * var(--tracking-widest));
}

/* No grey reads on green, so the bar is the accent foreground faded, the one
   way to keep it quieter than the slide without a second colour. */
.slide[data-theme="green"] .slide-head {
  opacity: 0.55;
}

/* In screen pixels like the rest of the bar it sits in. Aloud sized it in
   frame pixels, which means it grows and shrinks against the bar instead of
   with it, and the drift shows at the shapes a laptop and a projector are. */
.slide-logo {
  height: calc(24 * var(--px));
  width: auto;
  fill: currentColor;
  color: var(--muted-foreground);
}

/* The foot is a thin bar along the bottom edge as long as the way through the
   deck, with no track behind it. A rect's width is an attribute, so the deck
   draws the bar with no inline style and this file only places it. */
.slide-progress {
  position: absolute;
  left: 0;
  bottom: 0;
  width: 100%;
  height: calc(3 * var(--px));
  fill: var(--ink);
}

/* ---------------------------------------------------------------- the body */

/* Centred between the head's rule and the progress bar, with the same room
   above and below. The gap is the one spacing decision the frame makes: it is
   the distance between a slide's own blocks, and a deck overrides it per kind. */
.slide-main {
  flex: 1;
  min-height: 0;
  margin-block: 72px calc(72px + 3 * var(--px));
  display: flex;
  flex-direction: column;
  justify-content: center;
  gap: 64px;
}

/* ------------------------------------------------------------------- kinds */

/* A rule between a slide's own blocks: under a list row, between cards,
   around a table. The decks draw it as the foreground at a sixth, because no
   surface token holds a line on all three grounds: --border is the green's
   own value on a green slide and disappears there. Redeclared on the panel,
   which has a foreground of its own. */
.slide {
  --slide-rule: color-mix(in srgb, var(--foreground) 16%, transparent);
}

/* Titles and the display line. Family, weight and tracking come from the
   tokens, never a literal, and a title balances its lines rather than leaving
   one word on the last. A statement is a p and a highlight word an li, which
   the base styles set in --body, so the colour is stated here as well. */
.slide-display,
.slide-statement,
.slide-title,
.slide-figure,
.slide-quote blockquote,
.slide-access-value,
.slide-words > li {
  font-family: var(--font-display);
  font-weight: var(--weight-display);
  letter-spacing: var(--tracking-tight);
  line-height: 1.05;
  color: var(--foreground);
  text-wrap: balance;
}

.slide-display,
.slide-statement {
  font-size: var(--slide-display);
}

.slide-title {
  font-size: var(--slide-title);
  line-height: 1.08;
}

.slide-lead {
  font-family: var(--font-display);
  font-weight: var(--weight-body);
  letter-spacing: var(--tracking-snug);
  font-size: var(--slide-lead);
  line-height: 1.15;
  color: var(--body);
  text-wrap: pretty;
}

.slide code {
  font-family: var(--font-mono);
  font-size: 0.9em;
}

.slide strong {
  font-weight: var(--weight-semibold);
  color: var(--foreground);
}

/* The highlight is an em: the word a line turns on, which is what markdown's
   *word* already means. On dark it is the green as type. On light it is the
   decks' stripe, the green under the lower third of the word, cloned onto
   each line when the word wraps. On green the stripe would vanish, so it is
   an underline in the line's own colour. Side-by-side blocks carry no mark:
   in equal columns it marks one column over the other. */
.slide em {
  font-style: normal;
}

.slide[data-theme="dark"] em {
  color: var(--ink);
}

.slide[data-theme="light"] em {
  background: linear-gradient(to top, var(--accent) 0 34%, transparent 34%);
  padding: 0 3px;
  -webkit-box-decoration-break: clone;
  box-decoration-break: clone;
}

.slide[data-theme="green"] em {
  text-decoration: underline;
  text-decoration-color: color-mix(in srgb, currentColor 45%, transparent);
  text-decoration-thickness: max(2px, 0.04em);
  text-underline-offset: 0.12em;
}

.slide:is([data-theme="light"], [data-theme="green"]) :is(.slide-cards, .slide-compare, .slide-dos, .slide-table) em {
  background: none;
  padding: 0;
  text-decoration: none;
}

/* An eyebrow and a label: the section number over a divider, a field name on
   the access slide, a side's title. In the sans, not the mono. The chapter
   number is the --ink, which is the green on a dark slide. */
.slide-section-num,
.slide-side-title {
  font-family: var(--font-sans);
  font-weight: var(--weight-semibold);
  font-size: var(--slide-small);
  letter-spacing: var(--tracking-wider);
  text-transform: uppercase;
  color: var(--muted-foreground);
}

.slide-section-num {
  color: var(--ink);
}

.slide-note {
  font-size: var(--slide-small);
  color: var(--muted-foreground);
}

/* cover: .slide-display, and .slide-cover-art beside it when there is a
   drawing. The drawing is decoration and takes what the title leaves. The
   cover's line is the ladder's largest step. */
.slide[data-kind="cover"] .slide-display {
  font-size: var(--slide-cover);
}

.slide[data-kind="cover"] .slide-main:has(.slide-cover-art) {
  display: grid;
  grid-template-columns: minmax(min-content, 1fr) minmax(0, 720px);
  align-items: center;
  gap: 96px;
}

.slide-cover-art svg {
  display: block;
  width: 100%;
  height: auto;
}

/* statement: one .slide-statement, held under the decks' 1620 so a long one
   does not run the width of the frame. */
.slide-statement {
  max-width: 1620px;
  line-height: 1.08;
}

/* section: .slide-section-num over .slide-display. */
.slide[data-kind="section"] .slide-main {
  gap: 40px;
}

.slide[data-kind="section"] .slide-display {
  max-width: 1500px;
}

/* agenda: .slide-title over ol.slide-agenda, each li a .slide-step-num and a
   span. steps: .slide-title over ol.slide-steps, numbered the same way, or
   ul.slide-steps, bulleted. A row each, with a rule under it. */
.slide-agenda,
.slide-steps {
  list-style: none;
  padding: 0;
  display: flex;
  flex-direction: column;
  border-top: 1px solid var(--slide-rule);
  font-family: var(--font-display);
  font-weight: var(--weight-body);
  letter-spacing: var(--tracking-snug);
  font-size: var(--slide-lead);
  line-height: 1.15;
}

.slide-agenda > li,
.slide-steps > li {
  padding-block: 20px;
  border-bottom: 1px solid var(--slide-rule);
}

.slide-agenda > li,
ol.slide-steps > li {
  display: grid;
  grid-template-columns: 96px minmax(0, 1fr);
  align-items: baseline;
}

.slide-steps > li {
  color: var(--body);
}

ul.slide-steps > li {
  display: grid;
  grid-template-columns: 1.2em minmax(0, 1fr);
  align-items: baseline;
}

ul.slide-steps > li::before {
  content: "\25AA";
  color: var(--tert);
}

.slide-step-num {
  font-family: var(--font-mono);
  font-size: var(--slide-small);
  letter-spacing: normal;
  font-variant-numeric: tabular-nums;
  color: var(--tert);
}

/* highlight: .slide-title over ul.slide-words and an optional .slide-note, or
   over a .slide-lead. */
.slide-words {
  list-style: none;
  padding: 0;
  display: flex;
  flex-wrap: wrap;
  gap: 16px 48px;
  font-size: var(--slide-label);
}

/* The side-by-side kinds size against their own width, so four cards at 1280
   wrap where four cards at 1920 do not, and the text steps down inside the
   ladder rather than past its floor. */
.slide:is([data-kind="cards"], [data-kind="compare"], [data-kind="dos"], [data-kind="table"], [data-kind="timeline"]) .slide-main {
  container-type: inline-size;
}

/* cards: .slide-title over ul.slide-cards or ol.slide-cards, 2 to 4 of them,
   each li an h3.slide-card-title and a p. A numbered list counts its cards.
   The decks' three-up: no boxes, a rule over the row and one between the
   cards. */
.slide-cards,
.slide-compare,
.slide-dos {
  display: grid;
  grid-auto-flow: column;
  grid-auto-columns: minmax(0, 1fr);
  gap: 32px;
}

.slide-cards {
  list-style: none;
  padding: 0;
  gap: 0;
  border-top: 1px solid var(--slide-rule);
  counter-reset: cards;
}

.slide-cards > li,
.slide-compare > section,
.slide-dos > section {
  display: flex;
  flex-direction: column;
  gap: 24px;
  min-width: 0;
}

.slide-cards > li {
  padding: 48px clamp(24px, 2.8cqi, 48px) 0;
  border-left: 1px solid var(--slide-rule);
  counter-increment: cards;
}

.slide-cards > li:first-child {
  padding-left: 0;
  border-left: 0;
}

.slide-cards > li:last-child {
  padding-right: 0;
}

ol.slide-cards > li::before {
  content: counter(cards, decimal-leading-zero);
  font-family: var(--font-mono);
  font-size: var(--slide-small);
  color: var(--tert);
}

/* At heading weight, not display: in four columns at 1280 it lands under
   44, where a display weight closes up. */
.slide-card-title {
  font-family: var(--font-display);
  font-weight: var(--weight-heading);
  letter-spacing: var(--tracking-tight);
  font-size: clamp(var(--slide-body), 2.6cqi, var(--slide-label));
  line-height: 1.08;
  text-wrap: balance;
}

.slide-cards p {
  font-size: var(--slide-small);
  line-height: 1.45;
  color: var(--body);
  text-wrap: pretty;
}

/* A side's text is the small step, as the decks' before and after set it:
   two to four columns of sentences at the body size outrun a 1280 frame. */
.slide-compare :is(li, p),
.slide-dos li {
  font-size: var(--slide-small);
  line-height: 1.4;
  color: var(--body);
}

/* A side that is not the argument is a --surface block, which is what the
   light ground was picked to hold off. The column an argument lands in is the
   dark block, the design system's .panel. A deck does not load patterns.css,
   so the slide carries its own: the panel ground and the panel's text roles,
   which on a dark slide are the slide's own. */
.slide :is(.slide-compare, .slide-dos) > section {
  padding: clamp(32px, 2.8cqi, 48px);
  background: var(--surface);
}

.slide :is(.slide-compare, .slide-dos) > .panel {
  --foreground: var(--panel-foreground);
  --body: var(--panel-foreground);
  --ink: var(--panel-ink);
  --muted-foreground: color-mix(in srgb, var(--panel-foreground) 70%, transparent);
  --slide-rule: color-mix(in srgb, var(--foreground) 16%, transparent);
  background: var(--panel);
  color: var(--foreground);
}

/* compare: .slide-title over div.slide-compare, two to four sections, each an
   h3.slide-side-title and a ul or a p, the last one a .panel. An optional
   .slide-note under it. */
.slide-compare ul {
  list-style: square;
  padding-left: 1.2em;
  display: flex;
  flex-direction: column;
  gap: 16px;
}

.slide-compare li::marker {
  color: var(--tert);
}

/* An optional p.slide-side-head under a side's title: the decks' before and
   after, where a side is named in a line before its points. Sized like a card
   title, against the column. */
.slide-side-head {
  font-family: var(--font-display);
  font-weight: var(--weight-heading);
  letter-spacing: var(--tracking-tight);
  font-size: clamp(var(--slide-body), 2.6cqi, var(--slide-label));
  line-height: 1.08;
  color: var(--foreground);
  text-wrap: balance;
}

/* timeline: .slide-title over ol.slide-timeline, 2 to 5 markers, each li an
   optional .slide-timeline-mark (an img, or a short figure), a
   .slide-timeline-tag and a .slide-timeline-stat. Rules as the cards draw
   them. An empty li keeps its column, so a timeline can be built up one
   marker a slide on a fixed grid. */
.slide-timeline {
  list-style: none;
  padding: 0;
  display: grid;
  grid-auto-flow: column;
  grid-auto-columns: minmax(0, 1fr);
  border-top: 1px solid var(--slide-rule);
}

.slide-timeline > li {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 16px;
  min-width: 0;
  padding: 48px clamp(16px, 2cqi, 32px) 0;
  border-left: 1px solid var(--slide-rule);
  text-align: center;
}

.slide-timeline > li:first-child {
  border-left: 0;
}

.slide-timeline-mark {
  display: flex;
  align-items: center;
  justify-content: center;
  height: calc(var(--slide-label) * 2);
  margin-bottom: 12px;
  font-family: var(--font-display);
  font-weight: var(--weight-display);
  letter-spacing: var(--tracking-tight);
  font-size: var(--slide-title);
  line-height: 1;
  color: var(--ink);
}

.slide-timeline-mark img {
  display: block;
  height: 100%;
  width: auto;
  max-width: 100%;
  object-fit: contain;
}

.slide-timeline-tag {
  font-family: var(--font-mono);
  font-size: var(--slide-small);
  font-variant-numeric: tabular-nums;
  color: var(--body);
}

.slide-timeline-stat {
  font-family: var(--font-display);
  font-weight: var(--weight-heading);
  letter-spacing: var(--tracking-tight);
  font-size: clamp(var(--slide-body), 2.6cqi, var(--slide-label));
  line-height: 1.08;
  color: var(--foreground);
  text-wrap: balance;
}

/* about: .slide-about, a .slide-section-num, the name as .slide-display and
   one or two .slide-lead lines, with an optional img.slide-about-portrait
   beside it. The portrait is contained, never cropped, so a cut-out stands on
   the slide's floor and a round crop stays the deck's choice. */
.slide-about {
  display: flex;
  flex-direction: column;
  gap: 24px;
  min-width: 0;
}

.slide-about .slide-lead {
  max-width: 1500px;
}

.slide[data-kind="about"] .slide-main:has(.slide-about-portrait) {
  display: grid;
  grid-template-columns: minmax(0, 3fr) minmax(0, 2fr);
  align-items: center;
  gap: 96px;
}

.slide-about-portrait {
  display: block;
  width: 100%;
  height: 100%;
  min-height: 0;
  object-fit: contain;
  object-position: bottom;
}

/* dos: .slide-title over div.slide-dos, section.slide-dos-do.panel and
   section.slide-dos-avoid, each an h3.slide-side-title and a ul. Do is written
   first and laid out last, so the dark column sits on the right in every
   side-by-side block. */
.slide-dos-do {
  order: 2;
}

.slide-dos ul {
  list-style: none;
  padding: 0;
  display: flex;
  flex-direction: column;
  gap: 16px;
}

.slide-dos li {
  display: grid;
  grid-template-columns: 1.15em minmax(0, 1fr);
  gap: 0.85em;
}

.slide-dos li::before {
  font-family: var(--font-mono);
}

.slide-dos-do li::before {
  content: "\2713";
  color: var(--ink);
}

.slide-dos-avoid li::before {
  content: "\00D7";
  color: var(--tert);
}

/* table: .slide-title over table.slide-table, a thead row of th.slide-side-title
   and 2 to 7 body rows of a th and a td. A rule under every row, no boxes. */
.slide-table {
  width: 100%;
  border-collapse: collapse;
  table-layout: fixed;
  border-top: 1px solid var(--slide-rule);
}

.slide-table :is(th, td) {
  padding: 16px 24px 16px 0;
  border-bottom: 1px solid var(--slide-rule);
  text-align: left;
  vertical-align: top;
}

.slide-table thead th:first-child {
  width: 43%;
}

.slide-table tbody :is(th, td) {
  font-size: clamp(var(--slide-small), 2cqi, var(--slide-body));
}

.slide-table tbody th {
  font-weight: var(--weight-semibold);
}

.slide-table tbody td {
  color: var(--body);
}

/* number: p.slide-figure over a .slide-lead. The figure is the --ink, the
   green on a dark slide. */
.slide[data-kind="number"] .slide-main {
  gap: 40px;
}

.slide-figure {
  font-size: var(--slide-figure);
  line-height: 0.9;
  font-variant-numeric: tabular-nums;
  color: var(--ink);
}

/* quote: figure.slide-quote, a blockquote and an optional figcaption. Set
   snug and looser than a title, because it is read as a sentence. */
.slide-quote {
  display: flex;
  flex-direction: column;
  gap: 40px;
  max-width: 1300px;
}

.slide-quote blockquote {
  font-size: var(--slide-quote);
  letter-spacing: var(--tracking-snug);
  line-height: 1.2;
}

.slide-quote figcaption,
.slide-visual figcaption {
  font-size: var(--slide-small);
  color: var(--muted-foreground);
}

/* visual: an optional .slide-title over figure.slide-visual, a .diagram-art
   holding an inline SVG with a viewBox or an img, and an optional figcaption.
   The drawing takes the room the title leaves and scales inside it, which is
   how a slide that needs its own coordinates lives in a fluid frame. A
   screenshot is contained the same way, never cropped. */
.slide-visual {
  flex: 1;
  min-height: 0;
  display: flex;
  flex-direction: column;
  gap: 32px;
}

.slide-visual .diagram-art {
  flex: 1;
  min-height: 0;
}

.slide-visual .diagram-art :is(svg, img) {
  display: block;
  width: 100%;
  height: 100%;
}

.slide-visual .diagram-art img {
  object-fit: contain;
}

/* access: div.slide-access, two divs of a .slide-section-num label and a
   .slide-access-value, the second an input[data-deck-keep] the presenter types
   once. */
.slide-access {
  display: flex;
  flex-direction: column;
  gap: 72px;
}

.slide-access > div {
  display: flex;
  flex-direction: column;
  gap: 24px;
}

.slide-access-value {
  font-size: var(--slide-display);
  overflow-wrap: anywhere;
}

input.slide-access-value {
  width: 100%;
  padding: 0;
  border: 0;
  border-bottom: 2px solid;
  border-bottom-color: var(--background);
  background: none;
  color: inherit;
  outline: none;
}

input.slide-access-value:is(:placeholder-shown, :focus) {
  border-bottom-color: var(--border);
}

input.slide-access-value::placeholder {
  color: var(--tert);
  opacity: 1;
}

/* ---------------------------------------------------------------- controls */

/* nav.slide-controls[data-controls][hidden] with any of [data-deck-prev],
   [data-deck-count], [data-deck-next], [data-deck-fullscreen],
   [data-deck-notes] and [data-deck-close]. Hidden in the markup and shown by
   stage.js, so a page whose script did not run has no dead buttons. Visible
   only while stage.js marks them, and in screen pixels like the head bar. */
.slide-controls {
  position: fixed;
  z-index: 1;
  left: 50%;
  bottom: 24px;
  transform: translateX(-50%);
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 8px;
  background: var(--block);
  border: 1px solid var(--hair);
  font-family: var(--font-sans);
  font-size: var(--text-sm);
  color: var(--foreground);
  transition: opacity 200ms;
}

.slide-controls:not([data-visible], :focus-within) {
  opacity: 0;
  pointer-events: none;
}

.slide-controls :is(button, a) {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-width: 36px;
  height: 36px;
  padding: 0 12px;
  border: 0;
  background: none;
  color: inherit;
  font: inherit;
  text-decoration: none;
  cursor: pointer;
}

.slide-controls :is(button, a):hover {
  background: var(--sunken);
}

.slide-controls button:disabled {
  opacity: 0.4;
  cursor: default;
}

.slide-controls [data-deck-count] {
  padding: 0 8px;
  font-variant-numeric: tabular-nums;
  color: var(--muted-foreground);
}

/* ------------------------------------------------------------------- print */

/* One slide per page at the frame's own size, whatever the window was. The
   script's inline sizes and --px lose to these, so a print from a narrow
   window still draws 1920 by 1080. */
@page {
  size: 1920px 1080px;
  margin: 0;
}

@media print {
  body:has(.slide-deck) {
    margin: 0;
  }

  .slide-deck,
  .slide-deck[data-ready] {
    --px: 1px !important;
    position: static;
    min-height: 0;
    overflow: visible;
    print-color-adjust: exact;
    -webkit-print-color-adjust: exact;
  }

  .slide-deck .slide-stage {
    position: static;
    width: 1920px !important;
    height: auto !important;
    transform: none !important;
  }

  .slide-deck .slide-stage > .slide {
    display: flex;
    position: relative;
    inset: auto;
    width: 1920px;
    height: 1080px;
    margin: 0;
    break-after: page;
  }

  .slide-controls {
    display: none;
  }
}
