/* @blade-group/design-system — brand.css: fonts + tokens + base + components + Buddy (UI kit v1.0). */
/* @blade-group/design-system — fonts.css: every face the brand uses, self-hosted.
   Imported by styles.css (globals.css) and bundled first in brand.css. */

/* ── Brand type (v1.0) — Space Grotesk (titles), Onest (text), Azeret Mono (code, data).
   All three SIL Open Font License 1.1, self-hosted as variable woff2 (latin + latin-ext
   subsets, Fontsource builds): src/assets/fonts/OFL-*.txt. No Google Fonts request.
   Montserrat is gone from 1.0. ── */
@font-face {
  font-family: 'Space Grotesk';
  src: url('../assets/fonts/space-grotesk-latin-ext-wght-normal.woff2') format('woff2');
  font-weight: 300 700; font-style: normal; font-display: swap;
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}
@font-face {
  font-family: 'Space Grotesk';
  src: url('../assets/fonts/space-grotesk-latin-wght-normal.woff2') format('woff2');
  font-weight: 300 700; font-style: normal; font-display: swap;
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
@font-face {
  font-family: 'Onest';
  src: url('../assets/fonts/onest-latin-ext-wght-normal.woff2') format('woff2');
  font-weight: 100 900; font-style: normal; font-display: swap;
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}
@font-face {
  font-family: 'Onest';
  src: url('../assets/fonts/onest-latin-wght-normal.woff2') format('woff2');
  font-weight: 100 900; font-style: normal; font-display: swap;
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
@font-face {
  font-family: 'Azeret Mono';
  src: url('../assets/fonts/azeret-mono-latin-ext-wght-normal.woff2') format('woff2');
  font-weight: 100 900; font-style: normal; font-display: swap;
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}
@font-face {
  font-family: 'Azeret Mono';
  src: url('../assets/fonts/azeret-mono-latin-wght-normal.woff2') format('woff2');
  font-weight: 100 900; font-style: normal; font-display: swap;
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
/* ── Blade Credits — the credits mark (the "double kebab") as a GLYPH, mapped to
   U+00A4, the generic currency sign every credit figure prints (`¤7`, `¤0,04`,
   « Crédits (¤) »). One glyph, 640 bytes, first in both stacks below and limited
   to that code point by `unicode-range`: every other character falls through to
   Onest, so the mark lands everywhere without a call site changing. Built
   from `double-kebab.svg` at cap height (on the 0.x Montserrat metrics). The
   same drawing is `IconCredits` for icon slots. `font-display: block`: a swapped
   "¤" flashing before the mark is the one thing worse than a short blank. ── */
@font-face {
  font-family: 'Blade Credits';
  src: url('../assets/fonts/blade-credits.woff2') format('woff2');
  font-weight: 100 900; font-style: normal; font-display: block;
  unicode-range: U+00A4;
}


/* Blade · tokens · v1.0 · 8 octobre 2026
   Remplace site/tokens.css. Les noms existants sont conservés : seules les valeurs changent.
   Nouveaux tokens : --b-gold*, --color-selection, --radius-card, --radius-panel, --logo-*. */
:root{
  /* Couleurs de marque */
  --b-paper:#FAFAF8; --b-ink:#171A1F; --b-gold:#F2B92E; --b-gold-light:#FFD35C; --b-gold-deep:#D9961A;
  --b-night:#1A2029; --b-line:#E4E2DB; --b-muted:#5C6470; --b-surface:#FFFDF8;
  --b-select:#19B6C9;                    /* sélection de texte UNIQUEMENT (variante possible : #FF6F91) */

  /* Rôles (mêmes noms qu'aujourd'hui) */
  --color-paper:var(--b-paper); --color-ink:var(--b-ink);
  --color-accent:var(--b-gold); --color-accent-ink:var(--b-ink);
  --color-rule:var(--b-line); --color-dark:var(--b-night); --color-muted:var(--b-muted); --color-surface:var(--b-surface);
  --color-dark-muted:#AEB6C0; --color-dark-rule:#2C3440; --color-focus:#C25A3C;
  --color-example-soft:#FFF3D6;
  --color-selection:var(--b-select);

  /* Typographie */
  --font-display:'Space Grotesk',Arial,sans-serif;
  --font-body:'Onest',Arial,sans-serif;
  --font-code:'Azeret Mono',ui-monospace,SFMono-Regular,Menlo,monospace;
  --font-mono:var(--font-code);           /* nom de styles.css, lu par brand/logo.css (nom de produit du logo) */
  --text-display:clamp(2.4rem,5.3vw,4.9rem); --text-heading:clamp(2.2rem,3.8vw,3.9rem);
  --text-page-title:clamp(2.25rem,4.65vw,4.5rem); --text-page-title-mobile:clamp(2.25rem,7.8vw,3.75rem);
  --text-guide-heading:clamp(1.75rem,2.5vw,2rem); --text-card-title:2rem; --text-subheading:1.65rem;
  --text-footer-heading:clamp(2.2rem,5vw,4.8rem); --text-pricing-heading:clamp(2.2rem,3.4vw,3.5rem);

  /* Espacements (inchangés) */
  --space-xs:.5rem; --space-sm:1rem; --space-md:1.5rem; --space-lg:2rem; --space-xl:3rem; --space-2xl:4rem; --space-3xl:6rem; --space-4xl:8rem;
  --layout-pair:minmax(0,1fr) minmax(0,1fr); --layout-gap:var(--space-xl); --layout-inset:var(--space-xl);
  --gap-section:clamp(80px,7vw,128px);
  --wrap-max:1600px;                      /* colonne large, au lieu de 1328px */

  /* Formes, mouvement */
  --radius:6px; --radius-card:16px; --radius-panel:28px;
  --ease-out:cubic-bezier(.16,1,.3,1); --dur-short:160ms;
  --blade-cut-width:0px; --blade-cut-height:0px;   /* l’ancien « cut » du logo n’existe plus */
  --z-skip:30;

  /* Logo */
  --logo-lockup-ratio:1.8;                /* hauteur du Buddy / hauteur des lettres b, l, d */
  --logo-plate-min:33px;                  /* sous cette hauteur : version sans plaque */
}


/* Blade · base · à charger après tokens.css
   (UI kit v1.0. Design system: the Google Fonts @import is gone — the three families are
   self-hosted in this package, see ../fonts.css, bundled first in ../brand.css.) */
body{font-family:var(--font-body);background:var(--color-paper);color:var(--color-ink)}
h1,h2,h3,h4{font-family:var(--font-display);letter-spacing:-.03em;font-weight:700}
code,kbd,pre,samp{font-family:var(--font-code);font-variant-ligatures:none}
.wrap{width:calc(100% - 96px);max-width:var(--wrap-max);margin-inline:auto}
@media (max-width:640px){.wrap{width:calc(100% - 32px)}}

/* Sélection : la seule place de la couleur d’accent. Jamais en fond de bloc, jamais en bouton. */
::selection{background:color-mix(in srgb,var(--color-selection) 32%,transparent);color:inherit}
.hl{background:color-mix(in srgb,var(--color-selection) 32%,transparent);border-radius:3px;padding:0 .04em}
.hl::after{content:"";display:inline-block;width:.06em;height:.8em;margin-left:.06em;background:var(--color-selection);vertical-align:-.04em;animation:bl-caret 1.05s steps(1) infinite}
@keyframes bl-caret{50%{opacity:0}}
@media (prefers-reduced-motion:reduce){.hl::after{animation:none}}


/* Blade · composants · v1.0 */

/* Logo dans l’en-tête : Buddy + nom en un seul fichier (logo/blade-lockup.svg) */
.brand{display:inline-flex;align-items:center}
.brand img,.brand svg{height:40px;width:auto;display:block}          /* 40 px = Buddy ≥ 33 px, garde sa plaque */
@media (max-width:640px){.brand img,.brand svg{height:34px}}

/* Buddy seul, inline (logo/blade-buddy-inline.svg) : la plaque se retire en petit */
.blade-mark{display:block;height:var(--mark-h,48px);width:auto}
.blade-mark.is-small .bm-plate{display:none}                          /* ajouter .is-small quand --mark-h ≤ 32px */

/* Boutons (mêmes classes qu’aujourd’hui) */
.button{display:inline-flex;align-items:center;justify-content:space-between;gap:var(--space-lg);min-height:54px;padding:14px 20px;border-radius:var(--radius);border:1px solid transparent;font:600 16px/1 var(--font-body);white-space:nowrap;cursor:pointer;transition:background-color var(--dur-short) ease,transform var(--dur-short) var(--ease-out)}
.button.primary{background:var(--color-accent);color:var(--color-accent-ink)}
.button.primary:hover{background:color-mix(in srgb,var(--color-accent) 85%,var(--color-paper))}
.button.btn-line{background:transparent;border-color:var(--color-rule);color:var(--color-ink)}
.button.btn-line:hover{border-color:var(--color-ink)}
.button.dark{background:var(--color-ink);color:var(--color-paper)}
.button.dark:hover{background:color-mix(in srgb,var(--color-ink) 85%,var(--color-paper))}
.button .arrow{font-family:var(--font-code);font-weight:500}
.on-dark .button.btn-line{border-color:var(--color-dark-rule);color:var(--color-paper)}

/* Pastilles */
.pill{display:inline-flex;align-items:center;gap:8px;border-radius:999px;padding:6px 14px;font:500 14px var(--font-body);border:1px solid var(--color-rule);color:var(--color-muted);background:var(--color-surface)}
.pill .dot{width:7px;height:7px;border-radius:50%;background:var(--b-gold-deep)}
.tag{display:inline-block;font:500 11px var(--font-code);letter-spacing:.06em;text-transform:uppercase;background:var(--color-example-soft);color:var(--b-gold-deep);border-radius:999px;padding:3px 8px}
.chip{display:inline-block;font:500 12px var(--font-code);color:var(--color-dark-muted);background:#1E2530;border-radius:999px;padding:4px 10px}

/* Cartes */
.card{background:var(--color-surface);border:1px solid var(--color-rule);border-radius:var(--radius-card);padding:var(--space-lg)}
.card h3{font-size:var(--text-card-title);line-height:1.05;margin:0 0 var(--space-sm)}
.panel{background:var(--color-dark);color:var(--color-paper);border-radius:var(--radius-panel);padding:clamp(28px,4vw,56px)}

/* Bloc de code */
.code{background:var(--color-dark);color:#E6EBF0;border-radius:var(--radius-card);overflow:hidden;font:14px/1.7 var(--font-code)}
.code-bar{display:flex;gap:4px;padding:8px;border-bottom:1px solid var(--color-dark-rule)}
.code-bar button{all:unset;cursor:pointer;padding:6px 12px;border-radius:8px;font:500 13px var(--font-code);color:var(--color-dark-muted)}
.code-bar button[aria-selected="true"]{background:#262E3A;color:#fff}
.code pre{margin:0;padding:20px 22px;overflow-x:auto}
.code .k{color:#FFD35C} .code .s{color:#9FE3EA} .code .c{color:#7C8694}

/* FAQ */
.faq-item{border-top:1px solid var(--color-rule)}
.faq-item summary{list-style:none;display:flex;justify-content:space-between;gap:var(--space-md);padding:22px 0;font:600 20px var(--font-body);cursor:pointer}
.faq-item summary::-webkit-details-marker{display:none}
.faq-item summary::after{content:"+";font:500 24px/1 var(--font-code);color:var(--color-muted)}
.faq-item[open] summary::after{content:"−"}
.faq-item p{margin:0 0 22px;color:var(--color-muted);max-width:70ch}


/* Blade · Buddy, static (design system 1.0)
   For a page without React: inline one of assets/brand/buddy/*.svg (or the kit's
   logo/blade-buddy-inline.svg) with class="buddy", then add the loops below. The eyes
   are the file's <g class="eyes">. Recipes taken from the v10 home page. */
.buddy{display:block;overflow:visible}

/* Blink: shut for a beat every 5.2 s (v10 .blink .eyes). On `scale`, not `transform`,
   so it composes with the translate buddy-follow.js writes on the same group. */
.buddy-blink .eyes{animation:blade-buddy-blink 5.2s infinite;transform-box:fill-box;transform-origin:center}
@keyframes blade-buddy-blink{0%,93%,100%{scale:1 1}95%{scale:1 .1}}

/* Peek: rises from behind an edge and sinks back, every 7 s (v10 .ft .peek). Put it in
   a box with overflow:hidden, or position it at the top edge of a card. */
.buddy-peek{animation:blade-buddy-peek 7s ease-in-out infinite}
@keyframes blade-buddy-peek{0%,100%{transform:translateY(16px)}12%,60%{transform:translateY(0)}72%{transform:translateY(16px)}}

/* Follow: add class="buddy-follow" and load assets/brand/motion/buddy-follow.js. */

/* Key avatar (v10 .kav): the plateless dark Buddy on an ink tile, beside a name. */
.buddy-avatar{display:inline-flex;width:24px;height:24px;border-radius:7px;background:var(--color-ink,#171A1F);align-items:center;justify-content:center;margin:-4px 8px 0 0;vertical-align:middle}
.buddy-avatar svg{width:20px;height:20px}

/* Inline in a heading (v10 .inl): Buddy at the height of the letters. */
.buddy-inline{display:inline-block;width:.86em;height:.86em;vertical-align:-.1em;margin:0 .04em}
.buddy-inline svg{width:100%;height:100%}

@media (prefers-reduced-motion:reduce){.buddy-blink .eyes,.buddy-peek{animation:none}}


/* Blade · the animated lockup (design system 1.1). Markup: lib/bladeLogo (bladeLogoArt /
   bladeLogoHtml, or <BladeLogo>); controller: animateBladeLogo, or the static page's
   assets/brand/motion/blade-logo.js. Every rule is gated on data-motion="on", which the
   controller only sets when motion is allowed: without it (no script, reduced motion,
   animated={false}) this file draws the still lockup.

   Lengths inside the SVGs are user units of the drawing: Buddy's 240 box, the lockup's
   1260-unit height for the wordmark. Sources, nothing invented:
     [L] kit Lottie, motion/blade-buddy-intro.json + -idle.json (60 fps; easing
         cubic-bezier(.33,0,.67,1), breathing cubic-bezier(.45,0,.55,1));
     [V] kit animated logo, motion/blade-logo-light.mp4 (30 fps, read frame by frame);
     [P] v10 home page (blink .blink .eyes, follow, the `clin` expression). */

/* ── Still lockup (static pages; <BladeLogo> also has its CSS module) ── */
.blade-logo { display: inline-flex; align-items: center; flex-shrink: 0; color: var(--text-primary, var(--color-ink, #171A1F)); }
.blade-logo[data-tone="light"] { color: #171A1F; }
.blade-logo[data-tone="dark"] { color: #FAFAF8; }
.blade-logo-product {
  margin-left: 12px; padding-left: 12px; border-left: 1px solid var(--border, #E4E2DB);
  font: 600 11px/1 var(--font-mono); letter-spacing: .12em; text-transform: uppercase;
  color: var(--text-secondary, #5C6470); white-space: nowrap;
}
.blm-buddy, .blm-wordmark { display: block; flex-shrink: 0; overflow: visible; }
.blm-eyes-ink { color: #171A1F; }
.blm-eyes-flat { color: var(--blm-flat-eyes, #171A1F); }
.blade-logo[data-tone="auto"] { --blm-flat-eyes: var(--text-primary, #171A1F); }
.blade-logo[data-tone="dark"] { --blm-flat-eyes: #FAFAF8; }
.blm-wink, .blm-caret { display: none; }
.blm-caret { fill: var(--color-selection, #19B6C9); }

/* Every moving group scales and turns about its own centre, as the Lottie anchors do. */
.blade-logo[data-motion="on"] :is(.blm-pop, .blm-chev-l, .blm-chev-r, .blm-plate, .blm-eyes-in, .blm-blink) {
  transform-box: fill-box; transform-origin: center;
}

/* ── Intro « buddy » [L intro, 2.6 s, played once]: the chevrons slide in from 140 units
   out and overshoot by 6 (frames 0–27–36), fading in over 9 frames; the plate swells from
   nothing to 108 % and settles (21–42–51); the eyes open (48–60), blink (96–100–104) and
   glance up-right by 6 × 2 (114–126). The root's clock tells the controller it is over. ── */
.blade-logo[data-motion="on"][data-phase="intro-buddy"] { animation: blm-clock 2.6s linear; }
.blade-logo[data-motion="on"][data-phase="intro-buddy"] :is(.blm-chev-l, .blm-chev-r, .blm-plate, .blm-eyes-in) { animation-duration: 2.6s; animation-timing-function: cubic-bezier(.33,0,.67,1); animation-fill-mode: both; }
.blade-logo[data-motion="on"][data-phase="intro-buddy"] .blm-chev-l { animation-name: blm-in-fade, blm-in-chev-l; }
.blade-logo[data-motion="on"][data-phase="intro-buddy"] .blm-chev-r { animation-name: blm-in-fade, blm-in-chev-r; }
.blade-logo[data-motion="on"][data-phase="intro-buddy"] .blm-plate { animation-name: blm-in-plate; }
.blade-logo[data-motion="on"][data-phase="intro-buddy"] .blm-eyes-in { animation-name: blm-in-eyes; }
@keyframes blm-clock { from { opacity: 1; } to { opacity: 1; } }
@keyframes blm-in-fade { 0% { opacity: 0; } 5.769%, 100% { opacity: 1; } }
@keyframes blm-in-chev-l { 0% { translate: -140px 0; } 17.308% { translate: 6px 0; } 23.077%, 100% { translate: 0 0; } }
@keyframes blm-in-chev-r { 0% { translate: 140px 0; } 17.308% { translate: -6px 0; } 23.077%, 100% { translate: 0 0; } }
@keyframes blm-in-plate { 0%, 13.462% { scale: 0; } 26.923% { scale: 1.08; } 32.692%, 100% { scale: 1; } }
@keyframes blm-in-eyes {
  0%, 30.769% { scale: 1 0; translate: 0 0; }
  38.462%, 61.538% { scale: 1 1; }
  64.103% { scale: 1 .1; }
  66.667% { scale: 1 1; }
  73.077% { translate: 0 0; }
  80.769%, 100% { scale: 1 1; translate: 6px -2px; }
}

/* ── Intro « lockup » [V, 6 s]: Buddy pops in tilted and overshoots (0.03–0.8 s), his
   eyes rise from the bottom of the plate (0.9–1.13 s); a cyan caret appears (2.03 s),
   « b l a d e » is typed (2.17, 2.30, 2.40, 2.50, 2.60 s) while he looks at it, 9 units
   right (1.95–2.15 s, back 4.35–4.5 s); the caret blinks off (2.27–2.5 s) and leaves
   (2.77 s); he winks at 4.63 s and holds it to the end. ── */
.blade-logo[data-motion="on"][data-phase="intro-lockup"] { animation: blm-clock 6s linear; }
.blade-logo[data-motion="on"][data-phase="intro-lockup"] .blm-pop { animation: blm-pop 6s both; }
.blade-logo[data-motion="on"][data-phase="intro-lockup"] .blm-eyes-in { animation: blm-rise 6s cubic-bezier(.2,.6,.35,1) both; }
.blade-logo[data-motion="on"][data-phase="intro-lockup"] .blm-glance { animation: blm-look 6s cubic-bezier(.33,0,.67,1) both; }
.blade-logo[data-motion="on"][data-phase="intro-lockup"] .blm-wink { display: inline; animation: blm-wink-in 6s step-end both; }
.blade-logo[data-motion="on"][data-phase="intro-lockup"] .blm-rest { animation: blm-wink-out 6s step-end both; }
.blade-logo[data-motion="on"][data-phase="intro-lockup"] .blm-caret { display: inline; animation: blm-caret 6s step-end both; }
.blade-logo[data-motion="on"][data-phase="intro-lockup"] :is(.blm-g1, .blm-g2, .blm-g3, .blm-g4, .blm-g5) { animation: blm-type 0s both; }
.blade-logo[data-motion="on"][data-phase="intro-lockup"] .blm-g1 { animation-delay: 2.167s; }
.blade-logo[data-motion="on"][data-phase="intro-lockup"] .blm-g2 { animation-delay: 2.3s; }
.blade-logo[data-motion="on"][data-phase="intro-lockup"] .blm-g3 { animation-delay: 2.4s; }
.blade-logo[data-motion="on"][data-phase="intro-lockup"] .blm-g4 { animation-delay: 2.5s; }
.blade-logo[data-motion="on"][data-phase="intro-lockup"] .blm-g5 { animation-delay: 2.6s; }
@keyframes blm-pop {
  0%, .556% { opacity: 0; scale: .35; rotate: -40deg; animation-timing-function: cubic-bezier(.2,.6,.35,1); }
  2.778% { opacity: 1; }
  4.167% { rotate: 0deg; }
  7.222% { scale: 1.14; animation-timing-function: ease-in-out; }
  13.333%, 100% { opacity: 1; scale: 1; rotate: 0deg; }
}
@keyframes blm-rise {
  0%, 15% { opacity: 0; translate: 0 66px; scale: 1 .2; }
  15.556% { opacity: 1; translate: 0 60px; scale: 1 .33; }
  18.889%, 100% { opacity: 1; translate: 0 0; scale: 1 1; }
}
@keyframes blm-look { 0%, 32.5% { translate: 0 0; } 35.833%, 72.5% { translate: 9px 0; } 75%, 100% { translate: 0 0; } }
@keyframes blm-wink-out { 0% { opacity: 1; } 77.222%, 100% { opacity: 0; } }
@keyframes blm-wink-in { 0% { opacity: 0; } 77.222%, 100% { opacity: 1; } }
@keyframes blm-type { from { opacity: 0; } to { opacity: 1; } }
/* Caret x: 0 before the b, then 40 units after each glyph's right edge (602, 827.8, 1437.6, 2011.5, 2600.3). */
@keyframes blm-caret {
  0% { opacity: 0; translate: 0 0; }
  33.889% { opacity: 1; translate: 0 0; }
  36.111% { translate: 642px 0; }
  37.778% { opacity: 0; }
  38.333% { translate: 867.8px 0; }
  40% { translate: 1477.6px 0; }
  41.667% { opacity: 1; translate: 2051.5px 0; }
  43.333% { translate: 2640.3px 0; }
  46.111%, 100% { opacity: 0; translate: 2640.3px 0; }
}

/* ── Rest: blink [P, 5.2 s, shut at 95 %]; breathing [L idle, 6 s: down, back, up, back;
   the eyes do not breathe; the Lottie's ±3 units widened to ±8 at Lucas's request (12/10),
   since ±3 did not read at console sizes]; on a touch screen, the glance [L idle: right 7 × 2
   up at 2.0–2.3 s, left at 3.2–3.5 s, back at 3.9–4.1 s]. With a pointer, the controller
   moves .blm-gaze instead [P follow]. ── */
.blade-logo[data-motion="on"][data-phase="idle"] .blm-blink { animation: blm-blink 5.2s infinite; }
.blade-logo[data-motion="on"][data-phase="idle"] .blm-body { animation: blm-breathe 6s cubic-bezier(.45,0,.55,1) infinite; }
.blade-logo[data-motion="on"][data-phase="idle"][data-glance="true"] .blm-glance { animation: blm-glance 6s cubic-bezier(.33,0,.67,1) infinite; }
@keyframes blm-blink { 0%, 93%, 100% { scale: 1 1; } 95% { scale: 1 .1; } }
@keyframes blm-breathe { 0%, 50%, 100% { translate: 0 0; } 25% { translate: 0 8px; } 75% { translate: 0 -8px; } }
@keyframes blm-glance {
  0%, 33.333% { translate: 0 0; }
  38.333%, 53.333% { translate: 7px -2px; }
  58.333%, 65% { translate: -7px -2px; }
  68.333%, 100% { translate: 0 0; }
}

/* ── Hover: the wink the animated logo ends on [V 4.63 s; P `clin`]; about one hover in
   three the controller draws the peek instead (data-peek, never twice in a row): the
   <Buddy peek> loop [P .ft .peek, 7 s, 16 px], same keyframes, played once from the moment
   it starts to sink (60 %) to the moment it is back up (112 %): 3.64 s. The lockup clips
   it, as the peek's container does. ── */
.blade-logo[data-motion="on"][data-phase="idle"]:not([data-peek="true"]):hover .blm-rest { display: none; }
.blade-logo[data-motion="on"][data-phase="idle"]:not([data-peek="true"]):hover .blm-wink { display: inline; }
.blade-logo[data-motion="on"][data-phase="idle"][data-peek="true"] { overflow: hidden; }
.blade-logo[data-motion="on"][data-phase="idle"][data-peek="true"] .blm-buddy { animation: blm-peek 7s ease-in-out -4.2s 1.12; }
@keyframes blm-peek { 0%, 100% { transform: translateY(16px); } 12%, 60% { transform: translateY(0); } 72% { transform: translateY(16px); } }

/* ── A hidden tab holds every animation where it is. ── */
.blade-logo[data-paused="true"], .blade-logo[data-paused="true"] * { animation-play-state: paused !important; }

/* ── Belt and braces: the controller already stops on reduced motion. ── */
@media (prefers-reduced-motion: reduce) {
  .blade-logo, .blade-logo * { animation: none !important; }
}

