/**
 * The slideshow on the page.
 *
 * The stage holds every slide on top of one another; only the current one is
 * shown. Layers inside a slide are absolutely placed as a percentage of the
 * stage, so one slide fits every screen without a breakpoint.
 */

.dsl {
  position: relative;
  width: 100%;
  padding-top: var(--dsl-pad, 56.25%);
  overflow: hidden;
  /* A property rather than a literal, so a slideshow with a see-through
     slide on it can turn the frame off and show the page behind. */
  background: var(--dsl-bg, #0d0d0d);
}

/* A slideshow in a full screen row takes the screen rather than its own ratio.
   A percentage padding is a percentage of WIDTH, so a 16:9 box on a wide row is
   taller than the window - which pushed the footer a screen and a half down. */
.ds-row-screen .dsl {
  padding-top: 0;
  height: 100svh;
  max-height: 100svh;
}

/* The slide, at the size it was designed at, scaled to fit the frame.
 *
 * Not stretched to the frame. Layers are placed as per cent of the stage
 * and type is sized as per cent of the stage WIDTH - so on a frame wider and
 * shorter than the one the slide was arranged on, the type grew while the
 * gaps between the lines shrank, and a heading and the line under it ran
 * into each other. Two axes scaling independently can only ever agree at
 * one shape.
 *
 * So the stage is always exactly the design size in pixels and one transform
 * takes it to whatever the frame is. Everything on it keeps its proportions,
 * and what was arranged in the editor is what appears on the page at every
 * width there is.
 */
/* Nothing paints until the script says the first slide is at the start of its
   own intro. Without this the layers are in the document, in their resting
   place, for however long the browser takes to get from building them to
   placing them - and a paint in that gap is the finished slide. */
.dsl:not([data-dsl-ready]) .dsl-stage { visibility: hidden }

.dsl-stage {
  position: absolute;
  left: 50%;
  top: 50%;
  width: var(--dsl-design-w, 1600px);
  height: var(--dsl-design-h, 900px);
  /* Pushed down by half of whatever room was taken off the top, because the
     stage is centred - half of it lands above and half below, and taking the
     stage height down by the same amount leaves all of it clear at the top. */
  transform: translate(-50%, calc(-50% + var(--dsl-pad-top, 0px) / 2)) scale(var(--dsl-scale, 1));
  transform-origin: center center;
}

.dsl-slide {
  position: absolute;
  inset: 0;
  opacity: 0;
  /* Kept out of the way rather than removed: a slide that is display:none has
     no size, so GSAP cannot read where its layers start from. */
  pointer-events: none;
  visibility: hidden;
}

.dsl-slide.is-on {
  opacity: 1;
  pointer-events: auto;
  visibility: visible;
}

/* A video behind a slide. Covers the stage the way the picture does, sits
   under every layer, and never takes a click. */
.dsl-bgvid {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  pointer-events: none;
}

.dsl-bg {
  position: absolute;
  inset: 0;
  background-position: center;
  background-repeat: no-repeat;
}

/* A layer. Position and size come from the model as inline percentages; nothing
   here sets either, so this is only what every layer has in common.

   Two classes, because a themed button also wears .ds-btn and the theme sets
   that to position:relative - one class against one class, and whichever
   stylesheet loads last wins. A layer that stops being absolute stops being
   where it was put, so this cannot be left to load order. */
.dsl .dsl-l {
  position: absolute;
  /* The transform origin matters for scale and rotate keyframes: from the
     middle, a layer grows in place rather than away from its corner. */
  transform-origin: center center;
  will-change: transform, opacity;
}

.dsl-l-image img {
  display: block;
  width: 100%;
  height: 100%;
}

.dsl-l-text {
  white-space: pre-wrap;
  word-break: break-word;
}

.dsl-l-shape {
  width: 100%;
}

/* A button is a link, so it keeps a link's behavior and loses a link's look. */
.dsl-btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: auto;
  padding: 0.7em 1.6em;
  text-decoration: none;
  font-weight: 600;
  line-height: 1;
  transition: filter .2s ease;
}

.dsl-btn:hover { filter: brightness(1.12) }

/* Controls, unchanged in shape from the first version - every value reads a
   custom property so the element's Arrows and Navigation tabs can set them. */
.dsl-arrow {
  position: absolute;
  top: 50%;
  transform: translateY(-50%);
  z-index: 50;
  width: var(--dsl-ar-size, 44px);
  height: var(--dsl-ar-size, 44px);
  padding: var(--dsl-ar-pad, 0);
  border: 1px solid var(--dsl-ar-edge, transparent);
  border-radius: var(--dsl-ar-radius, 999px);
  background: var(--dsl-ar-bg, rgba(0, 0, 0, .42));
  color: var(--dsl-ar-fg, #fff);
  cursor: pointer;
  opacity: 0;
  transition: opacity .2s ease, background .2s ease;
}

.dsl:hover .dsl-arrow,
.dsl-arrow:focus-visible { opacity: 1 }

.dsl-arrow:hover {
  background: var(--dsl-ar-bghov, rgba(0, 0, 0, .68));
  color: var(--dsl-ar-hover, #fff);
}

.dsl-arrow::before {
  content: "";
  position: absolute;
  top: 50%;
  left: 50%;
  width: 11px;
  height: 11px;
  border-left: 2px solid currentColor;
  border-bottom: 2px solid currentColor;
}

.dsl-prev { left: var(--dsl-ar-gap, 14px) }
.dsl-next { right: var(--dsl-ar-gap, 14px) }
.dsl-prev::before { transform: translate(-40%, -50%) rotate(45deg) }
.dsl-next::before { transform: translate(-60%, -50%) rotate(-135deg) }

.dsl-arrow-icon::before { content: none }
.dsl-arrow-icon svg { width: 60%; height: 60%; display: block; margin: auto; fill: currentColor }
.dsl-next.dsl-arrow-icon svg { transform: rotate(180deg) }

.dsl-dots {
  position: absolute;
  left: 0;
  right: 0;
  bottom: var(--dsl-dt-gap, 12px);
  z-index: 50;
  display: flex;
  justify-content: center;
  gap: var(--dsl-dt-space, 8px);
  padding: var(--dsl-dt-pad, 0);
  background: var(--dsl-dt-bg, transparent);
}

.dsl-dot {
  width: var(--dsl-dt-size, 8px);
  height: var(--dsl-dt-size, 8px);
  padding: 0;
  border: 0;
  border-radius: 999px;
  background: var(--dsl-dt-fg, rgba(255, 255, 255, .45));
  cursor: pointer;
  transition: background .2s ease, width .2s ease;
}

.dsl-dot:hover { background: var(--dsl-dt-hover, rgba(255, 255, 255, .75)) }

.dsl-dot.is-on {
  width: calc(var(--dsl-dt-size, 8px) * 2.75);
  background: var(--dsl-dt-on, #fff);
}

.dsl-dt-shape-square .dsl-dot { border-radius: 0 }
.dsl-dt-shape-bar .dsl-dot {
  width: calc(var(--dsl-dt-size, 8px) * 2.5);
  height: calc(var(--dsl-dt-size, 8px) * 0.5);
  border-radius: 999px;
}
.dsl-dt-shape-bar .dsl-dot.is-on { width: calc(var(--dsl-dt-size, 8px) * 4) }
.dsl-dt-shape-line .dsl-dot {
  width: calc(var(--dsl-dt-size, 8px) * 3);
  height: 2px;
  border-radius: 0;
}
.dsl-dt-shape-line .dsl-dot.is-on { width: calc(var(--dsl-dt-size, 8px) * 5) }

.dsl-dt-where-top .dsl-dots { top: var(--dsl-dt-gap, 12px); bottom: auto }

.dsl-dt-where-left .dsl-dots,
.dsl-dt-where-right .dsl-dots {
  top: 0;
  bottom: 0;
  left: auto;
  right: auto;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  width: max-content;
}

.dsl-dt-where-left .dsl-dots { left: var(--dsl-dt-gap, 12px) }
.dsl-dt-where-right .dsl-dots { right: var(--dsl-dt-gap, 12px) }

.dsl-dt-align-start .dsl-dots { justify-content: flex-start }
.dsl-dt-align-end .dsl-dots { justify-content: flex-end }

/* The words again, as words: the layers above are elements, but a slide that is
   not the current one is hidden from a screen reader, so the whole slideshow is
   also written out once where anything reading rather than looking can find it. */
.dsl-said {
  position: absolute;
  width: 1px;
  height: 1px;
  margin: -1px;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
}

@media (prefers-reduced-motion: reduce) {
  .dsl-arrow,
  .dsl-dot,
  .dsl-btn { transition: none }
}

/* The preload copy of the first background.
 *
 * It exists to start the fetch with the page, never to be seen - the slide draws
 * the picture itself. Carried over from the first stylesheet and forgotten when
 * this one was written from scratch, so it rendered at full size in normal flow
 * and made the slideshow box three times its own height.
 *
 * Taken out of the layout rather than display:none, which in some browsers
 * cancels the very fetch it was added for. */
.dsl-pre {
  position: absolute;
  width: 1px;
  height: 1px;
  opacity: 0;
  pointer-events: none;
  z-index: -1;
}

/* --- an overlay slide ------------------------------------------------- */

/* Over every other slide and always on. It does not take a pointer itself -
   only the things on it that are meant to be pressed do - or it would be a lid
   over the slideshow running underneath. */
/* Two classes on the pointer rule, because .dsl-slide.is-on turns pointer
   events back on and one class cannot beat two - so the overlay sat over
   the slide catching every click meant for the button underneath it. */
.dsl-slide.dsl-over {
  z-index: 60;
  opacity: 1;
  visibility: visible;
  pointer-events: none;
}

.dsl-over .dsl-l { pointer-events: none }
.dsl-over .dsl-l-nav,
.dsl-over .dsl-l-button { pointer-events: auto }

/* --- navigation drawn from the slides --------------------------------- */

.dsl-l-nav { display: flex }

.dsl-nav-item {
  flex: 0 0 auto;
  padding: 0;
  margin: 0;
  border: 0;
  background: none;
  color: inherit;
  font: inherit;
  line-height: 1.2;
  text-align: left;
  cursor: pointer;
  transition: opacity .3s ease, color .2s ease, background .2s ease;
}

/* Words. The link version is bare; the button version is a button. */
/* Never underlined. It is navigation, not prose with a link in it - and an
   underline appearing on hover moves nothing but reads as a page from 1998. */
.dsl-nav-links { white-space: nowrap; text-decoration: none }
.dsl-nav-item,
.dsl-nav-item:hover,
.dsl-nav-item:focus { text-decoration: none }

.dsl-nav-buttons {
  padding: .55em 1.2em;
  white-space: nowrap;
}

/* Marks. Size and shape come from the layer, so all three are one rule. */
.dsl-nav-bars,
.dsl-nav-squares,
.dsl-nav-dots { padding: 0 }

.dsl-nav-icon { display: inline-flex; align-items: center; justify-content: center }
.dsl-nav-icon img { display: block }

/* The one showing does not dim on hover the way the others lift. */
.dsl-nav-item:not(.is-on):hover { filter: brightness(1.35) }

@media (prefers-reduced-motion: reduce) {
  .dsl-nav-item { transition: none }
}

/* Pictures: the slide in miniature, filling its box however tall it was made. */
.dsl-nav-images img {
  display: block;
  width: 100%;
  height: 100%;
  object-fit: cover;
}

/* Back and forward: two chevrons drawn from borders, so they need no font and
   no icon file and take the color they are given. */
.dsl-nav-arrows {
  position: relative;
  display: inline-flex;
  align-items: center;
  justify-content: center;
}

.dsl-nav-arrows::before {
  content: "";
  width: 40%;
  height: 40%;
  border-left: 2px solid currentColor;
  border-bottom: 2px solid currentColor;
}

.dsl-nav-back::before { transform: translateX(20%) rotate(45deg) }
.dsl-nav-next::before { transform: translateX(-20%) rotate(-135deg) }

/* Progress: the layer is the track and this is how far along it is. */
.dsl-nav-fill {
  display: block;
  height: 100%;
  transition: width .4s ease;
}

@media (prefers-reduced-motion: reduce) {
  .dsl-nav-fill { transition: none }
}

/* The run of items, when the current one is kept on the middle. It moves; the
   layer it is in does not. */
/* The run of items, when the current one holds its place. It moves; the box
   it is in does not, and clips what travels past. position:relative so the
   items report their offsets against it. */
.dsl-nav-run {
  position: relative;
  flex: 0 0 auto;
  transition: transform .45s cubic-bezier(.22, .61, .36, 1);
  will-change: transform;
}

@media (prefers-reduced-motion: reduce) {
  .dsl-nav-run { transition: none }
}

/* The one canvas every model on the slideshow is drawn into. It lies over the
   stage and takes no clicks - each model's own layer is what is dragged, so a
   canvas covering the slide must not swallow anything. */
.dsl-gl {
  position: absolute;
  inset: 0;
  z-index: 40;
  pointer-events: none;
}

/* --- a themed button on a timeline ------------------------------------ */

/* The theme gives .ds-btn a transition on transform, for its lift and its
   magnet. A layer's transform is written every frame by the slide's own
   timeline - so the two eased the same property at once and the button
   stuttered its way in instead of scaling.
   Everything else the theme transitions is left alone, so the hover fill still
   wipes; only the property the timeline owns is taken back. */
.dsl .dsl-l.ds-btn {
  transition-property: background-color, background-image, border-color, color, box-shadow, filter;
}

/* A button is never squeezed below its own words.
 *
 * Width is a per cent of the stage, and the padding and type inside it are
 * real pixels. On the desktop design 12% of 1600 is 192px and the padding sits
 * comfortably inside that; on the phone design 12% of 390 is 47px, which is
 * narrower than the padding on its own - so the box collapsed to the padding,
 * the label wrapped onto two lines, and a pill radius clamped to half the
 * height and drew a circle.
 *
 * max-content is the label plus its padding on one line. A button wider than
 * that is unaffected, which is every button on a desktop; one narrower grows
 * to fit rather than folding up. The same reasoning the themed button already
 * uses when it sets its width to auto - see build() in dsl-show.js. */
.dsl .dsl-l-button { min-width: max-content }

/* A themed button's padding, in em rather than pixels.
 *
 * The theme sizes its button in px, which is right on a page: a button is a
 * control and a control is the same size wherever it is. A slide is the other
 * way round - everything on it is a share of the stage, so the button has to
 * grow with the headline beside it or it shrinks away on a big screen.
 *
 * The script writes the font size in stage units and this makes the padding
 * follow it, so the whole button scales as one piece. The figures are the
 * theme's own large button read back as a ratio of its type - 18/17 and 34/17
 * - so at the size it was, it is the same button it was. */
.dsl .dsl-l-button.ds-btn{
  padding: 1.06em 2em;
  line-height: 1.2;
}
