/* =====================================================================
   AI-Native Web Development, Hands-On — deck theme
   ---------------------------------------------------------------------
   The Pristina deck theme (agentic-coding-workshop/slides/slides.css),
   unchanged apart from comments and one deletion, through "DESIGN
   SYSTEM v2" and its archetypes. This workshop's
   own components (Block slides, prompt boxes, cheat sheet)
   are appended at the end, under "AI-NATIVE WEB DEV ADDITIONS".

   The deletion: Pristina loads Google Sans from fonts.googleapis.com.
   That sends every viewer's IP address to Google, which slide 7 teaches
   against, so this deck loads nothing from other servers. The font
   stacks below still name Google Sans first: it is used only where it
   is installed on the computer, with no download. Everywhere else the
   system font shows (San Francisco on a Mac).
   ===================================================================== */

:root {
  /* Google brand */
  --google-blue:   #4285F4;
  --google-red:    #EA4335;
  --google-yellow: #FBBC04;
  --google-green:  #34A853;

  /* Neutrals */
  --grey-900:  #202124;
  --grey-700:  #5F6368;
  --grey-500:  #9AA0A6;
  --grey-200:  #E8EAED;
  --grey-100:  #F1F3F4;
  --surface:     #FFFFFF;
  --surface-alt: #F8F9FA;

  /* Radii / shadows */
  --radius-sm:   8px;
  --radius-md:   16px;
  --radius-lg:   24px;
  --shadow-card: 0 1px 2px rgba(60,64,67,.08), 0 1px 3px rgba(60,64,67,.10);
  --shadow-lift: 0 4px 8px rgba(60,64,67,.10), 0 8px 24px rgba(60,64,67,.15);

  /* Type */
  --font-display: 'Google Sans Display', system-ui, -apple-system, sans-serif;
  --font-body:    'Google Sans Text', system-ui, -apple-system, sans-serif;
  --font-code:    'Google Sans Code', ui-monospace, 'SF Mono', Menlo, monospace;
}

/* ---------- Reveal base overrides ---------- */
.reveal {
  font-family: var(--font-body);
  font-weight: 400;
  color: var(--grey-900);
  background: var(--surface);
}
.reveal .slides { text-align: left; }
.reveal .slides > section,
.reveal .slides > section > section {
  padding: 1.2em 1.6em;
  line-height: 1.5;
}

.reveal h1,
.reveal h2,
.reveal h3,
.reveal h4 {
  font-family: var(--font-display);
  font-weight: 700;
  color: var(--grey-900);
  text-transform: none;
  letter-spacing: -0.01em;
  line-height: 1.15;
  margin: 0 0 0.4em 0;
}
.reveal h1 { font-size: 2.6em; }
.reveal h2 { font-size: 2.0em; }
.reveal h3 { font-size: 1.4em; font-weight: 500; }
.reveal h4 { font-size: 1.1em; font-weight: 500; color: var(--grey-700); }

.reveal p,
.reveal li { font-size: 1.05em; }
.reveal .subtitle { font-size: 1.3em; color: var(--grey-700); font-weight: 400; }
.reveal .eyebrow {
  font-family: var(--font-body);
  font-size: 0.9em;
  font-weight: 500;
  text-transform: uppercase;
  letter-spacing: 0.08em;
  color: var(--google-blue);
  margin: 0 0 0.6em 0;
}

.reveal a { color: var(--google-blue); text-decoration: none; }
.reveal a:hover { text-decoration: underline; }
/* The addresses on the slides (the prep page, the guide, the demo site) are
   links that keep their look: the text's own colour, no underline, a new tab
   (Fabian, 2026-10-08). The QR card's address is a block, so the fitting
   code can measure it. */
.reveal .ds-plain-link, .reveal .ds-plain-link:hover { color: inherit; text-decoration: none; }
.reveal a.ds-qr-value { display: block; }

.reveal code {
  font-family: var(--font-code);
  font-size: 0.92em;
  background: var(--grey-100);
  color: var(--grey-900);
  padding: 0.1em 0.35em;
  border-radius: 4px;
}
.reveal pre {
  font-family: var(--font-code);
  font-size: 0.65em;
  background: var(--grey-100);
  border-radius: var(--radius-sm);
  padding: 0.8em 1em;
  box-shadow: none;
  width: 100%;
}
.reveal pre code { background: none; padding: 0; }

.reveal table {
  margin: 0.8em 0;
  border-collapse: collapse;
  width: 100%;
  font-size: 0.85em;
}
.reveal th,
.reveal td {
  text-align: left;
  padding: 0.55em 0.8em;
  border-bottom: 1px solid var(--grey-200);
}
.reveal th {
  font-family: var(--font-display);
  font-weight: 500;
  color: var(--grey-700);
  background: var(--surface-alt);
}

.reveal ul, .reveal ol { margin: 0.5em 0 0.5em 1.3em; }
.reveal li { margin: 0.2em 0; }
.reveal strong { font-weight: 700; color: var(--grey-900); }
.reveal em { font-style: italic; color: var(--grey-700); }

/* ---------- Brand stripe (4-color) ---------- */
.brand-stripe {
  height: 8px;
  width: 100%;
  background: linear-gradient(
    to right,
    var(--google-blue) 0%, var(--google-blue) 25%,
    var(--google-red) 25%, var(--google-red) 50%,
    var(--google-yellow) 50%, var(--google-yellow) 75%,
    var(--google-green) 75%, var(--google-green) 100%
  );
  margin: 0 0 1em 0;
  border-radius: 999px;
}
.brand-stripe.compact { height: 4px; max-width: 200px; margin-left: 0; }

/* ---------- Layouts ---------- */

/* Centered section divider: number + title */
.section-divider {
  text-align: center;
  display: flex;
  flex-direction: column;
  justify-content: center;
  align-items: center;
  height: 100%;
}
.section-divider .section-num {
  font-family: var(--font-display);
  font-size: 7em;
  font-weight: 700;
  color: var(--google-blue);
  line-height: 1;
}
.section-divider .section-title {
  font-family: var(--font-display);
  font-size: 1.8em;
  font-weight: 500;
  color: var(--grey-900);
  margin-top: 0.3em;
}
.section-divider .section-sub {
  font-size: 1em;
  color: var(--grey-700);
  margin-top: 0.5em;
}

/* Big-question / single-idea slide */
.bigq {
  display: flex;
  flex-direction: column;
  justify-content: center;
  height: 100%;
}
.bigq h1 { font-size: 2.8em; }
.bigq .sub { font-size: 1.4em; color: var(--grey-700); margin-top: 0.4em; }

/* Quiz slide: top half question, bottom half image */
.quiz {
  display: flex;
  flex-direction: column;
  height: 100%;
}
.quiz .q-num {
  font-family: var(--font-display);
  font-size: 0.9em;
  font-weight: 500;
  color: var(--google-blue);
  text-transform: uppercase;
  letter-spacing: 0.1em;
  margin-bottom: 0.4em;
}
.quiz h2 {
  font-size: 2.1em;
  font-weight: 500;
  margin-bottom: 0.8em;
  max-width: 900px;
}
.quiz .q-image {
  flex: 1;
  display: flex;
  align-items: center;
  justify-content: center;
  background: var(--surface-alt);
  border-radius: var(--radius-md);
  overflow: hidden;
  min-height: 300px;
}
.quiz .q-image img {
  max-width: 100%;
  max-height: 100%;
  object-fit: contain;
}

/* Two-column logistics layout (Pristina; this deck uses .ds-qr-card) */
.logistics-grid {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 2em;
  margin-top: 1em;
  height: 80%;
}
.logistics-card {
  background: var(--surface-alt);
  border-radius: var(--radius-md);
  padding: 1.2em 1.4em;
  display: flex;
  flex-direction: column;
}
.logistics-card .label {
  font-family: var(--font-display);
  font-size: 0.85em;
  font-weight: 500;
  text-transform: uppercase;
  letter-spacing: 0.08em;
  color: var(--google-blue);
  margin-bottom: 0.4em;
}
.logistics-card .value {
  font-family: var(--font-display);
  font-size: 1.7em;
  font-weight: 700;
  color: var(--grey-900);
  word-break: break-all;
  line-height: 1.2;
}
.logistics-card .value-sub {
  font-size: 0.95em;
  color: var(--grey-700);
  margin-top: 0.2em;
  word-break: break-all;
}
.logistics-card .qr-wrap {
  margin-top: auto;
  display: flex;
  justify-content: center;
  padding-top: 0.8em;
}
.logistics-card .qr {
  width: 200px;
  height: 200px;
}

/* 5-layer stack diagram */
.layer-stack { display: flex; flex-direction: column; gap: 0.4em; max-width: 800px; margin: 0.6em 0; }
.layer-stack .layer {
  padding: 0.7em 1.2em;
  border-radius: var(--radius-sm);
  font-family: var(--font-display);
  font-weight: 500;
  display: flex;
  align-items: center;
  justify-content: space-between;
}
.layer-stack .layer .layer-num { color: var(--surface); opacity: 0.7; font-size: 0.8em; }
.layer-stack .layer.l1 { background: var(--google-blue);   color: var(--surface); }
.layer-stack .layer.l2 { background: var(--google-green);  color: var(--surface); }
.layer-stack .layer.l3 { background: var(--google-yellow); color: var(--grey-900); }
.layer-stack .layer.l4 { background: var(--google-red);    color: var(--surface); }
.layer-stack .layer.l5 { background: var(--grey-900);      color: var(--surface); }
.layer-stack .layer.you-are-here { outline: 4px solid var(--google-yellow); outline-offset: 4px; }

/* Callouts */
.callout {
  background: var(--surface-alt);
  border-left: 4px solid var(--google-blue);
  border-radius: var(--radius-sm);
  padding: 0.8em 1em;
  margin: 0.8em 0;
  font-size: 0.95em;
}
.callout.tip   { border-left-color: var(--google-green); }
.callout.warn  { border-left-color: var(--google-red); }
.callout.rule  { border-left-color: var(--google-yellow); }
.callout strong { display: block; margin-bottom: 0.2em; color: var(--grey-900); }

/* Comparison columns */
.compare {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 1.4em;
  margin: 0.8em 0;
}
.compare.three { grid-template-columns: 1fr 1fr 1fr; }
.compare .col {
  background: var(--surface-alt);
  border-radius: var(--radius-md);
  padding: 1em 1.2em;
  border-top: 4px solid var(--grey-200);
}
.compare .col.blue   { border-top-color: var(--google-blue); }
.compare .col.red    { border-top-color: var(--google-red); }
.compare .col.yellow { border-top-color: var(--google-yellow); }
.compare .col.green  { border-top-color: var(--google-green); }
.compare .col h3 { font-size: 1.1em; margin-bottom: 0.3em; }
.compare .col p, .compare .col li { font-size: 0.9em; }

/* Google product callout — small chip */
.gproduct {
  display: inline-block;
  background: var(--google-blue);
  color: var(--surface);
  padding: 0.3em 0.8em;
  border-radius: 999px;
  font-size: 0.8em;
  font-weight: 500;
  margin-top: 0.6em;
}
.gproduct.green  { background: var(--google-green); }
.gproduct.red    { background: var(--google-red); }
.gproduct.yellow { background: var(--google-yellow); color: var(--grey-900); }

/* ---------- Footer band ---------- */
.deck-footer {
  position: fixed;
  bottom: 0;
  left: 0;
  right: 0;
  background: var(--surface-alt);
  border-top: 4px solid;
  border-image: linear-gradient(to right,
    var(--google-blue) 0 25%,
    var(--google-red) 25% 50%,
    var(--google-yellow) 50% 75%,
    var(--google-green) 75% 100%) 1;
  padding: 0.5em 1.4em;
  font-family: var(--font-body);
  font-size: 0.7em;
  color: var(--grey-700);
  display: flex;
  justify-content: space-between;
  align-items: center;
  z-index: 30;
}
.deck-footer[hidden] { display: none; }
.deck-footer .footer-item { white-space: nowrap; }
.deck-footer .footer-item strong { color: var(--grey-900); margin-right: 0.3em; }

/* ---------- Slide number (bottom-left, for "go back to slide X" callbacks) ---------- */
/* Container height matches Reveal's arrow box (3.6em × 10px-base = 36px) so the
   number sits at the same visual baseline AND the same visual height as the arrows. */
.reveal .slide-number {
  left: 28px;
  right: auto;
  bottom: 12px;
  top: auto;
  height: 36px;
  display: flex;
  align-items: center;
  background: transparent;
  color: var(--grey-500);
  font-family: var(--font-body);
  font-size: 36px;
  font-weight: 500;
  line-height: 1;
  padding: 0;
  z-index: 31;
}
.reveal .slide-number a { color: inherit; }

/* ---------- Motion ----------
   One motion for everything that comes in, on every slide: a short fade with
   a small rise (--ds-motion, --ds-rise). Each click (a Reveal fragment) uses
   it, and so do the few elements that come in by themselves when their slide
   opens (.ds-enter), again each time you come back. Quiet on purpose: the
   content should catch the eye, not the effect. */
.reveal .slides section .fragment {
  transform: translateY(var(--ds-rise));
  transition: opacity var(--ds-motion), transform var(--ds-motion), visibility var(--ds-motion);
}
.reveal .slides section .fragment.visible { transform: none; }
.reveal .slides section.present .ds-enter { animation: ds-enter var(--ds-motion) 0.15s both; }
@keyframes ds-enter { from { opacity: 0; transform: translateY(var(--ds-rise)); } to { opacity: 1; transform: none; } }
@media (prefers-reduced-motion: reduce) {
  .reveal .slides section { transition: none !important; }
  .reveal .fragment,
  .reveal .ds-face { transition: none !important; }
  .reveal .slides section.present .ds-enter { animation: none; }
}

/* =====================================================================
   DESIGN SYSTEM v2
   ---------------------------------------------------------------------
   Five slide archetypes — Title, Author, Content (layered, cards),
   Title + Image. Equal whitespace left/right, headline always anchored
   in the same place, brand stripe under headline at 30% width.
   ===================================================================== */

:root {
  --ds-pad-x: 96px;     /* equal left + right whitespace */
  --ds-pad-y: 40px;     /* tighter top + bottom          */
  --ds-h-size: 64px;    /* default headline size         */
  --ds-h-size-xl: 88px; /* title-slide headline size     */
  --ds-stripe-w: 30%;
  --ds-rise: 12px;      /* how far things rise in    */
  --ds-motion: 0.45s cubic-bezier(0.2, 0.7, 0.3, 1);
}

.reveal .slides > section.ds {
  /* 20px less above the headline than below the footer: the room at the
     bottom, where the bottom line meets the Wi-Fi line, is what gets tight
     (Fabian, 2026-10-08). */
  padding: calc(var(--ds-pad-y) - 20px) var(--ds-pad-x) var(--ds-pad-y);
  height: 100%;
  display: flex;
  flex-direction: column;
  box-sizing: border-box;
}

/* ---------- Header zone (anchored top of slide) ----------
   Brand stripe lives on the slide edge (see section.ds::before above);
   the header itself just stacks eyebrow / title / subtitle tightly.
*/
.reveal .ds-header { margin: 0 0 56px; }

.reveal .ds-eyebrow {
  font-family: var(--font-body);
  font-size: 18px;
  font-weight: 500;
  text-transform: uppercase;
  letter-spacing: 0.12em;
  color: var(--google-blue);
  margin: 0 0 8px;
}
.reveal .ds-eyebrow.layer-blue   { color: var(--google-blue); }
.reveal .ds-eyebrow.layer-green  { color: var(--google-green); }
.reveal .ds-eyebrow.layer-yellow { color: #C68400; } /* darker amber so yellow reads on white */
.reveal .ds-eyebrow.layer-red    { color: var(--google-red); }
.reveal .ds-eyebrow.layer-dark   { color: var(--grey-900); }
.reveal .ds-eyebrow.layer-grey   { color: var(--grey-500); }

.reveal .ds-title {
  font-family: var(--font-display);
  font-size: var(--ds-h-size);
  font-weight: 700;
  line-height: 1.08;
  letter-spacing: -0.015em;
  color: var(--grey-900);
  margin: 0;
  max-width: 36ch;       /* keep headlines from running edge-to-edge, but allow ~33-char titles on one line */
  text-wrap: balance;    /* even line breaks, no widow words */
}

.reveal .ds-subtitle {
  font-size: 32px;
  line-height: 1.3;
  color: var(--grey-700);
  font-weight: 400;
  margin: 12px 0 0;
  max-width: 50ch;
  text-wrap: balance;
}

/* ---------- Content zone ---------- */
.ds-body {
  flex: 1;
  min-height: 0;
  display: flex;
  flex-direction: column;
  justify-content: flex-start;
}
.ds-body.center { justify-content: center; }

/* ---------- Archetype 1: TITLE SLIDE ---------- */
.reveal .ds.ds-title-slide .ds-body { justify-content: center; }
.reveal .ds.ds-title-slide .ds-title { font-size: var(--ds-h-size-xl); max-width: 24ch; }
.reveal .ds-meta {
  margin-top: 64px;
  font-size: 20px;
  color: var(--grey-700);
}
.reveal .ds-meta strong { color: var(--grey-900); font-weight: 700; }

/* Learning-outcome cards under title */
.ds-outcomes {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 32px;
  margin-top: 64px;
}
.ds-outcome {
  padding: 48px 40px;
  border-radius: var(--radius-md);
  background: var(--google-blue);
  color: #fff;
}
.ds-outcome:nth-child(2) { background: var(--google-red); }
.ds-outcome:nth-child(3) { background: var(--google-green); }
.ds-outcome:nth-child(4) { background: var(--google-green); }
.reveal .ds-outcome-text {
  font-family: var(--font-display);
  font-size: 32px;
  font-weight: 700;
  line-height: 1.25;
  margin: 0;
  text-wrap: balance;
}

/* ---------- Archetype 2: AUTHOR / ABOUT ---------- */
.ds-author {
  display: grid;
  grid-template-columns: 320px 1fr;
  gap: 64px;
  align-items: center;
}
.ds-author-photo {
  width: 320px;
  height: 320px;
  border-radius: var(--radius-lg);
  background:
    linear-gradient(135deg, var(--google-blue) 0%, var(--google-green) 100%);
  background-size: cover;
  background-position: center;
  object-fit: cover;
  display: block;
}
.reveal .ds-author-name {
  font-family: var(--font-display);
  font-size: 44px;
  font-weight: 700;
  margin: 0 0 8px;
  line-height: 1.05;
}
.reveal .ds-author-role {
  font-size: 22px;
  color: var(--grey-700);
  margin: 0 0 28px;
}

/* Reusable bullets — flex layout keeps the dot on the text baseline */
.reveal .ds-bullets { list-style: none; margin: 0; padding: 0; }
.reveal .ds-bullets li {
  font-size: 22px;
  line-height: 1.4;
  margin: 0 0 14px;
  padding: 0;
  display: flex;
  align-items: baseline;
  gap: 16px;
}
.ds-bullets li::before {
  content: '';
  flex: 0 0 auto;
  width: 12px; height: 12px;
  border-radius: 50%;
  background: var(--google-blue);
  transform: translateY(-2px);
}
.ds-bullets li:nth-child(2)::before { background: var(--google-red); }
.ds-bullets li:nth-child(3)::before { background: var(--google-yellow); }
.ds-bullets li:nth-child(4)::before { background: var(--google-green); }
.ds-bullets li:nth-child(5)::before { background: var(--grey-900); }

/* Large bullets — used on full-slide content like About Me */
.reveal .ds-bullets-lg li {
  font-size: 44px;
  font-weight: 500;
  line-height: 1.3;
  margin: 0 0 28px;
  gap: 24px;
}
.reveal .ds-bullets-lg li::before {
  width: 18px; height: 18px;
  transform: translateY(-6px);
}


/* ---------- Archetype 3a: CONTENT — LAYERED STACK ---------- */
.ds-layers {
  display: flex;
  flex-direction: column;
  gap: 14px;
  width: 100%;
}
.ds-layer {
  padding: 26px 32px;
  border-radius: var(--radius-md);
  font-family: var(--font-display);
  font-weight: 500;
  font-size: 26px;
  display: flex;
  justify-content: space-between;
  align-items: center;
  line-height: 1.1;
}
.ds-layer .ds-layer-tag {
  font-size: 16px;
  font-weight: 400;
  opacity: 0.85;
  letter-spacing: 0.04em;
}
.ds-layer.l-blue   { background: var(--google-blue);   color: #fff; }
.ds-layer.l-green  { background: var(--google-green);  color: #fff; }
.ds-layer.l-yellow { background: var(--google-yellow); color: var(--grey-900); }
.ds-layer.l-red    { background: var(--google-red);    color: #fff; }
.ds-layer.l-dark   { background: var(--grey-900);      color: #fff; }
.ds-layer.l-gray   { background: var(--grey-700);      color: #fff; }

/* ---------- Archetype 3b: CONTENT — COLORED CARDS ---------- */
.ds-cards {
  display: grid;
  grid-template-columns: repeat(var(--cols, 3), 1fr);
  gap: 24px;
}
.ds-card {
  padding: 32px;
  border-radius: var(--radius-md);
  background: var(--surface-alt);
  display: flex;
  flex-direction: column;
  border-top: 6px solid var(--grey-200);
}
.ds-card.solid-blue   { background: var(--google-blue);   color: #fff; border-top: 0; }
.ds-card.solid-red    { background: var(--google-red);    color: #fff; border-top: 0; }
.ds-card.solid-yellow { background: var(--google-yellow); color: var(--grey-900); border-top: 0; }
.ds-card.solid-green  { background: var(--google-green);  color: #fff; border-top: 0; }
.ds-card.solid-dark   { background: var(--grey-900);      color: #fff; border-top: 0; }
.ds-card.outline-blue   { border-top-color: var(--google-blue); }
.ds-card.outline-red    { border-top-color: var(--google-red); }
.ds-card.outline-yellow { border-top-color: var(--google-yellow); }
.ds-card.outline-green  { border-top-color: var(--google-green); }
.ds-card.outline-dark   { border-top-color: var(--grey-900); }
.ds-card.outline-grey   { border-top-color: var(--grey-500); }
.reveal .ds-card-title {
  font-family: var(--font-display);
  font-size: 36px;
  font-weight: 700;
  margin: 0 0 24px;
  line-height: 1.1;
  color: inherit;
}
.reveal .ds-card .ds-bullets li {
  font-size: 24px;
  font-weight: 400;
  line-height: 1.35;
  margin: 0 0 14px;
  gap: 12px;
  color: inherit;
}
.reveal .ds-card .ds-bullets li::before {
  width: 10px; height: 10px;
  transform: translateY(-2px);
}
.ds-card .ds-bullets li::before {
  width: 8px; height: 8px;
  top: 12px;
  background: rgba(255,255,255,0.7);
}
.ds-card.outline-blue   .ds-bullets li::before,
.ds-card.outline-red    .ds-bullets li::before,
.ds-card.outline-yellow .ds-bullets li::before,
.ds-card.outline-green  .ds-bullets li::before { background: var(--grey-700); }
.ds-card.solid-yellow   .ds-bullets li::before { background: rgba(0,0,0,0.5); }

/* ---------- Archetype 4: TITLE + IMAGE ----------
   Fixed-geometry layout. Slide is 1280x720. Image lives in the top
   540px (with a 40px top inset). Title lives in the bottom 140px band,
   vertically centered.
*/
.reveal .slides > section.ds.ds-image-slide {
  padding: 0;
  display: block;
}
.ds-image-slide .ds-image-frame {
  position: absolute;
  top: 40px;
  left: var(--ds-pad-x);
  right: var(--ds-pad-x);
  height: 570px;
  display: flex;
  align-items: center;
  justify-content: center;
}
.ds-image-slide .ds-image-frame > img {
  max-width: 100%;
  max-height: 100%;
  object-fit: contain;
  display: block;
  border-radius: 24px;
}
.ds-image-slide .ds-title-band {
  position: absolute;
  left: 0;
  right: 0;
  top: 610px;
  bottom: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 0 var(--ds-pad-x);
}
.reveal .ds-image-slide .ds-title {
  font-size: 36px;
  line-height: 1.15;
  text-align: center;
  max-width: 28ch;
  margin: 0;
  text-wrap: balance;
}
.reveal .ds-image-slide .ds-eyebrow {
  text-align: center;
  margin: 0 0 8px;
}

/* ---------- Community guidelines slide ---------- */
.ds-community-grid {
  display: grid;
  grid-template-columns: 1fr 1.1fr;
  gap: 48px;
  align-items: center;
  width: 100%;
}
.ds-community-bears {
  width: 100%;
  height: auto;
  max-height: 380px;
  object-fit: contain;
  display: block;
}
.ds-community .ds-card {
  padding: 18px 24px;
}
.reveal .ds-community .ds-card-title {
  font-size: 26px;
  margin: 0 0 4px;
}
.reveal .ds-card-text {
  font-size: 22px;
  line-height: 1.4;
  margin: 0;
  color: inherit;
}
.reveal .ds-card-text + .ds-card-text { margin-top: 14px; }
.reveal .ds-card-text strong { color: inherit; }
.reveal .ds-community .ds-card-text {
  font-size: 18px;
  line-height: 1.35;
  margin: 0;
  color: inherit;
}
/* Footnote / note that sits below cards or layers */
/* A dark grey shape with white text, no coloured edge (Fabian, 2026-10-07). */
.reveal .ds-note {
  margin: 24px auto 0;
  max-width: 64ch;
  background: #3C4043;
  border-radius: var(--radius-md);
  padding: 14px 24px;
  font-size: 20px;
  line-height: 1.4;
  color: #fff;
  text-align: left;
  text-wrap: balance; /* lines of about equal length (Fabian, 2026-10-08) */
  margin-bottom: 10px; /* clear of the Wi-Fi line's rule below it */
}
.reveal .ds-note strong { color: #fff; }
/* Inline emphasis card used as a single-row callout under a header */
.ds-cards.ds-rule { max-width: 880px; margin: 0 auto; }
/* Tight layers for stacks with 6+ rows */
.ds-layers.ds-layers-tight { gap: 10px; }
.ds-layers.ds-layers-tight .ds-layer { padding: 18px 32px; font-size: 24px; }
.ds-layers.ds-layers-tight .ds-layer-tag { font-size: 16px; }
/* Tighter 6-up (3x2) layout for recap-style slides */
.ds-cards.ds-cards-compact { gap: 16px; }
.ds-cards.ds-cards-compact .ds-card { padding: 22px; }
.reveal .ds-cards.ds-cards-compact .ds-card-title { font-size: 26px; margin: 0 0 12px; }
.reveal .ds-cards.ds-cards-compact .ds-card-text { font-size: 18px; }
/* 4-up sizing — squeeze title and padding */
.ds-cards[style*="--cols: 4"] { gap: 16px; }
.ds-cards[style*="--cols: 4"] .ds-card { padding: 20px 22px; }
.reveal .ds-cards[style*="--cols: 4"] .ds-card-title { font-size: 26px; margin: 0 0 14px; }
.reveal .ds-cards[style*="--cols: 4"] .ds-card-text { font-size: 18px; }
/* Code block centered inside a ds slide */
.reveal .ds-body .ds-code {
  width: 100%;
  max-width: 820px;
  margin: 0 auto;
  background: var(--grey-900);
  color: #fff;
  border-radius: var(--radius-md);
  padding: 22px 28px;
  font-family: var(--font-code);
  font-size: 20px;
  line-height: 1.45;
  white-space: pre;
  overflow-x: auto;
  text-align: left;
}
.reveal .ds-body .ds-code .c { color: var(--grey-500); }
.reveal .ds-community-link {
  margin: 36px 0 0;
  text-align: center;
  font-size: 26px;
  color: var(--grey-700);
  letter-spacing: 0.02em;
}

/* ---------- Quiz intro slide (image + how-it-works card) ---------- */
.ds-quiz-intro {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 56px;
  align-items: center;
  width: 100%;
}
.ds-quiz-intro > img {
  width: 100%;
  max-height: 380px;
  object-fit: contain;
  display: block;
}

/* ---------- Logistics / QR cards ---------- */
.ds-card.ds-qr-card {
  padding: 24px 28px 26px;
  align-items: center;
  text-align: center;
}
.reveal .ds-qr-card .ds-card-title {
  margin: 0 0 12px;
  text-align: center;
}
.reveal .ds-qr-value {
  font-family: var(--font-display);
  font-size: 24px;
  font-weight: 700;
  color: var(--grey-900);
  margin: 0;
  line-height: 1.25;
  word-break: break-all;
}
.reveal .ds-qr-sub {
  font-size: 18px;
  color: var(--grey-700);
  margin: 6px 0 0;
  word-break: break-all;
}
.ds-qr-wrap {
  margin-top: 18px;
  padding: 14px;
  background: #fff;
  border-radius: var(--radius-sm);
  display: inline-flex;
  align-items: center;
  justify-content: center;
}
.ds-qr-card .qr {
  display: block;
  line-height: 0;
}
.ds-qr-card .qr img {
  display: block;
  max-width: 100%;
  height: auto;
}

/* =====================================================================
   AI-NATIVE WEB DEV ADDITIONS (2026-10)
   ---------------------------------------------------------------------
   Components this workshop needs on top of the Pristina archetypes:
   Block slides (time box, prompt box, mistake and catch-up cards),
   then-vs-now chips, the flow map, cheat sheet, QR cards.
   Brand colours stay as fills; small text uses the darker tokens below
   so it stays readable on a projector (all >= 4.5:1 on white).
   ===================================================================== */

:root {
  --blue-text:  #1967D2;
  --red-text:   #C5221F;
  --green-text: #137333;
  --amber-text: #A25A00; /* 4.98:1 on the grey cards, 5.25:1 on white */
  --blue-bg:    #E8F0FE;
  --green-bg:   #E6F4EA;
  --red-bg:     #FCE8E6;
  --yellow-bg:  #FEF7E0;
}

/* Eyebrows: darker shades of the same hues, readable at 18px. */
.reveal .ds-eyebrow,
.reveal .ds-eyebrow.layer-blue   { color: var(--blue-text); }
.reveal .ds-eyebrow.layer-green  { color: var(--green-text); }
.reveal .ds-eyebrow.layer-yellow { color: var(--amber-text); }
.reveal .ds-eyebrow.layer-red    { color: var(--red-text); }

/* Speaker notes never show on the slide itself. */
.reveal aside.notes { display: none; }

/* ---------- Small helpers ---------- */
.reveal .ds-small { font-size: 18px; line-height: 1.4; color: var(--grey-700); }
.reveal .ds-card .ds-small { color: inherit; opacity: 0.9; }
.reveal .ds-kicker {
  font-family: var(--font-body);
  font-size: 16px;
  font-weight: 700;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  margin: 0 0 6px;
  color: var(--grey-700);
}
.reveal .ds-kicker.red   { color: var(--red-text); }
.reveal .ds-kicker.green { color: var(--green-text); }
.reveal .ds-kicker.blue  { color: var(--blue-text); }
.reveal .ds-kicker.amber { color: var(--amber-text); }
.reveal .ds-meta-line {
  margin: 28px 0 0;
  font-size: 22px;
  color: var(--grey-700);
}
.reveal .ds-meta-line strong { color: var(--grey-900); }

/* Chat prompt the room types, word for word. */
.reveal .ds-prompt {
  display: block;
  margin: 10px 0 0;
  padding: 12px 18px;
  background: var(--blue-bg);
  border-left: 6px solid var(--blue-text);
  border-radius: 12px;
  font-family: var(--font-code);
  font-size: 30px;
  font-weight: 500;
  line-height: 1.25;
  color: var(--grey-900);
}
.reveal .ds-prompt.ds-prompt-md { font-size: 24px; line-height: 1.35; }

/* Terminal command, one line. */
.reveal .ds-cmd {
  display: block;
  margin: 8px 0 0;
  padding: 10px 16px;
  background: var(--grey-900);
  color: #fff;
  border-radius: var(--radius-sm);
  font-family: var(--font-code);
  font-size: 21px;
  line-height: 1.3;
  white-space: nowrap;
}
/* Inline text the room types (a prompt inside a sentence). */
.reveal .ds-type {
  font-family: var(--font-code);
  font-size: 0.9em;
  background: var(--blue-bg);
  color: var(--grey-900);
  padding: 0.05em 0.35em;
  border-radius: 4px;
  white-space: nowrap;
}
.reveal .ds-type.wrap { white-space: normal; }

/* ---------- Block slides ----------
   Two tiles, what we do (the guide's steps) and why we do it, and under
   them the Block's own timer: a dark bar with a split-flap clock. From one
   minute left the bar says how to catch up. slides.js runs the timer and
   sets .is-paused, .is-last-minute and .is-up on the slide. */
.reveal .ds-block .ds-title { font-size: 54px; }
/* The same frame on every Block slide: the tiles keep one height (the
   longest list, six steps, fits), so the timer never moves between slides. */
.reveal .ds-follow {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
  gap: 24px;
  align-items: stretch;
  height: 290px;
}
.reveal .ds-follow .ds-card { padding: 16px 24px 12px; }
.reveal ol.ds-guide-steps {
  display: block;
  margin: 4px 0 0;
  padding: 0 0 0 1.5em;
  list-style: decimal;
  font-size: 22px;
  line-height: 1.3;
}
.reveal ol.ds-guide-steps > li { margin: 0 0 6px; padding-left: 4px; }
.reveal ol.ds-guide-steps > li::marker { color: var(--grey-700); font-weight: 700; }
.reveal ul.ds-why {
  display: block;
  margin: 4px 0 0;
  padding: 0;
  list-style: none;
  font-size: 19px;
  line-height: 1.35;
  color: var(--grey-900);
}
.reveal ul.ds-why > li { position: relative; margin: 0 0 8px; padding-left: 22px; }
.reveal ul.ds-why > li::before {
  content: '';
  position: absolute;
  left: 3px;
  top: 0.5em;
  width: 9px;
  height: 9px;
  border-radius: 50%;
  background: var(--green-text);
}

/* The timer: a dark bar under the tiles. */
.reveal .ds-timer {
  position: relative;
  display: flex;
  align-items: center;
  gap: 28px;
  margin-top: 14px;
  padding: 14px 24px;
  border-radius: var(--radius-md);
  background: #3C4043;
  color: #fff;
}
.reveal .ds-timer-status { flex: 1 1 auto; min-width: 0; }
.reveal .ds-timer-label { margin: 0; font-size: 28px; font-weight: 600; color: #fff; }
/* Every bar also names the help mode, until the checkpoint text takes over. */
.reveal .ds-timer-hint { margin: 8px 0 0; font-size: 19px; color: var(--grey-200); }
.reveal .ds-block.is-last-minute .ds-timer-hint,
.reveal .ds-block.is-up .ds-timer-hint { display: none; }

/* Split-flap clock: one dark tile for the minutes, one for the seconds.
   slides.js splits each tile into two fixed halves and two leaves; when the
   number changes, the upper leaf turns down and shows the new number. */
.reveal .ds-flipclock { display: flex; align-items: center; gap: 10px; flex: 0 0 auto; }
.reveal .ds-flip-colon {
  font-family: var(--font-display);
  font-size: 72px;
  font-weight: 700;
  line-height: 1;
  color: var(--grey-500);
}
.reveal .ds-flip {
  position: relative;
  width: 172px;
  height: 136px;
  perspective: 700px;
  border-radius: 12px;
  background: #202124;
  color: #fff;
  font-family: var(--font-display);
  font-size: 108px;
  font-weight: 700;
  font-variant-numeric: tabular-nums;
  line-height: 136px;
  text-align: center;
}
.reveal .ds-flip > span {
  position: absolute;
  left: 0;
  right: 0;
  height: 50%;
  overflow: hidden;
  backface-visibility: hidden;
}
.reveal .ds-flip > span > span { position: absolute; left: 0; right: 0; height: 200%; }
.reveal .ds-flip-top,
.reveal .ds-flip-front { top: 0; border-radius: 12px 12px 0 0; background: #2B2C2F; transform-origin: 50% 100%; }
.reveal .ds-flip-bottom,
.reveal .ds-flip-back { bottom: 0; border-radius: 0 0 12px 12px; background: #202124; transform-origin: 50% 0; }
.reveal .ds-flip-top > span,
.reveal .ds-flip-front > span { top: 0; }
.reveal .ds-flip-bottom > span,
.reveal .ds-flip-back > span { top: -100%; }
/* The split between the two halves. */
.reveal .ds-flip::after {
  content: '';
  position: absolute;
  left: 0;
  right: 0;
  top: 50%;
  height: 2px;
  margin-top: -1px;
  background: #0B0C0D;
  z-index: 3;
}
.reveal .ds-block.is-paused .ds-flip { color: var(--grey-500); }
.reveal .ds-block.is-last-minute .ds-flip { color: var(--google-yellow); }
.reveal .ds-block.is-up .ds-flip { color: var(--google-red); }

/* Pause and Reset show while the pointer is on the timer. */
.reveal .ds-timer-controls {
  position: absolute;
  top: 10px;
  right: 12px;
  display: flex;
  gap: 8px;
  opacity: 0;
  transition: opacity 0.15s ease;
  z-index: 5;
}
.reveal .ds-timer:hover .ds-timer-controls,
.reveal .ds-timer:focus-within .ds-timer-controls { opacity: 1; }
.reveal .ds-timer-btn {
  padding: 6px 14px;
  border: 0;
  border-radius: 999px;
  background: var(--surface);
  color: var(--grey-900);
  font-family: var(--font-body);
  font-size: 15px;
  font-weight: 600;
  cursor: pointer;
}
.reveal .ds-timer-btn:hover { background: var(--grey-200); }

/* From one minute left the bar says how to catch up, instead of its label. */
.reveal .ds-fallback { display: none; font-size: 21px; line-height: 1.35; color: #fff; }
.reveal .ds-fallback p { margin: 0; }
.reveal .ds-fallback strong { color: #fff; }
.reveal .ds-fallback .state.when-up { color: #F28B82; }
.reveal .ds-block.is-last-minute .ds-fallback,
.reveal .ds-block.is-up .ds-fallback { display: block; }
.reveal .ds-block.is-last-minute .ds-timer-label,
.reveal .ds-block.is-up .ds-timer-label { display: none; }
.reveal .ds-fallback .when-up { display: none; }
.reveal .ds-block.is-up .ds-fallback .when-up { display: inline; }
.reveal .ds-block.is-up .ds-fallback .when-last { display: none; }

/* Wi-Fi and guide address at the foot of a working slide. */
.reveal .ds-venue-line {
  margin: auto 0 0;
  padding-top: 12px;
  border-top: 1px solid var(--grey-200);
  font-size: 20px;
  color: var(--grey-700);
}
/* A value never breaks inside itself (a hyphen at a line end would look
   like part of the password); the line wraps between the items instead. */
.reveal .ds-venue-line strong { color: var(--grey-900); font-weight: 700; white-space: nowrap; }
.reveal .ds-venue-line .sep { margin: 0 12px; color: var(--grey-500); }
/* Since 2026-10-08 the Wi-Fi line is on every slide, the title slide included,
   so latecomers read it instead of asking. On the title slide it sits above
   the presenter line; the second line needs no rule of its own. */
.reveal .ds-venue-line + .ds-venue-line { margin-top: 0; padding-top: 6px; border-top: 0; }

/* Source line under a slide: credit and link. */
.reveal .ds-source {
  margin: 18px 0 0;
  font-size: 17px;
  color: var(--grey-700);
}
.reveal .ds-source a { color: var(--blue-text); }

/* ---------- Cheat sheet ---------- */
.reveal ol.ds-cheats {
  list-style: none;
  margin: 0;
  padding: 0;
  display: grid;
  grid-template-columns: 1fr 1fr;
  grid-auto-flow: column;
  grid-template-rows: repeat(4, auto);
  gap: 14px 36px;
}
.reveal ol.ds-cheats > li {
  margin: 0;
  display: grid;
  grid-template-columns: 44px 1fr;
  gap: 14px;
  align-items: start;
  padding: 12px 16px;
  border-radius: var(--radius-md);
  background: var(--surface-alt);
}
.reveal ol.ds-cheats .num {
  width: 44px;
  height: 44px;
  border-radius: 50%;
  background: var(--blue-text);
  color: #fff;
  font-family: var(--font-display);
  font-size: 24px;
  font-weight: 700;
  line-height: 44px;
  text-align: center;
}
.reveal ol.ds-cheats > li:nth-child(2) .num { background: var(--red-text); }
.reveal ol.ds-cheats > li:nth-child(3) .num { background: var(--amber-text); }
.reveal ol.ds-cheats > li:nth-child(4) .num { background: var(--green-text); }
/* The right column repeats the left one, so each row shares a colour. */
.reveal ol.ds-cheats > li:nth-child(5) .num { background: var(--blue-text); }
.reveal ol.ds-cheats > li:nth-child(6) .num { background: var(--red-text); }
.reveal ol.ds-cheats > li:nth-child(7) .num { background: var(--amber-text); }
.reveal ol.ds-cheats > li:nth-child(8) .num { background: var(--green-text); }
.reveal ol.ds-cheats h3 {
  display: flex;
  align-items: baseline;
  gap: 10px;
  font-family: var(--font-display);
  font-size: 28px;
  font-weight: 700;
  margin: 0 0 4px;
  line-height: 1.2;
}
.reveal ol.ds-cheats p { margin: 0; font-size: 22px; line-height: 1.35; color: var(--grey-900); }

/* ---------- QR cards ---------- */
.reveal .ds-qr-card .ds-qr-wrap { margin-top: 10px; }
.reveal .ds-qr-card .ds-qr-value { font-size: 22px; margin-top: 12px; word-break: normal; overflow-wrap: anywhere; }
.reveal .ds-qr-card .ds-qr-sub { font-size: 20px; margin-top: 4px; word-break: normal; overflow-wrap: break-word; }
.reveal .ds-qr-card .ds-qr-label { font-size: 18px; color: var(--grey-700); margin: 6px 0 0; line-height: 1.3; }
.reveal .ds-qr-card .ds-qr-pass {
  font-family: var(--font-code);
  font-size: 22px;
  font-weight: 700;
  color: var(--grey-900);
  margin: 2px 0 0;
  line-height: 1.25;
}
/* An open network's sign-in hint under the password line; empty on a
   network with a password. */
.reveal .ds-qr-card .ds-qr-note { font-size: 16px; color: var(--grey-700); margin: 6px 0 0; line-height: 1.3; max-width: 30ch; margin-left: auto; margin-right: auto; }
.reveal .ds-qr-card .ds-qr-note:empty { display: none; }
.reveal .ds-qr-card--open .ds-qr-label, .reveal .ds-qr-card--open .ds-qr-pass { display: none; }
.reveal .ds-qr-card--open .ds-qr-note { font-size: 18px; color: var(--grey-900); max-width: 32ch; margin-top: 8px; }
/* Values the room must read exactly (Wi-Fi name, password, addresses).
   slides.js wraps them in unbreakable pieces: a password never breaks,
   an address only before a dot or after a slash, never at a hyphen.
   A value too wide for its card shrinks until it fits. */
.reveal [data-fit] { align-self: stretch; min-width: 0; overflow-wrap: normal; }
.reveal [data-fit] .nobreak { white-space: nowrap; }
/* The Wi-Fi line at the foot of a slide stays one line and shrinks a
   little for long values (slides.js), so it never pushes the slide over. */
.reveal [data-fit="keep"] { white-space: nowrap; }
/* A card never grows wider than its grid column because of a long value. */
.reveal .ds-cards > .ds-card { min-width: 0; }
/* "What we build today": three cards for what people keep. */
.reveal .ds-keep-label { margin: 0 0 12px; }
.reveal .ds-needs .ds-bullets li { font-size: 22px; margin-bottom: 12px; }

.reveal .ds-watch {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 16px;
  margin-top: 18px;
}
.reveal .ds-watch > div {
  padding: 14px 18px;
  border-radius: var(--radius-md);
  background: var(--yellow-bg);
  border-top: 5px solid var(--google-yellow);
}
.reveal .ds-watch p { margin: 0; font-size: 22px; line-height: 1.35; }
.reveal .ds-watch strong { font-family: var(--font-display); }

/* Timeline on the "models are outdated" slide. */
.ds-timeline {
  position: relative;
  display: grid;
  grid-template-columns: minmax(0, 1fr) 150px minmax(0, 1fr);
  align-items: stretch;
  gap: 0;
  margin-top: 8px;
}
.reveal .ds-timeline .tl-seg {
  padding: 18px 22px 16px;
  border-radius: var(--radius-md);
  background: var(--surface-alt);
  border-top: 6px solid var(--grey-500);
}
.reveal .ds-timeline .tl-seg.after {
  background: var(--yellow-bg);
  border-top-color: var(--google-yellow);
}
.reveal .ds-timeline .tl-cut {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: flex-start;
  padding-top: 2px;
}
.reveal .ds-timeline .tl-cut::before {
  content: '';
  width: 4px;
  flex: 1;
  background: var(--red-text);
  border-radius: 2px;
}
.reveal .ds-timeline .tl-cut span {
  order: -1;
  font-size: 16px;
  font-weight: 700;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--red-text);
  margin-bottom: 6px;
  text-align: center;
  line-height: 1.2;
}
.reveal .ds-timeline h3 { font-size: 26px; font-weight: 700; margin: 0 0 8px; }
.reveal .ds-timeline p { margin: 0 0 6px; font-size: 20px; line-height: 1.38; }
/* The cutoff, line and label, comes in by itself when the slide opens
   (.ds-enter); "What it missed" and the bottom line follow, one per click. */

/* Title slide: room for the Wi-Fi line under the outcome cards. */
.reveal .ds.ds-title-slide .ds-outcomes { margin-top: 44px; }
.reveal .ds.ds-title-slide .ds-outcome { padding: 36px 36px; }
/* Title slide: a Workshop label at the top, so nobody expects a talk; your
   name, the event and its date (config.js) in the footer line below. */
.reveal .ds.ds-title-slide .ds-title-eyebrow {
  display: flex;
  align-items: center;
  gap: 16px;
  font-size: 20px;
  color: var(--grey-700);
  margin: 0 0 22px;
}
.reveal .ds.ds-title-slide .ds-label {
  padding: 5px 14px;
  border-radius: 999px;
  background: var(--google-blue);
  color: #fff;
  font-weight: 700;
}

/* Four cards in a row ("What makes a good website"): Pristina sets 18px,
   too small for the back of the room. */
.reveal .ds-cards[style*="--cols: 4"] .ds-card-text { font-size: 21px; line-height: 1.35; }
.reveal .ds-cards[style*="--cols: 4"] .ds-card-text + .ds-card-text { margin-top: 8px; }
.reveal .ds-cards[style*="--cols: 4"] .ds-card-title { margin-bottom: 10px; }
/* Five cards in a row ("What makes a good website", with Visibility): a
   little tighter than four, still readable at the back of the room. */
.ds-cards[style*="--cols: 5"] { gap: 14px; }
.ds-cards[style*="--cols: 5"] .ds-card { padding: 18px 18px; }
.reveal .ds-cards[style*="--cols: 5"] .ds-card-title { font-size: 24px; margin: 0 0 10px; }
.reveal .ds-cards[style*="--cols: 5"] .ds-card-text { font-size: 19px; line-height: 1.35; }
.reveal .ds-cards[style*="--cols: 5"] .ds-card-text + .ds-card-text { margin-top: 8px; }
/* Headline-only cards ("What makes a good website."): the presenter says the rest. */
.ds-cards.ds-cards-headlines .ds-card { padding: 40px 18px; justify-content: center; text-align: center; }
.reveal .ds-cards.ds-cards-headlines .ds-card-title { font-size: 28px; margin: 0; }

/* Tighter header for dense slides (demo, cheat sheet). */
.reveal .ds-header.tight { margin-bottom: 24px; }
.reveal .ds-cards.tight .ds-card { padding: 18px 20px; }

/* Building blocks slide: eight cards in two rows, each with a "Today" line.
   Tighter than the other card slides, so the two rows, the bottom line and
   the Wi-Fi line fit under each other (2026-10-08). */
.reveal #building-blocks .ds-header.tight { margin-bottom: 16px; }
.reveal .ds-cards.ds-blocks .ds-card { padding: 12px 20px; }
.reveal .ds-cards.ds-blocks .ds-card-title { font-size: 24px; margin: 0 0 6px; }
.reveal .ds-cards.ds-blocks .ds-card-text.ds-today { margin-top: 6px; color: var(--grey-700); font-weight: 500; }
.reveal #building-blocks .ds-note { margin-top: 14px; }

/* The first slide, "Before we start": tighter QR cards, so the workshop line at
   the foot (title, event, date, presenter) fits under them (2026-10-08). */
.reveal #before-we-start .ds-header.tight { margin-bottom: 16px; }
.reveal #before-we-start .ds-qr-card { padding: 16px 28px 18px; }
/* The third card gets the same top padding, so its title sits level with
   "Wi-Fi" and "Guide" (Fabian, 2026-10-08). */
.reveal #before-we-start .ds-needs { padding-top: 16px; }
.reveal #before-we-start .ds-qr-card .ds-qr-wrap { padding: 10px; }
.reveal #before-we-start .ds-subtitle { max-width: none; text-wrap: initial; }
/* The workshop line at the foot: a Workshop pill and the title on one line,
   the event, the date and the presenter below, so whoever walks in sees the
   right room at a glance (Fabian, 2026-10-08). */
.reveal #before-we-start .ds-venue-line { margin-top: 16px; }
.reveal #before-we-start .ds-which-title { display: flex; align-items: center; gap: 14px; }
.reveal #before-we-start .ds-which-title strong { font-size: 30px; line-height: 1.2; }
.reveal #before-we-start .ds-label {
  display: inline-block;
  padding: 4px 12px;
  border-radius: 999px;
  background: var(--google-blue);
  color: #fff;
  font-weight: 700;
  font-size: 16px;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  line-height: 1.3;
}
.reveal #before-we-start .ds-which-meta { display: block; font-size: 22px; margin-top: 4px; }

/* Context slide: the four habits, one short line each. */
.reveal .ds-cards.ds-habits { margin-top: 16px; gap: 12px; }
.reveal .ds-cards.ds-habits .ds-card { padding: 12px 16px; }

/* Context slide: input and output tokens, one line each. */
.reveal .ds-cards.ds-io { margin-top: 14px; gap: 12px; }
.reveal .ds-cards.ds-io .ds-card { padding: 12px 18px; }

/* "Vibe coding or agentic coding.": a yellow star lands on the agentic card on a click. */
.reveal .ds-card.ds-starred { position: relative; }
.reveal .ds-star {
  position: absolute;
  top: -30px;
  right: -26px;
  width: 92px;
  height: 92px;
  pointer-events: none;
}
.reveal .ds-star svg {
  display: block;
  width: 100%;
  height: 100%;
  fill: var(--google-yellow);
  filter: drop-shadow(0 4px 8px rgba(0, 0, 0, 0.18));
}

/* Title slide: the two parts of the session, sized by their share of the time. */
.reveal .ds-parts {
  display: grid;
  grid-template-columns: minmax(190px, 1fr) 5fr;
  gap: 12px;
  margin-top: 40px;
  max-width: 1040px;
}
.reveal .ds-part {
  display: flex;
  flex-direction: column;
  gap: 4px;
  padding: 14px 20px 16px;
  border-radius: var(--radius-md);
  background: var(--surface-alt);
  border-top: 6px solid var(--grey-200);
}
.reveal .ds-part.theory { border-top-color: var(--google-blue); }
.reveal .ds-part.handson { border-top-color: var(--google-green); }
.reveal .ds-part-name {
  font-family: var(--font-display);
  font-size: 26px;
  font-weight: 700;
  color: var(--grey-900);
}
.reveal .ds-part-time {
  font-size: 20px;
  color: var(--grey-700);
}

/* Context slide: the habits as a labelled second row of cards. */
.reveal .ds-kicker.ds-habits-label { margin: 28px 0 0; }
.reveal .ds-cards.ds-habits .ds-card-title { font-size: 24px; margin: 0 0 6px; }
/* ...and the same columns, gap and inner padding as the row above. */
.reveal .ds-cards.ds-habits { gap: 24px; }
.reveal .ds-cards.ds-habits .ds-card { padding: 14px 20px 16px; }




/* "Thank you.": one QR card, not stretched across the whole slide. */
.reveal .ds-thanks-cards { width: 100%; max-width: 380px; margin: 0 auto; }
/* "Thank you.": title and subtitle centred over the card, on this slide only. */
.reveal #thanks .ds-header { text-align: center; }
.reveal #thanks .ds-subtitle { margin-left: auto; margin-right: auto; }

/* ---------- How professionals build a website: then and now ----------
   Ten cards, grey: how a team did each step before. Each click brings in
   one card's today face over the grey one, with the deck's one motion:
   its row's colour, and how it works today. Both faces share one grid
   cell, so a card is as tall as its taller face. */
.reveal ol.ds-swapcards {
  list-style: none;
  margin: 0;
  padding: 0;
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
  grid-auto-flow: column;
  grid-template-rows: repeat(4, auto); /* eight cards since 2026-10-08: four per column */
  gap: 10px 28px;
}
.reveal ol.ds-swapcards > li { margin: 0; }
/* The list item only counts the click; the today face does the moving. */
.reveal .slides section ol.ds-swapcards > li.fragment { opacity: 1; visibility: inherit; transform: none; transition: none; }
.reveal .ds-swapcard { display: grid; }
.reveal .ds-face {
  grid-area: 1 / 1;
  display: grid;
  grid-template-columns: 40px minmax(0, 1fr);
  gap: 14px;
  align-items: center;
  padding: 12px 18px;
  border-radius: var(--radius-md);
}
.reveal .ds-face.then { background: var(--surface-alt); }
.reveal .ds-face.now {
  opacity: 0;
  transform: translateY(var(--ds-rise));
  transition: opacity var(--ds-motion), transform var(--ds-motion);
}
.reveal ol.ds-swapcards > li.visible .ds-face.now { opacity: 1; transform: none; }
.reveal .ds-face .num {
  width: 40px;
  height: 40px;
  border-radius: 50%;
  color: #fff;
  font-family: var(--font-display);
  font-size: 20px;
  font-weight: 700;
  line-height: 40px;
  text-align: center;
}
.reveal .ds-face.then .num { background: var(--grey-700); }
.reveal .ds-face.now .num { background: rgba(255, 255, 255, 0.24); }
.reveal .ds-face h3 {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 10px;
  margin: 0;
  font-family: var(--font-display);
  font-size: 26px;
  font-weight: 700;
  line-height: 1.2;
  color: var(--grey-900);
}
.reveal .ds-face p { margin: 3px 0 0; font-size: 21px; line-height: 1.3; color: var(--grey-700); }
.reveal .ds-face.now h3,
.reveal .ds-face.now p,
.reveal .ds-face.now strong { color: #fff; }
.reveal .ds-face .where {
  flex: 0 0 auto;
  padding: 2px 10px;
  border-radius: 999px;
  background: rgba(255, 255, 255, 0.2);
  font-family: var(--font-body);
  font-size: 15px;
  font-weight: 600;
  white-space: nowrap;
}
/* Each row shares a colour: four rows, so 1 and 5, 2 and 6, 3 and 7, 4 and 8 (since 2026-10-08). */
.reveal ol.ds-swapcards > li:nth-child(4n+1) .ds-face.now { background: var(--blue-text); }
.reveal ol.ds-swapcards > li:nth-child(4n+2) .ds-face.now { background: var(--red-text); }
.reveal ol.ds-swapcards > li:nth-child(4n+3) .ds-face.now { background: var(--amber-text); }
.reveal ol.ds-swapcards > li:nth-child(4n) .ds-face.now { background: var(--green-text); }

/* Opening pace clock: small, beside the arrows, on the Opening slides only.
   Neutral grey; yellow when the Opening would end late at the planned pace;
   red past 20:00, counting the minutes over. */
.reveal .ds-pace {
  position: absolute;
  right: 104px;
  bottom: 26px;
  z-index: 30;
  padding: 2px 9px;
  border-radius: 999px;
  font-family: var(--font-body);
  font-size: 15px;
  font-weight: 600;
  line-height: 1.4;
  font-variant-numeric: tabular-nums;
  color: var(--grey-500);
  pointer-events: none;
}
.reveal .ds-pace.is-behind { background: var(--google-yellow); color: var(--grey-900); }
.reveal .ds-pace.is-over { background: var(--red-text); color: #fff; }
.reveal .ds-pace[hidden] { display: none; }

/* =====================================================================
   GALLERY WALK (#23, #28)
   ===================================================================== */

/* The sites the room sent from the guide, each with a button that opens it
   in this window; until the first one arrives, the slide asks for them. */
.reveal .ds-gallery {
  flex: 1;
  min-height: 0;
  display: flex;
  flex-direction: column;
  justify-content: center;
}
.reveal .ds-gallery-empty {
  max-width: 960px;
  margin: 0 auto;
  text-align: center;
  text-wrap: balance;
  font-size: 34px;
  line-height: 1.35;
  color: var(--grey-700);
}
/* The five drawn sites, one column. */
.reveal .ds-gallery-sites {
  display: grid;
  grid-template-columns: 600px;
  justify-content: center;
  gap: 10px 16px;
  max-height: 100%;
  margin: 0;
  padding: 2px;
  overflow: auto;
  list-style: none;
}
.reveal .ds-gallery-sites li {
  display: flex;
  align-items: center;
  gap: 12px;
  margin: 0;
  padding: 6px 6px 6px 20px;
  border: 1px solid var(--grey-200);
  border-radius: 999px;
  background: #fff;
}
.reveal .ds-gallery-site {
  flex: 1;
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  font-size: 21px;
  color: var(--grey-900);
}
.reveal .ds-gallery-open {
  flex: none;
  padding: 7px 18px;
  border: 1px solid var(--grey-900);
  border-radius: 999px;
  background: var(--grey-900);
  color: #fff;
  font-size: 17px;
  font-weight: 600;
  line-height: 1.2;
  text-decoration: none;
}
/* An Open already clicked turns into an outline, so the walk keeps its place. */
.reveal .ds-gallery-open:visited { background-color: #fff; color: var(--grey-700); border-color: var(--grey-500); }
.reveal .ds-gallery-open:hover { background: #3C4043; color: #fff; }
.reveal .ds-gallery-open:focus-visible { outline: 3px solid var(--blue-text); outline-offset: 2px; }
/* Under the five: how many sites came in, and the button for five others. */
.reveal .ds-gallery-more {
  display: flex;
  justify-content: center;
  align-items: center;
  gap: 16px;
  margin: 18px 0 0;
  font-size: 20px;
  color: var(--grey-700);
}
.reveal .ds-gallery-draw {
  padding: 7px 18px;
  border: 1px solid var(--grey-500);
  border-radius: 999px;
  background: #fff;
  color: var(--grey-900);
  font-family: var(--font-body);
  font-size: 17px;
  font-weight: 600;
  cursor: pointer;
}
.reveal .ds-gallery-draw:hover { background: var(--grey-100); }
.reveal .ds-gallery-draw:focus-visible { outline: 3px solid var(--blue-text); outline-offset: 2px; }

/* ---------- Venue Wi-Fi form (W) ----------
   Opens over the deck in the top layer, outside Reveal's scaling. */
.ds-wifi-dialog {
  width: min(440px, 90vw);
  padding: 24px 28px;
  border: 0;
  border-radius: 14px;
  background: #fff;
  color: #202124;
  font: 18px/1.45 var(--font-body);
  box-shadow: 0 24px 64px rgb(0 0 0 / 0.35);
}
.ds-wifi-dialog::backdrop { background: rgb(32 33 36 / 0.6); }
.ds-wifi-dialog h2 { margin: 0 0 8px; font: 600 26px/1.2 var(--font-display); }
.ds-wifi-dialog label { display: block; margin-top: 14px; font-weight: 600; }
.ds-wifi-dialog input {
  box-sizing: border-box;
  width: 100%;
  margin-top: 4px;
  padding: 9px 12px;
  border: 1px solid #9aa0a6;
  border-radius: 8px;
  font: 20px/1.3 var(--font-code);
}
.ds-wifi-dialog input:focus-visible,
.ds-wifi-dialog button:focus-visible { outline: 3px solid #1967D2; outline-offset: 2px; }
.ds-wifi-hint { margin: 8px 0 0; font-size: 15px; color: #5f6368; }
.ds-wifi-actions { display: flex; flex-wrap: wrap; gap: 8px; margin: 20px 0 0; }
.ds-wifi-actions button {
  padding: 8px 16px;
  border: 1px solid #9aa0a6;
  border-radius: 999px;
  background: #f1f3f4;
  color: #202124;
  font: 600 16px/1.2 var(--font-body);
  cursor: pointer;
}
.ds-wifi-actions button[value="save"] { background: #1967D2; border-color: #1967D2; color: #fff; }

/* ---------- Code factory (Closing): the whole day as one cycle ----------
   Fixed geometry: a 1040x440 board, the width of the slide's content; each box sits at --x/--y (and --w/--h where
   it differs), in px, set per box in the markup, and the SVG layers draw the
   arrows in the same coordinates. Colour carries one meaning: blue where a
   person decides (.human, the "You" badges), green where it runs by itself
   (.auto, the ticket loop), red for a failing gate.
   It builds up one station per click: the station and its arrows share a
   fragment index; what to say about it is in the speaker notes. The current
   one is in colour; the ones before it turn grey, so the eye follows the click. The
   last click (.ds-fall) brings every station back to colour. */
.reveal .ds-factory {
  --human: var(--blue-text);
  --human-bg: var(--blue-bg);
  --auto: var(--green-text);
  --auto-bg: var(--green-bg);
  position: relative;
  width: 1040px;
  height: 440px;
  margin: 8px auto 0;
}
.reveal .ds-factory-lines {
  position: absolute;
  inset: 0;
  overflow: visible;
  fill: none;
  stroke: var(--grey-500);
  stroke-width: 2.5;
}
.reveal .ds-factory-lines marker path { fill: var(--grey-500); stroke: none; }
.reveal .ds-factory-lines.fail { stroke: var(--red-text); stroke-dasharray: 7 6; }
.reveal .ds-factory-lines.back { stroke: var(--auto); stroke-dasharray: 7 6; }
.reveal .ds-factory-lines marker.fail path { fill: var(--red-text); }
.reveal .ds-factory-lines marker.back path { fill: var(--auto); }
.reveal .ds-fnode,
.reveal .ds-fknow,
.reveal .ds-freview,
.reveal .ds-fdecide,
.reveal .ds-flabel,
.reveal .ds-floop,
.reveal .ds-flegend {
  position: absolute;
  left: calc(var(--x) * 1px);
  top: calc(var(--y) * 1px);
  box-sizing: border-box;
}
.reveal .ds-fnode {
  width: calc(var(--w, 128) * 1px);
  height: calc(var(--h, 92) * 1px);
  padding: 8px 12px;
  border-radius: 12px;
  background: var(--surface-alt);
  border-top: 5px solid var(--grey-500);
  display: flex;
  flex-direction: column;
  justify-content: center;
}
.reveal .ds-fnode.human { background: var(--human-bg); border-top-color: var(--human); }
.reveal .ds-fnode.auto  { background: var(--auto-bg);  border-top-color: var(--auto); }
.reveal .ds-fnode.auto.inloop { background: var(--surface); }
.reveal .ds-fnode h3,
.reveal .ds-fgate h3 {
  margin: 0;
  font-size: 21px;
  font-weight: 700;
  line-height: 1.15;
  white-space: nowrap;
}
.reveal .ds-fnode p {
  margin: 3px 0 0;
  font-size: 16px;
  line-height: 1.25;
  color: var(--grey-700);
  white-space: nowrap;
}
/* "You": a person decides here. */
.reveal .ds-fyou {
  position: absolute;
  top: -14px;
  right: 8px;
  display: inline-flex;
  align-items: center;
  gap: 4px;
  padding: 2px 9px 2px 7px;
  border-radius: 999px;
  background: var(--human);
  color: #fff;
  font-size: 14px;
  font-weight: 700;
  line-height: 1.2;
}
.reveal .ds-fyou svg { width: 14px; height: 14px; fill: currentColor; }
.reveal .ds-floop {
  width: calc(var(--w) * 1px);
  height: calc(var(--h) * 1px);
  border: 2px dashed var(--auto);
  border-radius: 18px;
  background: rgba(230, 244, 234, 0.6);
}
/* The loop's name sits on its top edge, like the "You" badges; on the right,
   clear of the arrow that comes down into Build. */
.reveal .ds-floop-tag {
  position: absolute;
  top: -13px;
  right: 14px;
  margin: 0;
  padding: 1px 10px;
  border-radius: 999px;
  background: var(--auto);
  color: #fff;
  font-size: 15px;
  font-weight: 700;
  line-height: 1.4;
  white-space: nowrap;
}
.reveal .ds-fknow {
  width: calc(var(--w) * 1px);
  height: 38px;
  padding: 0 20px;
  border-radius: 10px;
  background: var(--surface-alt);
  border: 1px solid var(--grey-200);
  display: flex;
  align-items: center;
  justify-content: center;
}
.reveal .ds-fknow p { margin: 0; font-size: 16px; line-height: 1.2; white-space: nowrap; }
.reveal .ds-fknow .ds-kicker { display: inline; font-size: 13px; margin: 0 10px 0 0; color: var(--grey-700); }
.reveal .ds-fknow .sep { margin: 0 5px; color: var(--grey-500); }
.reveal .ds-fknow .gap { display: inline-block; width: 18px; }
/* Review: the five checks in one box. One arrow in from Build, one arrow out to
   the decision; inside, no arrows. */
.reveal .ds-freview {
  width: calc(var(--w) * 1px);
  height: calc(var(--h) * 1px);
  padding: 6px 6px 10px;
  border-radius: 12px;
  background: var(--surface);
  border: 2px solid var(--auto);
  display: grid;
  grid-template-rows: 18px repeat(5, 1fr);
  gap: 6px;
}
.reveal .ds-freview .ds-kicker { margin: 0; font-size: 13px; line-height: 18px; color: var(--auto); }
/* The decision, a diamond as in a flow chart: its text sits in its middle. */
.reveal .ds-fdecide {
  width: 64px;
  height: 64px;
  display: grid;
  place-items: center;
}
.reveal .ds-fdecide svg { position: absolute; inset: 0; width: 100%; height: 100%; overflow: visible; }
.reveal .ds-fdecide path { fill: var(--surface); stroke: var(--auto); stroke-width: 2.5; }
.reveal .ds-fdecide span { position: relative; font-size: 14px; font-weight: 700; line-height: 1; color: var(--auto); }
/* The checks are plain lines in the review box: one box, not five. */
.reveal .ds-fgate {
  padding: 0 4px;
  border-top: 1px solid var(--grey-200);
  display: flex;
  align-items: center;
}
.reveal .ds-fgate h3 { font-size: 16px; }
.reveal .ds-flabel {
  width: calc(var(--w) * 1px);
  margin: 0;
  font-size: 15px;
  font-weight: 700;
  line-height: 20px;
  text-align: center;
  white-space: nowrap;
}
.reveal .ds-flabel.fail { color: var(--red-text); }
.reveal .ds-flabel.back { color: var(--auto); background: var(--surface); }
.reveal .ds-flabel.left { text-align: left; background: none; }
/* Spans its line; only the words cover it, so the line breaks as little as possible. */
.reveal .ds-flabel.mid { background: none; }
.reveal .ds-flabel.mid span { padding: 0 8px; background: var(--surface); }
.reveal .ds-flegend p { margin: 0 0 4px; font-size: 15px; font-weight: 700; line-height: 1.2; white-space: nowrap; }
.reveal .ds-flegend .dot { display: inline-block; width: 12px; height: 12px; margin-right: 7px; border-radius: 3px; vertical-align: -1px; }
.reveal .ds-flegend .dot.human { background: var(--human); }
.reveal .ds-flegend .dot.auto  { background: var(--auto); }
.reveal .ds-flegend .dash { display: inline-block; width: 12px; height: 0; margin-right: 7px; border-top: 3px dashed var(--red-text); vertical-align: 4px; }

/* The focus moves with the click: what came before turns grey. The bar
   "Every station" stays: it applies to every station that follows. */
.reveal .ds-factory .fragment,
.reveal .ds-factory .ds-fbase { transition: opacity var(--ds-motion), transform var(--ds-motion), filter var(--ds-motion); }
.reveal .ds-factory .fragment.visible:not(.current-fragment):not(.ds-fknow),
.reveal .ds-factory:has(.fragment.visible) .ds-fbase { filter: grayscale(1); opacity: 0.4; }
.reveal .ds-factory:has(.ds-fall.visible) .fragment.visible,
.reveal .ds-factory:has(.ds-fall.visible) .ds-fbase { filter: none; opacity: 1; }


/* An address that must not break at its hyphen (the at-home slide's repo link). */
.reveal .ds-nowrap { white-space: nowrap; }
/* The GitHub mark before a repo link (Octicons mark-github, MIT), sized to the text. */
.reveal .ds-gh { width: 0.9em; height: 0.9em; margin-right: 0.3em; vertical-align: -0.1em; fill: currentColor; }
/* "Your next steps at home.": four ways to go on next to one QR code. */
.reveal .ds-cards.ds-home { grid-template-columns: 1.55fr 1fr; }
.reveal .ds-card .ds-home-list li { font-size: 24px; line-height: 1.3; margin-bottom: 16px; }
.reveal .ds-home-list li strong { font-weight: 700; }
