/* =============================================================================
   Jay Lyon tools: shared brand layer
   -----------------------------------------------------------------------------
   One stylesheet for the whole family of browser tools. Link it before a tool's
   own stylesheet:

     <link rel="stylesheet" href="/tools/brand.css">
     <link rel="stylesheet" href="css/app.css">

   WHAT THIS IS FOR
   This layer owns identity only: ground, panel treatment, rules, corners, type,
   accent and chrome. It does not own meaning. A tool's own palette, the colors
   that say "this layer is stone wool" or "this line is the dew point" or "this
   result failed", belongs to the tool and must not be restyled to match a brand.
   Those colors are the content.

   THE RULES THAT MAKE IT LOOK LIKE ITS OWN THING
   1. Cool ground, never warm. The default look of generated interfaces right now
      is a cream or parchment background under white rounded cards. The ground
      here is a cool blue-gray, which reads as drawing paper rather than stock.
   2. Rules, not shadows. Separation comes from a hairline. --jl-shadow is none
      and is kept only so a tool that asks for it gets nothing rather than breaks.
   3. Corners at 2px. Enough to avoid looking unfinished, far short of the soft
      card. Pills are reserved for nothing at all.
   4. Figures line up. That is the goal; monospacing is only one way to reach it.
      Dense numeric contexts (tables, readouts, small stats) use the mono face.
      Headline values use the condensed face with tabular figures, because a
      headline often carries a word rather than a number ("Dries by March",
      "Stable"), and mono is both too wide for those and wrong for prose.
   5. Labels are small, letterspaced and uppercase, in the condensed face. This is
      the same treatment as the menus on jaylyonvt.com, which is what ties the
      tools to the site without repeating its layout.
   6. The navy is the one on jaylyonvt.com. The family resemblance costs nothing
      because the color is already in use.
   ========================================================================== */

/* -----------------------------------------------------------------------------
   Fonts, served from this site.
   Self-hosted rather than pulled from Google: no third party sees who opened a
   tool, there is no second DNS lookup and TLS handshake in front of the first
   paint, and the tools keep working if that service is blocked or down.

   IBM Plex Sans is a variable font, and Google serves one file for 400 through
   600; it is declared once over that range instead of three times over the same
   bytes. Plex Mono and Plex Condensed ship as separate static weights.
   Latin and latin-ext only. A tool needing other scripts should add the faces
   it needs rather than everyone carrying them.

   IBM Plex is licensed under the SIL Open Font License 1.1. See fonts/OFL.txt.

   The ?v= on each file is what earns the year-long immutable cache the server
   gives a versioned URL: without it these revalidate on every visit, and a
   round trip for a font is a round trip before any text can be painted. The
   files themselves never change in place, so if one is ever replaced, bump the
   number here rather than trusting caches to notice.
   -------------------------------------------------------------------------- */

@font-face {
  font-family: 'IBM Plex Mono';
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url('/tools/fonts/ibm-plex-mono-400-latin.woff2?v=1') 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: 500;
  font-display: swap;
  src: url('/tools/fonts/ibm-plex-mono-500-latin.woff2?v=1') 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: 600;
  font-display: swap;
  src: url('/tools/fonts/ibm-plex-mono-600-latin.woff2?v=1') 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('/tools/fonts/ibm-plex-mono-400-latin-ext.woff2?v=1') format('woff2');
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C4, U+2113, U+2C60-2C7F, U+A720-A7FF;
}
@font-face {
  font-family: 'IBM Plex Mono';
  font-style: normal;
  font-weight: 500;
  font-display: swap;
  src: url('/tools/fonts/ibm-plex-mono-500-latin-ext.woff2?v=1') format('woff2');
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C4, U+2113, U+2C60-2C7F, U+A720-A7FF;
}
@font-face {
  font-family: 'IBM Plex Mono';
  font-style: normal;
  font-weight: 600;
  font-display: swap;
  src: url('/tools/fonts/ibm-plex-mono-600-latin-ext.woff2?v=1') format('woff2');
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C4, U+2113, U+2C60-2C7F, U+A720-A7FF;
}
@font-face {
  font-family: 'IBM Plex Sans';
  font-style: normal;
  font-weight: 400 600;
  font-display: swap;
  src: url('/tools/fonts/ibm-plex-sans-latin.woff2?v=1') 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 Sans';
  font-style: normal;
  font-weight: 400 600;
  font-display: swap;
  src: url('/tools/fonts/ibm-plex-sans-latin-ext.woff2?v=1') format('woff2');
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C4, U+2113, U+2C60-2C7F, U+A720-A7FF;
}
@font-face {
  font-family: 'IBM Plex Sans Condensed';
  font-style: normal;
  font-weight: 500;
  font-display: swap;
  src: url('/tools/fonts/ibm-plex-sans-condensed-500-latin.woff2?v=1') 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 Sans Condensed';
  font-style: normal;
  font-weight: 600;
  font-display: swap;
  src: url('/tools/fonts/ibm-plex-sans-condensed-600-latin.woff2?v=1') 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 Sans Condensed';
  font-style: normal;
  font-weight: 500;
  font-display: swap;
  src: url('/tools/fonts/ibm-plex-sans-condensed-500-latin-ext.woff2?v=1') format('woff2');
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C4, U+2113, U+2C60-2C7F, U+A720-A7FF;
}
@font-face {
  font-family: 'IBM Plex Sans Condensed';
  font-style: normal;
  font-weight: 600;
  font-display: swap;
  src: url('/tools/fonts/ibm-plex-sans-condensed-600-latin-ext.woff2?v=1') format('woff2');
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C4, U+2113, U+2C60-2C7F, U+A720-A7FF;
}

:root {
  /* --- identity ------------------------------------------------------- */
  --jl-navy:        #2d4059;   /* the jaylyonvt.com navy */
  --jl-navy-hover:  #243449;
  --jl-navy-ink:    #ffffff;
  --jl-navy-faint:  #9fb0c4;   /* type that sits on the navy and must recede */

  /* --- surfaces ------------------------------------------------------- */
  --jl-bg:          #eef1f5;   /* cool, not cream: the whole point */
  --jl-panel:       #ffffff;
  --jl-panel-2:     #f6f8fa;
  --jl-inset:       #e7ecf2;

  /* --- ink ------------------------------------------------------------ */
  --jl-ink:         #131a24;
  --jl-muted:       #5a6675;
  --jl-faint:       #8a97a7;

  /* --- rules ---------------------------------------------------------- */
  --jl-line:        #ccd4de;
  --jl-line-2:      #e3e9ef;
  --jl-rule:        1px solid var(--jl-line);
  --jl-rule-2:      1px solid var(--jl-line-2);
  --jl-rule-heavy:  2px solid var(--jl-ink);

  /* --- accent --------------------------------------------------------- */
  /* An instrument blue, deliberately off the default framework blue. */
  --jl-accent:      #1f6f9c;
  --jl-accent-ink:  #ffffff;
  --jl-accent-soft: #e0edf4;
  --jl-focus:       #1f6f9c;

  /* --- verdicts ------------------------------------------------------- */
  /* Semantic, and intentionally the same hues a tool would pick on its own,
     so a tool can adopt the brand without its results changing meaning. */
  --jl-ok:          #1d7448;
  --jl-ok-soft:     #e3f0e9;
  --jl-warn:        #8a5a00;
  --jl-warn-soft:   #f6eeda;
  --jl-danger:      #bb362f;
  --jl-danger-soft: #f8e5e3;

  /* --- geometry ------------------------------------------------------- */
  --jl-radius:      2px;
  --jl-radius-lg:   3px;
  --jl-shadow:      none;      /* see rule 2 */

  /* --- type ----------------------------------------------------------- */
  --jl-font:  "IBM Plex Sans", ui-sans-serif, system-ui, "Segoe UI", sans-serif;
  --jl-cond:  "IBM Plex Sans Condensed", "IBM Plex Sans", ui-sans-serif, sans-serif;
  --jl-mono:  "IBM Plex Mono", ui-monospace, "SF Mono", Menlo, Consolas, monospace;

  /* --- spacing -------------------------------------------------------- */
  --jl-1: 4px;  --jl-2: 8px;  --jl-3: 12px;
  --jl-4: 16px; --jl-5: 24px; --jl-6: 32px;

  color-scheme: light;
}

/* Dark follows the system unless a tool has pinned itself light. Both selectors
   carry the same weight as the light block above but come later, so a tool that
   defines its own dark values earlier in the cascade is still overridden. */
@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) {
    --jl-navy:        #1b2838;
    --jl-navy-hover:  #223145;
    --jl-navy-ink:    #e9eef4;
    --jl-navy-faint:  #8b99ac;

    --jl-bg:          #10151c;
    --jl-panel:       #171e27;
    --jl-panel-2:     #1d2630;
    --jl-inset:       #202a35;

    --jl-ink:         #e7edf4;
    --jl-muted:       #9aa7b6;
    --jl-faint:       #6b7889;

    --jl-line:        #2e3a48;
    --jl-line-2:      #242f3b;
    --jl-rule-heavy:  2px solid var(--jl-ink);

    --jl-accent:      #5aa7d4;
    --jl-accent-ink:  #0c1620;
    --jl-accent-soft: #1a2c3a;
    --jl-focus:       #7cbde6;

    --jl-ok:          #4cc38a;
    --jl-ok-soft:     #14301f;
    --jl-warn:        #e0a33c;
    --jl-warn-soft:   #322513;
    --jl-danger:      #ef7a74;
    --jl-danger-soft: #35191a;

    color-scheme: dark;
  }
}

:root[data-theme="dark"] {
  --jl-navy:        #1b2838;
  --jl-navy-hover:  #223145;
  --jl-navy-ink:    #e9eef4;
  --jl-navy-faint:  #8b99ac;

  --jl-bg:          #10151c;
  --jl-panel:       #171e27;
  --jl-panel-2:     #1d2630;
  --jl-inset:       #202a35;

  --jl-ink:         #e7edf4;
  --jl-muted:       #9aa7b6;
  --jl-faint:       #6b7889;

  --jl-line:        #2e3a48;
  --jl-line-2:      #242f3b;
  --jl-rule-heavy:  2px solid var(--jl-ink);

  --jl-accent:      #5aa7d4;
  --jl-accent-ink:  #0c1620;
  --jl-accent-soft: #1a2c3a;
  --jl-focus:       #7cbde6;

  --jl-ok:          #4cc38a;
  --jl-ok-soft:     #14301f;
  --jl-warn:        #e0a33c;
  --jl-warn-soft:   #322513;
  --jl-danger:      #ef7a74;
  --jl-danger-soft: #35191a;

  color-scheme: dark;
}

/* =============================================================================
   Components
   Prefixed jl- so a tool can adopt them one at a time without a name colliding
   with whatever it already calls things.
   ========================================================================== */

.jl-body {
  margin: 0;
  background: var(--jl-bg);
  color: var(--jl-ink);
  font-family: var(--jl-font);
  font-size: 14px;
  line-height: 1.45;
}

/* --- the bar across the top ------------------------------------------- */
.jl-bar {
  display: flex;
  align-items: center;
  gap: var(--jl-3);
  padding: var(--jl-2) var(--jl-3);
  background: var(--jl-navy);
  color: var(--jl-navy-ink);
}

/* Name of the family member, set like the menus on the main site. */
.jl-mark {
  display: flex;
  align-items: baseline;
  gap: var(--jl-2);
  margin: 0;
  font-family: var(--jl-cond);
  font-size: 14px;
  font-weight: 600;
  letter-spacing: .22em;
  text-transform: uppercase;
}
.jl-mark svg { align-self: center; display: block; }

/* What the tool is, beside its name, quiet and not shouting. */
.jl-mark-sub {
  font-family: var(--jl-mono);
  font-size: 11px;
  font-weight: 400;
  letter-spacing: 0;
  text-transform: none;
  color: var(--jl-navy-faint);
}

.jl-bar-end { margin-left: auto; display: flex; gap: var(--jl-1); }

/* --- surfaces ---------------------------------------------------------- */
.jl-panel {
  background: var(--jl-panel);
  border: var(--jl-rule);
  border-radius: var(--jl-radius);
  box-shadow: var(--jl-shadow);
}

/* --- small capitals used for every field label ------------------------- */
.jl-label {
  font-family: var(--jl-cond);
  font-size: 10px;
  font-weight: 600;
  letter-spacing: .12em;
  text-transform: uppercase;
  color: var(--jl-muted);
}

/* --- a single headline number ------------------------------------------ */
.jl-tile {
  background: var(--jl-panel);
  border: var(--jl-rule);
  border-left: 3px solid var(--jl-navy);
  border-radius: var(--jl-radius);
  padding: var(--jl-2) var(--jl-3);
  min-width: 0;
}
.jl-tile-v {
  display: block;
  /* Condensed rather than mono: a headline value is as likely to read
     "Dries by March" as "0.036", and tabular figures keep the numbers aligned
     without mono's width. */
  font-family: var(--jl-cond);
  font-size: 24px;
  font-weight: 600;
  line-height: 1.15;
  letter-spacing: .005em;
  font-variant-numeric: tabular-nums;
}
.jl-tile-s { display: block; font-family: var(--jl-mono); font-size: 11px; color: var(--jl-muted); }
.jl-tile.is-ok     { border-left-color: var(--jl-ok); }
.jl-tile.is-ok     .jl-tile-v { color: var(--jl-ok); }
.jl-tile.is-warn   { border-left-color: var(--jl-warn); }
.jl-tile.is-warn   .jl-tile-v { color: var(--jl-warn); }
.jl-tile.is-danger { border-left-color: var(--jl-danger); }
.jl-tile.is-danger .jl-tile-v { color: var(--jl-danger); }

/* --- buttons ----------------------------------------------------------- */
.jl-btn {
  font: inherit;
  font-size: 12px;
  padding: 5px 11px;
  cursor: pointer;
  color: var(--jl-ink);
  background: var(--jl-panel);
  border: var(--jl-rule);
  border-radius: var(--jl-radius);
}
.jl-btn:hover { border-color: var(--jl-faint); }
.jl-btn-primary {
  background: var(--jl-navy);
  border-color: var(--jl-navy);
  color: var(--jl-navy-ink);
}
.jl-btn-primary:hover { background: var(--jl-navy-hover); border-color: var(--jl-navy-hover); }

/* On the navy bar the outline button has to invert. */
.jl-bar .jl-btn {
  background: transparent;
  color: var(--jl-navy-ink);
  border-color: rgba(255, 255, 255, .35);
}
.jl-bar .jl-btn:hover { border-color: rgba(255, 255, 255, .7); }

/* --- segmented control -------------------------------------------------- */
.jl-seg {
  display: inline-flex;
  border: var(--jl-rule);
  border-radius: var(--jl-radius);
  overflow: hidden;
}
.jl-seg button {
  font: inherit;
  font-size: 12px;
  padding: 5px 12px;
  cursor: pointer;
  border: 0;
  border-right: var(--jl-rule);
  background: var(--jl-panel);
  color: var(--jl-muted);
}
.jl-seg button:last-child { border-right: 0; }
.jl-seg button[aria-checked="true"],
.jl-seg button.is-on {
  background: var(--jl-navy);
  color: var(--jl-navy-ink);
}

/* --- tables ------------------------------------------------------------- */
.jl-table { width: 100%; border-collapse: collapse; font-size: 12px; }
.jl-table th {
  text-align: left;
  padding: 5px 8px;
  background: var(--jl-navy);
  color: var(--jl-navy-ink);
  font-family: var(--jl-cond);
  font-size: 10px;
  font-weight: 600;
  letter-spacing: .1em;
  text-transform: uppercase;
}
.jl-table td { padding: 5px 8px; border-bottom: var(--jl-rule-2); }
.jl-table tbody tr:last-child td { border-bottom: 0; }
.jl-table .num, .jl-table th.num { text-align: right; font-family: var(--jl-mono); font-variant-numeric: tabular-nums; }

/* --- verdict badges ------------------------------------------------------ */
.jl-badge {
  display: inline-block;
  font-family: var(--jl-mono);
  font-size: 11px;
  padding: 2px 8px;
  border-radius: var(--jl-radius);
  border: 1px solid transparent;
}
.jl-badge.is-ok     { background: var(--jl-ok-soft);     color: var(--jl-ok);     border-color: color-mix(in srgb, var(--jl-ok) 28%, transparent); }
.jl-badge.is-warn   { background: var(--jl-warn-soft);   color: var(--jl-warn);   border-color: color-mix(in srgb, var(--jl-warn) 28%, transparent); }
.jl-badge.is-danger { background: var(--jl-danger-soft); color: var(--jl-danger); border-color: color-mix(in srgb, var(--jl-danger) 28%, transparent); }

/* --- focus --------------------------------------------------------------- */
/* One visible treatment everywhere, because a keyboard user should never have to
   wonder which tool they are in. */
.jl-body :focus-visible,
.jl-btn:focus-visible,
.jl-seg button:focus-visible {
  outline: 2px solid var(--jl-focus);
  outline-offset: 1px;
}

/* --- anything numeric ----------------------------------------------------- */
.jl-num { font-family: var(--jl-mono); font-variant-numeric: tabular-nums; }

@media (prefers-reduced-motion: reduce) {
  .jl-body *, .jl-body *::before, .jl-body *::after {
    animation-duration: .001ms !important;
    transition-duration: .001ms !important;
  }
}

/* =============================================================================
   Tour (see tour.js)
   A balloon anchored to a real control, with the control ringed. No dimming
   backdrop: the point is to show someone the tool, and graying it out hides the
   thing being explained.
   ========================================================================== */

.jl-tour { position: fixed; inset: 0; z-index: 9000; pointer-events: none; }

/* The ring sits over the control being described. */
.jl-tour-ring {
  position: fixed;
  border: 2px solid var(--jl-accent);
  border-radius: var(--jl-radius);
  box-shadow: 0 0 0 9999px rgba(19, 26, 36, .28);
  opacity: 0;
  transition: left .18s ease, top .18s ease, width .18s ease, height .18s ease,
              opacity .16s ease;
}
/* The ring is placed before it is shown, so the first step does not watch it
   slide in from the corner of the screen. */
.jl-tour-ring-still { transition: none !important; }
.jl-tour-ring.is-in { opacity: 1; }

.jl-tour-pop {
  position: fixed;
  pointer-events: auto;
  /* No transition on left/top on purpose: the balloon only ever moves while it
     is invisible, so there is nothing to animate and a slide would only put the
     move back on screen. */
  opacity: 0;
  transition: opacity .16s ease;
  width: 290px;
  max-width: calc(100vw - 16px);
  background: var(--jl-panel);
  color: var(--jl-ink);
  border: var(--jl-rule);
  border-top: 3px solid var(--jl-navy);
  border-radius: var(--jl-radius);
  padding: var(--jl-3);
  font-family: var(--jl-font);
  font-size: 13px;
  line-height: 1.5;
}
.jl-tour-pop.is-in { opacity: 1; }
.jl-tour.is-leaving .jl-tour-ring { opacity: 0; }
.jl-tour-pop:focus { outline: none; }
.jl-tour-pop:focus-visible { outline: 2px solid var(--jl-focus); outline-offset: 2px; }

.jl-tour-h {
  margin: 0 0 var(--jl-1);
  font-family: var(--jl-cond);
  font-size: 12px;
  font-weight: 600;
  letter-spacing: .12em;
  text-transform: uppercase;
  color: var(--jl-navy);
}
:root[data-theme="dark"] .jl-tour-h { color: var(--jl-accent); }
@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) .jl-tour-h { color: var(--jl-accent); }
}

.jl-tour-b { margin: 0 0 var(--jl-3); color: var(--jl-ink); }

.jl-tour-foot { display: flex; align-items: center; gap: var(--jl-1); }
.jl-tour-count {
  margin-right: auto;
  font-family: var(--jl-mono);
  font-size: 11px;
  color: var(--jl-faint);
}
.jl-tour-skip { border-color: transparent; color: var(--jl-muted); }
.jl-tour-back[disabled] { opacity: .4; cursor: default; }

@media (prefers-reduced-motion: reduce) {
  .jl-tour-ring, .jl-tour-pop { transition: none; }
}

/* ---------- page entry ---------- */

/* The document starts transparent and fades up once this stylesheet has applied,
   so a late stylesheet or a swapping webfont never shows as a flash of unstyled
   text. Same half second the main site uses, so every page on the domain enters
   the same way, and it is skipped for anyone who has asked for less motion.

   Deliberately no animation-fill-mode: forwards. The last keyframe is opacity 1,
   which is the resting value anyway, so forwards changes nothing when the
   animation runs. When it does not run it is the whole difference between a page
   that is simply there and a page pinned at opacity 0 with nothing on it, which
   is where an extension that pauses animations would leave it. */
body {
  animation: fadeIn 0.5s ease-in;
}

@keyframes fadeIn {
  from { opacity: 0; }
  to   { opacity: 1; }
}

@media (prefers-reduced-motion: reduce) {
  body { animation: none; }
}
