/*
 * ZeusMarket — design layer
 * =========================
 * Hooks onto the theme's stable `sa-*` classes only. No theme file is forked,
 * so a SellAuth update cannot overwrite any of this. If a rule stops applying
 * after an update, the hook it targets was renamed — that is the only way
 * this file can break.
 *
 * ── Performance note (read before adding anything) ──
 * There is deliberately NO @import here. An @import inside a stylesheet is a
 * CHAINED request: the browser must download this file, parse it, and only
 * then discover the font and fetch it. The theme's own font <link> in
 * master.njk is already loaded non-blocking (media="print" onload), so the
 * @import was the single blocking request on the page. Numbers are set in the
 * system mono stack instead: zero requests, and every OS ships a good one.
 * Keep it that way.
 *
 * ── The brief: "less AI-looking" ──
 * The generated-storefront look is a specific set of habits. This file is
 * mostly the inverse of them:
 *   centred stacks           -> left-aligned, asymmetric
 *   generic blue             -> amber, the colour of an instrument readout
 *   white text on the accent -> near-black on amber
 *   soft rounded + shadows   -> 3px, hairlines, no shadows
 *   Inter / Geist            -> Bricolage Grotesque + Instrument Sans
 *   pill eyebrow with a dot  -> mono label on a rule
 *   glow everywhere          -> one grid, behind the hero only
 *   every section stacked    -> four sections cut entirely
 *
 * Index
 *   1  Tokens and the mono voice
 *   2  Section headers
 *   3  Buttons
 *   4  Navbar and announcement
 *   5  Product cards
 *   6  Boost planner
 *   7  Steps, stats, reviews, FAQ
 *   8  Policy and description pages
 *   9  Footer
 *  10  Motion and reduced-motion
 *
 * The theme's own `sa-` hook reference is kept at the bottom.
 */

/* ============================================================
   1  Tokens and the mono voice
   ============================================================ */

:root {
  /* No webfont. See the performance note above. */
  --ff-mono: ui-monospace, 'SF Mono', SFMono-Regular, 'Cascadia Mono',
             'Segoe UI Mono', 'Roboto Mono', Menlo, Consolas, monospace;

  --bp-rail: rgba(var(--cl-t-primary), 0.09);
  --bp-ease: cubic-bezier(0.22, 1, 0.36, 1);

  /* Two colours, one rule.
     Blurple is the SHOP: buttons, links, labels, section eyebrows.
     Pink is BOOSTED: it appears only where Discord itself uses it, on state
     that is actually unlocked — the meter, the level blocks, the perks you
     have paid for, the server preview. That means the pink is never
     decoration. When you see it, something is on. */
  --boost: 255 115 250;
}

body {
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
}

/* Bricolage is a variable grotesque. At display sizes it wants tight tracking
   or it settles back into looking like a default web font. */
.sa-hero-title,
.sa-section-title,
.sa-page-product-title {
  letter-spacing: -0.035em;
  text-wrap: balance;
}

.sa-hero-title { line-height: 0.98; }
.sa-hero-subtitle { max-width: 54ch; line-height: 1.6; }

/* Every price, count and unit is mono with tabular figures. This single
   decision does more for "reads as a real shop" than any amount of layout
   work: numbers look measured rather than typed. */
.sa-product-card-price,
.sa-page-product-price,
.sa-page-cart-price,
.sa-product-card-stock,
.sa-product-form-badge,
.sa-page-customer-reseller-stat {
  font-family: var(--ff-mono);
  font-variant-numeric: tabular-nums;
  letter-spacing: -0.02em;
}

/* ============================================================
   0  Rythme vertical

   Releve en production : les huit sections avaient EXACTEMENT 96px de
   respiration en haut et en bas. Une cadence parfaitement reguliere est ce
   qui fait lire une page comme un empilement de blocs plutot que comme un
   document — un oeil humain hierarchise, il ne repete pas.

   Trois registres desormais :
     bande utilitaire  40px  — les chiffres, les faits : dense, ca se balaie
     section courante  72px  — avis, FAQ, revendeur
     le catalogue      104px — c'est ce qu'on vend, il a droit a l'espace

   Effet de bord voulu : le catalogue remonte d'environ 800px, il n'est plus
   enterre sous deux blocs de remplissage.
   ============================================================ */

.sa-stats,
.sa-features {
  padding-block: 2.5rem;
}

/* Un filet plutot qu'une section : la bande de chiffres appartient a ce qui
   la precede, elle ne s'annonce pas. */
.sa-stats {
  border-top: 1px solid var(--cl-border);
  border-bottom: 1px solid var(--cl-border);
}

[data-component-id="products"] {
  padding-block: 6.5rem;
}

[data-component-id="feedbacks"],
[data-component-id="faq"],
[data-component-id="reseller-block"] {
  padding-block: 4.5rem;
}

@media (max-width: 768px) {
  .sa-stats,
  .sa-features { padding-block: 2rem; }
  [data-component-id="products"] { padding-block: 3.5rem; }
  [data-component-id="feedbacks"],
  [data-component-id="faq"],
  [data-component-id="reseller-block"] { padding-block: 3rem; }
}

/* ============================================================
   1a  Accent par scheme

   Aucune valeur unique ne passe le contraste AA sur un fond quasi blanc ET
   sur un fond quasi noir — le blurple d'origine echouait des deux cotes
   (4,41 sur clair, 4,29 sur sombre). L'accent est donc defini par scheme,
   avec l'encre des aplats qui suit : clair sur fond sombre, sombre sur fond
   clair. Les deux valeurs de settings.json servent de repli.
   ============================================================ */

html[data-scheme="dark"] {
  --cl-accent: 76, 194, 255;      /* #4CC2FF — 9,86:1 sur #0A0A0C */
  --cl-on-accent: 6, 18, 26;      /* encre sombre sur l'aplat clair, 9,44:1 */
}

html[data-scheme="light"] {
  --cl-accent: 10, 111, 184;      /* #0A6FB8 — 5,05:1 sur #FAFAF8 */
  --cl-on-accent: 255, 255, 255;  /* blanc sur l'aplat profond, 5,25:1 */
}

/* ============================================================
   1b  Echelle typographique

   Releve sur la page en production : 13 tailles distinctes en circulation
   (9, 10, 11, 12, 14, 15, 16, 17, 18, 34, 59, 64, 80). Ce n'est pas une
   echelle, c'est un empilement — avec des marches que personne ne choisit a
   la main (15 ET 16 ET 17) et un trou entre 18 et 34. Les petits libelles
   sont ramenes a deux marches, ce qui suffit a les distinguer.
   ============================================================ */

:root {
  --fs-micro: 0.6875rem;  /* 11px — etiquettes mono en majuscules */
  --fs-small: 0.8125rem;  /* 13px — texte secondaire, navigation */
  --fs-base:  1rem;       /* 16px — prix, corps */
}

.sa-section-eyebrow,
.sa-announcement,
.sa-announcement-item,
.bp-srv-look,
.pc-name-tag,
.bp-row-need {
  font-size: var(--fs-micro);
}

.sa-navbar-link,
.sa-footer-link,
.sa-product-card-stock {
  font-size: var(--fs-small);
}

/* 17px n'existe nulle part ailleurs dans le systeme : le prix revient sur la
   marche de base, sa force vient de la graisse et de la couleur. */
.sa-product-card-price {
  font-size: var(--fs-base);
}

/* ============================================================
   2  Section headers

   The default eyebrow is small accent-coloured text, or a pill with a dot
   in it. Both are the tell. Replaced with a mono label sitting on a hairline
   that runs to the edge of the column — a device from print.
   ============================================================ */

.sa-section-header { max-width: none; margin-bottom: 3.5rem; }

.sa-section-eyebrow {
  display: flex;
  align-items: center;
  gap: 1rem;
  margin-bottom: 1.25rem;
  font-family: var(--ff-mono);
  font-size: 0.6875rem;
  font-weight: 500;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: rgba(var(--cl-t-primary), 0.42);
}

.sa-section-eyebrow::after {
  content: '';
  flex: 1;
  height: 1px;
  background: var(--cl-border);
}

.sa-section-header.text-center .sa-section-eyebrow { justify-content: center; }
.sa-section-header.text-center .sa-section-eyebrow::before {
  content: '';
  flex: 1;
  height: 1px;
  background: var(--cl-border);
}

.sa-section-subtitle { max-width: 56ch; margin-top: 1rem; line-height: 1.6; }

/* ============================================================
   3  Buttons
   ============================================================ */

.sa-btn {
  font-family: var(--ff-mono);
  font-size: 0.75rem;
  font-weight: 500;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  padding-inline: 1.25rem;
  transition: background-color var(--dur) ease, color var(--dur) ease,
              border-color var(--dur) ease, transform var(--dur) ease;
}

.sa-btn--solid:hover { transform: translateY(-1px); }
.sa-btn--solid:active { transform: translateY(0); }

.sa-btn--outline {
  border-color: rgba(var(--cl-t-primary), 0.18);
  color: rgba(var(--cl-t-primary), 0.78);
}

.sa-btn--outline:hover {
  border-color: rgb(var(--cl-accent));
  color: rgb(var(--cl-accent));
  background: transparent;
}

/* ============================================================
   4  Navbar and announcement
   ============================================================ */

.sa-navbar-link {
  position: relative;
  padding-bottom: 2px;
  font-family: var(--ff-mono);
  letter-spacing: 0.06em;
  text-transform: uppercase;
}

/* Grows from the left rather than fading in: a direction, not a glow. */
.sa-navbar-link::after {
  content: '';
  position: absolute;
  left: 0;
  bottom: 0;
  height: 1px;
  width: 100%;
  background: currentColor;
  transform: scaleX(0);
  transform-origin: left;
  transition: transform 220ms var(--bp-ease);
}

.sa-navbar-link:hover::after { transform: scaleX(1); }

/* Le bloc logo porte `shrink-0`, qui annule le `min-w-0` et le `truncate`
   poses juste a cote : sous 400px le logo + le nom de boutique mesurent plus
   que la barre entiere et poussent les boutons hors de l'ecran (138px de
   debordement horizontal constates a 375px). On lui rend le droit de se
   comprimer, et on plafonne la largeur du logo pour qu'un wordmark large ne
   puisse pas reproduire le probleme. */
.sa-navbar-logo {
  flex-shrink: 1;
  min-width: 0;
}

.sa-navbar-logo img {
  max-width: 9rem;
  object-fit: contain;
}

@media (max-width: 480px) {
  .sa-navbar-logo img { max-width: 6rem; }
}

.sa-announcement,
.sa-announcement-item {
  font-family: var(--ff-mono);
  font-size: 0.6875rem;
  letter-spacing: 0.1em;
  text-transform: uppercase;
}

/* Etiquette de format de livraison, extraite du nom du produit.
   Volontairement discrete : elle qualifie le titre, elle ne le concurrence
   pas. Meme voix mono que le reste des libelles du theme. */
.pc-name-tag {
  display: inline-block;
  margin-left: 0.5rem;
  padding: 0.05rem 0.4rem;
  border: 1px solid var(--cl-border);
  border-radius: 3px;
  font-family: var(--ff-mono);
  font-size: var(--fs-micro);
  font-weight: 500;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: rgb(var(--cl-t-muted));
  vertical-align: 0.1em;
  white-space: nowrap;
}

.sa-product-card:hover .pc-name-tag {
  border-color: rgba(var(--cl-accent), 0.45);
  color: rgb(var(--cl-accent));
}

/* ============================================================
   5  Product cards

   The default is a soft rounded card that lifts. Replaced with a hairline
   frame that tightens while the media pushes in slightly, so the card
   behaves like a physical tile rather than a floating panel.
   ============================================================ */

.sa-product-card {
  position: relative;
  border: 1px solid var(--cl-border);
  background: transparent;
  transition: border-color var(--dur) ease, background-color var(--dur) ease;
}

.sa-product-card:hover {
  border-color: rgba(var(--cl-accent), 0.5);
  background: rgba(var(--cl-t-primary), 0.012);
}

/* A hairline that draws itself along the top edge on hover. Two properties,
   no glow, and it points at the card you are about to open. */
.sa-product-card::before {
  content: '';
  position: absolute;
  top: -1px;
  left: -1px;
  height: 2px;
  width: calc(100% + 2px);
  background: rgb(var(--cl-accent));
  transform: scaleX(0);
  transform-origin: left;
  transition: transform 320ms var(--bp-ease);
  z-index: 2;
  pointer-events: none;
}

.sa-product-card:hover::before { transform: scaleX(1); }

.sa-product-card-media {
  overflow: hidden;
  border-bottom: 1px solid var(--cl-border);
}

.sa-product-card-media img { transition: transform 600ms var(--bp-ease); }
.sa-product-card:hover .sa-product-card-media img { transform: scale(1.04); }

.sa-product-card-title { letter-spacing: -0.015em; line-height: 1.25; }
.sa-product-card-price { font-size: var(--fs-base); font-weight: 700; }

.sa-product-card-price-slash {
  color: rgba(var(--cl-t-primary), 0.32);
  font-weight: 400;
}

.sa-product-card-stock {
  font-size: var(--fs-micro);
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: rgba(var(--cl-t-primary), 0.45);
}

.sa-product-card-badges > * {
  font-family: var(--ff-mono);
  font-size: var(--fs-micro);
  letter-spacing: 0.1em;
  text-transform: uppercase;
}

/* ============================================================
   6  Boost planner

   Every buyer arrives with one question: how many boosts do I need? No shop
   in this category answers it, so the page answers it before it sells
   anything.

   Three things move, and each one earns it:
     the server preview  — shows the perks instead of listing them
     the counter bump    — every step registers
     the level flash     — only crossing 2 / 7 / 14, so it still means
                           something when it happens
   ============================================================ */

.bp {
  border: 1px solid var(--cl-border);
  background: rgb(var(--cl-surface));
}

.bp-sprite { position: absolute; width: 0; height: 0; overflow: hidden; }

.bp-head {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: 0.5rem 1.5rem;
  padding: 1.125rem 1.5rem;
  border-bottom: 1px solid var(--cl-border);
}

.bp-index {
  font-family: var(--ff-mono);
  font-size: var(--fs-micro);
  font-weight: 500;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: rgb(var(--cl-accent));
}

.bp-heading {
  font-family: var(--ff-heading);
  font-size: 1rem;
  font-weight: 600;
  letter-spacing: -0.01em;
  color: rgba(var(--cl-t-primary), 0.9);
}

.bp-body { padding: 1.75rem 1.5rem 1.5rem; }

@media (min-width: 900px) {
  .bp-body {
    display: grid;
    grid-template-columns: minmax(0, 20rem) minmax(0, 1fr);
    grid-template-areas: 'stage ledger' 'foot foot';
    gap: 0 3.5rem;
    padding: 2.25rem 2.25rem 1.75rem;
  }
  .bp-stage  { grid-area: stage; }
  .bp-ledger { grid-area: ledger; }
  .bp-foot   { grid-area: foot; }
}

/* ---- The server preview ----
   A Discord invite card, not an abstraction of one. The earlier version used
   a spinning ring and a badge that popped in, which read as a toy; this one
   only does what Discord itself does, so a buyer recognises it instead of
   decoding it.

   Every state hangs off one class on the wrapper, so this panel and the
   ledger beside it can never disagree. Transitions are long and eased —
   perks arriving should feel like a page settling, not like a slot machine.

   The card keeps Discord's own dark surface regardless of the site scheme.
   A server preview that turns white in light mode stops being a preview. */

.bp-server {
  --d-bg: #1E1F22;
  --d-surface: #2B2D31;
  --d-text: #F2F3F5;
  --d-muted: #949BA4;
  --d-online: #23A55A;

  position: relative;
  margin-bottom: 1.5rem;
  border: 1px solid rgba(0, 0, 0, 0.4);
  border-radius: 6px;
  background: var(--d-surface);
  overflow: hidden;
}

/* Banner: arrives at level 2, exactly as Discord unlocks it. */
.bp-srv-banner {
  position: relative;
  height: 0;
  background: #1E1F22;
  transition: height 420ms var(--bp-ease);
  overflow: hidden;
}

/* The banner is drawn SVG, not a stack of CSS gradients. The gradient
   version read as grey with a shimmer on it — too many translucent layers
   over a dark base, and nothing with an edge. Real artwork needs shapes:
   a night sky, a glow on the horizon, two ridge lines. It renders
   identically everywhere and it is editable in the Custom HTML block. */

.bp-srv-art {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  display: block;
}

/* Level 3 is the ANIMATED banner. The glow breathes and the stars drift —
   slow enough to notice only if you look, which is how a real animated
   banner behaves. */
.bp-server.lv-3 .bp-srv-sun { animation: bp-breathe 7s ease-in-out infinite; transform-origin: 318px 74px; }
.bp-server.lv-3 .bp-srv-stars { animation: bp-twinkle 4.5s ease-in-out infinite; }
.bp-server.lv-3 .bp-srv-ridge { animation: bp-slide 16s ease-in-out infinite alternate; }

@keyframes bp-breathe {
  0%, 100% { transform: scale(1); opacity: 0.85; }
  50%      { transform: scale(1.12); opacity: 1; }
}

@keyframes bp-twinkle {
  0%, 100% { opacity: 0.35; }
  50%      { opacity: 0.9; }
}

@keyframes bp-slide {
  from { transform: translateX(0); }
  to   { transform: translateX(-14px); }
}

/* Restored. A block replacement here removed these three rules along with
   the ones it was meant to replace, which is why the banner stayed at zero
   height and the sweep vanished: the artwork was rendering the whole time,
   inside a container collapsed to nothing. */

.bp-server.lv-2 .bp-srv-banner,
.bp-server.lv-3 .bp-srv-banner { height: 5rem; }

.bp-srv-shine {
  position: absolute;
  inset: 0;
  background: linear-gradient(100deg, transparent 36%,
    rgba(255, 255, 255, 0.30) 50%, transparent 64%);
  transform: translateX(-110%);
  opacity: 0;
  pointer-events: none;
}

.bp-server.lv-3 .bp-srv-shine {
  opacity: 1;
  animation: bp-sweep 4.5s ease-in-out infinite;
}

@keyframes bp-sweep {
  0%, 45% { transform: translateX(-110%); }
  100%    { transform: translateX(110%); }
}

.bp-srv-main {
  display: flex;
  align-items: center;
  gap: 0.75rem;
  padding: 0.875rem 1rem 0.5rem;
}

/* Icon: a Discord server icon is a squircle that rounds to a circle. The
   GIF chip in the corner is how Discord marks an animated one, so that is
   what level 1 shows instead of a spinning ring. */
.bp-srv-icon {
  position: relative;
  flex-shrink: 0;
  width: 2.75rem;
  height: 2.75rem;
  border-radius: 34%;
  background: #4E5058;
  display: grid;
  place-items: center;
  box-shadow: 0 0 0 3px var(--d-surface);
  transition: border-radius 420ms var(--bp-ease), background-color 420ms ease;
}

.bp-srv-icon b {
  font-family: var(--ff-heading);
  font-size: 0.8125rem;
  font-weight: 700;
  letter-spacing: 0.02em;
  color: #DBDEE1;
}

.bp-server.lv-1 .bp-srv-icon,
.bp-server.lv-2 .bp-srv-icon,
.bp-server.lv-3 .bp-srv-icon {
  border-radius: 50%;
  background: #3A2E6B;
}

/* The animated avatar. A "GIF" chip on a still image was the weakest thing
   in this panel: it asserted the perk instead of showing it. This layer is
   the perk — a conic sweep that actually turns, so the icon is visibly
   animated the moment level 1 is reached. */
.bp-srv-av {
  position: absolute;
  inset: 0;
  border-radius: inherit;
  /* Was a five-colour rainbow, which fought everything around it. Two
     brand hues and a dark gap: the icon still visibly turns, but it stops
     shouting. */
  background: conic-gradient(from 0deg,
    #5865F2, rgb(var(--boost)) 28%, #FF5FD2 48%, rgb(var(--boost)) 70%, #5865F2);
  /* En anneau plutot qu'en disque : les initiales couvraient le dégradé,
     on voyait un rond uni au lieu d'une icone qui tourne. */
  -webkit-mask: radial-gradient(closest-side, transparent 56%, #000 59%);
  mask: radial-gradient(closest-side, transparent 56%, #000 59%);
  opacity: 0;
  transition: opacity 380ms ease;
}

.bp-server.lv-1 .bp-srv-av,
.bp-server.lv-2 .bp-srv-av,
.bp-server.lv-3 .bp-srv-av {
  opacity: 1;
  animation: bp-spin 3.5s linear infinite;
}

@keyframes bp-spin { to { transform: rotate(360deg); } }

/* The initials sit above the animation and stay readable against it. */
.bp-srv-icon b {
  position: relative;
  z-index: 1;
  text-shadow: 0 1px 3px rgba(0, 0, 0, 0.55);
}

.bp-srv-gif {
  position: absolute;
  right: -3px;
  bottom: -3px;
  padding: 1px 3px;
  border-radius: 3px;
  background: var(--d-bg);
  color: var(--d-text);
  font-family: var(--ff-mono);
  font-size: 0.4375rem;
  font-style: normal;
  font-weight: 700;
  letter-spacing: 0.04em;
  opacity: 0;
  transition: opacity 300ms ease;
}

.bp-server.lv-1 .bp-srv-gif,
.bp-server.lv-2 .bp-srv-gif,
.bp-server.lv-3 .bp-srv-gif { opacity: 1; }

.bp-srv-id { min-width: 0; flex: 1; }

.bp-srv-name {
  display: flex;
  align-items: center;
  gap: 0.375rem;
  font-family: var(--ff-body);
  font-size: var(--fs-base);
  font-weight: 600;
  color: var(--d-text);
}

/* Discord's boost badge: a small diamond with the level number beside it. */
.bp-srv-lvlbadge {
  display: inline-flex;
  align-items: center;
  gap: 2px;
  padding: 1px 5px 1px 3px;
  border-radius: 4px;
  background: rgba(var(--boost), 0.16);
  color: rgb(var(--boost));
  font-size: var(--fs-micro);
  font-weight: 700;
  opacity: 0;
  transform: translateY(2px);
  transition: opacity 300ms ease, transform 300ms var(--bp-ease);
}

.bp-srv-lvlbadge svg { width: 0.5625rem; height: 0.5625rem; }
.bp-srv-lvlbadge em { font-style: normal; }

.bp-server.lv-1 .bp-srv-lvlbadge,
.bp-server.lv-2 .bp-srv-lvlbadge,
.bp-server.lv-3 .bp-srv-lvlbadge { opacity: 1; transform: none; }

.bp-srv-counts {
  display: flex;
  align-items: center;
  gap: 0.375rem;
  margin-top: 3px;
  font-size: 0.75rem;
  color: var(--d-muted);
}

.bp-srv-counts i {
  width: 7px;
  height: 7px;
  border-radius: 999px;
  background: var(--d-online);
}

.bp-srv-counts i.off { background: #80848E; margin-left: 0.25rem; }

/* The vanity URL is the headline level 3 perk, so it arrives rather than
   just changing colour. */
.bp-srv-vanity {
  max-height: 0;
  margin: 0 1rem;
  overflow: hidden;
  font-family: var(--ff-mono);
  font-size: 0.75rem;
  color: rgb(var(--boost));
  opacity: 0;
  transition: max-height 380ms var(--bp-ease), opacity 300ms ease, padding 380ms var(--bp-ease);
}

.bp-server.lv-3 .bp-srv-vanity {
  max-height: 1.5rem;
  padding-bottom: 0.25rem;
  opacity: 1;
}

/* ---- The perks, as numbers that move ----
   Discord's real per-level allowances. Dragging the fader changes them in
   place, so a buyer watches their own server's limits rise instead of
   reading a list of claims. This is the part that makes the panel worth
   having. */

.bp-srv-perks {
  display: grid;
  grid-template-columns: repeat(4, minmax(0, 1fr));
  gap: 1px;
  margin: 0.625rem 1rem 0;
  background: rgba(255, 255, 255, 0.06);
  border: 1px solid rgba(255, 255, 255, 0.06);
  border-radius: 4px;
  overflow: hidden;
}

.bp-srv-perk {
  display: flex;
  flex-direction: column;
  gap: 3px;
  padding: 0.5rem 0.5rem 0.5625rem;
  background: rgba(255, 255, 255, 0.02);
}

.bp-srv-perk em {
  font-family: var(--ff-mono);
  font-size: var(--fs-micro);
  font-style: normal;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--d-muted);
}

.bp-srv-perk b {
  font-family: var(--ff-heading);
  font-size: 0.8125rem;
  font-weight: 700;
  letter-spacing: -0.02em;
  color: var(--d-text);
  font-variant-numeric: tabular-nums;
  transition: color 260ms ease;
}

.bp-server.lv-2 .bp-srv-perk b,
.bp-server.lv-3 .bp-srv-perk b { color: rgb(var(--boost)); }

@media (max-width: 400px) {
  .bp-srv-perks { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}

/* Discord's own boost bar, at the foot of the card. */
.bp-srv-boost {
  margin: 0.5rem 1rem 0.9375rem;
  padding-top: 0.75rem;
  border-top: 1px solid rgba(255, 255, 255, 0.06);
}

.bp-srv-boost-head {
  display: flex;
  justify-content: space-between;
  margin-bottom: 0.4375rem;
  font-family: var(--ff-mono);
  font-size: var(--fs-micro);
  font-weight: 500;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--d-muted);
  font-variant-numeric: tabular-nums;
}

.bp-srv-boost-rail {
  height: 6px;
  border-radius: 999px;
  background: rgba(255, 255, 255, 0.07);
  overflow: hidden;
}

.bp-srv-boost-rail span {
  display: block;
  height: 100%;
  width: var(--f, 0%);
  border-radius: 999px;
  background: linear-gradient(90deg, #B14BF4, rgb(var(--boost)));
  transition: width 420ms var(--bp-ease);
}

/* Server Tag: Discord clips it beside the name. It fades and slides rather
   than scaling from zero — the pop was the goofiest thing in the old
   version. */
.bp-srv-tag {
  flex-shrink: 0;
  padding: 1px 5px;
  border-radius: 4px;
  background: rgba(var(--boost), 0.16);
  color: rgb(var(--boost));
  font-family: var(--ff-mono);
  font-size: var(--fs-micro);
  font-weight: 700;
  letter-spacing: 0.06em;
  opacity: 0;
  transform: translateX(-4px);
  transition: opacity 300ms ease, transform 300ms var(--bp-ease);
}

.bp-server.has-tag .bp-srv-tag { opacity: 1; transform: none; }

/* Perks visuels, nommes.
   L'icone tourne deja et la banniere balaie deja au niveau 3, mais rien ne
   disait au visiteur que c'etaient LA les perks : il voyait une pastille
   "GIF" de 7px et un reflet discret. Cette ligne met un mot sur chaque effet
   et s'allume au seuil exact du grand livre en dessous. */
.bp-srv-looks {
  display: flex;
  flex-wrap: wrap;
  gap: 0.3rem;
  margin: 0 1rem 0.75rem;
}

.bp-srv-look {
  padding: 0.1rem 0.4rem;
  border: 1px solid var(--cl-border);
  border-radius: 3px;
  font-family: var(--ff-mono);
  font-size: var(--fs-micro);
  font-weight: 600;
  letter-spacing: 0.07em;
  text-transform: uppercase;
  color: rgb(var(--cl-t-muted));
  opacity: 0.5;
  transition: opacity 300ms ease, color 300ms ease, border-color 300ms ease;
}

.bp-srv-look.is-on {
  opacity: 1;
  color: rgb(var(--boost));
  border-color: rgba(var(--boost), 0.45);
  background: rgba(var(--boost), 0.1);
}

.bp-srv-look.is-on::before {
  content: '';
  display: inline-block;
  width: 0.3rem;
  height: 0.55rem;
  margin-right: 0.3rem;
  border: solid currentColor;
  border-width: 0 1.5px 1.5px 0;
  transform: rotate(45deg) translateY(-1px);
}

@media (prefers-reduced-motion: reduce) {
  .bp-srv-look { transition: none; }
}

/* ---- Readout ---- */

.bp-readout {
  display: flex;
  align-items: flex-end;
  justify-content: space-between;
  gap: 1.5rem;
}

.bp-figure { display: flex; align-items: baseline; gap: 0.5rem; }

.bp-count {
  display: inline-block;
  font-family: var(--ff-heading);
  font-size: clamp(3.5rem, 11vw, 5rem);
  font-weight: 800;
  line-height: 0.8;
  letter-spacing: -0.05em;
  font-variant-numeric: tabular-nums;
  color: rgb(var(--cl-t-primary));
  /* Tabular figures still jump at the 1->2 digit boundary. A floor width
     keeps the panel still while the fader moves. */
  min-width: 2.2ch;
}

/* Small, fast, and it lands rather than bouncing. A spring here would be
   exhausting at twenty steps of travel. */
.bp-count.is-bump { animation: bp-bump 260ms var(--bp-ease); }

@keyframes bp-bump {
  0%   { transform: translateY(0.14em) scale(0.94); opacity: 0.55; }
  100% { transform: none; opacity: 1; }
}

.bp-unit {
  font-family: var(--ff-mono);
  font-size: 0.6875rem;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: rgba(var(--cl-t-primary), 0.38);
}

.bp-tier { text-align: right; }

.bp-tier-blocks {
  display: flex;
  justify-content: flex-end;
  gap: 3px;
  margin-bottom: 0.5rem;
}

.bp-tier-blocks span {
  width: 1.375rem;
  height: 5px;
  background: var(--bp-rail);
  transition: background-color 220ms ease;
}

.bp-tier-blocks span.is-on { background: rgb(var(--boost)); }

/* Only fires when a LEVEL is crossed. Every step nudging the counter is
   feedback; this is an event. */
.bp-tier.is-flash .bp-tier-blocks span.is-on { animation: bp-charge 700ms ease; }
.bp-tier.is-flash .bp-tier-blocks span.is-on:nth-child(2) { animation-delay: 60ms; }
.bp-tier.is-flash .bp-tier-blocks span.is-on:nth-child(3) { animation-delay: 120ms; }
.bp-tier.is-flash .bp-tier-label { animation: bp-lift 700ms var(--bp-ease); }

@keyframes bp-charge {
  0%   { transform: scaleY(1); filter: brightness(1); }
  30%  { transform: scaleY(2.4); filter: brightness(1.6); }
  100% { transform: scaleY(1); filter: brightness(1); }
}

@keyframes bp-lift {
  0%   { transform: translateY(0.35em); opacity: 0; }
  100% { transform: none; opacity: 1; }
}

.bp-tier-label {
  display: block;
  font-family: var(--ff-mono);
  font-size: 0.75rem;
  font-weight: 500;
  letter-spacing: 0.04em;
  color: rgba(var(--cl-t-primary), 0.62);
}

/* ---- The fader ---- */

.bp-control { padding-top: 1.5rem; }

.bp-scale {
  position: relative;
  height: 1.125rem;
  margin-bottom: 0.375rem;
  font-family: var(--ff-mono);
  font-size: var(--fs-micro);
  letter-spacing: 0.06em;
  color: rgba(var(--cl-t-primary), 0.34);
}

.bp-tick { position: absolute; top: 0; transform: translateX(-50%); }

.bp-tick i {
  display: block;
  width: 1px;
  height: 5px;
  margin: 0 auto 2px;
  background: var(--cl-border);
}

.bp-rail {
  position: relative;
  height: 5px;
  background: var(--bp-rail);
  overflow: hidden;
}

.bp-fill {
  position: absolute;
  top: 0;
  bottom: 0;
  left: 0;
  width: var(--f, 0%);
  max-width: 100%;
  background: rgb(var(--boost));
  overflow: hidden;
  /* Tuned for continuous dragging: attached to the thumb, damped enough
     not to strobe. */
  transition: width 260ms var(--bp-ease);
}

/* Stripes only travel WHILE dragging. Ambient motion on a progress bar is
   the thing that makes a page feel like a template; motion that starts when
   you touch it feels like a machine responding. */
.bp-fill-stripe {
  position: absolute;
  inset: 0 -40% 0 0;
  background-image: repeating-linear-gradient(115deg,
    rgba(0, 0, 0, 0.16) 0 6px, transparent 6px 14px);
  opacity: 0;
  transition: opacity 200ms ease;
}

.bp-control.is-dragging .bp-fill-stripe {
  opacity: 1;
  animation: bp-stripes 700ms linear infinite;
}

@keyframes bp-stripes { to { transform: translateX(14px); } }

.bp-range {
  -webkit-appearance: none;
  appearance: none;
  display: block;
  position: relative;
  z-index: 2;
  width: 100%;
  height: 2rem;
  margin-top: -1rem;
  background: transparent;
  cursor: grab;
  touch-action: pan-y;
}

.bp-range:active { cursor: grabbing; }
.bp-range::-webkit-slider-runnable-track { height: 2rem; background: transparent; }
.bp-range::-moz-range-track { height: 2rem; background: transparent; }

/* A fader cap, not a bubble: taller than it is wide, with a grip line. */
.bp-range::-webkit-slider-thumb {
  -webkit-appearance: none;
  appearance: none;
  width: 0.875rem;
  height: 1.75rem;
  margin-top: 0.125rem;
  border-radius: 2px;
  border: 0;
  background:
    linear-gradient(rgba(0, 0, 0, 0.28), rgba(0, 0, 0, 0.28)) center / 60% 1px no-repeat,
    rgb(var(--cl-t-primary));
  transition: background-color 160ms ease, transform 160ms var(--bp-ease);
}

.bp-range::-moz-range-thumb {
  width: 0.875rem;
  height: 1.75rem;
  border-radius: 2px;
  border: 0;
  background: rgb(var(--cl-t-primary));
  transition: transform 160ms var(--bp-ease);
}

.bp-range:hover::-webkit-slider-thumb { transform: scaleY(1.08); }
.bp-range:active::-webkit-slider-thumb { transform: scaleY(1.14); background: rgb(var(--boost)); }
.bp-range:hover::-moz-range-thumb { transform: scaleY(1.08); }
.bp-range:active::-moz-range-thumb { transform: scaleY(1.14); background: rgb(var(--boost)); }

.bp-range:focus-visible::-webkit-slider-thumb {
  outline: 2px solid rgb(var(--cl-accent));
  outline-offset: 2px;
}

.bp-bounds {
  display: flex;
  justify-content: space-between;
  margin-top: 0.5rem;
  font-family: var(--ff-mono);
  font-size: var(--fs-micro);
  letter-spacing: 0.1em;
  color: rgba(var(--cl-t-primary), 0.28);
}

/* ---- The ledger ---- */

.bp-ledger-head {
  display: flex;
  justify-content: space-between;
  gap: 1rem;
  padding-bottom: 0.625rem;
  margin-bottom: 0.25rem;
  border-bottom: 1px solid var(--cl-border);
  font-family: var(--ff-mono);
  font-size: var(--fs-micro);
  font-weight: 500;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: rgba(var(--cl-t-primary), 0.34);
}

.bp-ledger-count { color: rgb(var(--boost)); font-variant-numeric: tabular-nums; }

.bp-row {
  display: flex;
  align-items: center;
  gap: 0.625rem;
  padding: 0.375rem 0;
  color: rgba(var(--cl-t-primary), 0.3);
  transition: color 220ms ease;
}

.bp-row.is-on { color: rgb(var(--cl-t-primary)); }

.bp-row-ico {
  flex-shrink: 0;
  width: 1.375rem;
  height: 1.375rem;
  display: grid;
  place-items: center;
  border: 1px solid transparent;
  border-radius: 3px;
  color: rgba(var(--cl-t-primary), 0.28);
  transition: color 220ms ease, border-color 220ms ease,
              background-color 220ms ease, transform 260ms var(--bp-ease);
}

.bp-row-ico svg {
  width: 0.875rem;
  height: 0.875rem;
  fill: none;
  stroke: currentColor;
  stroke-width: 1.6;
  stroke-linecap: round;
  stroke-linejoin: round;
}

.bp-row.is-on .bp-row-ico {
  color: rgb(var(--boost));
  border-color: rgba(var(--boost), 0.4);
  background: rgba(var(--boost), 0.1);
  /* A stagger down the list, so unlocking a tier reads as a run of perks
     rather than twelve rows changing at once. Capped by the calc so a
     bottom row never lags noticeably behind the fader. */
  transition-delay: calc(var(--i, 0) * 18ms);
}

.bp-row-name { font-size: 0.875rem; }

/* The dotted leader. Purely typographic, and the reason this reads as a
   printed price list rather than a feature grid. */
.bp-row-leader {
  flex: 1;
  min-width: 1.5rem;
  height: 1px;
  background-image: radial-gradient(circle, currentColor 0.8px, transparent 0.9px);
  background-size: 5px 1px;
  background-repeat: repeat-x;
  opacity: 0.3;
}

.bp-row-need {
  font-family: var(--ff-mono);
  font-size: 0.75rem;
  font-variant-numeric: tabular-nums;
  color: inherit;
  opacity: 0.55;
}

.bp-row.is-on .bp-row-need { color: rgb(var(--boost)); opacity: 1; }

/* ---- Verdict and route ---- */

.bp-foot {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: 1rem;
  margin-top: 1.75rem;
  padding-top: 1.25rem;
  border-top: 1px solid var(--cl-border);
}

.bp-verdict {
  flex: 1 1 16rem;
  font-size: 0.875rem;
  line-height: 1.5;
  color: rgba(var(--cl-t-primary), 0.6);
}

.bp-cta {
  display: inline-flex;
  align-items: center;
  gap: 0.5rem;
  padding: 0.6875rem 1.125rem;
  background: rgb(var(--cl-accent));
  color: rgb(var(--cl-on-accent));
  font-family: var(--ff-mono);
  font-size: 0.6875rem;
  font-weight: 700;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  white-space: nowrap;
  transition: transform var(--dur) ease, filter var(--dur) ease;
}

.bp-cta:hover { transform: translateY(-1px); filter: brightness(1.08); }
.bp-cta svg { transition: transform 220ms var(--bp-ease); }
.bp-cta:hover svg { transform: translateX(3px); }

@media (max-width: 899px) {
  .bp-ledger { margin-top: 1.75rem; }
}

/* ---- Boost meter on every product card ----
   The card answers the same question the planner does, in one line: how far
   up the ladder does this listing get you. Same 2 / 7 / 14 thresholds, same
   pink for "reached", so a buyer scanning the grid is reading the same
   instrument they just used at the top of the page. */

.pc-boost { margin-top: 0.625rem; }

.pc-boost-rail {
  height: 4px;
  border-radius: 999px;
  background: rgba(var(--cl-t-primary), 0.08);
  overflow: hidden;
  /* The three notches ARE the levels. Drawn on the track rather than
     labelled, so the bar reads at a glance without a legend. */
  background-image:
    linear-gradient(rgba(var(--cl-t-primary), 0.28), rgba(var(--cl-t-primary), 0.28)),
    linear-gradient(rgba(var(--cl-t-primary), 0.28), rgba(var(--cl-t-primary), 0.28));
  background-size: 1px 100%, 1px 100%;
  background-position: 14.3% 0, 50% 0;
  background-repeat: no-repeat;
}

.pc-boost-rail span {
  display: block;
  height: 100%;
  border-radius: 999px;
  background: linear-gradient(90deg, #B14BF4, rgb(var(--boost)));
  transition: width 420ms var(--bp-ease);
}

.pc-boost-meta {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 0.5rem;
  margin-top: 0.375rem;
}

.pc-boost-lvl {
  display: inline-flex;
  align-items: center;
  gap: 3px;
  font-family: var(--ff-mono);
  font-size: var(--fs-micro);
  font-weight: 700;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: rgb(var(--boost));
}

.pc-boost-lvl svg { width: 0.5rem; height: 0.5rem; }

.pc-boost-n {
  font-family: var(--ff-mono);
  font-size: var(--fs-micro);
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: rgba(var(--cl-t-primary), 0.4);
  font-variant-numeric: tabular-nums;
}

/* The card is a link, so nothing inside it should intercept the pointer. */
.pc-boost, .pc-boost * { pointer-events: none; }

/* ---- Category filter ----
   Chips derived from the product name, so a new listing files itself the
   moment it is named. The count sits inside the chip because a filter that
   does not tell you how much is behind it makes you click to find out. */

.sa-cat-bar {
  display: flex;
  flex-wrap: wrap;
  gap: 0.5rem;
  margin-bottom: 2rem;
}

.sa-cat {
  display: inline-flex;
  align-items: center;
  gap: 0.5rem;
  padding: 0.5rem 0.875rem;
  border: 1px solid var(--cl-border);
  border-radius: 3px;
  background: transparent;
  color: rgba(var(--cl-t-primary), 0.6);
  font-family: var(--ff-mono);
  font-size: 0.6875rem;
  font-weight: 500;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  cursor: pointer;
  transition: border-color var(--dur) ease, color var(--dur) ease,
              background-color var(--dur) ease;
}

.sa-cat:hover {
  border-color: rgba(var(--cl-accent), 0.5);
  color: rgb(var(--cl-t-primary));
}

.sa-cat.is-on {
  border-color: rgb(var(--cl-accent));
  background: rgb(var(--cl-accent));
  color: rgb(var(--cl-on-accent));
}

.sa-cat i {
  font-style: normal;
  font-variant-numeric: tabular-nums;
  font-size: var(--fs-micro);
  opacity: 0.55;
}

.sa-cat.is-on i { opacity: 0.8; }

/* ============================================================
   7  Stats, reviews, FAQ

   The stats are the argument this shop actually has: ten thousand orders and
   a public 4.99. They were a cramped inline row; now they are a band, set at
   display size, sitting immediately before the catalogue so the credibility
   lands exactly where someone decides whether to buy.
   ============================================================ */

.sa-stats-items {
  /* The theme's row variant ships as a rounded, shadowed card. Stripped back
     to hairlines: the numbers should be the object, not the box holding
     them. */
  border-radius: 0 !important;
  border-left: 0;
  border-right: 0;
  box-shadow: none !important;
  background: transparent !important;
}

.sa-stats-item {
  position: relative;
  padding: 2.25rem 1.5rem !important;
  text-align: left !important;
  overflow: hidden;
}

/* A rule that draws itself under each figure as the band scrolls in. It
   arrives with the count-up, so the number and its underline land together
   instead of competing. */
.sa-stats-item::after {
  content: '';
  position: absolute;
  left: 1.5rem;
  right: 1.5rem;
  bottom: 1.5rem;
  height: 2px;
  background: rgb(var(--cl-accent));
  transform: scaleX(0);
  transform-origin: left;
  transition: transform 900ms 200ms var(--bp-ease);
}

.sa-stats:has(.sa-stats-item) .sa-stats-item::after { transform: scaleX(0.28); }

.sa-stats-item .text-h2 {
  display: block;
  font-family: var(--ff-heading);
  font-size: clamp(2.75rem, 6vw, 4rem) !important;
  font-weight: 800;
  line-height: 0.85;
  letter-spacing: -0.045em;
  font-variant-numeric: tabular-nums;
  /* The digits change every frame while counting. Without a reserved box the
     whole band reflows twenty times a second. */
  min-height: 1em;
}

.sa-stats-item p {
  margin-top: 1.375rem !important;
  font-family: var(--ff-mono);
  font-size: var(--fs-micro) !important;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: rgba(var(--cl-t-primary), 0.42) !important;
}

@media (max-width: 640px) {
  .sa-stats-item { padding: 1.75rem 1.25rem !important; }
  .sa-stats-item::after { bottom: 1.125rem; left: 1.25rem; right: 1.25rem; }
}

.sa-steps-icon {
  font-family: var(--ff-mono);
  font-variant-numeric: tabular-nums;
  letter-spacing: -0.02em;
}

/* The FAQ rows are <button>, not <summary> — checked against the markup
   rather than assumed, because a wrong selector fails silently. */
.sa-faq-item { background: transparent; }

.sa-faq-item > button {
  letter-spacing: -0.01em;
  transition: color var(--dur) ease;
}

.sa-faq-item > button:hover { color: rgb(var(--cl-accent)); }

.sa-feedback-card {
  border: 1px solid var(--cl-border);
  transition: border-color var(--dur) ease;
}

.sa-feedback-card:hover { border-color: rgba(var(--cl-t-primary), 0.2); }

.sa-trust-badges-items {
  font-family: var(--ff-mono);
  font-size: 0.6875rem;
  letter-spacing: 0.1em;
  text-transform: uppercase;
}

/* ============================================================
   8  Policy and description pages

   Terms, refund policy and every product description render through the
   theme's `.editor` wrapper. Styling it once here means the text pasted
   into the dashboard comes out typeset, with no per-product HTML fiddling:
   write plain headings, lists and paragraphs and they land correctly.
   ============================================================ */

/* ---- Normalising pasted HTML ----
   Terms, refund policy and any dashboard-written description arrive from a
   WYSIWYG editor, which means inline `style="..."` attributes: serif font
   stacks, hard-coded colours, fixed pixel sizes, and runs of empty
   paragraphs and <br> used as spacing.

   Inline styles beat any selector, so nothing here works without
   !important. That is not laziness — it is the only way to reach them.
   Everything below is the minimum needed to hand the text back to the
   page's own typography. */

.editor,
.editor * {
  font-family: inherit !important;
  background: none !important;
}

/* Headings are excluded: each :not() adds specificity, so this selector
   outranks `.editor h1` and was silently flattening every heading size the
   rules below try to set. */
.editor *:not(strong):not(b):not(a):not(code):not(h1):not(h2):not(h3):not(h4) {
  color: inherit !important;
  font-size: inherit !important;
  line-height: inherit !important;
}

.editor h2, .editor h3, .editor h4 { line-height: 1.2 !important; }

/* WYSIWYG spacing: an empty paragraph is not content. */
.editor p:empty,
.editor div:empty,
.editor p > br:only-child { display: none !important; }

.editor br + br { display: none !important; }

.editor {
  /* Rules inside a document need to be visible. The global border token is
     8% white, which vanishes on a near-black page — fine for a card edge,
     useless as a section divider. */
  --doc-rule: rgba(var(--cl-t-primary), 0.13);
  --doc-1: 88 101 242;    /* blurple */
  --doc-2: 255 95 210;    /* boost pink */
  --doc-3: 87 242 135;    /* discord green */
  max-width: 68ch;
  line-height: 1.7;
  counter-reset: doc;
}

.editor > * + * { margin-top: 0.9em; }

.editor h1, .editor h2, .editor h3, .editor h4 {
  font-family: var(--ff-heading);
  font-weight: 800;
  letter-spacing: -0.03em;
  color: rgb(var(--cl-t-primary));
  text-wrap: balance;
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: 0.5rem;
}

/* ---- The masthead ----
   A legal page arrives looking like a wall. Giving the title its own tinted
   block with a rule under it means the reader knows, before reading a word,
   that this is a document with sections rather than more page. */

.editor h1 {
  position: relative;
  margin: 0 0 2.5rem;
  padding: 1.75rem 1.5rem;
  border: 1px solid var(--doc-rule);
  border-radius: 4px;
  background:
    radial-gradient(120% 180% at 0% 0%, rgba(var(--doc-1), 0.22), transparent 60%),
    radial-gradient(120% 180% at 100% 100%, rgba(var(--doc-2), 0.16), transparent 60%),
    rgba(var(--cl-t-primary), 0.02) !important;
  font-size: clamp(1.625rem, 4.5vw, 2.25rem) !important;
  line-height: 1.05 !important;
}

body.sa-tpl-product .editor h1 { padding: 0; border: 0; background: none !important; }
body.sa-tpl-product .editor h1::before { content: none; }

.editor h1::before {
  content: 'Legal document';
  order: -1;
  flex-basis: 100%;
  margin-bottom: 0.875rem;
  font-family: var(--ff-mono);
  font-size: var(--fs-micro);
  font-weight: 500;
  letter-spacing: 0.2em;
  text-transform: uppercase;
  color: rgb(var(--doc-2));
}

/* ---- Numbered sections ----
   The index is a filled chip, not a grey numeral: at a glance you can count
   how far through you are, and the colour cycles so adjacent sections never
   blur together. */

.doc-part:first-child > h2:first-child {
  /* The document's own title. It is a section heading like any other in the
     source, so it is lifted here rather than in the markup. */
  font-size: 1.75rem !important;
  margin-bottom: 1.5rem;
}

.editor h2 {
  counter-increment: doc;
  align-items: center;
  margin-top: 3.25rem;
  padding-top: 1.75rem;
  border-top: 1px solid var(--doc-rule);
  font-size: 1.375rem !important;
}

.editor h2::before {
  content: counter(doc, decimal-leading-zero);
  display: inline-grid;
  place-items: center;
  width: 1.75rem;
  height: 1.75rem;
  border-radius: 4px;
  background: rgb(var(--doc-1));
  color: #fff;
  font-family: var(--ff-mono);
  font-size: 0.6875rem;
  font-weight: 700;
  letter-spacing: 0;
}

/* Colour is carried by the containing .doc-part, so sections inside one
   product's rules stay visually together. */

/* ---- Sub-sections ----
   An accent bar plus a tinted ground: clearly subordinate to a section,
   clearly not body copy. This is where your emoji headings live, and they
   finally have somewhere to sit. */

.editor h3 {
  align-items: center;
  margin-top: 2.25rem;
  padding: 0.5rem 0.875rem;
  border-left: 3px solid rgb(var(--doc-2));
  border-radius: 0 4px 4px 0;
  background: rgba(var(--doc-2), 0.07) !important;
  font-size: 1rem !important;
  font-weight: 700;
}

.editor h4 { margin-top: 1.75rem; font-size: var(--fs-base) !important; }

.editor h1:first-child, .editor h2:first-child, .editor h3:first-child {
  margin-top: 0;
  border-top: 0;
}

.editor h2:first-child { padding-top: 0; }

.editor > p:first-of-type {
  font-size: var(--fs-base) !important;
  color: rgba(var(--cl-t-primary), 0.9) !important;
}

.editor p, .editor li { color: rgba(var(--cl-t-primary), 0.72); }

.editor ul, .editor ol { padding-left: 0; list-style: none; }
.editor li + li { margin-top: 0.5em; }

.editor ul > li { position: relative; padding-left: 1.5rem; }

.editor ul > li::before {
  content: '';
  position: absolute;
  left: 0;
  top: 0.58em;
  width: 0.4375rem;
  height: 0.4375rem;
  border-radius: 999px;
  background: rgb(var(--doc-2));
}

.editor ol { counter-reset: e; }
.editor ol > li { position: relative; counter-increment: e; padding-left: 2.125rem; }

.editor ol > li::before {
  content: counter(e, decimal-leading-zero);
  position: absolute;
  left: 0;
  top: 0.1em;
  font-family: var(--ff-mono);
  font-size: 0.6875rem;
  font-weight: 700;
  color: rgb(var(--doc-1));
}

.editor strong { color: rgb(var(--cl-t-primary)); font-weight: 600; }

.editor code {
  font-family: var(--ff-mono);
  font-size: 0.875em;
  padding: 0.15em 0.4em;
  border-radius: 3px;
  background: rgba(var(--doc-1), 0.16) !important;
  color: rgb(var(--cl-t-primary));
}

/* The one callout style. Deadlines, eligibility, anything that turns into a
   support ticket when missed. */
.editor blockquote {
  padding: 0.9rem 1.1rem;
  border: 1px solid rgba(var(--doc-2), 0.4);
  border-left-width: 3px;
  border-radius: 0 4px 4px 0;
  background: rgba(var(--doc-2), 0.08) !important;
  color: rgba(var(--cl-t-primary), 0.88);
  font-size: var(--fs-base);
}

.editor blockquote p { color: inherit; }

.editor a { color: rgb(var(--cl-accent)); text-decoration: underline; text-underline-offset: 3px; }

.editor hr { margin: 2em 0; border: 0; border-top: 1px solid var(--doc-rule); }

.editor table {
  width: 100%;
  border-collapse: collapse;
  font-size: var(--fs-base);
}

.editor th, .editor td {
  padding: 0.6rem 0.75rem;
  border-bottom: 1px solid var(--doc-rule);
  text-align: left;
}

.editor th {
  font-family: var(--ff-mono);
  font-size: var(--fs-micro);
  font-weight: 500;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: rgba(var(--cl-t-primary), 0.45);
}

.editor td { font-variant-numeric: tabular-nums; }

/* ---- Document parts ----
   The terms page is three documents in one: server boosts, Netflix keys,
   Nitro gift links, separated by rows of em-dashes. Each becomes its own
   card with its own accent, so a buyer looking for the Netflix rules stops
   scrolling through boost rules to find them. The colour rotates, which is
   what makes the boundaries legible at a glance. */

.doc-part {
  position: relative;
  margin-top: 2.5rem;
  padding: 2rem 1.75rem;
  border: 1px solid var(--doc-rule);
  border-radius: 6px;
  background:
    radial-gradient(90% 120% at 0% 0%, rgba(var(--part), 0.09), transparent 55%),
    rgba(var(--cl-t-primary), 0.015);
  --part: var(--doc-1);
}

.doc-part:first-child { margin-top: 0; }
.doc-part:nth-child(2) { --part: var(--doc-2); }
.doc-part:nth-child(3) { --part: var(--doc-3); }

/* A coloured spine down the left edge — the cheapest possible signal that
   you have crossed into a different product's rules. */
.doc-part::before {
  content: '';
  position: absolute;
  left: -1px;
  top: -1px;
  bottom: -1px;
  width: 3px;
  border-radius: 6px 0 0 6px;
  background: rgb(var(--part));
}

.doc-part > *:first-child { margin-top: 0 !important; }

@media (max-width: 640px) {
  .doc-part { padding: 1.5rem 1.125rem; }
}

/* Section chips inherit the part's colour instead of cycling on their own,
   so the whole block reads as one document. */
.doc-part .editor h2::before,
.doc-part h2::before { background: rgb(var(--part)) !important; }
.doc-part:nth-child(2) h2::before { color: #1A0416 !important; }
.doc-part:nth-child(3) h2::before { color: #04210F !important; }

.doc-part h3 {
  border-left-color: rgb(var(--part)) !important;
  background: rgba(var(--part), 0.08) !important;
}

.doc-part ul > li::before { background: rgb(var(--part)) !important; }
.doc-part ol > li::before { color: rgb(var(--part)) !important; }

/* ---- Policy pages ----
   Terms and refund pages are reference documents. Nobody reads them front to
   back; they arrive looking for one clause. So they get a contents list, a
   scrollspy marker, and an anchor on every heading — which also means you can
   send a customer straight to a section in a ticket instead of saying
   "it's in the terms somewhere".

   The contents list is built by custom.js from whatever headings your own
   text already has. Nothing rewrites the content. */

.sa-page-terms-body,
.sa-page-refund-policy-body,
.sa-page-privacy-policy-body { max-width: 72ch; }

.legal-layout { max-width: 64rem !important; }

@media (min-width: 1024px) {
  .legal-layout {
    display: grid;
    grid-template-columns: 13rem minmax(0, 1fr);
    gap: 0 4rem;
    align-items: start;
  }
}

.legal-toc { margin-bottom: 2.5rem; }

@media (min-width: 1024px) {
  .legal-toc {
    position: sticky;
    top: 7rem;
    margin-bottom: 0;
    max-height: calc(100vh - 10rem);
    overflow-y: auto;
  }
}

.legal-toc ol {
  list-style: none;
  padding: 0;
  margin: 0;
  border-left: 1px solid var(--cl-border);
}

.legal-toc a {
  display: block;
  padding: 0.4375rem 0 0.4375rem 1rem;
  margin-left: -1px;
  border-left: 1px solid transparent;
  font-family: var(--ff-mono);
  font-size: 0.6875rem;
  line-height: 1.45;
  letter-spacing: 0.02em;
  color: rgba(var(--cl-t-primary), 0.45);
  text-decoration: none;
  transition: color var(--dur) ease, border-color var(--dur) ease;
}

.legal-toc a:hover { color: rgb(var(--cl-t-primary)); }

/* The marker is the rule itself moving, not a highlight block. */
.legal-toc a.is-on {
  border-left-color: rgb(var(--cl-accent));
  color: rgb(var(--cl-t-primary));
}

/* Anchors: visible on hover, always reachable by keyboard. */
.legal-h { position: relative; scroll-margin-top: 6.5rem; }

.legal-h::before {
  content: '#';
  position: absolute;
  left: -1.25rem;
  font-family: var(--ff-mono);
  font-size: 0.875rem;
  font-weight: 400;
  color: rgb(var(--cl-accent));
  opacity: 0;
  transition: opacity var(--dur) ease;
}

.legal-h:hover::before { opacity: 1; }

@media (max-width: 1023px) {
  .legal-h::before { display: none; }
}

/* On a policy page the first paragraph is a summary line, not a sales lead,
   so it is set apart rather than merely enlarged. */
.sa-page-terms-body > p:first-child,
.sa-page-refund-policy-body > p:first-child,
.sa-page-privacy-policy-body > p:first-child {
  padding-bottom: 1.5rem;
  margin-bottom: 0.5rem;
  border-bottom: 1px solid var(--cl-border);
}

/* ============================================================
   9  Footer
   ============================================================ */

.sa-footer-link {
  font-family: var(--ff-mono);
  font-size: 0.75rem;
  letter-spacing: 0.04em;
  transition: color var(--dur) ease;
}

/* ============================================================
   10  Motion

   The rule the rest of the file follows: animate state the visitor caused,
   never arrival. Hover, drag, open, cross a threshold — yes. Things that
   float in because the page loaded — no. That restraint is most of the
   difference between a shop that looks designed and one that looks
   generated, and it is also why scroll-reveal is switched off: it hid every
   section behind `visibility: hidden` until a library finished loading.
   ============================================================ */

@media (prefers-reduced-motion: reduce) {
  .bp-fill, .bp-fill-stripe, .bp-tier-blocks span, .bp-row, .bp-row-ico,
  .bp-cta, .bp-cta svg, .bp-srv-banner, .bp-srv-vanity, .bp-srv-tag,
  .bp-srv-icon, .bp-srv-gif, .bp-srv-lvlbadge, .bp-srv-boost-rail span,
  .sa-product-card, .sa-product-card::before, .sa-product-card-media img,
  .sa-navbar-link::after, .sa-btn {
    transition: none !important;
  }

  .bp-count.is-bump,
  .bp-tier.is-flash .bp-tier-blocks span.is-on,
  .bp-tier.is-flash .bp-tier-label,
  .bp-server.lv-3 .bp-srv-shine,
  .bp-server.lv-3 .bp-srv-sun,
  .bp-server.lv-3 .bp-srv-stars,
  .bp-server.lv-3 .bp-srv-ridge,
  .bp-server.lv-1 .bp-srv-av,
  .bp-server.lv-2 .bp-srv-av,
  .bp-server.lv-3 .bp-srv-av,
  .bp-control.is-dragging .bp-fill-stripe {
    animation: none !important;
  }

  .sa-btn--solid:hover, .bp-cta:hover { transform: none; }
  .sa-product-card:hover .sa-product-card-media img { transform: none; }
  .sa-product-card::before, .sa-navbar-link::after { transform: scaleX(1); }
}

/*
 * ── Theme hook reference (from the stock file, kept for future edits) ──
 * Page scope   body.sa-tpl-<template>      e.g. .sa-tpl-product, .sa-tpl-shop
 * Chrome       .sa-header .sa-navbar .sa-footer
 *              .sa-navbar-link .sa-navbar-logo .sa-navbar-cart .sa-footer-link
 * Sections     .sa-<component>             e.g. .sa-hero, .sa-features, .sa-faq
 *   variant    .sa-<component>--<variant>  e.g. .sa-hero--split-media
 *   inner      .sa-<component>-title / -subtitle / -eyebrow / -media /
 *              -items / -item / -actions / -link / -price / -badge / -icon
 * Primitives   .sa-btn (+ .sa-btn--<variant>), .sa-section-header
 *              (.sa-section-title / -eyebrow / -subtitle),
 *              .sa-product-card (+ .sa-product-card--<style>,
 *              .sa-product-card-title / -price / -stock / -status),
 *              .sa-product-form + .sa-add-to-cart, .sa-product-gallery,
 *              .sa-cart-panel + .sa-cart-item, .sa-searchbar, .sa-pagination,
 *              .sa-breadcrumbs, .sa-toasts + .sa-toast, .sa-feedback-card
 */