/* The context you choose: the compositions the slide package has no kind for.
   Loaded after _shared/slides/slides.css. Every slide is a package kind; this
   file only adds the drawings inside them: the cover's crop of the graph, the
   tick boxes and scored rows, the two-currency schematic, the hinge, the bar,
   the file icons, the fork shots, and the graph with its layers, which deck.js
   draws in 1920 by 1080 coordinates. Colours are the surface tokens, so a
   slide repaints with its data-theme. */

/* ── Cover: a crop of the Graph slide's graph. It drifts, never grows in. The
   mask fades it out so it has no hard edge, and it bleeds to the right edge. */
.slide[data-kind="cover"] .slide-main:has(.cover-graph) {
  grid-template-columns: max-content minmax(0, 1fr);
  align-items: stretch;
  gap: 80px;
}
.slide[data-kind="cover"] .slide-main:has(.cover-graph) .slide-display { align-self: center; }
.cover-graph {
  justify-self: end;
  width: min(1000px, 100% + var(--slide-pad));
  margin-right: calc(-1 * var(--slide-pad));
  -webkit-mask-image: radial-gradient(closest-side, #000 55%, transparent);
  mask-image: radial-gradient(closest-side, #000 55%, transparent);
}
.slide-cover-art.cover-graph svg { height: 100%; }
.cover-graph .g-node {
  transform-box: fill-box;
  transform-origin: center;
  animation: gNodeBreathe var(--bdur, 6s) ease-in-out infinite alternate;
}
.cover-graph .g-edge { animation: gEdgePulse var(--bdur, 9s) ease-in-out infinite alternate; }

/* ── Thank you: the contact line under the close ── */
.contact { display: flex; gap: 64px; font-family: var(--font-mono); color: var(--foreground); }
.contact span { display: inline-flex; align-items: center; gap: 16px; }
.contact svg { width: 1em; height: 1em; flex: none; }

/* ── It guesses: a field of dots, one in ten told, the rest filled in ── */
.slide-visual .guess-key { display: flex; gap: 48px; color: var(--foreground); }
.guess-key span { display: inline-flex; align-items: center; gap: 16px; }
.guess-key svg { width: 28px; height: 28px; overflow: visible; }
.guess-dim { opacity: 0.6; }
.guess .told { fill: var(--foreground); }
.guess .guessed { fill: none; stroke: var(--foreground); stroke-width: 2; stroke-dasharray: 4 4; }
.guess-dots .guessed { opacity: 0.45; }

/* ── Boxes: a tick or a cross in a square. A tick is the brand green as a
   fill with the check in ink, so it reads from the back of the room. A cross
   and a skipped box stay outlined. ── */
.box {
  display: grid; place-items: center; flex: none;
  box-sizing: border-box; border: 2px solid var(--foreground);
  color: var(--foreground);
}
.box .mark { width: 62%; height: 62%; fill: none; stroke: currentColor; stroke-width: 3; stroke-linecap: square; }
.ticked .box, .scored .yes .box { background: var(--accent); border-color: var(--accent-foreground); color: var(--accent-foreground); }

/* Every box ticked: the box takes the bullet's place */
ul.slide-steps.ticked > li { grid-template-columns: auto minmax(0, 1fr); column-gap: 0.6em; align-items: center; }
ul.slide-steps.ticked > li::before { content: none; }
.ticked .box { width: 0.8em; height: 0.8em; }

/* ── The year off: before and after recede behind the year ── */
.slide-timeline-mark.dim { color: var(--muted-foreground); }

/* ── Two currencies: the axes take the text colour ── */
.schematic { color: var(--foreground); }
.schematic text { font-family: var(--font-sans); font-weight: var(--weight-semibold); letter-spacing: 0.06em; }

/* ── Money and energy: an icon over each currency, and the two words at cover
   size, since they are the whole slide ── */
.currencies .slide-card-title { font-size: var(--slide-cover); }
.currencies .slide-card-title + p { font-size: var(--slide-lead); }
.currency-icon { width: 96px; height: 96px; fill: none; stroke: var(--foreground); stroke-width: 2; }
.currency-dot { fill: var(--foreground); stroke: none; }

/* ── One request and So I wrote it down: the outcome closes each side, level
   across the two. A veiled side keeps its place and its size until the next
   slide shows it. ── */
.slide-compare > section > .slide-side-head:last-child { margin-top: auto; }
.slide-compare > .veiled > * { visibility: hidden; }
.slide-compare ul.scored { list-style: none; padding-left: 0; gap: 0; border-top: 1px dashed var(--slide-rule); }
.scored li {
  display: grid; grid-template-columns: auto auto minmax(0, 1fr); align-items: center; column-gap: 20px;
  padding-block: 8px; border-bottom: 1px dashed var(--slide-rule);
}
.scored .box { width: 28px; height: 28px; }
.scored strong { font-family: var(--font-display); font-weight: var(--weight-heading); letter-spacing: var(--tracking-snug); color: var(--foreground); }
.scored li > span:last-child { justify-self: end; color: var(--muted-foreground); }
.scored .skip { opacity: 0.45; }
.scored .skip .box { border-style: dashed; }
.wrote section > p:not(.slide-side-head) { color: var(--muted-foreground); }

/* The files the machine reads, a file icon before each name */
.slide-compare ul.files { list-style: none; padding-left: 0; }
.files li {
  display: flex; align-items: center; gap: 20px;
  padding: 14px 20px; border: 1.5px solid var(--foreground);
  font-family: var(--font-mono);
}
.files code { font-size: inherit; }
.file-icon { flex: none; width: 0.7em; height: 1.05em; fill: none; stroke: currentColor; stroke-width: 2; stroke-linejoin: round; }

/* ── The honest line: you and a machine, one default ── */
.hinge-big { font-family: var(--font-display); font-weight: var(--weight-heading); font-size: 64px; letter-spacing: var(--tracking-snug); fill: var(--foreground); }
.hinge-end { font-size: 62px; }
.hinge-label { font-family: var(--font-sans); font-size: 30px; fill: var(--foreground); fill-opacity: 0.65; }
.hinge-path { fill: none; stroke: var(--foreground); stroke-width: 2; stroke-dasharray: 8 6; stroke-opacity: 0.7; }
.hinge-ring { fill: none; stroke: var(--foreground); stroke-width: 2; }
.hinge-dot { fill: var(--foreground); }

/* ── Mirror: the share of men as a bar, even marked at half ── */
.bar-track { position: relative; height: 48px; border: 2px solid var(--foreground); }
.bar-track i { position: absolute; top: 0; bottom: 0; }
.bar-solid { left: 0; right: 25%; background: var(--foreground); }
.bar-range { left: 75%; right: 0; background: repeating-linear-gradient(135deg, var(--foreground) 0 4px, transparent 4px 14px); }
/* The even mark is ink above and below the bar and ground colour inside it */
.bar-track .bar-even {
  left: calc(50% - 1px); width: 2px; top: -26px; bottom: -26px;
  background: repeating-linear-gradient(to bottom, var(--foreground) 0 8px, transparent 8px 14px);
}
.bar-even::after {
  content: ""; position: absolute; left: 0; right: 0; top: 24px; bottom: 24px;
  background: repeating-linear-gradient(to bottom, var(--background) 0 8px, transparent 8px 14px);
}
.bar-scale {
  display: grid; grid-template-columns: 1fr auto 1fr;
  margin-top: 36px;
  font-family: var(--font-mono); font-size: var(--slide-small);
  letter-spacing: var(--tracking-wider); text-transform: uppercase;
  color: var(--muted-foreground);
}
.bar-scale span:last-child { justify-self: end; }

/* ── Same tools, different outcome: a shot over each path ── */
.fork-shot { display: block; width: min(100%, 420px); height: auto; }

/* ── Thought experiment: how mine was built, one step after the other ── */
.loop i { font-style: normal; margin-inline: 0.4em; color: var(--tert); }

/* ── Graph and layers: the art takes the whole body, edge to edge, and the
   title and the foot sit over it. The geometry is the one the layer camera
   was measured in, so the cut from the Graph slide into the layers holds. */
.slide-visual.bleed { margin-inline: calc(-1 * var(--slide-pad)); }
.slide-visual.bleed .diagram-art svg { overflow: visible; }
.art-head { position: absolute; z-index: 2; left: var(--slide-pad); top: calc(50 * var(--px) + 72px); }
.art-sub { margin-top: 12px; font-size: var(--slide-body); color: var(--muted-foreground); }
.art-foot {
  position: absolute; z-index: 2; left: var(--slide-pad); bottom: calc(72px + 3 * var(--px));
  font-family: var(--font-mono); font-size: var(--slide-small);
  letter-spacing: var(--tracking-wider); text-transform: uppercase;
}

/* The graph: nodes grow in and edges draw when the slide is reached, then drift */
.graph-stage .g-node {
  opacity: 0;
  scale: 0;
  transform-box: fill-box;
  transform-origin: center;
  animation: gNodeBreathe var(--bdur, 6s) ease-in-out infinite alternate;
}
.graph-stage .g-edge {
  opacity: 0;
  stroke-dasharray: var(--len, 1200);
  stroke-dashoffset: var(--len, 1200);
  animation: gEdgePulse var(--bdur, 9s) ease-in-out infinite alternate;
}
.graph-stage[data-animate] .g-node {
  animation-name: gNodeGrow, gNodeBreathe;
  animation-duration: 1100ms, var(--bdur, 6s);
  animation-delay: var(--in-delay, 0ms), 0ms;
  animation-timing-function: cubic-bezier(0.34, 1.4, 0.5, 1), ease-in-out;
  animation-iteration-count: 1, infinite;
  animation-direction: normal, alternate;
  animation-fill-mode: forwards, none;
}
.graph-stage[data-animate] .g-edge {
  animation-name: gEdgeDraw, gEdgePulse;
  animation-duration: 1400ms, var(--bdur, 9s);
  animation-delay: var(--in-delay, 0ms), 0ms;
  animation-timing-function: cubic-bezier(0.4, 0, 0.2, 1), ease-in-out;
  animation-iteration-count: 1, infinite;
  animation-direction: normal, alternate;
  animation-fill-mode: forwards, none;
}
@keyframes gNodeGrow {
  0%   { opacity: 0; scale: 0; }
  55%  { opacity: 1; scale: 1.18; }
  100% { opacity: 1; scale: 1; }
}
@keyframes gNodeBreathe {
  0%   { translate: 0 0; }
  100% { translate: var(--dx, 0px) var(--dy, 0px); }
}
@keyframes gEdgeDraw {
  0%   { opacity: 0; stroke-dashoffset: var(--len, 1200); }
  20%  { opacity: 1; }
  100% { opacity: 1; stroke-dashoffset: 0; }
}
@keyframes gEdgePulse {
  0%   { opacity: 1; }
  100% { opacity: 0.45; }
}

.g-hub, .g-hub-lg, .g-green-leaf { fill: var(--ink); }
.g-leaf         { fill: color-mix(in srgb, var(--foreground) 62%, transparent); }
.g-orphan-yel   { fill: #E6C658; }
.g-orphan-cream { fill: color-mix(in srgb, var(--foreground) 50%, transparent); }
.g-edge { stroke: color-mix(in srgb, var(--foreground) 18%, transparent); stroke-width: 1; fill: none; vector-effect: non-scaling-stroke; }

/* decisions.md, marked once the graph has grown */
.graph-stage .g-mark { opacity: 0; animation: gNodeBreathe var(--bdur, 6s) ease-in-out infinite alternate; }
.graph-stage[data-animate] .g-mark {
  animation-name: gMarkIn, gNodeBreathe;
  animation-duration: 700ms, var(--bdur, 6s);
  animation-delay: 2000ms, 0ms;
  animation-timing-function: ease-out, ease-in-out;
  animation-iteration-count: 1, infinite;
  animation-direction: normal, alternate;
  animation-fill-mode: forwards, none;
}
@keyframes gMarkIn { from { opacity: 0; } to { opacity: 1; } }
.g-mark circle { fill: none; stroke: var(--foreground); stroke-width: 2; vector-effect: non-scaling-stroke; }
/* A ground-colour halo keeps the label legible where it crosses nodes and edges */
.g-mark text { paint-order: stroke; stroke: var(--background); stroke-width: 10px; stroke-linejoin: round; }
.g-mark-file { font-family: var(--font-mono); font-size: 30px; fill: var(--foreground); }
.g-mark-what { font-family: var(--font-sans); font-size: 26px; fill: color-mix(in srgb, var(--foreground) 62%, transparent); }

/* ── Layers: each layer is a plane, the camera steps back one plane per slide ── */
.layer-art { font-family: var(--font-sans); }
.layer-word, .layer-name { font-family: var(--font-display); font-weight: var(--weight-heading); letter-spacing: var(--tracking-snug); }
.layer-art .l-mono { font-family: var(--font-mono); }
.layer-art .l-caps { letter-spacing: var(--tracking-wider); }
.layer-rail { display: flex; gap: 24px; }
.layer-rail span, .layer-rail i { color: color-mix(in srgb, var(--foreground) 30%, transparent); }
.layer-rail .past { color: color-mix(in srgb, var(--foreground) 80%, transparent); }
.layer-rail .now { color: var(--ink); }
.layer-rail i { font-style: normal; }

/* The graph keeps the drift it has on the Graph slide, with no grow-in: it is
   already there. A mark or ring rides its node with the same drift, scaled to
   the .96 copy. --phase starts the drift as far into its cycle as the Graph
   slide's is, so the cut does not jump. A hidden slide is display: none, so
   only the slide on screen runs its animations. */
.layer-nodes .g-node { transform-box: fill-box; transform-origin: center; animation: gNodeBreathe var(--bdur, 6s) ease-in-out var(--phase, 0ms) infinite alternate; }
.layer-nodes .g-edge { animation: gEdgePulse var(--bdur, 9s) ease-in-out var(--phase, 0ms) infinite alternate; }
.layer-art .lm, .layer-art .lr { animation: gNodeBreathe var(--bdur, 6s) ease-in-out var(--phase, 0ms) infinite alternate; }
.layer-dim { opacity: 0.5; }
/* deck.js stacks the planes in .depth and moves the camera through them.
   It sets each plane's transform, opacity and blur, and three custom properties:
   --txt fades a plane's labels as it recedes, --mk and --rg hand the marks over
   to rings as the stack lies flat under the surface on the last layer. */
.depth { position: relative; width: 100%; height: 100%; }
.depth > :is(.layer-plane, .layer-top) { position: absolute; inset: 0; }
.layer-plane .lm { opacity: var(--mk, 1); }
.layer-plane .lr { opacity: var(--rg, 1); }
.layer-plane :is(.lm-file, .lm-what, .lm-rule, .lm-lead) { opacity: var(--txt, 1); }
/* The read lines and the studio wires, drawn by deck.js once their plane is in focus */
.ldl { opacity: 0; }

/* Entrances run only while data-animate is set, which deck.js does when a
   slide is reached by stepping forward. Without it every slide shows complete. */
.layer-art[data-animate][data-layer="0"] .layer-dim { animation: lDim 1200ms ease-in-out backwards; }
/* decisions.md is already on screen from the Graph slide, so it does not grow in */
.layer-art[data-animate] .lm.lm-kept > * { animation: none; }
.layer-art[data-animate] .lm-dot { transform-box: fill-box; transform-origin: center; animation: lPop 600ms cubic-bezier(0.34, 1.4, 0.5, 1) var(--d) backwards; }
.layer-art[data-animate] .lm-ring { animation: lDraw 700ms ease-out calc(var(--d) + 120ms) backwards; }
.layer-art[data-animate] .lm-lead { animation: lDraw 450ms ease-out calc(var(--d) + 450ms) backwards; }
.layer-art[data-animate] .lm-file { animation: lRise 500ms ease-out calc(var(--d) + 650ms) backwards; }
.layer-art[data-animate] .lm-what { animation: lRise 500ms ease-out calc(var(--d) + 780ms) backwards; }
.layer-art[data-animate] .lm-rule { animation: lRise 500ms ease-out calc(var(--d) + 1000ms) backwards; }
.layer-art[data-animate] .lb { animation: lIn 550ms cubic-bezier(0.2, 0.8, 0.2, 1) var(--d) backwards; }
.layer-art[data-animate] .lb-line { animation: lDraw 500ms ease-out calc(var(--d) + 450ms) backwards; }
.layer-art[data-animate] .lwipe { transform-box: fill-box; transform-origin: left center; animation: lWipe 700ms cubic-bezier(0.65, 0, 0.25, 1) var(--d) backwards; }
@keyframes lDim { from { opacity: 1; } }
@keyframes lPop { 0% { scale: 0; opacity: 0; } 60% { scale: 1.5; opacity: 1; } 100% { scale: 1; } }
/* pathLength="1" on the element makes one unit the whole line or ring */
@keyframes lDraw { from { stroke-dasharray: 1 1; stroke-dashoffset: 1; } to { stroke-dasharray: 1 1; stroke-dashoffset: 0; } }
@keyframes lRise { from { opacity: 0; translate: 0 14px; } }
@keyframes lIn { from { opacity: 0; translate: var(--fx, 0px) var(--fy, 14px); } }
@keyframes lWipe { from { scale: 0 1; } }
