/* Shared styles for FluentVerify slide decks — extracted unchanged from
   /explainer.html so the decks look and behave exactly like it. */
/* Self-hosted (SIL Open Font License), so no visitor's browser contacts a
   third-party font server — the reason Google Fonts had to go under GDPR. */
@font-face { font-family: 'Archivo'; font-style: normal; font-weight: 500 700; font-display: swap;
  src: url(/fonts/archivo-latin.woff2) format('woff2');
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD; }
@font-face { font-family: 'IBM Plex Mono'; font-style: normal; font-weight: 400; font-display: swap;
  src: url(/fonts/ibm-plex-mono-400-latin.woff2) format('woff2'); }
@font-face { font-family: 'IBM Plex Mono'; font-style: normal; font-weight: 500; font-display: swap;
  src: url(/fonts/ibm-plex-mono-500-latin.woff2) format('woff2'); }
/* ============================================================ tokens
   Taken from the FluentVerify product's own stylesheet, not invented here, so the
   explainer and the site it explains are visibly the same thing.

   Single-dark on purpose: this is an instrument readout, and it is embedded in
   a dark product. Every colour is painted explicitly so the page holds on any
   host ground. */
:root {
  color-scheme: dark;
  --bg:      #0b0d10;
  --panel:   #14171c;
  --panel-2: #1b1f26;
  --line:    #262b33;
  --text:    #e8eaed;
  --muted:   #98a1ad;
  --accent:  #6ee7b7;
  --dim:     #2b6d55;
  --warn:    #fbbf24;
  --bad:     #f87171;

  --display: "Archivo", ui-sans-serif, system-ui, -apple-system, "Segoe UI", Roboto, sans-serif;
  --body: ui-sans-serif, system-ui, -apple-system, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;
  --mono: "IBM Plex Mono", ui-monospace, SFMono-Regular, Menlo, monospace;
}

* { box-sizing: border-box; }

body {
  margin: 0;
  background: var(--bg);
  color: var(--text);
  font-family: var(--body);
  font-size: 16px;
  line-height: 1.6;
  -webkit-font-smoothing: antialiased;
}

.shell {
  max-width: 940px;
  margin: 0 auto;
  padding-inline: 16px;
  padding-block: 28px 44px;
}

/* ------------------------------------------------------------- masthead */
.masthead {
  display: flex; align-items: baseline; justify-content: space-between;
  gap: 12px; flex-wrap: wrap; margin-bottom: 14px;
}
.brand {
  font-family: var(--display);
  font-weight: 700; font-size: 17px; letter-spacing: -.02em;
}
.brand span { color: var(--accent); }
.kicker {
  font-family: var(--mono);
  font-size: 11px; letter-spacing: .16em; text-transform: uppercase;
  color: var(--muted);
}

/* ---------------------------------------------------------------- stage */
.stage {
  position: relative;
  width: 100%;
  max-width: 100%;
  aspect-ratio: 16 / 9;
  background: var(--panel);
  border: 1px solid var(--line);
  border-radius: 14px;
  overflow: hidden;
}

.scene {
  position: absolute; inset: 0;
  display: flex; flex-direction: column;
  align-items: center; justify-content: center;
  gap: 14px;
  padding: clamp(16px, 4.2vw, 46px);
  text-align: center;
  opacity: 0;
  visibility: hidden;
  transition: opacity .5s ease;
}
.scene.on { opacity: 1; visibility: visible; }

.scene h2 {
  font-family: var(--display);
  font-weight: 700;
  font-size: clamp(20px, 4.4vw, 40px);
  line-height: 1.12;
  letter-spacing: -.025em;
  margin: 0;
  text-wrap: balance;
  max-width: 20ch;
}
.scene p.sub {
  margin: 0;
  color: var(--muted);
  font-size: clamp(13px, 1.9vw, 17px);
  max-width: 44ch;
  text-wrap: balance;
}
.num {
  font-family: var(--mono);
  color: var(--accent);
  font-size: clamp(11px, 1.5vw, 13px);
  letter-spacing: .14em;
  text-transform: uppercase;
}
.stage svg { max-width: 100%; height: auto; display: block; }

/* ------------------------------------------------- per-scene animation
   Every animation is attached to `.scene.on`, so it starts when the scene
   becomes current and restarts when the scene is revisited (the player forces
   a reflow between removing and re-adding the class). */
.scene [data-anim] { opacity: 0; }
.scene.on [data-anim] {
  animation: rise .62s cubic-bezier(.2,.7,.25,1) forwards;
  animation-delay: calc(var(--i, 0) * .16s + .12s);
}
@keyframes rise {
  from { opacity: 0; transform: translateY(12px); }
  to   { opacity: 1; transform: none; }
}

/* scene 1 — the useless compliment */
.strike { position: relative; display: inline-block; }
.strike::after {
  content: ""; position: absolute; left: -2%; top: 52%;
  width: 0; height: 3px; background: var(--bad); border-radius: 2px;
}
.scene.on .strike::after { animation: strike .5s ease forwards 1.5s; }
@keyframes strike { to { width: 104%; } }
.scene.on .after-strike { animation: rise .6s ease forwards 2.1s; }

/* drawn lines: waveform, meters */
.draw { stroke-dasharray: 1200; stroke-dashoffset: 1200; }
.scene.on .draw { animation: draw 2.2s ease forwards .3s; }
@keyframes draw { to { stroke-dashoffset: 0; } }

/* a bar that fills to a width set inline as --w */
.fill { width: 0; }
.scene.on .fill {
  animation: fill .9s cubic-bezier(.2,.7,.25,1) forwards;
  animation-delay: calc(var(--i, 0) * .18s + .5s);
}
@keyframes fill { to { width: var(--w, 60%); } }

/* the reorder moment in scene 6 */
.scene.on .lift { animation: lift .7s cubic-bezier(.2,.7,.25,1) forwards 2.6s; }
@keyframes lift { to { transform: translateY(-58px); } }
.scene.on .drop { animation: drop .7s cubic-bezier(.2,.7,.25,1) forwards 2.6s; }
@keyframes drop { to { transform: translateY(58px); } }

/* the provisional stamp */
.scene.on .stamp { animation: stamp .5s cubic-bezier(.3,1.4,.5,1) forwards 1.5s; }
@keyframes stamp {
  from { opacity: 0; transform: scale(1.5) rotate(-9deg); }
  to   { opacity: 1; transform: scale(1) rotate(-9deg); }
}

/* a pulsing recording dot */
.scene.on .pulse { animation: pulse 1.5s ease-in-out infinite .4s; }
@keyframes pulse { 0%,100% { opacity: 1; } 50% { opacity: .35; } }

/* ------------------------------------------------------------- captions */
.caption {
  min-height: 60px;
  display: flex; align-items: center; justify-content: center;
  padding: 12px 16px;
  font-size: 15px;
  color: var(--text);
  background: var(--panel-2);
  border: 1px solid var(--line);
  border-top: 0;
  border-radius: 0 0 14px 14px;
  margin-top: -14px;
  text-wrap: balance;
}
.stagewrap { display: flex; flex-direction: column; }

/* ------------------------------------------------------------ transport */
.transport {
  display: flex; align-items: center; gap: 12px;
  margin-top: 14px; flex-wrap: wrap;
}
.pbtn {
  flex: none;
  width: 46px; height: 46px; border-radius: 50%;
  border: 1px solid var(--dim);
  background: var(--accent); color: #06231a;
  display: grid; place-items: center;
  cursor: pointer; font: inherit;
}
.pbtn:hover { filter: brightness(1.08); }
.pbtn:focus-visible, .tick:focus-visible, .jump button:focus-visible {
  outline: 2px solid var(--accent); outline-offset: 2px;
}
.ticks { display: flex; gap: 5px; flex: 1 1 200px; min-width: 0; }
.tick {
  flex: 1; height: 6px; padding: 0;
  border: 0; border-radius: 99px; background: var(--panel-2);
  cursor: pointer; position: relative; overflow: hidden;
}
.tick i { display: block; height: 100%; width: 0; background: var(--dim); }
.tick.done i { width: 100%; background: var(--dim); }
.tick.now i { background: var(--accent); }
.counter {
  font-family: var(--mono); font-size: 12px; color: var(--muted);
  font-variant-numeric: tabular-nums; flex: none;
}

/* --------------------------------------------------------- scene index */
.jump {
  display: grid; gap: 6px; margin-top: 22px;
  grid-template-columns: repeat(auto-fill, minmax(210px, 1fr));
}
.jump button {
  display: flex; gap: 10px; align-items: baseline;
  text-align: left; padding: 10px 12px;
  border: 1px solid var(--line); border-radius: 10px;
  background: transparent; color: var(--muted);
  font: inherit; font-size: 13px; cursor: pointer;
}
.jump button:hover { border-color: var(--dim); color: var(--text); }
.jump button[aria-current="true"] { border-color: var(--accent); color: var(--text); }
.jump b { font-family: var(--mono); font-size: 11px; color: var(--accent); flex: none; }

.foot {
  margin-top: 26px; padding-top: 18px;
  border-top: 1px solid var(--line);
  color: var(--muted); font-size: 13px;
}
.foot a { color: var(--accent); }

/* ----------------------------------------------------------- reduced motion
   Someone who has asked the system to stop animating gets the finished frame
   of every scene immediately, and the player stops advancing on its own. The
   explainer still works — it becomes a set of slides they step through. */
@media (prefers-reduced-motion: reduce) {
  .scene, .scene [data-anim] { transition: none; }
  .scene.on [data-anim],
  .scene.on .draw, .scene.on .fill,
  .scene.on .lift, .scene.on .drop,
  .scene.on .stamp, .scene.on .after-strike, .scene.on .pulse {
    animation: none;
    opacity: 1;
    transform: none;
  }
  .scene.on .draw { stroke-dashoffset: 0; }
  .scene.on .fill { width: var(--w, 60%); }
  .scene.on .strike::after { width: 104%; }
}

@media (max-width: 620px) {
  .caption { min-height: 76px; font-size: 14px; }
  .jump { grid-template-columns: 1fr; }
}

/* ----------------------------------------------------------- embed mode
   Set by ?embed=1, which only the site's own pages use.

   Embedded, the page is a panel inside somebody else's column, not a page:
   the scene index and the footer are duplicated by the surrounding article,
   and the host cannot know how tall they will be. So they go, and the layout
   flips from width-driven to height-driven — the shell fills the iframe and
   the stage takes whatever is left after the caption and the transport. Any
   iframe height then works, which is the only way to be honest about not
   knowing the reader's screen. */
:root.embed, :root.embed body { height: 100%; }
:root.embed .shell {
  height: 100%;
  max-width: none;
  padding-block: 14px 12px;
  display: flex; flex-direction: column; gap: 10px;
}
:root.embed .masthead { margin-bottom: 0; }
:root.embed .jump, :root.embed .foot { display: none; }
:root.embed .stagewrap { flex: 1 1 auto; min-height: 0; }
:root.embed .stage {
  flex: 1 1 auto;
  aspect-ratio: auto;   /* height now comes from the box, not the width */
  min-height: 0;
}
:root.embed .transport { margin-top: 0; }

/* Start prompt over scene 1 until the viewer first presses play. */
.startcard {
  position: absolute; inset: 0; z-index: 5;
  display: flex; flex-direction: column; align-items: center; justify-content: center;
  gap: 10px; width: 100%; padding: 16px;
  border: 0; cursor: pointer; font: inherit; color: var(--text);
  background: color-mix(in srgb, var(--panel) 72%, transparent);
  -webkit-backdrop-filter: blur(3px); backdrop-filter: blur(3px);
}
.startcard-btn {
  display: grid; place-items: center;
  width: 64px; height: 64px; border-radius: 50%;
  background: var(--accent); color: var(--bg);
  box-shadow: 0 6px 24px rgba(0,0,0,.35);
  transition: transform .15s ease;
}
.startcard-btn svg { margin-left: 3px; }
.startcard:hover .startcard-btn, .startcard:focus-visible .startcard-btn { transform: scale(1.07); }
.startcard:focus-visible { outline: 2px solid var(--accent); outline-offset: -4px; }
.startcard-text { font-weight: 700; font-size: clamp(16px, 2.6vw, 22px); }
.startcard-meta { font-family: var(--mono); font-size: 11px; letter-spacing: .12em; text-transform: uppercase; color: var(--muted); }
