/* ============================================================
   COUCHON BJJ — _motion-stencil.css
   Primary-button brush paint-in. Applied to EVERY .btn-primary —
   hero CTA, form submit buttons, header/footer CTAs, the success
   "open the guide" button, etc. (.btn-secondary, .btn-inverted, and
   default WooCommerce buttons are NOT included.) A primary button is
   no longer a flat red rectangle: it is a hand-painted brush stroke.

   Effect:
     - Resting: accent (red) text on a transparent background —
       no border, no box.
     - On entering the viewport (.is-painted, added once by
       motion-stencil.js): a real brush-stroke asset (one of the
       brush-stroke-banner-* PNGs) — selected by the random
       .cb-brush-N class motion-stencil.js adds, with the URL set
       in CSS (below) and used as a mask over an accent fill so the
       shape "fills with red" — is REVEALED left → right. As the
       paint covers the label, the text turns white.
     - Hover: the label gains an underline.
     - Focus-visible: ink keyboard ring (accessibility).
     - Reduced-motion: the painted final state is applied instantly.

   Each button gets a random brush (so the page reads as individually
   hand-painted, not stamped). The brush URLs live in CSS classes
   (.cb-brush-N, defined below, relative to this file's location);
   motion-stencil.js only ADDS a random .cb-brush-N class. No inline
   styles, no JS-injected URLs, no PHP-injected fallback var. The
   .btn.btn-primary base carries a default brush so no-JS / pre-paint /
   reduced-motion still renders a swash (never a bare rectangle).

   Token discipline: palette/motion via :root (--accent, --white,
   --ink, --muted, --motion-*).
   ============================================================ */

/* Brush treatment on every primary button. Bounding box + base
   padding come from .btn. .btn.btn-primary (two classes) out-
   specifies the base .btn-primary solid-fill rule so the resting
   state is red-on-transparent. */
.btn.btn-primary {
  position: relative;
  isolation: isolate;
  overflow: visible;                /* the brush overflows the box */
  background: transparent;
  color: var(--accent);
  border: none;                     /* no box — just text + brush paint */
  transition: text-decoration-color 120ms ease;

  /* Brush width is capped at 11% wider than the button (111% of the
     button's box) — centred, so it bleeds 5.5% past each edge for the
     frayed ends without running long. Height stays a fixed knob;
     mask-size:contain keeps the brush's true aspect inside the box,
     so the swash still blankets the label and is never compressed. */
  --cb-brush-w: 111%;
  --cb-brush-h: 140px;

  /* Default brush — banner-2 is the safe thin swash (~5.4:1). Used
     when no .cb-brush-N class is present yet (no-JS, pre-paint frame,
     reduced-motion before init). .cb-brush-N below overrides it. */
  --couchon-brush-url: url('../img/brush/brush-stroke-banner-2.png');
}

/* ── Per-brush classes ──
   The single source of truth for which brushes exist and where they
   live. Paths are relative to THIS file (assets/css/ → assets/img/).
   motion-stencil.js's BRUSH_POOL must list exactly these N values.
   Specificity (.btn.btn-primary.cb-brush-N = 0,3,0) intentionally
   out-ranks the .btn.btn-primary default (0,2,0) so the class wins.
   Adding a brush = normalize the asset (see design system) + add a
   rule here + add its number to BRUSH_POOL. */
.btn.btn-primary.cb-brush-1 { --couchon-brush-url: url('../img/brush/brush-stroke-banner-1.png'); }
.btn.btn-primary.cb-brush-2 { --couchon-brush-url: url('../img/brush/brush-stroke-banner-2.png'); }
.btn.btn-primary.cb-brush-3 { --couchon-brush-url: url('../img/brush/brush-stroke-banner-3.png'); }
.btn.btn-primary.cb-brush-5 { --couchon-brush-url: url('../img/brush/brush-stroke-banner-5.png'); }
.btn.btn-primary.cb-brush-6 { --couchon-brush-url: url('../img/brush/brush-stroke-banner-6.png'); }
.btn.btn-primary.cb-brush-7 { --couchon-brush-url: url('../img/brush/brush-stroke-banner-7.png'); }

/* The paint layer: an accent-red box, masked to the shape of a real
   brush-stroke asset (black-on-transparent PNG → alpha mask → the
   brush "fills with red"). The PNG (not the SVG) is used because the
   PNGs are tightly cropped to the ink — the SVGs carry a big empty
   Inkscape canvas that would make `contain` render the brush small.

   Sized by --cb-brush-w/h (NOT the button) and centered behind the
   label, overflowing the button via overflow:visible. mask-size is
   `contain`, so the brush keeps its true aspect — uncompressed — and
   because the source is content-cropped, the ink spans the box and
   covers the whole label. Hidden at rest by a right-side clip;
   .is-painted wipes the clip away left → right (paints on). */
.btn.btn-primary::before {
  content: "";
  position: absolute;
  left: 50%;
  top: 50%;
  width: var(--cb-brush-w);
  height: var(--cb-brush-h);
  transform: translate(-50%, -50%);
  z-index: -1;
  pointer-events: none;
  background-color: var(--accent);
  -webkit-mask-image: var(--couchon-brush-url);
          mask-image: var(--couchon-brush-url);
  -webkit-mask-repeat: no-repeat;
          mask-repeat: no-repeat;
  -webkit-mask-position: center;
          mask-position: center;
  -webkit-mask-size: contain;       /* keep the brush's true aspect */
          mask-size: contain;
  clip-path: inset(0 100% 0 0);
  -webkit-clip-path: inset(0 100% 0 0);
}

/* ── Painted (in viewport) ── reveal L→R, then label flips to white. */
.btn.btn-primary.is-painted::before {
  animation: couchon-cta-reveal 720ms var(--motion-stamp, cubic-bezier(0.22,0.61,0.36,1)) forwards;
}
.btn.btn-primary.is-painted {
  /* 1) label flips accent→white over the reveal (couchon-cta-ink)
     2) a hard-edged offset text-shadow — the same bold, no-blur,
        opaque-black offset as the splash wordmark typography —
        fades in ~300ms AFTER the brush reveal finishes
        (reveal 720ms + 300ms = 1020ms delay). */
  animation:
    couchon-cta-ink     720ms linear forwards,
    couchon-cta-tshadow 220ms ease-out var(--cta-shadow-delay, 1020ms) forwards;
}

/* ── Pre-painted ── final painted state with NO animation. Used for
   the site-header CTA: it is the same call-to-action as the hero, so
   its brush is already rendered (it carries the hero's brush class,
   assigned in motion-stencil.js) rather than re-animating when the
   header slides in. Same end-state as the reduced-motion block. */
.btn.btn-primary.cb-prepainted::before {
  animation: none;
  clip-path: inset(0 0 0 0);
  -webkit-clip-path: inset(0 0 0 0);
}
.btn.btn-primary.cb-prepainted {
  animation: none;
  color: var(--white);
  text-shadow: 0 var(--cta-shadow-y, 3px) 0 rgba(0, 0, 0, 1);
}

@keyframes couchon-cta-reveal {
  from { clip-path: inset(0 100% 0 0); -webkit-clip-path: inset(0 100% 0 0); }
  to   { clip-path: inset(0 0    0 0); -webkit-clip-path: inset(0 0    0 0); }
}

/* Label rides accent until the paint has covered it, then flips
   white — timed to land just behind the reveal. */
@keyframes couchon-cta-ink {
  0%   { color: var(--accent); }
  55%  { color: var(--accent); }
  80%  { color: var(--white); }
  100% { color: var(--white); }
}

/* Hard-edged offset shadow — mirrors the splash wordmark style
   (opaque black, no blur, offset down). Scaled down for button
   text. --cta-shadow-y is the offset; tune per placement. */
@keyframes couchon-cta-tshadow {
  from { text-shadow: 0 0 0 rgba(0, 0, 0, 0); }
  to   { text-shadow: 0 var(--cta-shadow-y, 3px) 0 rgba(0, 0, 0, 1); }
}

/* Hover — underline the label. (Override the base .btn:hover
   opacity dim so the paint stays clean.) */
.btn.btn-primary:hover {
  opacity: 1;
  text-decoration: underline;
  text-underline-offset: 3px;
  text-decoration-thickness: 1.5px;
}

/* Focus-visible (keyboard) — ink ring 4px outside the box. */
.btn.btn-primary:focus-visible {
  outline: 3px solid var(--ink);
  outline-offset: 4px;
}

/* Active (pressed) — JS spawns .btn-stencil-spatter dots at the
   click point as a brief press feedback. */
.btn-stencil-spatter {
  position: absolute;
  width: 6px;
  height: 6px;
  border-radius: 50%;
  background-color: var(--accent);
  pointer-events: none;
  transform: scale(0);
  opacity: 1;
  z-index: 2;
}
.btn-stencil-spatter.is-spattering {
  animation: couchon-cta-spatter var(--motion-cta-spatter, 200ms) var(--motion-stamp, cubic-bezier(0.2,0,0.2,1)) forwards;
}
@keyframes couchon-cta-spatter {
  0%   { transform: scale(0); opacity: 1; }
  30%  { transform: scale(1); opacity: 1; }
  70%  { transform: scale(1); opacity: 1; }
  100% { transform: scale(1); opacity: 0; }
}

/* Disabled — paint suppressed, muted label. */
.btn.btn-primary:disabled,
.btn.btn-primary[aria-disabled="true"] {
  color: var(--muted);
  pointer-events: none;
  opacity: 0.7;
}
.btn.btn-primary:disabled::before,
.btn.btn-primary[aria-disabled="true"]::before {
  display: none;
}

/* ── Reduced-motion ──
   Painted final state instantly: full brush revealed, white label,
   no animation. Hover underline + focus ring unchanged. No spatter. */
@media (prefers-reduced-motion: reduce) {
  .btn.btn-primary.is-painted::before {
    animation: none;
    clip-path: inset(0 0 0 0);
    -webkit-clip-path: inset(0 0 0 0);
  }
  .btn.btn-primary.is-painted {
    animation: none;
    color: var(--white);
    /* shadow present in the final state, no fade-in */
    text-shadow: 0 var(--cta-shadow-y, 3px) 0 rgba(0, 0, 0, 1);
  }
  .btn-stencil-spatter { display: none !important; }
}
