﻿/* ============================================================
   StreamUP Design System
   ------------------------------------------------------------
   Built on top of Pico CSS v2 (dark theme). This file is loaded
   AFTER Pico in _Layout.cshtml, so its tokens & component styles
   override the framework defaults.

   This is the single source of truth for visual style. If you
   need something that isn't defined here, FLAG IT, design it
   properly, then add it to this file + DESIGN_SYSTEM.md.

   Sections:
     1. Design tokens (:root custom properties)
     2. Pico variable overrides (dark theme)
     3. Base elements
     4. Utilities
     5. Components (button, card, badge, section, grid, hero)
     6. Accessibility
   ============================================================ */

/* ---------- 1. DESIGN TOKENS ---------- */
:root {
  /* Brand core — pulled from the logo SVGs */
  --sup-midnight: #1f1f4f;
  --sup-cyan:     #6af4ff;
  --sup-pink:     #ff86bd;
  --sup-cream:    #fff6d9;

  /* Dark surface scale (midnight-tinted) */
  --sup-bg:        #0b0b1c; /* page background        */
  --sup-surface-1: #14142e; /* cards / panels         */
  --sup-surface-2: #1f1f4f; /* elevated / hover (midnight) */
  --sup-surface-3: #2a2a5e; /* highest elevation      */

  /* Text */
  --sup-text:        #f2f2f8;
  --sup-text-muted:  #a9a9c6;
  --sup-text-subtle: #74749a;

  /* Lines */
  --sup-border:        rgba(255, 255, 255, 0.10);
  --sup-border-strong: rgba(255, 255, 255, 0.18);

  /* Accents */
  --sup-accent:   var(--sup-cyan);
  --sup-accent-2: var(--sup-pink);

  /* Brand gradient (cyan -> pink). Use for primary/hero/premium emphasis. */
  --sup-gradient:      linear-gradient(100deg, #6af4ff 0%, #9da5e9 50%, #ff86bd 100%);
  --sup-gradient-soft: linear-gradient(100deg, rgba(106, 244, 255, .16) 0%, rgba(255, 134, 189, .16) 100%);

  /* Editorial accents (v0.6) -------------------------------------------
     The cyan hairline used to divide shared surfaces (shelves, figures,
     process). No dot-grid: that is Andi Stone Media's, not StreamUP's. */
  --sup-hairline:   rgba(106, 244, 255, .18);           /* cyan accent divider */

  /* Cream light-panel family — the ONE deliberate light moment per page.
     Midnight ink on cream keeps it on-brand (midnight + cream are both
     brand colours). Used full-bleed, 1× per page, to punctuate the dark. */
  --sup-cream-bg:         #f5edd3;                       /* panel surface (calmed cream) */
  --sup-cream-ink:        #181838;                       /* headings / primary text */
  --sup-cream-ink-medium: #3b3950;                       /* body copy */
  --sup-cream-ink-muted:  #6a6347;                       /* eyebrow / labels */
  --sup-cream-line:       rgba(24, 24, 56, .16);         /* hairline on cream */
  --sup-cream-link:       #0c6f7d;                       /* deepened cyan, legible on cream */

  /* Typography */
  --sup-font-display: "Bebas Neue", system-ui, sans-serif;            /* headings / display */
  --sup-font-body:    "Manrope", system-ui, -apple-system, "Segoe UI", Roboto, sans-serif;

  /* Type scale */
  --sup-text-xs:    0.75rem;
  --sup-text-sm:    0.875rem;
  --sup-text-base:  1rem;
  --sup-text-lg:    1.125rem;
  --sup-text-xl:    1.375rem;
  --sup-display-sm: clamp(2rem, 4vw, 2.75rem);
  --sup-display-md: clamp(2.75rem, 6vw, 4rem);
  --sup-display-lg: clamp(3.5rem, 9vw, 6.5rem);

  /* Spacing scale (4px base) */
  --sup-space-1: 0.25rem;
  --sup-space-2: 0.5rem;
  --sup-space-3: 0.75rem;
  --sup-space-4: 1rem;
  --sup-space-5: 1.5rem;
  --sup-space-6: 2rem;
  --sup-space-7: 3rem;
  --sup-space-8: 4rem;
  --sup-space-9: 6rem;

  /* Radii */
  --sup-radius-sm:   8px;
  --sup-radius-md:   14px;
  --sup-radius-lg:   22px;
  --sup-radius-full: 999px;

  /* Shadows & glows */
  /* Shadows on a near-black page band badly: one black layer fading over a
     long distance has only a handful of distinct 8-bit values to work with,
     so each shows as a ring. One dense layer instead of one faint one fixes
     the banding but stops dead at its edge, which looks worse.

     The answer is several layers on a decaying curve. Each contributes a
     short ramp, their steps land at different distances so they never line
     up into rings, and the outermost is faint enough (5-6%) that the shadow
     genuinely reaches nothing rather than being cut off. Tinted toward the
     page's own dark navy so the ramp stays in one hue as it fades. */
  --sup-shadow-sm: 0 1px 2px rgba(3, 3, 12, .35);
  --sup-shadow-md:
    0 1px 1px rgba(3, 3, 12, .14),
    0 3px 5px rgba(3, 3, 12, .12),
    0 7px 12px rgba(3, 3, 12, .10),
    0 14px 24px rgba(3, 3, 12, .07);
  --sup-shadow-lg:
    0 2px 3px rgba(3, 3, 12, .16),
    0 5px 9px rgba(3, 3, 12, .13),
    0 11px 20px rgba(3, 3, 12, .11),
    0 22px 40px rgba(3, 3, 12, .08),
    0 40px 70px rgba(3, 3, 12, .05);
  --sup-glow-cyan: 0 0 0 1px rgba(106, 244, 255, .5), 0 8px 30px rgba(106, 244, 255, .25);
  --sup-glow-pink: 0 0 0 1px rgba(255, 134, 189, .5), 0 8px 30px rgba(255, 134, 189, .25);

  /* Motion */
  --sup-ease:      cubic-bezier(.2, .7, .2, 1);  /* general */
  --sup-ease-out:  cubic-bezier(.22, 1, .36, 1); /* smooth decel — hovers */
  --sup-ease-pop:  cubic-bezier(.34, 1.4, .5, 1);/* gentle overshoot — lifts */
  --sup-dur-fast:  120ms;
  --sup-dur:       220ms;
  --sup-dur-slow:  360ms;

  /* Layout */
  --sup-container:      1140px;
  --sup-container-wide: 1320px;

  /* Z-index scale (use these instead of magic numbers) */
  --sup-z-base:    1;
  --sup-z-raised:  10;
  --sup-z-sticky:  100;
  --sup-z-overlay: 1000;
  --sup-z-modal:   2000;
  --sup-z-toast:   3000;
}

/* ---------- 2. PICO VARIABLE OVERRIDES (dark) ---------- */
[data-theme="dark"],
:root:not([data-theme]) {
  --pico-font-family:            var(--sup-font-body);
  --pico-font-family-sans-serif: var(--sup-font-body);
  --pico-background-color:       var(--sup-bg);
  --pico-color:                  var(--sup-text);
  --pico-h1-color:               var(--sup-cream);
  --pico-h2-color:               var(--sup-cream);
  --pico-h3-color:               #e7e7f2;
  --pico-h4-color:               #e7e7f2;
  --pico-muted-color:            var(--sup-text-muted);
  --pico-border-color:           var(--sup-border);
  --pico-border-radius:          var(--sup-radius-md);

  /* Primary = cyan (links, focus rings). The gradient is applied to
     .primary buttons explicitly in section 5.1. */
  --pico-primary:                var(--sup-cyan);
  --pico-primary-background:      var(--sup-cyan);
  --pico-primary-hover:          #8af7ff;
  --pico-primary-hover-background:#8af7ff;
  --pico-primary-focus:          rgba(106, 244, 255, .35);
  --pico-primary-inverse:        #06121f;

  /* Cards / panels */
  --pico-card-background-color: var(--sup-surface-1);
  --pico-card-border-color:     var(--sup-border);
  --pico-card-box-shadow:       var(--sup-shadow-md);

  /* Forms */
  --pico-form-element-background-color:   #101027;
  --pico-form-element-border-color:       var(--sup-border-strong);
  --pico-form-element-active-border-color:var(--sup-cyan);
}

/* ---------- 3. BASE ELEMENTS ---------- */
/* G1 — root font-size cap (master fix).
   Pico v2 ships a fluid :root font-size that scales UP on wide screens
   (computing to ~21px on desktop), which inflates the whole rem-based
   design system ~30%. Cap it here (this file loads after Pico) with a
   touch of fluidity. !important + html specificity beats Pico's own
   media-query rules so type, spacing and nav all settle at 16px. */
html {
  font-size: clamp(15px, 0.2vw + 14.5px, 17px) !important;
  /* Let full-bleed panels (.sup-bleed: width:100vw) span the viewport without
     dragging out a horizontal scrollbar. `clip` (not hidden) doesn't create a
     scroll container, so the sticky nav keeps working. */
  overflow-x: clip;
}

body {
  /* Flat base. No dot-grid: that texture belongs to the Andi Stone Media
     sites, not StreamUP.

     No brand glows either. A 1100x600 wash at 8% alpha over a near-black
     page bands into broad diagonal steps, most visible in an empty corner.
     Nothing fixes that at this size, so the canvas is flat. */
  background-color: var(--sup-bg);
  color: var(--sup-text);
  font-family: var(--sup-font-body);
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
}

/* Display headings (h1/h2) use Bebas Neue; smaller headings stay Manrope
   for readability (e.g. product card titles). */
h1, h2, .sup-display {
  font-family: var(--sup-font-display);
  font-weight: 400;
  letter-spacing: .01em;
  line-height: .95;
  text-transform: uppercase;
}
h1 { font-size: clamp(2.2rem, 4vw, 3rem); }
h2 { font-size: clamp(1.8rem, 3vw, 2.4rem); }
h3, h4, h5, h6 {
  font-family: var(--sup-font-body);
  font-weight: 700;
  letter-spacing: -0.01em;
}

a { --pico-text-decoration: none; color: var(--sup-cyan); }
a:hover { color: #9df8ff; }

/* ---------- 4. UTILITIES ---------- */
.sup-gradient-text {
  background: var(--sup-gradient);
  -webkit-background-clip: text;
  background-clip: text;
  color: transparent;
}
.sup-container { max-width: var(--sup-container); margin-inline: auto; padding-inline: var(--sup-space-4); }
.sup-muted    { color: var(--sup-text-muted); }
.sup-stack > * + * { margin-top: var(--sup-space-4); }
.sup-eyebrow {
  display: inline-block;
  font-family: var(--sup-font-body);
  font-weight: 700;
  font-size: var(--sup-text-sm);
  letter-spacing: .14em;
  text-transform: uppercase;
  color: var(--sup-cyan);
}

/* ---------- 5. COMPONENTS ---------- */

/* 5.1 Buttons -------------------------------------------------
   Primary  = brand gradient CTA  (class="primary")
   Secondary= outline             (class="secondary outline" / "outline")
   Built on Pico's button/[role=button] base. */
button, [type="submit"], [type="button"], [role="button"], .button {
  font-family: var(--sup-font-body);
  font-weight: 700;
  border-radius: var(--sup-radius-full);
  will-change: transform;
  transition: transform var(--sup-dur) var(--sup-ease-pop),
              box-shadow var(--sup-dur-slow) var(--sup-ease-out),
              background-position var(--sup-dur-slow) var(--sup-ease-out),
              filter var(--sup-dur) var(--sup-ease-out),
              border-color var(--sup-dur) var(--sup-ease-out),
              color var(--sup-dur) var(--sup-ease-out);
}
[role="button"].primary, button.primary, .button.primary, [type="submit"].primary {
  background: var(--sup-gradient);
  background-size: 220% 100%;
  background-position: 0% 50%;
  border: none;
  color: #08121d;
  box-shadow: var(--sup-shadow-md);
}
[role="button"].primary:hover, button.primary:hover, .button.primary:hover, [type="submit"].primary:hover {
  transform: translateY(-3px) scale(1.015);
  background-position: 100% 50%;
  filter: brightness(1.06) saturate(1.08);
  box-shadow: var(--sup-glow-cyan);
  color: #08121d;
}
/* tactile press — quick settle back down */
[role="button"].primary:active, button.primary:active, .button.primary:active, [type="submit"].primary:active {
  transform: translateY(-1px) scale(.99);
  transition-duration: var(--sup-dur-fast);
  filter: brightness(.98);
}
[role="button"].secondary.outline, .button.secondary.outline, [role="button"].outline, button.outline {
  background: transparent;
  border: 1px solid var(--sup-border-strong);
  color: var(--sup-text);
}
[role="button"].secondary.outline:hover, [role="button"].outline:hover, button.outline:hover {
  transform: translateY(-3px);
  border-color: var(--sup-cyan);
  color: var(--sup-cyan);
  box-shadow: 0 0 0 3px rgba(106, 244, 255, .12);
}
[role="button"].secondary.outline:active, [role="button"].outline:active, button.outline:active {
  transform: translateY(-1px);
  transition-duration: var(--sup-dur-fast);
}

/* 5.2 Card --------------------------------------------------- */
.sup-card {
  background: var(--sup-surface-1);
  border: 1px solid var(--sup-border);
  border-radius: var(--sup-radius-lg);
  padding: var(--sup-space-5);
  box-shadow: var(--sup-shadow-md);
  will-change: transform;
  transition: transform var(--sup-dur-slow) var(--sup-ease-out),
              border-color var(--sup-dur-slow) var(--sup-ease-out),
              box-shadow var(--sup-dur-slow) var(--sup-ease-out);
}
.sup-card:hover {
  transform: translateY(-6px) scale(1.01);
  border-color: var(--sup-border-strong);
  box-shadow: var(--sup-shadow-lg);
}

/* 5.2b Tip jar ------------------------------------------------ */
/* A slowly turning brand-gradient rim, a mug, and a gradient pill
   with a light sweep on hover. Loud enough to notice, calm enough to sit
   under content without shouting over it. */
@property --sup-tip-angle {
  syntax: "<angle>";
  inherits: false;
  initial-value: 0deg;
}
.sup-tip {
  position: relative;
  display: grid;
  grid-template-columns: auto 1fr auto;
  align-items: center;
  gap: var(--sup-space-5);
  margin: var(--sup-space-7) auto;
  max-width: 880px;
  padding: var(--sup-space-5) var(--sup-space-6);
  border: 1px solid transparent;
  border-radius: var(--sup-radius-lg);
  background:
    radial-gradient(90% 140% at 0% 50%, rgba(106, 244, 255, .10), transparent 60%) padding-box,
    radial-gradient(90% 140% at 100% 50%, rgba(255, 134, 189, .10), transparent 60%) padding-box,
    linear-gradient(var(--sup-surface-1), var(--sup-surface-1)) padding-box,
    conic-gradient(from var(--sup-tip-angle), rgba(106, 244, 255, .9), rgba(157, 165, 233, .25), rgba(255, 134, 189, .9), rgba(157, 165, 233, .25), rgba(106, 244, 255, .9)) border-box;
  box-shadow: var(--sup-shadow-md);
  color: var(--sup-text);
  animation: sup-tip-spin 8s linear infinite;
}
@keyframes sup-tip-spin { to { --sup-tip-angle: 360deg; } }

.sup-tip__icon {
  position: relative;
  display: grid;
  place-items: center;
  width: 3.5rem;
  height: 3.5rem;
  border-radius: 50%;
  background: var(--sup-gradient-soft);
  box-shadow: inset 0 0 0 1px var(--sup-border-strong);
  font-size: 1.4rem;
  color: var(--sup-cream);
}

.sup-tip__copy { min-width: 0; }
.sup-tip .sup-tip__title {
  margin: 0 0 var(--sup-space-1);
  font-family: var(--sup-font-display);
  font-size: 1.75rem;
  line-height: 1.05;
  letter-spacing: .02em;
  color: var(--sup-text);
}
.sup-tip .sup-tip__text {
  margin: 0;
  font-size: var(--sup-text-sm);
  color: var(--sup-text-muted);
}

.sup-tip__btn {
  position: relative;
  overflow: hidden;
  display: inline-flex;
  align-items: center;
  gap: var(--sup-space-2);
  padding: .8rem 1.5rem;
  border-radius: var(--sup-radius-full);
  background: var(--sup-gradient);
  background-size: 200% 100%;
  background-position: 0% 50%;
  color: #08121d;
  font-weight: 800;
  white-space: nowrap;
  text-decoration: none;
  box-shadow: 0 6px 22px rgba(255, 134, 189, .22);
  transition: transform var(--sup-dur-slow) var(--sup-ease-pop),
              background-position var(--sup-dur-slow) var(--sup-ease-out),
              box-shadow var(--sup-dur-slow) var(--sup-ease-out);
}
/* The light sweep that crosses the pill on hover. */
.sup-tip__btn::after {
  content: "";
  position: absolute;
  inset: 0;
  background: linear-gradient(110deg, transparent 30%, rgba(255, 255, 255, .55) 50%, transparent 70%);
  transform: translateX(-120%);
  transition: transform 700ms var(--sup-ease-out);
}
.sup-tip__btn .fa-heart { transition: transform var(--sup-dur-slow) var(--sup-ease-pop); }
.sup-tip__btn:hover,
.sup-tip__btn:focus-visible {
  color: #08121d;
  transform: translateY(-2px);
  background-position: 100% 50%;
  box-shadow: var(--sup-glow-pink);
}
.sup-tip__btn:hover::after,
.sup-tip__btn:focus-visible::after { transform: translateX(120%); }
.sup-tip__btn:hover .fa-heart { transform: scale(1.25); }
.sup-tip__btn:active { transform: translateY(0) scale(.98); }

/* Compact: one line, sits inside another section rather than on its own. */
.sup-tip--compact {
  grid-template-columns: auto 1fr auto;
  gap: var(--sup-space-4);
  max-width: 640px;
  margin: var(--sup-space-6) auto 0;
  padding: var(--sup-space-3) var(--sup-space-3) var(--sup-space-3) var(--sup-space-4);
  border-radius: var(--sup-radius-full);
  text-align: left;
}
.sup-tip--compact .sup-tip__icon { width: 2.5rem; height: 2.5rem; font-size: 1rem; }
.sup-tip--compact .sup-tip__title { font-size: 1.2rem; }
.sup-tip--compact .sup-tip__text { font-size: var(--sup-text-xs); }
.sup-tip--compact .sup-tip__btn { padding: .6rem 1.15rem; font-size: var(--sup-text-sm); }

@media (max-width: 640px) {
  .sup-tip,
  .sup-tip--compact {
    grid-template-columns: 1fr;
    justify-items: center;
    text-align: center;
    border-radius: var(--sup-radius-lg);
    padding: var(--sup-space-5);
  }
}

/* Footer link: gradient text and a mug, so it reads as the tip jar. */
.sup-footer__list a.sup-footer__tip {
  display: inline-flex;
  align-items: center;
  gap: .4em;
  background: var(--sup-gradient);
  -webkit-background-clip: text;
  background-clip: text;
  color: transparent;
  font-weight: 700;
}
.sup-footer__list a.sup-footer__tip i { color: var(--sup-pink); }
.sup-footer__list a.sup-footer__tip:hover { filter: brightness(1.15); }

@media (prefers-reduced-motion: reduce) {
  .sup-tip { animation: none; }
  .sup-tip__btn, .sup-tip__btn::after, .sup-tip__btn .fa-heart { transition: none; }
}

/* 5.3 Badge / tag -------------------------------------------- */
.sup-badge {
  display: inline-flex;
  align-items: center;
  gap: .4em;
  font-size: var(--sup-text-xs);
  font-weight: 700;
  letter-spacing: .06em;
  text-transform: uppercase;
  padding: .35em .7em;
  border-radius: var(--sup-radius-full);
  background: var(--sup-surface-2);
  color: var(--sup-text);
  border: 1px solid var(--sup-border-strong);
}
.sup-badge--premium { background: var(--sup-gradient); color: #08121d; border: none; }
.sup-badge--free    { color: var(--sup-cyan); border-color: rgba(106, 244, 255, .4); background: transparent; }
.sup-badge--beta    { color: var(--sup-pink); border-color: rgba(255, 134, 189, .45); background: rgba(255, 134, 189, .12); }

/* 5.4 Section rhythm -----------------------------------------
   G2 — tighter vertical rhythm. Was --sup-space-9 (6rem top+bottom),
   which left ~250px of dead space between any two stacked sections.
   A clamped 2.5–4rem keeps pages compact without feeling cramped. */
.sup-section { padding-block: clamp(2.5rem, 5vw, 4rem); }
.sup-section__head { margin-bottom: var(--sup-space-6); }
.sup-section__head h1,
.sup-section__head h2 { font-size: var(--sup-display-sm); margin-bottom: var(--sup-space-2); }
.sup-section__head p  { color: var(--sup-text-muted); margin: 0; }

/* 5.5 Card grid ---------------------------------------------- */
.sup-grid {
  display: grid;
  gap: var(--sup-space-5);
  grid-template-columns: repeat(auto-fill, minmax(280px, 1fr));
}

/* 5.6 Hero ---------------------------------------------------
   G2 — hero sits close to the nav now (no dead band under the bar).
   Top padding cut hard; a little more breathing room beneath. */
.sup-hero { text-align: center; padding-block: clamp(2rem, 4vw, 3rem) clamp(2.5rem, 5vw, 4rem); }
.sup-hero h1 { font-size: var(--sup-display-lg); margin-bottom: var(--sup-space-4); }
.sup-hero p  { color: var(--sup-text-muted); max-width: 48ch; margin-inline: auto; }
.sup-hero .call-to-actions { display: flex; gap: var(--sup-space-4); justify-content: center; flex-wrap: wrap; margin-top: var(--sup-space-6); }

/* 5.7 Expanding logo tag ------------------------------------
   Collapsed = just the logo (pill is circular). On hover the pill
   smoothly expands to reveal the name. The label stays in the DOM
   (always readable by screen readers) and shows by default on
   touch devices (no hover). Uses an animated grid track so it
   works without hard-coded widths.

   Markup:
     <span class="sup-tag">
       <span class="sup-tag__icon"><img src="/img/bots/streamerbot.svg" alt="Streamer.bot"></span>
       <span class="sup-tag__label"><span>Streamer.bot</span></span>
     </span>                                                      */
.sup-tag {
  display: inline-flex;
  align-items: center;
  padding: .4rem;
  border-radius: var(--sup-radius-full);
  background: var(--sup-surface-2);
  border: 1px solid var(--sup-border-strong);
  color: var(--sup-text);
  font-size: var(--sup-text-xs);
  font-weight: 700;
  letter-spacing: .04em;
  line-height: 1;
  cursor: default;
  transition: background var(--sup-dur) var(--sup-ease-out),
              border-color var(--sup-dur) var(--sup-ease-out),
              box-shadow var(--sup-dur) var(--sup-ease-out);
}
.sup-tag__icon {
  display: block;
  width: 1.05rem;
  height: 1.05rem;
  flex: 0 0 auto;
  line-height: 0;
}
.sup-tag__icon img,
.sup-tag__icon svg {
  width: 100%;
  height: 100%;
  object-fit: contain;   /* scales each logo to the same box, centered, no overflow */
  display: block;
  border-radius: 3px;    /* rounds square logos (e.g. SAMMI) so they sit nicely */
}
/* Glyph-based tags (e.g. Independent) instead of a logo image. */
.sup-tag__icon i {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 100%;
  height: 100%;
  font-size: .82rem;
  line-height: 1;
  color: var(--sup-cyan);
}
.sup-tag__label {
  display: grid;
  grid-template-columns: 0fr;
  transition: grid-template-columns var(--sup-dur-slow) var(--sup-ease-out);
}
.sup-tag__label > span {
  overflow: hidden;
  white-space: nowrap;
  min-width: 0;
  padding: 0;
  transition: padding var(--sup-dur-slow) var(--sup-ease-out);
}
.sup-tag:hover {
  background: var(--sup-surface-3);
  border-color: var(--sup-cyan);
  box-shadow: 0 0 0 3px rgba(106, 244, 255, .10);
}
.sup-tag:hover .sup-tag__label { grid-template-columns: 1fr; }
.sup-tag:hover .sup-tag__label > span { padding: 0 .5rem 0 .45rem; }

/* Touch / no-hover devices: show the full label by default */
@media (hover: none) {
  .sup-tag__label { grid-template-columns: 1fr; }
  .sup-tag__label > span { padding: 0 .5rem 0 .45rem; }
}

/* 5.8 Skeleton loading --------------------------------------
   Placeholder shapes shown while data loads (e.g. product cards
   during the Notion cache warm-up). The shimmer is a keyframe
   animation, so it goes static under reduced-motion automatically. */
.sup-skeleton {
  position: relative;
  overflow: hidden;
  background: var(--sup-surface-2);
  border-radius: var(--sup-radius-sm);
}
.sup-skeleton::after {
  content: "";
  position: absolute;
  inset: 0;
  transform: translateX(-100%);
  background: linear-gradient(90deg, transparent, rgba(255, 255, 255, .08), transparent);
  animation: sup-shimmer 1.4s infinite;
}
@keyframes sup-shimmer { 100% { transform: translateX(100%); } }

.sup-skeleton-card {
  background: var(--sup-surface-1);
  border: 1px solid var(--sup-border);
  border-radius: var(--sup-radius-lg);
  padding: var(--sup-space-3);
}
.sup-skeleton-card .sk-image {
  width: 100%;
  padding-top: 56.25%; /* 16:9, matches product cover */
  border-radius: var(--sup-radius-md);
  margin-bottom: var(--sup-space-4);
}
.sup-skeleton-card .sk-line { height: .8rem; margin-bottom: var(--sup-space-2); }
.sup-skeleton-card .sk-line.title { height: 1.1rem; width: 70%; }
.sup-skeleton-card .sk-line.short { width: 45%; margin-bottom: 0; }

/* 5.9 Pricing tier card -------------------------------------
   Anchored pricing for the Premium page. A `.sup-pricing` grid of
   `.sup-tier` cards. The `--featured` variant gets a gradient border,
   glow and a "Most Popular" ribbon.

   Markup:
     <div class="sup-pricing">
       <article class="sup-tier sup-tier--featured">
         <div class="sup-tier__ribbon">Most Popular</div>
         <header class="sup-tier__head">
           <h3 class="sup-tier__name">All Access</h3>
           <div class="sup-tier__price"><span class="sup-tier__amount">£10</span><span class="sup-tier__period">/mo</span></div>
           <p class="sup-tier__blurb">Everything, plus early access.</p>
         </header>
         <ul class="sup-tier__features">
           <li>Entire 50+ catalogue</li>
           <li>Early access to new drops</li>
         </ul>
         <p class="sup-tier__note">Cancel anytime</p>
         <a role="button" class="primary sup-tier__cta">Start All Access</a>
       </article>
     </div>                                                      */
.sup-pricing {
  display: grid;
  gap: var(--sup-space-5);
  grid-template-columns: repeat(auto-fit, minmax(260px, 1fr));
  align-items: stretch;
}
.sup-tier {
  position: relative;
  display: flex;
  flex-direction: column;
  background: var(--sup-surface-1);
  border: 1px solid var(--sup-border);
  border-radius: var(--sup-radius-lg);
  padding: var(--sup-space-6);
  box-shadow: var(--sup-shadow-md);
  transition: transform var(--sup-dur-slow) var(--sup-ease-out),
              border-color var(--sup-dur-slow) var(--sup-ease-out),
              box-shadow var(--sup-dur-slow) var(--sup-ease-out);
}
.sup-tier:hover {
  transform: translateY(-6px);
  border-color: var(--sup-border-strong);
  box-shadow: var(--sup-shadow-lg);
}
/* Featured: gradient border via a layered background + glow + lift. */
.sup-tier--featured {
  border-color: transparent;
  background:
    linear-gradient(var(--sup-surface-1), var(--sup-surface-1)) padding-box,
    var(--sup-gradient) border-box;
  border: 1px solid transparent;
  box-shadow: var(--sup-glow-cyan), var(--sup-shadow-lg);
}
.sup-tier--featured:hover { box-shadow: var(--sup-glow-pink), var(--sup-shadow-lg); }
.sup-tier__ribbon {
  position: absolute;
  top: 0;
  left: 50%;
  transform: translate(-50%, -50%);
  background: var(--sup-gradient);
  color: #08121d;
  font-size: var(--sup-text-xs);
  font-weight: 800;
  letter-spacing: .08em;
  text-transform: uppercase;
  padding: .4em .9em;
  border-radius: var(--sup-radius-full);
  box-shadow: var(--sup-shadow-sm);
  white-space: nowrap;
}
.sup-tier__head { margin-bottom: var(--sup-space-5); }
.sup-tier__name {
  font-family: var(--sup-font-display);
  text-transform: uppercase;
  letter-spacing: .02em;
  font-size: var(--sup-text-xl);
  margin: 0 0 var(--sup-space-3);
}
.sup-tier__price { display: flex; align-items: baseline; gap: .25rem; }
.sup-tier__amount {
  font-family: var(--sup-font-display);
  font-size: var(--sup-display-sm);
  line-height: 1;
  background: var(--sup-gradient);
  -webkit-background-clip: text;
  background-clip: text;
  color: transparent;
}
.sup-tier__period { color: var(--sup-text-muted); font-weight: 600; }
.sup-tier__blurb { color: var(--sup-text-muted); margin: var(--sup-space-3) 0 0; font-size: var(--sup-text-sm); }
.sup-tier__features {
  list-style: none;
  padding: 0;
  margin: 0 0 var(--sup-space-5);
  display: flex;
  flex-direction: column;
  gap: var(--sup-space-3);
}
.sup-tier__features li {
  position: relative;
  list-style: none;        /* the tick (::before) is the only marker — kill the
                              inherited square bullet some base styles put on <li> */
  padding-left: 1.75rem;
  color: var(--sup-text);
  font-size: var(--sup-text-sm);
  line-height: 1.4;
}
.sup-tier__features li::before {
  content: "\f00c"; /* fa-check */
  font-family: "Font Awesome 6 Free";
  font-weight: 900;
  position: absolute;
  left: 0;
  top: .05em;
  color: var(--sup-cyan);
  font-size: .85em;
}
.sup-tier__note {
  color: var(--sup-text-subtle);
  font-size: var(--sup-text-xs);
  text-align: center;
  margin: var(--sup-space-3) 0 0;
}
/* Push CTA to the bottom so cards line up regardless of feature count. */
.sup-tier__cta { margin-top: auto; width: 100%; }
.sup-tier__features + .sup-tier__cta { margin-top: auto; }

/* 5.10 Plan comparison table --------------------------------
   Rows = features, columns = tiers. Check/cross marks via the
   `.sup-compare__yes` / `.sup-compare__no` helpers. Wrap in
   `.sup-compare` (the wrapper scrolls horizontally on small screens). */
.sup-compare { width: 100%; overflow-x: auto; -webkit-overflow-scrolling: touch; }
.sup-compare table {
  width: 100%;
  border-collapse: collapse;
  min-width: 540px;
  margin: 0;
}
.sup-compare th,
.sup-compare td {
  padding: var(--sup-space-3) var(--sup-space-4);
  text-align: center;
  border-bottom: 1px solid var(--sup-border);
}
.sup-compare thead th {
  position: sticky;
  top: 0;
  background: var(--sup-surface-2);
  color: var(--sup-cream);
  font-family: var(--sup-font-display);
  text-transform: uppercase;
  letter-spacing: .03em;
  font-size: var(--sup-text-lg);
  font-weight: 400;
  z-index: var(--sup-z-raised);
}
.sup-compare thead th:first-child,
.sup-compare tbody th { text-align: left; }
.sup-compare tbody th {
  font-weight: 600;
  color: var(--sup-text);
  font-size: var(--sup-text-sm);
}
.sup-compare tbody tr:hover td,
.sup-compare tbody tr:hover th { background: rgba(255, 255, 255, .02); }
.sup-compare th.sup-compare__featured,
.sup-compare td.sup-compare__featured { background: var(--sup-gradient-soft); }
.sup-compare__yes { color: var(--sup-cyan); }
.sup-compare__yes::before { content: "\f00c"; font-family: "Font Awesome 6 Free"; font-weight: 900; }
.sup-compare__no { color: var(--sup-text-subtle); }
.sup-compare__no::before { content: "\f00d"; font-family: "Font Awesome 6 Free"; font-weight: 900; }

/* 5.11 Billing toggle ---------------------------------------
   Monthly / Annual switch. Visual only — the JS that actually swaps
   prices lives on the Premium page. The `is-annual` class on
   `.sup-toggle` slides the knob and flips the active option.

   Markup:
     <div class="sup-toggle" role="group" aria-label="Billing period">
       <button class="sup-toggle__opt is-active" type="button">Monthly</button>
       <button class="sup-toggle__opt" type="button">Annual</button>
       <span class="sup-toggle__knob" aria-hidden="true"></span>
     </div>                                                     */
.sup-toggle {
  position: relative;
  display: inline-flex;
  padding: .3rem;
  background: var(--sup-surface-1);
  border: 1px solid var(--sup-border-strong);
  border-radius: var(--sup-radius-full);
}
.sup-toggle__opt {
  position: relative;
  z-index: var(--sup-z-raised);
  appearance: none;
  background: transparent;
  border: none;
  border-radius: var(--sup-radius-full);
  padding: .5rem 1.25rem;
  font-size: var(--sup-text-sm);
  font-weight: 700;
  color: var(--sup-text-muted);
  cursor: pointer;
  transition: color var(--sup-dur) var(--sup-ease-out);
}
.sup-toggle__opt.is-active { color: #08121d; }
.sup-toggle__knob {
  position: absolute;
  top: .3rem;
  left: .3rem;
  bottom: .3rem;
  width: calc(50% - .3rem);
  background: var(--sup-gradient);
  border-radius: var(--sup-radius-full);
  box-shadow: var(--sup-shadow-sm);
  transition: transform var(--sup-dur-slow) var(--sup-ease-pop);
}
.sup-toggle.is-annual .sup-toggle__knob { transform: translateX(100%); }
.sup-toggle__save {
  margin-left: var(--sup-space-3);
  font-size: var(--sup-text-xs);
  font-weight: 700;
  color: var(--sup-cyan);
  letter-spacing: .04em;
}

/* 5.12 Stat bar ---------------------------------------------
   Row of big-number + label stats with gradient numbers.
   Markup:
     <div class="sup-stats">
       <div class="sup-stat"><span class="sup-stat__num">50+</span><span class="sup-stat__label">Products</span></div>
     </div>

   `__num--text` variant: for word-based / multi-word stat values
   (e.g. "1-click", "Let's talk", "7-day", "£0", "∞") that aren't a
   short display digit. Drops to a smaller, semi-condensed size and
   wraps gracefully so long values stay tidy inside the 140px min
   column without the giant display font breaking the row rhythm.
   Markup:
     <span class="sup-stat__num sup-stat__num--text">1-click</span>     */
.sup-stats {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(140px, 1fr));
  gap: var(--sup-space-5);
  padding: var(--sup-space-6);
  background: var(--sup-surface-1);
  border: 1px solid var(--sup-border);
  border-radius: var(--sup-radius-lg);
  text-align: center;
}
/* Flat variant: not a bordered panel — a divider-separated row of stats
   sitting on the page. Use where stats are a quiet supporting band (e.g.
   the home page) rather than a boxed feature. */
.sup-stats--flat {
  background: none;
  border: none;
  border-block: 1px solid var(--sup-border);
  border-radius: 0;
  padding-block: var(--sup-space-5);
  padding-inline: 0;
}
.sup-stats--flat .sup-stat + .sup-stat {
  /* hairline dividers between stats on wider screens */
  position: relative;
}
@media (min-width: 720px) {
  .sup-stats--flat { gap: 0; }
  .sup-stats--flat .sup-stat { padding-inline: var(--sup-space-5); }
  .sup-stats--flat .sup-stat + .sup-stat {
    border-left: 1px solid var(--sup-border);
  }
}
.sup-stat { display: flex; flex-direction: column; gap: var(--sup-space-2); }
.sup-stat__num {
  font-family: var(--sup-font-display);
  font-size: var(--sup-display-sm);
  line-height: 1;
  background: var(--sup-gradient);
  -webkit-background-clip: text;
  background-clip: text;
  color: transparent;
}
/* Word-based stat values: smaller, tighter, wraps neatly so multi-word
   text doesn't overflow / get dwarfed beside the large display digits. */
.sup-stat__num--text {
  font-size: clamp(1.35rem, 2.6vw, 1.85rem);
  letter-spacing: .01em;
  line-height: 1.1;
  overflow-wrap: anywhere;
  hyphens: auto;
}
.sup-stat__label {
  font-size: var(--sup-text-sm);
  color: var(--sup-text-muted);
  letter-spacing: .04em;
  text-transform: uppercase;
}

/* 5.13 Testimonial card -------------------------------------
   Quote + handle/avatar + optional platform tag. Drop inside a
   `.sup-grid`. Markup:
     <figure class="sup-quote">
       <blockquote>"Game-changer for my stream."</blockquote>
       <figcaption class="sup-quote__by">
         <img class="sup-quote__avatar" src="..." alt="" />
         <span class="sup-quote__handle">@@streamer</span>
         <span class="sup-badge sup-quote__platform">Twitch</span>
       </figcaption>
     </figure>                                                  */
.sup-quote {
  display: flex;
  flex-direction: column;
  gap: var(--sup-space-4);
  background: var(--sup-surface-1);
  border: 1px solid var(--sup-border);
  border-radius: var(--sup-radius-lg);
  padding: var(--sup-space-5);
  box-shadow: var(--sup-shadow-md);
  margin: 0;
}
.sup-quote::before {
  content: "\201C";
  font-family: var(--sup-font-display);
  font-size: 3rem;
  line-height: .5;
  color: var(--sup-pink);
  height: 1.2rem;
}
.sup-quote blockquote {
  margin: 0;
  padding: 0;
  border: none;
  font-size: var(--sup-text-lg);
  color: var(--sup-text);
  line-height: 1.5;
}
.sup-quote__by {
  display: flex;
  align-items: center;
  gap: var(--sup-space-3);
  margin-top: auto;
}
.sup-quote__avatar {
  width: 2.5rem;
  height: 2.5rem;
  border-radius: var(--sup-radius-full);
  object-fit: cover;
  flex: 0 0 auto;
  border: 1px solid var(--sup-border-strong);
}
.sup-quote__handle { font-weight: 700; color: var(--sup-text); }
.sup-quote__platform { margin-left: auto; }

/* 5.14 FAQ accordion ----------------------------------------
   Styled native <details>/<summary>. Animated open via grid-rows.
   Markup:
     <div class="sup-faq">
       <details class="sup-faq__item">
         <summary>Can I cancel anytime?</summary>
         <div class="sup-faq__body"><p>Yes — cancel whenever.</p></div>
       </details>
     </div>                                                     */
.sup-faq { display: flex; flex-direction: column; gap: var(--sup-space-3); }
.sup-faq__item {
  background: var(--sup-surface-1);
  border: 1px solid var(--sup-border);
  border-radius: var(--sup-radius-md);
  overflow: hidden;
  transition: border-color var(--sup-dur) var(--sup-ease-out);
}
.sup-faq__item[open] { border-color: var(--sup-border-strong); }
.sup-faq__item > summary {
  list-style: none;
  cursor: pointer;
  padding: var(--sup-space-4) var(--sup-space-5);
  font-weight: 700;
  color: var(--sup-text);
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--sup-space-4);
}
.sup-faq__item > summary::-webkit-details-marker { display: none; }
.sup-faq__item > summary::after {
  content: "\f078"; /* fa-chevron-down */
  font-family: "Font Awesome 6 Free";
  font-weight: 900;
  font-size: .75em;
  color: var(--sup-cyan);
  flex: 0 0 auto;
  transition: transform var(--sup-dur) var(--sup-ease-out);
}
.sup-faq__item[open] > summary::after { transform: rotate(180deg); }
/* Animated reveal: collapse via a grid track that opens to 1fr. */
.sup-faq__body {
  display: grid;
  grid-template-rows: 0fr;
  transition: grid-template-rows var(--sup-dur-slow) var(--sup-ease-out);
}
.sup-faq__item[open] .sup-faq__body { grid-template-rows: 1fr; }
.sup-faq__body > * {
  overflow: hidden;
  margin: 0;
  padding: 0 var(--sup-space-5);
  color: var(--sup-text-muted);
}
.sup-faq__item[open] .sup-faq__body > * { padding-bottom: var(--sup-space-5); }

/* 5.15 Feature grid item ------------------------------------
   FontAwesome icon + benefit headline + one line. Use in a `.sup-grid`.
   Markup:
     <div class="sup-feature">
       <span class="sup-feature__icon"><i class="fa-solid fa-bolt"></i></span>
       <h3 class="sup-feature__title">Built for OBS</h3>
       <p class="sup-feature__text">Native performance, not browser sources.</p>
     </div>                                                     */
.sup-feature {
  display: flex;
  flex-direction: column;
  gap: var(--sup-space-3);
  padding: var(--sup-space-5);
  background: var(--sup-surface-1);
  border: 1px solid var(--sup-border);
  border-radius: var(--sup-radius-lg);
  transition: transform var(--sup-dur-slow) var(--sup-ease-out),
              border-color var(--sup-dur-slow) var(--sup-ease-out);
}
.sup-feature:hover { transform: translateY(-4px); border-color: var(--sup-border-strong); }
.sup-feature__icon {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 3rem;
  height: 3rem;
  border-radius: var(--sup-radius-md);
  background: var(--sup-gradient-soft);
  color: var(--sup-cyan);
  font-size: 1.35rem;
}
.sup-feature__title { margin: 0; font-size: var(--sup-text-lg); }
.sup-feature__text { margin: 0; color: var(--sup-text-muted); font-size: var(--sup-text-sm); line-height: 1.5; }

/* 5.15a Bento feature tiles ---------------------------------
   Lighter alternative to a row of identical bordered .sup-feature
   cards. Tiles are FLAT (no border, no card fill) so they read as
   content blocks on the page, not boxes. Hierarchy comes from one
   `--feature` tile carrying a soft gradient wash instead of every
   tile being a card. Use for "why us" / "what you get" grids.
   Markup:
     <div class="sup-bento">
       <div class="sup-bento__tile sup-bento__tile--feature">
         <span class="sup-bento__icon"><i class="fa-solid fa-bolt"></i></span>
         <h3 class="sup-bento__title">Built for OBS</h3>
         <p class="sup-bento__text">…</p>
       </div>
       <div class="sup-bento__tile"> … </div>
     </div>                                                     */
.sup-bento {
  display: grid;
  gap: var(--sup-space-3);
  grid-template-columns: repeat(2, 1fr);
}
@media (min-width: 880px) {
  .sup-bento { grid-template-columns: repeat(3, 1fr); }
  .sup-bento--4 { grid-template-columns: repeat(4, 1fr); }
}
.sup-bento__tile {
  display: flex;
  flex-direction: column;
  gap: var(--sup-space-2);
  padding: var(--sup-space-5);
  border-radius: var(--sup-radius-lg);
  transition: background var(--sup-dur) var(--sup-ease-out);
}
.sup-bento__tile:hover { background: var(--sup-surface-1); }
/* The one emphasised tile: soft gradient wash + hairline, no full card. */
.sup-bento__tile--feature {
  background: linear-gradient(150deg, var(--sup-gradient-soft), transparent 70%), var(--sup-surface-1);
  border: 1px solid var(--sup-border);
}
.sup-bento__tile--feature:hover { background: linear-gradient(150deg, var(--sup-gradient-soft), transparent 70%), var(--sup-surface-1); }
/* On wide screens the feature tile can span two columns so the grid
   reads as bento (mixed weights) rather than a uniform row. */
@media (min-width: 880px) {
  .sup-bento__tile--wide { grid-column: span 2; }
}
.sup-bento__icon {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 2.75rem;
  height: 2.75rem;
  border-radius: var(--sup-radius-md);
  background: var(--sup-gradient-soft);
  color: var(--sup-cyan);
  font-size: 1.2rem;
  margin-bottom: var(--sup-space-1);
}
/* Image-based bento icon (e.g. the Streamer.bot logo) instead of a font glyph.
   The logo carries its own colour, so it sits in the same soft box but ignores
   the cyan text colour. */
.sup-bento__icon--img img {
  width: 1.6rem;
  height: 1.6rem;
  object-fit: contain;
  display: block;
}
.sup-bento__title { margin: 0; font-size: var(--sup-text-lg); }
.sup-bento__text { margin: 0; color: var(--sup-text-muted); font-size: var(--sup-text-sm); line-height: 1.5; }

/* 5.15b Numbered step flow ----------------------------------
   For "how it works" sequences. A gradient-soft numbered badge per
   step, then title + text — no card borders, so three steps read as
   a flow, not three more cards.
   Markup:
     <ol class="sup-steps">
       <li class="sup-step">
         <span class="sup-step__num">1</span>
         <h3 class="sup-step__title">Subscribe</h3>
         <p class="sup-step__text">…</p>
       </li>
     </ol>                                                      */
.sup-steps {
  list-style: none;
  margin: 0;
  padding: 0;
  display: grid;
  gap: var(--sup-space-5);
  grid-template-columns: repeat(auto-fit, minmax(220px, 1fr));
}
.sup-step {
  display: flex;
  flex-direction: column;
  gap: var(--sup-space-3);
}
.sup-step__num {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 2.75rem;
  height: 2.75rem;
  flex: 0 0 auto;
  border-radius: var(--sup-radius-full);
  background: var(--sup-gradient-soft);
  border: 1px solid var(--sup-border-strong);
  font-family: var(--sup-font-display);
  font-size: var(--sup-text-xl);
  line-height: 1;
  color: var(--sup-cyan);
}
.sup-step__title { margin: 0; font-size: var(--sup-text-lg); }
.sup-step__text { margin: 0; color: var(--sup-text-muted); font-size: var(--sup-text-sm); line-height: 1.5; }

/* 5.15c Rundown list ----------------------------------------
   A compact, scannable list (icon · name · one line · trailing meta)
   separated by hairlines instead of a grid of cards. Built for the
   "here's the whole plugin suite" showcase where seven cards was too
   many boxes. Two columns on wide screens.
   Markup:
     <ul class="sup-rundown">
       <li class="sup-rundown__item">
         <span class="sup-rundown__icon"><i class="fa-solid fa-box"></i></span>
         <div class="sup-rundown__body">
           <h3 class="sup-rundown__name">StreamUP</h3>
           <p class="sup-rundown__desc">…</p>
         </div>
         <span class="sup-rundown__meta"><span class="sup-badge sup-badge--free">Free</span></span>
       </li>
     </ul>                                                      */
.sup-rundown {
  list-style: none;
  margin: 0;
  padding: 0;
  display: grid;
  grid-template-columns: 1fr;
  column-gap: var(--sup-space-6);
}
@media (min-width: 760px) {
  .sup-rundown--2col { grid-template-columns: 1fr 1fr; }
}
.sup-rundown__item {
  display: flex;
  align-items: center;
  gap: var(--sup-space-4);
  padding: var(--sup-space-4) var(--sup-space-3);
  margin-inline: calc(var(--sup-space-3) * -1);
  border-top: 1px solid var(--sup-border);
  border-radius: var(--sup-radius-md);
  transition: background var(--sup-dur) var(--sup-ease-out);
}
/* Hover-reveal: the row warms slightly and its icon picks up the brand
   wash, signalling the whole row is a live entry. Restrained, no motion. */
.sup-rundown__item:hover { background: var(--sup-surface-1); }
.sup-rundown__icon { transition: background var(--sup-dur) var(--sup-ease-out), color var(--sup-dur) var(--sup-ease-out); }
.sup-rundown__item:hover .sup-rundown__icon { background: var(--sup-gradient); color: #08121d; }
.sup-rundown__icon {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 2.5rem;
  height: 2.5rem;
  flex: 0 0 auto;
  border-radius: var(--sup-radius-md);
  background: var(--sup-gradient-soft);
  color: var(--sup-cyan);
  font-size: 1.05rem;
}
.sup-rundown__icon img { width: 1.4rem; height: 1.4rem; object-fit: contain; }
.sup-rundown__body { flex: 1 1 auto; min-width: 0; }
.sup-rundown__name { margin: 0; font-size: var(--sup-text-base); font-weight: 700; }
.sup-rundown__desc { margin: 2px 0 0; color: var(--sup-text-muted); font-size: var(--sup-text-sm); line-height: 1.45; }
.sup-rundown__meta { flex: 0 0 auto; display: inline-flex; align-items: center; gap: var(--sup-space-3); }

/* 5.15d Roster ----------------------------------------------
   Team / people as flat horizontal rows (photo + name + handle +
   one-line bio + socials), not a grid of profile cards.
   Markup:
     <div class="sup-roster">
       <div class="sup-roster__member">
         <img class="sup-roster__photo" src="…" alt="…">
         <div class="sup-roster__body">
           <h3 class="sup-roster__name">Andi</h3>
           <span class="sup-roster__handle">/Andilippi</span>
           <p class="sup-roster__bio">…</p>
         </div>
       </div>
     </div>                                                     */
.sup-roster {
  display: grid;
  gap: var(--sup-space-5) var(--sup-space-6);
  grid-template-columns: repeat(auto-fill, minmax(300px, 1fr));
}
.sup-roster__member { display: flex; align-items: flex-start; gap: var(--sup-space-4); }
.sup-roster__photo {
  width: 3.5rem;
  height: 3.5rem;
  flex: 0 0 auto;
  border-radius: var(--sup-radius-full);
  object-fit: cover;
  border: 1px solid var(--sup-border-strong);
}
.sup-roster__body { min-width: 0; }
.sup-roster__name { margin: 0; font-size: var(--sup-text-base); font-weight: 700; display: inline; }
.sup-roster__handle { color: var(--sup-text-subtle); font-size: var(--sup-text-sm); margin-left: var(--sup-space-2); }
.sup-roster__bio { margin: var(--sup-space-2) 0 var(--sup-space-2); color: var(--sup-text-muted); font-size: var(--sup-text-sm); line-height: 1.45; }
.sup-roster__link { font-size: var(--sup-text-sm); font-weight: 600; }

/* Feature variant. The default roster is a compact row for a credits list;
   this makes the people the subject of the section: a large square portrait
   with the name and bio stacked under it. Source photos are 1:1, so nothing
   is cropped. Add `.sup-roster--feature` alongside `.sup-roster`. */
/* Explicit column counts rather than auto-fit: a 4-person team on an
   auto-fit grid lands on 3 across at common widths and leaves the fourth
   person sitting alone on a row of their own. 1, then 2, then 4. */
.sup-roster--feature {
  grid-template-columns: 1fr;
  gap: var(--sup-space-7) var(--sup-space-6);
}
@media (min-width: 560px) {
  .sup-roster--feature { grid-template-columns: repeat(2, 1fr); }
}
@media (min-width: 1000px) {
  .sup-roster--feature { grid-template-columns: repeat(4, 1fr); }
}
.sup-roster--feature .sup-roster__member {
  display: flex;
  flex-direction: column;
  align-items: stretch;
  gap: var(--sup-space-4);
}
.sup-roster--feature .sup-roster__photo {
  width: 100%;
  height: auto;
  aspect-ratio: 1 / 1;
  border-radius: var(--sup-radius-lg);
  border: 1px solid var(--sup-border);
  transition: border-color var(--sup-dur-slow) var(--sup-ease-out),
              transform var(--sup-dur-slow) var(--sup-ease-out);
}
.sup-roster--feature .sup-roster__member:hover .sup-roster__photo {
  border-color: var(--sup-border-strong);
  transform: translateY(-4px);
}
.sup-roster--feature .sup-roster__name {
  display: block;
  font-family: var(--sup-font-display);
  font-size: var(--sup-display-xs, 1.75rem);
  font-weight: 400;
  line-height: 1;
  color: var(--sup-cream);
}
.sup-roster--feature .sup-roster__handle {
  display: block;
  margin-left: 0;
  margin-top: var(--sup-space-1);
}
.sup-roster--feature .sup-roster__bio {
  font-size: var(--sup-text-base);
  line-height: 1.55;
  margin-block: var(--sup-space-3) var(--sup-space-3);
}
@media (prefers-reduced-motion: reduce) {
  .sup-roster--feature .sup-roster__photo { transition-duration: var(--sup-dur-slow) !important; }
}

/* 5.16 CTA banner -------------------------------------------
   Full-width gradient-edged panel: heading + button. For
   "all 50+ for £5/mo" style nudges.
   Markup:
     <div class="sup-cta-banner">
       <div class="sup-cta-banner__text">
         <h2>Get all 50+ products</h2>
         <p>Every overlay, alert and effect — £5/mo.</p>
       </div>
       <a role="button" class="primary">See Premium</a>
     </div>                                                     */
.sup-cta-banner {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: var(--sup-space-5);
  padding: var(--sup-space-6) var(--sup-space-7);
  border-radius: var(--sup-radius-lg);
  border: 1px solid transparent;
  background:
    linear-gradient(var(--sup-surface-1), var(--sup-surface-1)) padding-box,
    var(--sup-gradient) border-box;
  box-shadow: var(--sup-shadow-md);
}
/* Slim one-line variant: a compact gradient-edged strip (heading + line
   on one row, button on the right) for places where a full banner would
   push real content too far down — e.g. the top of the Products page. */
.sup-cta-banner--slim {
  padding: var(--sup-space-3) var(--sup-space-5);
  gap: var(--sup-space-4);
}
.sup-cta-banner--slim .sup-cta-banner__text {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: var(--sup-space-1) var(--sup-space-3);
}
.sup-cta-banner--slim .sup-cta-banner__text h2 {
  font-size: var(--sup-text-xl);
  margin: 0;
}
.sup-cta-banner--slim .sup-cta-banner__text p { font-size: var(--sup-text-sm); }
.sup-cta-banner__text { flex: 1 1 320px; }
.sup-cta-banner__text h2 { margin: 0 0 var(--sup-space-2); font-size: var(--sup-display-sm); }
.sup-cta-banner__text p { margin: 0; color: var(--sup-text-muted); }
/* On phones, collapse the most-repeated CTA into a tidy centred stack:
   text centres above a full-width action instead of an unbalanced
   left-aligned heading with the button dropped beneath it. */
@media (max-width: 540px) {
  .sup-cta-banner {
    text-align: center;
    justify-content: center;
  }
  .sup-cta-banner a,
  .sup-cta-banner button {
    width: 100%;
  }
}

/* 5.17 Plugin card ------------------------------------------
   For the free OBS plugin suite: icon/logo, name, one-line, Free
   badge, link.
   Markup:
     <article class="sup-plugin">
       <span class="sup-plugin__icon"><i class="fa-solid fa-wand-magic-sparkles"></i></span>
       <div class="sup-plugin__body">
         <h3 class="sup-plugin__name">Scene As Transition</h3>
         <p class="sup-plugin__desc">Use any scene as a transition.</p>
       </div>
       <footer class="sup-plugin__foot">
         <span class="sup-badge sup-badge--free">Free</span>
         <a href="#">GitHub</a>
       </footer>
     </article>                                                 */
.sup-plugin {
  display: flex;
  flex-direction: column;
  gap: var(--sup-space-4);
  padding: var(--sup-space-5);
  background: var(--sup-surface-1);
  border: 1px solid var(--sup-border);
  border-radius: var(--sup-radius-lg);
  box-shadow: var(--sup-shadow-md);
  transition: transform var(--sup-dur-slow) var(--sup-ease-out),
              border-color var(--sup-dur-slow) var(--sup-ease-out),
              box-shadow var(--sup-dur-slow) var(--sup-ease-out);
}
.sup-plugin:hover {
  transform: translateY(-5px);
  border-color: var(--sup-border-strong);
  box-shadow: var(--sup-shadow-lg);
}
.sup-plugin__icon {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 2.75rem;
  height: 2.75rem;
  border-radius: var(--sup-radius-md);
  background: var(--sup-surface-2);
  color: var(--sup-cyan);
  font-size: 1.2rem;
  flex: 0 0 auto;
}
.sup-plugin__icon img { width: 1.5rem; height: 1.5rem; object-fit: contain; }
.sup-plugin__body { flex: 1 1 auto; }
.sup-plugin__name { margin: 0 0 var(--sup-space-2); font-size: var(--sup-text-lg); }
.sup-plugin__desc { margin: 0; color: var(--sup-text-muted); font-size: var(--sup-text-sm); line-height: 1.5; }
.sup-plugin__foot {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--sup-space-3);
  margin-top: auto;
}

/* 5.18 "Included with Premium" badge ------------------------
   A `.sup-badge` variant for product cards / upsell framing. Has a
   small premium glyph. Use `.sup-badge--included`. */
.sup-badge--included {
  background: var(--sup-gradient-soft);
  color: var(--sup-cyan);
  border: 1px solid rgba(106, 244, 255, .4);
}
.sup-badge--included::before {
  content: "\f00c"; /* fa-check */
  font-family: "Font Awesome 6 Free";
  font-weight: 900;
  font-size: .85em;
}

/* 5.19 Compact sticky nav bar -------------------------------
   G3 — the site header was bare Pico <header><nav> (~82px tall, no
   bar, links floating on the page). This gives it a real compact
   sticky bar: ~58px, blurred translucent surface, 1px bottom border,
   inner content capped to the container width, balanced logo/links.
   Applied via `.sup-nav` on the <header> in _Layout.cshtml. The
   existing active-underline + Premium pill styles live in the layout. */
.sup-nav {
  position: sticky;
  top: 0;
  z-index: var(--sup-z-sticky);
  padding: 0;          /* Pico gives <header> generous block padding — kill it */
  margin: 0;
  background: color-mix(in srgb, var(--sup-surface-1) 85%, transparent);
  -webkit-backdrop-filter: blur(10px);
  backdrop-filter: blur(10px);
  border-bottom: 1px solid var(--sup-border);
  transition: padding var(--sup-dur) var(--sup-ease-out),
              background var(--sup-dur) var(--sup-ease-out);
}
.sup-nav > nav {
  max-width: var(--sup-container-wide);
  margin-inline: auto;
  padding-inline: var(--sup-space-4);
  min-height: 50px;          /* one static height — does not shrink on scroll */
  --pico-nav-element-spacing-vertical: 0.5rem;
}
/* Vertically centre every item in the bar (logo, links, pill, login button)
   so nothing sits high or low regardless of its own box height. Centre the
   list rows only — do NOT set `display` on the <li>s, or it overrides the
   .mobile-only / .not-mobile show-hide and the mobile Menu + logo leak onto
   desktop. */
.sup-nav nav > ul { align-items: center; }
/* Slightly bigger, balanced logo against the small links. */
.sup-nav .header-logo { height: 1.5rem; }
/* Nav links: calm, consistent sizing + hover. */
.sup-nav nav a.secondary {
  font-size: var(--sup-text-sm);
  font-weight: 600;
  padding-inline: var(--sup-space-2);
  transition: color var(--sup-dur) var(--sup-ease-out);
}
.sup-nav nav a.secondary:hover { color: var(--sup-text); }
/* The dropdown summaries (mobile Menu, Account) match link sizing. */
.sup-nav nav summary { font-size: var(--sup-text-sm); font-weight: 600; }
/* Login (and any nav button) + the Premium pill share one compact control
   height: inline-flex centring with line-height:1 stops Pico's tall default
   line box from making them taller than the surrounding links. */
.sup-nav nav [role="button"],
.sup-nav nav button,
.sup-nav nav a.nav-premium {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: .45rem;
  line-height: 1;
  padding-block: .35rem;
  padding-inline: .9rem;
  font-size: var(--sup-text-sm);
  min-height: 0;
}
/* Login: the leading icon picks up the cyan accent so the button reads as the
   one sign-in action without shouting. */
.sup-nav nav a.nav-login i { color: var(--sup-cyan); font-size: .85em; }
/* Once the page scrolls, only the surface deepens — the bar height is fixed. */
.sup-nav.is-scrolled {
  background: color-mix(in srgb, var(--sup-surface-1) 92%, transparent);
  box-shadow: var(--sup-shadow-sm);
}
/* Mobile (≤767px): the bar shows the Menu trigger + logo + Login. Give the
   drawer items comfortable ≥44px tap targets and keep the bar gutters tidy. */
@media only screen and (max-width: 767px) {
  .sup-nav > nav { padding-inline: var(--sup-space-3); }
  .sup-nav nav .dropdown.menu summary { padding-block: .6rem; }
  .sup-nav nav .dropdown ul li a,
  .sup-nav nav .dropdown ul li a.secondary {
    display: block;
    padding-block: .7rem;          /* ~44px row height */
    font-size: var(--sup-text-base);
  }
  /* Premium pill spans the drawer row so it reads as the primary action. */
  .sup-nav nav .dropdown ul li a.nav-premium { text-align: center; }
}

/* ============================================================
   5E. EDITORIAL LAYER (v0.6)
   ------------------------------------------------------------
   Ported from the andistonemedia visual language. The philosophy,
   in order:
     1. Typography carries the page (big display titles, disciplined
        eyebrows, restrained body).
     2. Surfaces are SHARED, not individual — related items sit on one
        surface divided by hairlines, never a grid of bordered cards.
     3. Containment is earned — a box exists only to frame media
        (video/image) or a functional chip, never as decoration
        around text.
   One cream `.sup-panel--cream` punctuates the dark per page; feathered
   shadows live only on `.sup-frame`. PREFER these over the boxed
   components (5.2/5.9/5.13/5.15/5.17) for new + marketing layout — those
   are kept for back-compat but deprecated for editorial pages.
   ============================================================ */

/* 5E.1 Full-bleed panel --------------------------------------
   Breaks out of `main.container` to span the viewport, then re-centres
   its content to the container width. Lets a section own a full-width
   background band (flat dark by default, or the cream variant).
   Markup:
     <section class="sup-bleed sup-panel sup-panel--cream">
       <div class="sup-panel__inner sup-editorial"> … </div>
     </section>                                                 */
.sup-bleed { width: 100vw; margin-inline: calc(50% - 50vw); }
.sup-panel { position: relative; }
.sup-panel__inner {
  max-width: var(--sup-container);
  margin-inline: auto;
  padding: clamp(2.5rem, 5vw, 4rem) var(--sup-space-4);
}
.sup-panel--wide .sup-panel__inner { max-width: var(--sup-container-wide); }

/* Cream variant — the single deliberate light moment. Recolours headings,
   eyebrows, body, links, hairlines and outline buttons for the light
   surface. Keep to 1× per page so it stays special. */
.sup-panel--cream {
  background-color: var(--sup-cream-bg);
  color: var(--sup-cream-ink-medium);
  --sup-hairline: var(--sup-cream-line);
}
.sup-panel--cream h1, .sup-panel--cream h2, .sup-panel--cream h3,
.sup-panel--cream h4, .sup-panel--cream .sup-display { color: var(--sup-cream-ink); }
.sup-panel--cream p, .sup-panel--cream li { color: var(--sup-cream-ink-medium); }
.sup-panel--cream .sup-eyebrow { color: var(--sup-cream-ink-muted); }
.sup-panel--cream a:not([role="button"]) { color: var(--sup-cream-link); }
.sup-panel--cream a:not([role="button"]):hover { color: var(--sup-cream-ink); }
.sup-panel--cream .sup-lede { color: var(--sup-cream-ink-medium); }
/* Outline button on cream: dark ink instead of light text. */
.sup-panel--cream [role="button"].secondary.outline,
.sup-panel--cream [role="button"].outline,
.sup-panel--cream button.outline {
  border-color: rgba(24, 24, 56, .25);
  color: var(--sup-cream-ink);
}
.sup-panel--cream [role="button"].outline:hover,
.sup-panel--cream button.outline:hover {
  border-color: var(--sup-cream-link);
  color: var(--sup-cream-link);
  box-shadow: 0 0 0 3px rgba(12, 111, 125, .12);
}

/* 5E.2 Editorial head + typographic utilities ---------------
   The canonical eyebrow → big title → lede stack, left-aligned, with a
   readable measure. Use on a section's intro instead of the small,
   centred `.sup-section__head` when the section should read editorially. */
.sup-editorial > .sup-editorial__head,
.sup-editorial__head { max-width: 60ch; margin-bottom: var(--sup-space-6); }
.sup-editorial__head h1,
.sup-editorial__head h2 { font-size: var(--sup-display-md); margin: var(--sup-space-2) 0 var(--sup-space-3); }

/* Centred variant. `text-align: center` on its own is not enough: the head
   is capped at 60ch and the lede at 56ch with no auto margin, so the text
   centres inside a box still hugging the left edge, which reads as a
   left-aligned section. Centre the boxes as well as the text. */
.sup-editorial__head--centred { margin-inline: auto; text-align: center; }
.sup-editorial__head--centred > *,
.sup-editorial__head--centred .sup-lede { margin-inline: auto; }
.sup-lede {
  font-size: var(--sup-text-lg);
  color: var(--sup-text-muted);
  line-height: 1.6;
  max-width: 56ch;
  margin: 0;
}
/* Inline "learn more" arrow link — the default in-copy CTA (no pill). */
.sup-arrow { font-weight: 600; white-space: nowrap; }
.sup-arrow::after { content: " \2192"; transition: margin var(--sup-dur) var(--sup-ease-out); }
.sup-arrow:hover::after { margin-left: .25rem; }

/* 5E.3 Shelf — shared surface, hairline-divided columns ------
   Replaces a row of bordered cards (why-us, pricing, value props). Items
   sit on the page surface; cyan hairlines do the structural work. No
   per-item border/background/shadow.
   Markup:
     <div class="sup-shelf sup-shelf--3">
       <div class="sup-shelf__item"> … </div> …
     </div>                                                     */
.sup-shelf {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(220px, 1fr));
}
.sup-shelf--2,
.sup-shelf--3,
.sup-shelf--4 { grid-template-columns: 1fr; }
.sup-shelf > * { padding: var(--sup-space-5); }
@media (max-width: 719px) {
  .sup-shelf > * + * { border-top: 1px solid var(--sup-hairline); }
}
@media (min-width: 720px) {
  .sup-shelf--2 { grid-template-columns: repeat(2, 1fr); }
  .sup-shelf--3 { grid-template-columns: repeat(3, 1fr); }
  .sup-shelf--4 { grid-template-columns: repeat(2, 1fr); }
  .sup-shelf > * + * { border-left: 1px solid var(--sup-hairline); }
  /* 4-up shelves keep a hairline on the left column of the lower row too;
     re-establish the top hairline for items that wrap onto a second row. */
  .sup-shelf--4 > *:nth-child(odd):not(:first-child) { border-top: 1px solid var(--sup-hairline); }
}
@media (min-width: 980px) {
  .sup-shelf--4 { grid-template-columns: repeat(4, 1fr); }
  .sup-shelf--4 > *:nth-child(odd):not(:first-child) { border-top: 0; }
}
.sup-shelf__icon {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 2.5rem;
  height: 2.5rem;
  margin-bottom: var(--sup-space-3);
  color: var(--sup-cyan);
  font-size: 1.3rem;
}
.sup-shelf__icon img { width: 1.6rem; height: 1.6rem; object-fit: contain; }
.sup-shelf__title { margin: 0 0 var(--sup-space-2); font-size: var(--sup-text-lg); font-weight: 700; }
.sup-shelf__text  { margin: 0; color: var(--sup-text-muted); font-size: var(--sup-text-sm); line-height: 1.55; }
.sup-panel--cream .sup-shelf__icon { color: var(--sup-cream-link); }
.sup-panel--cream .sup-shelf__text { color: var(--sup-cream-ink-medium); }

/* 5E.4 Meta rows — label + value, horizontal hairlines -------
   The editorial "breakdown" list. Always a <dl> of <div><dt><dd></div>.
   Replaces bullet lists and feature grids for spec-style content.
   Markup:
     <dl class="sup-meta">
       <div><dt>I build</dt><dd>Plugins, alerts, widgets</dd></div>
     </dl>                                                      */
.sup-meta { margin: 0; }
.sup-meta > div {
  display: flex;
  justify-content: space-between;
  align-items: baseline;
  gap: var(--sup-space-5);
  padding: var(--sup-space-4) 0;
  border-top: 1px solid var(--sup-border);
}
.sup-meta > div:last-child { border-bottom: 1px solid var(--sup-border); }
.sup-meta dt {
  font-size: var(--sup-text-xs);
  font-weight: 700;
  letter-spacing: .14em;
  text-transform: uppercase;
  color: var(--sup-text-subtle);
  flex: 0 0 auto;
}
.sup-meta dd { margin: 0; text-align: right; font-weight: 600; color: var(--sup-text); }
.sup-panel--cream .sup-meta > div { border-color: var(--sup-cream-line); }
.sup-panel--cream .sup-meta dt { color: var(--sup-cream-ink-muted); }
.sup-panel--cream .sup-meta dd { color: var(--sup-cream-ink); }

/* 5E.5 Figures — big thin numerals, hairline-separated -------
   The un-boxed stat row: large display numerals + muted uppercase labels,
   no card per stat. Use `__num--accent` to gradient-fill one hero number.
   Markup:
     <div class="sup-figures">
       <div class="sup-figure"><span class="sup-figure__num">50+</span><span class="sup-figure__label">Products</span></div>
     </div>                                                     */
.sup-figures {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(150px, 1fr));
}
.sup-figure { padding: var(--sup-space-4) var(--sup-space-5); }
@media (max-width: 719px) {
  .sup-figure + .sup-figure { border-top: 1px solid var(--sup-border); }
}
@media (min-width: 720px) {
  .sup-figure + .sup-figure { border-left: 1px solid var(--sup-border); }
}
.sup-figure__num {
  display: block;
  font-family: var(--sup-font-display);
  font-size: clamp(2.8rem, 6vw, 4.5rem);
  line-height: .9;
  letter-spacing: .01em;
  color: var(--sup-text);
}
.sup-figure__num--accent {
  background: var(--sup-gradient);
  -webkit-background-clip: text;
  background-clip: text;
  color: transparent;
}
.sup-figure__label {
  display: block;
  margin-top: var(--sup-space-2);
  font-size: var(--sup-text-xs);
  letter-spacing: .14em;
  text-transform: uppercase;
  color: var(--sup-text-muted);
}
.sup-panel--cream .sup-figure + .sup-figure { border-color: var(--sup-cream-line); }
.sup-panel--cream .sup-figure__num { color: var(--sup-cream-ink); }
.sup-panel--cream .sup-figure__label { color: var(--sup-cream-ink-muted); }

/* 5E.6 Process — numbered steps on a shared surface ----------
   "How it works" as huge thin numerals on one surface, divided by
   hairlines. Replaces the badge-and-card `.sup-steps` for editorial pages.
   Markup:
     <ol class="sup-process">
       <li><span class="sup-process__num">1</span>
           <h3 class="sup-process__title">Subscribe</h3>
           <p class="sup-process__text">…</p></li>
     </ol>                                                      */
.sup-process {
  list-style: none;
  margin: 0;
  padding: 0;
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(220px, 1fr));
}
.sup-process > li { padding: var(--sup-space-5); }
@media (max-width: 719px) {
  .sup-process > li + li { border-top: 1px solid var(--sup-border); }
}
@media (min-width: 720px) {
  .sup-process > li + li { border-left: 1px solid var(--sup-border); }
}
.sup-process__num {
  display: block;
  font-family: var(--sup-font-display);
  font-size: clamp(2.6rem, 5vw, 3.6rem);
  line-height: 1;
  color: var(--sup-cyan);
  opacity: .55;
  margin-bottom: var(--sup-space-3);
}
.sup-process__title { margin: 0 0 var(--sup-space-2); font-size: var(--sup-text-lg); font-weight: 700; }
.sup-process__text  { margin: 0; color: var(--sup-text-muted); font-size: var(--sup-text-sm); line-height: 1.55; }
.sup-panel--cream .sup-process > li + li { border-color: var(--sup-cream-line); }
.sup-panel--cream .sup-process__num { color: var(--sup-cream-link); }
.sup-panel--cream .sup-process__text { color: var(--sup-cream-ink-medium); }

/* 5E.7 Framed media — the ONLY place feathered shadows live ---
   A rounded, multi-layer-shadow frame for non-text media (video iframe,
   image, embed). The 3-layer shadow is the "feathered" treatment.
   Markup:
     <div class="sup-frame sup-frame--video"><iframe …></iframe></div>
     <figure class="sup-frame"><img …></figure>                */
.sup-frame {
  border-radius: var(--sup-radius-lg);
  overflow: hidden;
  margin: 0;
  isolation: isolate;
  transform: translateZ(0);
  /* Six layers on a decaying curve rather than 3 chunky ones. Peak alpha
     around 50% right under the frame, falling to 6% at the far edge, so it
     feathers out to nothing instead of stopping at a visible line. See the
     note on the shadow tokens for why the layers beat a single ramp here.

     No hairline: --sup-border is white at 10%, which on a dark page traces a
     light outline and reads as a halo, worst on a short wide strip where the
     22px radius makes it a pill. The screenshots have their own edges. */
  box-shadow:
    0 1px 1px rgba(3, 3, 12, .16),
    0 3px 4px rgba(3, 3, 12, .14),
    0 6px 9px rgba(3, 3, 12, .12),
    0 12px 18px rgba(3, 3, 12, .10),
    0 22px 34px rgba(3, 3, 12, .08),
    0 40px 62px rgba(3, 3, 12, .06);
}
.sup-frame > img,
.sup-frame > video,
.sup-frame > iframe { display: block; width: 100%; height: auto; border: 0; }
.sup-frame--video { aspect-ratio: 16 / 9; }
.sup-frame--video > iframe { width: 100%; height: 100%; }

/* 5E.8 Editorial two-column split ---------------------------
   A simple text-beside-media (or text-beside-list) split that stacks on
   mobile. The media column gets `.sup-split__media`; reverse order with
   `--flip`. Use for story/feature blocks instead of a row of cards. */
.sup-split {
  display: grid;
  gap: var(--sup-space-6);
  align-items: center;
}
@media (min-width: 820px) {
  .sup-split { grid-template-columns: 1fr 1fr; gap: var(--sup-space-8); }
  .sup-split--flip .sup-split__media { order: -1; }
}

/* 5E.9 Carousel — horizontal scroll-snap card row -----------
   A swipeable, scroll-snapping row for product cards (or any cards) with
   optional prev/next arrows. Cards keep their own styling; the track only
   lays them out and snaps. Wire the arrows with the small initCarousels()
   loop (querySelectorAll('.sup-carousel')); arrows self-hide at the ends.
   Markup:
     <div class="sup-carousel">
       <button class="sup-carousel__btn sup-carousel__btn--prev" …>‹</button>
       <div class="sup-carousel__track"> …cards… </div>
       <button class="sup-carousel__btn sup-carousel__btn--next" …>›</button>
     </div>                                                     */
.sup-carousel { position: relative; }
.sup-carousel__track {
  display: flex;
  gap: var(--sup-space-5);
  overflow-x: auto;
  scroll-snap-type: x mandatory;
  scroll-behavior: smooth;
  scrollbar-width: none;
  -ms-overflow-style: none;
  /* breathing room so a card's hover-lift + shadow isn't clipped */
  padding: var(--sup-space-2) var(--sup-space-1) var(--sup-space-4);
  margin-inline: calc(var(--sup-space-1) * -1);
  scroll-padding-inline: var(--sup-space-1);
}
.sup-carousel__track::-webkit-scrollbar { display: none; }
.sup-carousel__track > * {
  flex: 0 0 300px;
  scroll-snap-align: start;
}
@media (max-width: 640px) {
  .sup-carousel__track > * { flex-basis: 82%; }
}
.sup-carousel__btn {
  position: absolute;
  top: 50%;
  z-index: var(--sup-z-raised);
  width: 2.75rem;
  height: 2.75rem;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  padding: 0;
  border-radius: var(--sup-radius-full);
  background: color-mix(in srgb, var(--sup-surface-2) 88%, transparent);
  -webkit-backdrop-filter: blur(8px);
  backdrop-filter: blur(8px);
  border: 1px solid var(--sup-border-strong);
  color: var(--sup-text);
  box-shadow: var(--sup-shadow-md);
  cursor: pointer;
}
.sup-carousel__btn:hover { border-color: var(--sup-cyan); color: var(--sup-cyan); }
.sup-carousel__btn--prev { left: 0; transform: translate(-35%, -50%); }
.sup-carousel__btn--next { right: 0; transform: translate(35%, -50%); }
.sup-carousel__btn[hidden] { display: none; }
/* On narrower screens the arrows would float off-canvas; tuck them inside. */
@media (max-width: 900px) {
  .sup-carousel__btn--prev { transform: translate(4px, -50%); }
  .sup-carousel__btn--next { transform: translate(-4px, -50%); }
}
/* Bleed variant. A contained track guillotines the last visible card dead
   straight down the container edge, mid-title, which reads as a broken
   layout rather than "there is more, keep scrolling". This runs the track
   out to the viewport edges instead, so a partial card leaves the screen,
   and fades it into the gutter on the way. The first card still lines up
   with the container, and snapping still lands on the container edge.
   Add `.sup-carousel--bleed` alongside `.sup-carousel`. */
.sup-carousel--bleed {
  /* Distance from the viewport edge to the container's content edge. */
  --sup-carousel-gutter: calc(max((100vw - var(--sup-container)) / 2, 0px) + var(--sup-space-4));
}
.sup-carousel--bleed .sup-carousel__track {
  width: 100vw;
  margin-inline: calc(50% - 50vw);
  padding-inline: var(--sup-carousel-gutter);
  scroll-padding-inline-start: var(--sup-carousel-gutter);
  -webkit-mask-image: linear-gradient(to right,
              transparent 0,
              #000 var(--sup-carousel-gutter),
              #000 calc(100% - var(--sup-carousel-gutter)),
              transparent 100%);
  mask-image: linear-gradient(to right,
              transparent 0,
              #000 var(--sup-carousel-gutter),
              #000 calc(100% - var(--sup-carousel-gutter)),
              transparent 100%);
}
/* Once the track bleeds there is no space beside it to put arrows without
   covering a card, so they move above the row and sit right-aligned with the
   container, in the gap under the section head. */
.sup-carousel--bleed .sup-carousel__btn {
  top: auto;
  bottom: calc(100% + var(--sup-space-2));
  transform: none;
  width: 2.5rem;
  height: 2.5rem;
}
.sup-carousel--bleed .sup-carousel__btn--next { right: 0; left: auto; }
.sup-carousel--bleed .sup-carousel__btn--prev { right: 3rem; left: auto; }

@media (prefers-reduced-motion: reduce) {
  .sup-carousel__track { scroll-behavior: auto; }
}

/* 5E.10 Live banner -----------------------------------------
   The "X is live right now!" bar above the fold, wrapping a Twitch
   embed in a native <details>. Twitch purple is the one non-brand
   colour we allow here, because the bar IS the Twitch affordance; it
   is paired with white text rather than the dark body text, which the
   purple was never contrasty enough to carry. Opens with the same
   grid-rows reveal as the FAQ accordion (5.14) so the embed unfolds
   instead of snapping in.
   Markup:
     <details class="sup-live">
       <summary class="sup-live__bar">...</summary>
       <div class="sup-live__body"><div class="sup-live__panel">embed</div></div>
     </details>                                                 */
.sup-live {
  --sup-twitch: #9146ff;
  border-radius: var(--sup-radius-lg);
  overflow: hidden;
  margin-bottom: var(--sup-space-5);
  box-shadow: var(--sup-shadow-md);
}
.sup-live__bar {
  list-style: none;
  cursor: pointer;
  display: flex;
  align-items: center;
  gap: var(--sup-space-3);
  padding: var(--sup-space-4) var(--sup-space-5);
  background: var(--sup-twitch);
  border: 1px solid var(--sup-twitch);
  border-radius: var(--sup-radius-lg);
  color: #fff;
  font-weight: 700;
  transition: background var(--sup-dur) var(--sup-ease-out),
              border-radius var(--sup-dur) var(--sup-ease-out);
}
.sup-live__bar::-webkit-details-marker { display: none; }
/* Pico recolours a summary on focus and again while open (its accordion
   palette), which turned the label cyan the moment you clicked the bar.
   The bar is a solid purple block, so the label is white in every state. */
.sup-live > .sup-live__bar,
.sup-live > .sup-live__bar:hover,
.sup-live > .sup-live__bar:focus,
.sup-live > .sup-live__bar:focus-visible,
.sup-live[open] > .sup-live__bar,
.sup-live[open] > .sup-live__bar:not(:focus) { color: #fff; }
/* Pico also drops a `margin-bottom: var(--pico-spacing)` on an open
   summary, which is what split the bar away from the embed. */
.sup-live[open] > .sup-live__bar { margin-bottom: 0; }
.sup-live__bar:hover { background: color-mix(in srgb, var(--sup-twitch) 85%, #fff); }
/* Square off the bottom corners only once the panel is actually there. */
.sup-live[open] > .sup-live__bar {
  border-end-start-radius: 0;
  border-end-end-radius: 0;
}
.sup-live__bar > i { font-size: 1.1em; }
/* Chevron sits hard right and flips on open. */
.sup-live__bar::after {
  /* Pico paints its own chevron here as a fixed-colour background SVG
     and floats it; switch that off so ours is the only one. */
  content: "\f078"; /* fa-chevron-down */
  font-family: "Font Awesome 6 Free";
  font-weight: 900;
  font-size: .8em;
  background-image: none;
  float: none;
  display: inline-block;
  width: auto;
  height: auto;
  margin-inline-start: auto;
  flex: 0 0 auto;
  transition: transform var(--sup-dur) var(--sup-ease-out);
}
.sup-live[open] > .sup-live__bar::after { transform: rotate(180deg); }
/* Animated reveal: a grid track that opens from 0fr to 1fr, so the
   panel unfolds at its natural height without a hard-coded max-height. */
.sup-live__body {
  display: grid;
  grid-template-rows: 0fr;
  opacity: 0;
  transition: grid-template-rows var(--sup-dur-slow) var(--sup-ease-out),
              opacity var(--sup-dur-slow) var(--sup-ease-out);
}
.sup-live[open] > .sup-live__body { grid-template-rows: 1fr; opacity: 1; }
/* A native <details> yanks its content out of the render tree the instant
   `open` is removed, so a closing transition never gets to run. site.js holds
   `open` on until this collapse finishes, flagging the element meanwhile. */
.sup-live.is-closing > .sup-live__body { grid-template-rows: 0fr; opacity: 0; }
.sup-live.is-closing > .sup-live__bar {
  border-end-start-radius: var(--sup-radius-lg);
  border-end-end-radius: var(--sup-radius-lg);
}
.sup-live.is-closing > .sup-live__bar::after { transform: rotate(0deg); }
.sup-live__panel {
  overflow: hidden;
  background: var(--sup-surface-1);
  border: 1px solid var(--sup-border);
  border-top: 0;
  border-end-start-radius: var(--sup-radius-lg);
  border-end-end-radius: var(--sup-radius-lg);
}
/* The Twitch iframe is a replaced element and ignores the parent's
   radius, so clip it on its own wrapper. */
.sup-live__panel > div { overflow: hidden; }
/* Loader and embed share one grid cell, so the panel is already the right
   height before Twitch answers and the player crossfades in on top of the
   shimmer instead of popping into an empty box. The 720px matches the
   height the embed is created at in the LiveOverview component. */
.sup-live__stage { display: grid; }
.sup-live__stage > * { grid-area: 1 / 1; min-width: 0; }
.sup-live__loader {
  height: 720px;
  border-radius: 0;
  transition: opacity var(--sup-dur-slow) var(--sup-ease-out);
}
.sup-live__embed {
  opacity: 0;
  transition: opacity var(--sup-dur-slow) var(--sup-ease-out);
}
.sup-live__stage.is-ready > .sup-live__loader { opacity: 0; pointer-events: none; }
.sup-live__stage.is-ready > .sup-live__embed { opacity: 1; }

/* A full-bleed panel as the last thing on a page left the container's own
   bottom padding showing as an empty dark band above the footer. Close the
   gap so the panel runs straight into it. */
/* Three separate Pico defaults stack up under a closing panel: the section's
   own margin, the container's bottom padding and the footer's top margin. All
   three have to go, or the panel still floats above the footer on a band of
   background. Tested against the home page, where the last SECTION is the
   panel (a trailing <script> means :last-child would never match). */
main.container:has(> section:last-of-type.sup-bleed) { padding-bottom: 0 !important; }
/* Pull the panel down over the container's own bottom padding. Zeroing that
   padding through :has() reads correctly in the cascade but Chrome does not
   always recompute it, so the panel does the work from its own side. */
main.container > section.sup-bleed:last-of-type {
  margin-bottom: calc(-1 * var(--pico-block-spacing-vertical, 0px)) !important;
}
main.container:has(> section:last-of-type.sup-bleed) + .sup-footer { margin-top: 0; }

/* Product body media. Screenshots and clips inside a Notion product body get
   the framed-media treatment and a real caption, so a product page reads as a
   designed page rather than a text post with attachments. */
.product-body__figure {
  margin-block: var(--sup-space-6);
  margin-inline: 0;
}
.product-body__figure img {
  display: block;
  width: 100%;
  height: auto;
}
.product-body__figure figcaption {
  margin-top: var(--sup-space-3);
  font-size: var(--sup-text-sm);
  color: var(--sup-text-muted);
  text-align: center;
}

/* ---------- 5F. LINE BREAKS ----------
   Copy was breaking in places that split an idea in half: a heading
   with one word stranded on its own line, a lede ending "Free, and /
   open source.", "one-file" broken across lines at the hyphen. Browsers
   only look at where a line runs out, not at where a sentence makes
   sense, so give them better instructions and take manual control where
   the meaning depends on it.

   - `balance` on headings evens out short multi-line text.
   - `pretty` on prose stops single-word orphans on the last line.
   - `.sup-nowrap` is the manual escape hatch: wrap a phrase in it and it
     stays whole, for hyphenated compounds and short closing beats. */
h1, h2, h3, h4,
.sup-eyebrow,
.sup-tier__name,
.sup-shelf__title,
.sup-rundown__name,
.sup-process__title,
.sup-bento__title,
.sup-roster__name,
.sup-figure__label {
  text-wrap: balance;
}

p,
li,
figcaption,
.sup-lede,
.sup-tier__blurb,
.sup-shelf__text,
.sup-rundown__desc,
.sup-process__text,
.sup-bento__text,
.sup-roster__bio,
.product-listing__tagline,
.sup-section__head p {
  text-wrap: pretty;
}

/* Never break these across lines. */
.sup-nowrap { white-space: nowrap; }

/* ---------- 6. GLOBAL POLISH ---------- */
::selection { background: var(--sup-pink); color: #1a0a12; }

/* Brand-tinted scrollbar (dark) */
* { scrollbar-color: var(--sup-surface-3) transparent; scrollbar-width: thin; }
::-webkit-scrollbar { width: 12px; height: 12px; }
::-webkit-scrollbar-track { background: transparent; }
::-webkit-scrollbar-thumb {
  background: var(--sup-surface-3);
  border: 3px solid var(--sup-bg);
  border-radius: var(--sup-radius-full);
}
::-webkit-scrollbar-thumb:hover { background: #3a3a78; }

/* ---------- 7. ACCESSIBILITY ---------- */
:where(a, button, [role="button"], input, select, summary, [tabindex]):focus-visible {
  outline: 2px solid var(--sup-cyan);
  outline-offset: 2px;
}
/* Reduced motion.
   Pico CSS ships its own reduced-motion reset that zeroes ALL
   transition/animation durations on `*` with !important. Our motions
   are intentionally small and non-vestibular (subtle hovers, lifts,
   gradient sweeps, a loading shimmer) — feedback, not spectacle — so we
   deliberately KEEP them by restoring durations on our own components
   (higher specificity + !important beats Pico's `*` rule). Only
   smooth-scroll is dropped. Gate any future large/parallax/auto-playing
   motion behind this query specifically. */
@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }

  button, [type="submit"], [type="button"], [role="button"], .button {
    /* order matches transition-property: transform, box-shadow,
       background-position, filter, border-color, color */
    transition-duration: var(--sup-dur), var(--sup-dur-slow), var(--sup-dur-slow),
                         var(--sup-dur), var(--sup-dur), var(--sup-dur) !important;
  }
  .sup-card               { transition-duration: var(--sup-dur-slow) !important; }
  .sup-tag                { transition-duration: var(--sup-dur) !important; }
  .sup-tag__label,
  .sup-tag__label > span  { transition-duration: var(--sup-dur-slow) !important; }
  .sup-skeleton::after    { animation-duration: 1.4s !important; animation-iteration-count: infinite !important; }
  /* Keep the system's subtle, non-vestibular motions running (lifts,
     reveals, knob slide) — same rationale as the components above. */
  .sup-tier, .sup-feature, .sup-plugin { transition-duration: var(--sup-dur-slow) !important; }
  .sup-faq__body                       { transition-duration: var(--sup-dur-slow) !important; }
  .sup-live__body                      { transition-duration: var(--sup-dur-slow) !important; }
  .sup-live__loader,
  .sup-live__embed                     { transition-duration: var(--sup-dur-slow) !important; }
  .sup-faq__item > summary::after      { transition-duration: var(--sup-dur) !important; }
  .sup-toggle__knob                    { transition-duration: var(--sup-dur-slow) !important; }
  .sup-toggle__opt                     { transition-duration: var(--sup-dur) !important; }
}
