.hf{
  --void:#070808; --bg:#0F0F10; --surf:#151617; --raised:#1C1E1F;
  --hair:rgba(233,240,243,.10); --hair2:rgba(233,240,243,.19);
  --tx:#E9EEF0; --br:#F4F8FA; --dim:#A9B6BC; --faint:#7D888E; --ghost:#545D62;
  --entity:#F5A97F; --note:#8BD5CA; --project:#C6A0F6; --fact:#A6DA95; --relation:#8AADF4; --decay:#EE99A0;
  --contre:#F4F8FA;
  /* L'accent est une PROJECTION d'une couleur de rôle, jamais un hex à lui.
     Le choisir mauve ne repeint pas le rôle projet : une puce de projet reste
     mauve parce qu'elle est un projet. Même règle que dans l'application. */
  --accent:var(--note);
  --onacc:#0D0E0F; --lead:#C6D0D4;
  background:var(--bg); color:var(--tx);
  font-family:Geist,ui-sans-serif,system-ui,sans-serif; font-size:16px; line-height:1.55;
  -webkit-font-smoothing:antialiased; min-height:100%; position:relative;
}
.hf.light{
  --void:#E8E8E8; --bg:#F4F4F4; --surf:#FAFAFA; --raised:#FFFFFF;
  --hair:rgba(17,17,17,.12); --hair2:rgba(17,17,17,.22);
  --tx:#141414; --br:#0A0A0A; --dim:#4B4B4B; --faint:#7B7B7B; --ghost:#A6A6A6;
  --entity:#D9760B; --note:#178F86; --project:#8839EF; --fact:#3D9A2A; --relation:#1E66F5; --decay:#E64553;
  --contre:#141414;
  --onacc:#FFFFFF; --lead:#2E2E2E;
}
.hf *{box-sizing:border-box}
.hf .mono,.hf h1,.hf h2,.hf h3,.hf .kick,.hf .tag,.hf .lay{font-family:"Monaspace Neon","Geist Mono",ui-monospace,monospace}
.hf h1,.hf h2,.hf h3{font-weight:500;margin:0}
.hf h1{font-size:clamp(32px,4.1vw,52px);line-height:1.02;letter-spacing:-.035em}
.hf h2{font-size:32px;line-height:1.1;letter-spacing:-.025em}
.hf h3{font-size:16px;line-height:1.25;letter-spacing:-.01em}
.hf p{margin:0 0 14px;color:var(--dim);max-width:60ch}
.hf .lead{font-size:18px;line-height:1.5;color:var(--lead);max-width:54ch}
.hf .kick{font-size:10.5px;letter-spacing:.18em;text-transform:uppercase;color:var(--faint)}
.hf .wrap{max-width:1200px;margin:0 auto;padding:0 60px}
.hf .sec{padding:104px 0;border-top:1px solid var(--hair);position:relative}
.hf .sec.flush{border-top:0}
.hf a{color:var(--accent);text-decoration:none}
.hf a:hover{color:var(--tx)}
.hf .btn{display:inline-flex;align-items:center;justify-content:center;min-height:50px;padding:0 26px;
  background:var(--accent);color:var(--onacc);font-size:14.5px;font-weight:500;border-radius:10px;border:0;
  font-family:inherit;cursor:pointer;transition:transform .16s ease,filter .16s ease}
.hf .btn:hover{transform:translateY(-1px);filter:brightness(1.08)}
.hf .btn.ghost{background:transparent;color:var(--tx);border:1px solid var(--hair2)}
.hf .btn.ghost:hover{border-color:var(--tx);filter:none}
.hf .btn.sm{min-height:40px;padding:0 18px;font-size:13px}
.hf .card{background:var(--surf);border:1px solid var(--hair);border-radius:12px;padding:24px;transition:border-color .2s ease}
.hf .tag{font-size:10px;letter-spacing:.05em;padding:3px 7px;border:1px solid var(--hair2);border-radius:6px;color:var(--faint);white-space:nowrap}
.hf .tag.e{border-color:color-mix(in oklab,var(--entity) 55%,transparent);color:var(--entity)}
.hf .tag.n{border-color:color-mix(in oklab,var(--accent) 55%,transparent);color:var(--accent)}
.hf .tag.p{border-color:color-mix(in oklab,var(--project) 55%,transparent);color:var(--project)}
.hf .tag.r{border-color:color-mix(in oklab,var(--relation) 55%,transparent);color:var(--relation)}
.hf ul.b{margin:0;padding:0;list-style:none;display:flex;flex-direction:column;gap:10px}
.hf ul.b li{position:relative;padding-left:18px;color:var(--dim);font-size:14.5px;line-height:1.5}
.hf ul.b li::before{content:"";position:absolute;left:1px;top:9px;width:5px;height:5px;border-radius:50%;background:var(--ghost)}

/* en-tête */
.hf .hdr{position:sticky;top:0;z-index:20;background:color-mix(in oklab,var(--bg) 88%,transparent);
  backdrop-filter:blur(14px);border-bottom:1px solid var(--hair)}
.hf .hdr .in{max-width:1200px;margin:0 auto;padding:14px 60px;display:flex;align-items:center;gap:26px}
.hf .nav{display:flex;gap:22px;flex-grow:1}
.hf .nav span{font-family:"Monaspace Neon","Geist Mono",monospace;font-size:11.5px;letter-spacing:.06em;color:var(--dim);cursor:pointer}
.hf .nav span:hover{color:var(--tx)}
.hf .vsw{display:inline-flex;border:1px solid var(--hair2);border-radius:9px;overflow:hidden;cursor:pointer;background:transparent;padding:0;font-family:inherit}
.hf .vsw b{font-weight:400;font-family:"Monaspace Neon","Geist Mono",monospace;font-size:10px;letter-spacing:.12em;
  text-transform:uppercase;padding:8px 12px;color:var(--faint)}
.hf .vsw b.on{background:var(--tx);color:var(--bg)}

/* champ de caractères en fond */
.hf .live{position:absolute;inset:0;overflow:hidden;pointer-events:auto}
.hf .lay{position:absolute;inset:0;margin:0;white-space:pre;pointer-events:none;font-weight:400}
.hf .lay.a{color:var(--br)}
.hf .lay.b{color:var(--br)}   /* le contour de l'astre creux : même encre que l'astre plein, comme le signe */
.hf .lay.c{color:var(--ghost);opacity:.55}
.hf .lay.d{color:var(--entity)}

/* mur de captures */
.hf .mas{column-count:4;column-gap:16px}
.hf .cap{break-inside:avoid;margin-bottom:16px;display:inline-flex;width:100%;flex-direction:column;gap:12px;
  background:var(--surf);border:1px solid var(--hair);border-radius:12px;padding:18px}
.hf .cap q{font-style:italic;font-size:15.5px;line-height:1.45;color:var(--br);quotes:none}
.hf .cap .out{display:flex;gap:6px;flex-wrap:wrap;padding-top:12px;border-top:1px solid var(--hair)}

/* l'oubli : ça pâlit seul, le curseur rallume */
@keyframes hfsink{from{opacity:1}to{opacity:.14}}
.hf .liv{animation:hfsink 11s ease-in 1.5s forwards}
.hf .liv:hover{animation:none;opacity:1;transition:opacity .2s ease-out;border-color:var(--hair2)}

/* parcours */
.hf .step{display:grid;grid-template-columns:92px 1fr;gap:22px;padding:20px 0;border-top:1px solid var(--hair)}
.hf .step .when{font-family:"Monaspace Neon","Geist Mono",monospace;font-size:10.5px;letter-spacing:.12em;
  text-transform:uppercase;color:var(--faint);padding-top:4px}
.hf .ramp{font-family:"Monaspace Neon","Geist Mono",monospace;font-size:15px;letter-spacing:.08em;white-space:pre}
.hf .ftr{padding:64px 0 48px;border-top:1px solid var(--hair)}
.hf .ftr h4{font-family:"Monaspace Neon","Geist Mono",monospace;font-size:10px;letter-spacing:.16em;
  text-transform:uppercase;color:var(--faint);margin:0 0 14px;font-weight:400}
.hf .ftr li{font-size:13.5px;color:var(--dim);margin-bottom:9px;list-style:none;cursor:pointer}
.hf .ftr li:hover{color:var(--tx)}
.hf .ftr ul{margin:0;padding:0}
.hf.n{font-size:15px}
.hf.n .wrap{padding:0 20px}
.hf.n .hdr .in{padding:12px 20px;gap:12px}
.hf.n .nav{display:none}
.hf.n .sec{padding:64px 0}
.hf.n h1{font-size:38px;letter-spacing:-.03em}
.hf.n h2{font-size:25px}
.hf.n .lead{font-size:16.5px;max-width:none}
.hf.n p{max-width:none}
.hf.n .mas{column-count:1}
.hf.n .btn{width:100%}
.hf.n .step{grid-template-columns:66px 1fr;gap:14px;padding:16px 0}
.hf.n .ftr{padding:44px 0 36px}

/* pas numérotés, onglets factices, encadrés (pages secondaires) */
.hf .st{display:grid;grid-template-columns:58px 1fr;gap:20px;align-items:start}
.hf .st .no{font-family:"Monaspace Neon","Geist Mono",monospace;font-size:30px;line-height:1;
  letter-spacing:-.04em;color:var(--hair2);padding-top:2px}
.hf .tabbar{display:flex;border:1px solid var(--hair);border-radius:12px;overflow:hidden;background:var(--surf)}
.hf .tabbar > div{flex:1;padding:13px 8px;text-align:center;border-right:1px solid var(--hair);
  font-family:"Monaspace Neon","Geist Mono",monospace;font-size:11.5px;letter-spacing:.09em;color:var(--faint)}
.hf .tabbar > div:last-child{border-right:0}
.hf .tabbar > div.on{color:var(--tx);background:var(--raised);box-shadow:inset 0 -2px 0 var(--accent)}
.hf .seg{display:inline-flex;flex-wrap:wrap;gap:6px}
.hf .warn{border-left:2px solid var(--entity)}
.hf .todo{display:inline-block;font-family:"Monaspace Neon","Geist Mono",monospace;font-size:10.5px;
  letter-spacing:.04em;color:var(--entity);border:1px dashed color-mix(in oklab,var(--entity) 50%,transparent);
  border-radius:6px;padding:2px 7px}
.hf .acc{border-bottom:1px solid var(--hair);padding:20px 24px}
.hf .acc:last-child{border-bottom:0}
.hf .acc .q{display:flex;justify-content:space-between;align-items:baseline;gap:20px}
.hf .acc .q h3{margin:0;font-size:15.5px;color:var(--tx)}
.hf .acc .q i{font-style:normal;color:var(--faint);font-size:16px}
.hf .acc p{margin:11px 0 0;font-size:14.5px;max-width:78ch}
.hf .tbl{display:grid;font-size:14px}
.hf .tbl > div{padding:15px 20px;border-bottom:1px solid var(--hair)}
.hf .col{max-width:720px}
.hf .col p{max-width:none}
.hf.n .st{grid-template-columns:42px 1fr;gap:14px}
.hf.n .tabbar > div{font-size:10px;padding:11px 4px}

/* ============================================================ le framing
   Vocabulaire repris de runner.now et transposé sur notre versant : un filet
   POINTILLÉ 1 px découpe la page en cellules et traverse toutes les sections,
   un filet PLEIN cerne les objets de contenu. Tout vient d'un seul dégradé
   répété, il n'y a pas une ligne de markup pour ça. */
.hf{--guide:color-mix(in oklab,var(--tx) 24%,transparent);
  --grille:repeating-linear-gradient(to bottom,var(--guide) 0 5px,transparent 5px 10px);
  --grille-h:repeating-linear-gradient(to right,var(--guide) 0 5px,transparent 5px 10px)}

/* Les deux verticales se suivent d'une section à l'autre : la gouttière est
   continue sur toute la hauteur du document. Le trait du haut remplace la
   bordure pleine des sections, sinon les deux se superposeraient. */
.hf{counter-reset:sinamSec}
.hf .sec{counter-increment:sinamSec;border-top:0}
.hf:not(.n) .sec::before{content:"";position:absolute;inset:0;z-index:0;pointer-events:none;
  background-repeat:no-repeat;background-size:1px 100%,1px 100%,100% 1px;
  background-position:calc(50% - 592px) 0,calc(50% + 592px) 0,0 0;
  background-image:var(--grille),var(--grille),var(--grille-h)}
/* une section « flush » ouvre une page : pas de trait au dessus d'elle */
.hf:not(.n) .sec.flush::before{background-image:var(--grille),var(--grille)}
.hf:not(.n) .sec::after{content:counter(sinamSec,decimal-leading-zero);position:absolute;z-index:1;
  top:13px;left:calc(50% - 540px);pointer-events:none;
  font-family:"Monaspace Neon","Geist Mono",monospace;font-size:10.5px;letter-spacing:.1em;
  color:var(--entity);opacity:.6}
.hf:not(.n) .sec.flush::after{display:none}
.hf .sec > .wrap{position:relative;z-index:1}
/* en dessous, la gouttière tomberait dans le texte : on la retire, et la
   bordure pleine reprend son rôle de séparateur */
@media (max-width:1240px){
  .hf .sec::before,.hf .sec::after{display:none}
  .hf .sec{border-top:1px solid var(--hair)}
  .hf .sec.flush{border-top:0}
}

/* Boîte de recadrage du champ ASCII. Elle existe pour que le rognage ne soit
   plus porté par la section : sinon tout bloc qui déborde vers le bas
   disparaîtrait avec l'astre. */
.hf .ch{position:absolute;inset:0;overflow:hidden;pointer-events:none}
/* clip et non hidden : l'axe vertical reste débordable, seul l'horizontal est coupé */
.hf .sec.flush{overflow-x:clip}

/* ------------------------------------------------------ lettres et cadres */
/* les lettres en cours d'arrivée, pendant le brouillage */
.hf .sc{transition:color .3s ease}
.hf .sc.go{color:var(--ghost)}
/* cadre SVG : filet net, calé au demi-pixel, tracé par hero.js */
.hf .cadre{position:absolute;top:0;left:0;overflow:visible;pointer-events:none;z-index:0}
.hf .cadre rect,.hf .cadre line{stroke:var(--hair2);stroke-width:1;vector-effect:non-scaling-stroke;
  stroke-dasharray:100;stroke-dashoffset:100}
.hf .cadre.trace rect,.hf .cadre.trace line{stroke-dashoffset:0}
.hf .cadre.pointille rect{stroke-dasharray:4 5;stroke-dashoffset:0;stroke:var(--hair)}
.hf .cadre.pointille line{stroke-dasharray:4 5;stroke-dashoffset:0}

/* --------------------------------------------------------------- odomètre */
/* Emprunté à contentarchitecture.dev, transposé sur notre rampe. Chaque lettre
   est une colonne de six glyphes : la vraie, quatre tirées de la rampe de la
   trame, la vraie à nouveau. Au survol une variable CSS passe de 0 à 1 et les
   colonnes descendent, décalées l'une après l'autre. Après la mise en place par
   hero.js plus rien ne tourne : c'est une transition.
   La nav de l'en-tête en est volontairement exclue : elle garde son survol. */
.hf .odo{position:relative;display:inline-block;overflow:hidden;height:1em;line-height:1em;vertical-align:baseline}
.hf .odo .sz{visibility:hidden}
.hf .odo-l{display:inline;text-align:center}
.hf .odo .rl{position:absolute;top:0;left:0;right:0;display:flex;flex-direction:column;
  transform:translateY(calc(var(--odo,0) * -5em))}
.hf .odo .rl b{display:block;height:1em;line-height:1em;font-weight:inherit}
/* Le rouleau ne tourne qu'à l'ENTRÉE. À la sortie il revient en place d'un coup :
   la première et la dernière case portent la même vraie lettre, donc le saut ne
   se voit pas. Le laisser remonter à rebours repassait par les glyphes au
   hasard et donnait l'air d'un bouton cassé, surtout en balayant plusieurs
   boutons à la suite. Réservé aux vrais pointeurs : au doigt, :hover reste
   collé après le toucher. */
@media (hover:hover) and (pointer:fine){
  .hf .btn:hover,.hf [data-odo]:hover{--odo:1}
  @media (prefers-reduced-motion:no-preference){
    .hf .btn:hover .odo .rl,.hf [data-odo]:hover .odo .rl{transition:transform 520ms cubic-bezier(.23,1,.32,1)}
  }
}

/* Le point d'état, dans l'angle du bouton principal : un rond plein et un halo
   qui s'ouvre. C'est le seul élément du site qui dit « ça tourne, là, chez toi ». */
.hf .btn{position:relative}
.hf .pt{position:absolute;top:7px;right:7px;width:6px;height:6px;color:inherit}
.hf .pt i,.hf .pt u{position:absolute;inset:0;border-radius:50%;background:currentColor}
.hf .pt i{opacity:.5;animation:sinamPing 2.6s cubic-bezier(0,0,.2,1) infinite}
@keyframes sinamPing{0%{opacity:.5;transform:scale(1)}75%,100%{opacity:0;transform:scale(2.8)}}
@media (prefers-reduced-motion:reduce){.hf .pt i{animation:none}}

/* Le curseur de terminal, en fin de ligne : un bloc plein qui clignote net.
   À ne pas confondre avec le point du bouton, qui pulse avec un halo : celui-ci
   dit « la ligne continue », l'autre dit « ça tourne ». */
.hf .cl{display:inline-block;width:7px;height:14px;border-radius:0;background:var(--accent);
  vertical-align:-3px;margin-left:1px;animation:sinamClignote 1.05s steps(1) infinite}
@keyframes sinamClignote{0%,50%{opacity:1}50.01%,100%{opacity:0}}
@media (prefers-reduced-motion:reduce){.hf .cl{animation:none}}

/* ------------------------------------------------------- bandeau défilant */
/* Deux copies du fil se suivent : quand la première a fini de sortir par la
   gauche, la seconde est exactement à sa place, donc la boucle ne se voit pas.
   Il faut que les deux copies bout à bout soient plus larges que la fenêtre. */
.hf .ban{position:relative;display:flex;overflow:hidden;
  -webkit-mask-image:linear-gradient(to right,transparent,#000 7%,#000 90%,transparent);
  mask-image:linear-gradient(to right,transparent,#000 7%,#000 90%,transparent)}
.hf .ban .fil{display:flex;flex:0 0 auto;white-space:nowrap;align-items:center;
  font-family:"Monaspace Neon","Geist Mono",monospace;font-size:11px;letter-spacing:.05em;
  color:var(--faint);animation:sinamDefile 32s linear infinite}
.hf .ban .fil span{padding-right:26px}
.hf .ban .fil span::after{content:"·";padding-left:26px;color:var(--hair2)}
.hf .ban .fil b{font-weight:400;color:var(--dim)}
@keyframes sinamDefile{to{transform:translateX(-100%)}}
@media (prefers-reduced-motion:reduce){.hf .ban .fil{animation:none}}

/* ------------------------------------------------------------- la vitrine */
/* Elle représente l'app, donc c'est un bloc normal : fond, rayon, filet plein.
   Sans JS elle est simplement posée, avec sa phrase d'exemple. Avec JS, la
   classe « anim » la vide, éteint sa bordure CSS, et hero.js retrace le filet
   en SVG : même géométrie exacte, donc rien ne bouge au passage. */
/* Le filet au repos est une ombre INTÉRIEURE, pas une bordure : une bordure
   décalerait la boîte de rognage d'un pixel, et le rectangle SVG tracé par
   hero.js perdrait son bord droit et son bord bas dans l'overflow. */
.hf .demo{position:relative;display:flex;flex-direction:column;min-height:330px;
  border:0;border-radius:14px;overflow:hidden;box-shadow:inset 0 0 0 1px var(--hair2);
  background:color-mix(in oklab,var(--surf) 86%,transparent);backdrop-filter:blur(12px)}
.hf .demo.anim{box-shadow:none}
.hf .demo .top{position:relative;z-index:2;display:flex;align-items:center;
  justify-content:space-between;padding:16px 22px 15px}
/* la zone de saisie porte la trame de points, le reste non */
.hf .demo .ph{position:relative;z-index:2;padding:26px 22px 20px;min-height:132px;
  font-family:"Monaspace Neon","Geist Mono",monospace;font-size:18.5px;line-height:1.42;
  letter-spacing:-.015em;color:var(--br)}
.hf .demo .trame{position:absolute;top:48px;left:0;right:0;height:132px;z-index:1;
  background-image:radial-gradient(circle at center,var(--tx) .8px,transparent 1px);
  background-size:5px 5px;opacity:.07}
.hf .demo .sep{position:relative;z-index:2;display:flex;align-items:center;gap:12px;padding:14px 22px 0}
.hf .demo.anim .sep{visibility:hidden}
.hf .demo.anim.range .sep{visibility:visible}
.hf .demo .sep .ln{flex:1;overflow:hidden;white-space:nowrap;
  font-family:"Monaspace Neon","Geist Mono",monospace;font-size:11px;line-height:1;
  letter-spacing:.22em;color:var(--hair2)}
.hf .demo .out{position:relative;z-index:2;display:flex;flex-wrap:wrap;gap:8px;
  padding:15px 22px 24px;margin-top:auto}
.hf .demo.anim .top,.hf .demo.anim .ph,.hf .demo.anim .sep,.hf .demo.anim .out{opacity:0;transition:opacity .45s ease}
.hf .demo.anim.on .top,.hf .demo.anim.on .ph,.hf .demo.anim.on .sep,.hf .demo.anim.on .out{opacity:1}
/* les étiquettes : objets de contenu, donc filet PLEIN, comme les puces de runner */
.hf .demo .tag{border:1px solid var(--hair2);border-radius:7px;padding:5px 10px;font-size:11px;
  letter-spacing:.01em;background:color-mix(in oklab,var(--surf) 70%,transparent)}
.hf .demo .tag.build{border-color:var(--hair)}
.hf .demo.anim .out .tag{opacity:0;transform:translateY(7px);
  transition:opacity .34s ease,transform .34s ease,border-color .4s ease}
.hf .demo.anim .out .tag.in{opacity:1;transform:none}

/* Le mode de capture, en haut à droite de la carte : l'étiquette dit la
   modalité, l'onde ne bat que pendant une dictée. Ce n'est pas un curseur de
   terminal : elle dit « ça écoute », et elle s'arrête quand la phrase est là. */
.hf .demo .mode{display:inline-flex;align-items:center;gap:9px}
.hf .demo .onde{display:none;align-items:center;gap:2px;height:12px}
.hf .demo.voix .onde{display:inline-flex}
.hf .demo .onde i{width:2px;height:100%;background:var(--accent);opacity:.8;border-radius:1px;
  animation:sinamOnde .9s ease-in-out infinite}
.hf .demo.voix.pose .onde i{animation:none;transform:scaleY(.22)}
@keyframes sinamOnde{0%,100%{transform:scaleY(.22)}50%{transform:scaleY(1)}}
@media (prefers-reduced-motion:reduce){.hf .demo .onde i{animation:none;transform:scaleY(.5)}}

/* ================================================================= le hero
   Quatre zones, une vraie grille 2 × 2 : titre en haut à gauche, astre en haut
   à droite, texte et boutons en bas à gauche, vitrine en bas à droite. Les deux
   rangées sont centrées verticalement, donc chaque zone se répond en miroir. */
.hf .hero .stage{position:relative;padding:80px 0 88px}
.hf .hero .wrap{position:relative;z-index:2;width:100%}
.hf .hero .quatre{position:relative;display:grid;
  grid-template-columns:minmax(0,1fr) 452px;   /* la colonne droite = la largeur de la vitrine */
  grid-template-rows:320px minmax(300px,auto);
  column-gap:64px;row-gap:52px;align-items:center}
/* l'astre et la vitrine occupent toute la hauteur de leur rangée */
.hf .hero .z-astre,.hf .hero .demo{align-self:stretch}
/* L'astre est TOUJOURS au premier plan, et il n'est JAMAIS coupé. Deux règles,
   deux conséquences : il passe au dessus des quatre zones, et sa boîte ne
   rogne plus rien, sinon le disque se tronque net dès qu'il tourne vers la
   gauche. Le champ ne prend aucun clic, il peut donc couvrir les boutons. */
.hf .hero .z-titre,.hf .hero .z-texte,.hf .hero .demo{position:relative;z-index:1}
.hf .hero .z-astre{z-index:3}
.hf .hero .ch{overflow:visible}
.hf .hero .live{pointer-events:none}
.hf .hero h1{margin:16px 0 0;max-width:19ch}
/* La légende défile dans une fenêtre étroite, à l'aplomb du titre : c'est ce
   qui la fait lire comme un bandeau et pas comme une ligne de texte. */
.hf .hero .lgd{max-width:470px;margin-top:30px;height:20px}
.hf .hero .lead{max-width:46ch;margin:0 0 26px}
.hf .hero .cta{display:flex;gap:12px;margin:0 0 22px}
.hf .hero .z-astre{position:relative}
/* L'astre déborde de sa zone : à droite jusqu'au repère vertical, à gauche dans
   la gouttière. Son rayon vient de min(largeur, hauteur × 1,55) en cellules :
   pour le redimensionner il faut donc toucher les DEUX axes ensemble, sinon
   rien ne change. Pour le déplacer à taille constante, compenser left et right
   l'un par l'autre. */
.hf .hero .z-astre .live{left:-91px;right:-30px;top:-124px;bottom:-124px}
/* on calme le grain de fond ici : à densité égale, l'astre ressort */
.hf .hero .z-astre .lay.c{opacity:.3}
/* la vitrine, à la taille trouvée : elle remplit sa cellule, elle ne la déborde plus */
.hf .hero .demo{max-width:none;margin:0;min-height:300px}
.hf .hero .demo .top{padding:14px 20px 13px}
.hf .hero .demo .ph{font-size:17px;min-height:116px;padding:22px 20px 18px}
.hf .hero .demo .trame{top:44px;height:116px}
.hf .hero .demo .sep{padding:12px 20px 0}
.hf .hero .demo .out{padding:13px 20px 20px}

@media (max-width:1040px){
  /* minmax(0,1fr) et pas 1fr : une colonne 1fr ne descend jamais sous son
     contenu le plus large (le bandeau défilant, la vitrine), et tout le hero
     débordait de l'écran du téléphone. */
  .hf .hero .quatre{grid-template-columns:minmax(0,1fr) !important;grid-template-rows:auto !important;row-gap:30px}
  .hf .hero .stage{padding:36px 0 56px}
  .hf .hero .z-astre{height:230px}
  /* le champ suit la scène : la bride de site.css ne s'applique pas ici */
  .hf .hero .live{height:auto !important}
  .hf .hero .z-astre .live{left:-20px;right:-20px;top:-20px;bottom:-20px}
  .hf .hero .lgd{max-width:100%}
}
@media (max-width:720px){
  /* Sur téléphone, les astres sont agrandis sans que la zone grandisse : c'est
     le champ qui déborde en hauteur (le rayon suit la hauteur, voir plus haut),
     et comme il ne prend aucun clic et n'a plus de fond, rien d'autre ne bouge. */
  .hf .hero .z-astre .live{top:-70px;bottom:-70px}
}
@media (max-width:720px){
  .hf .hero .cta{flex-direction:column}
  .hf .hero .demo{min-height:0}
}

/* La barre d'onglets collante de Fonctionnalités traverse toute la page. Elle
   n'est pas une section, elle n'héritait donc pas des repères, et ses deux
   filets pleins coupaient la gouttière en deux. Elle porte maintenant la même
   grille : deux verticales, et des horizontales en pointillés comme partout. */
.hf .barre{position:sticky;top:69px;z-index:15;
  background:color-mix(in oklab,var(--bg) 90%,transparent);backdrop-filter:blur(14px)}
.hf:not(.n) .barre::before{content:"";position:absolute;inset:0;z-index:0;pointer-events:none;
  background-repeat:no-repeat;
  background-size:1px 100%,1px 100%,100% 1px,100% 1px;
  background-position:calc(50% - 592px) 0,calc(50% + 592px) 0,0 0,0 100%;
  background-image:var(--grille),var(--grille),var(--grille-h),var(--grille-h)}
.hf .barre > .wrap{position:relative;z-index:1}
/* sous 1240 px la grille disparaît : les filets pleins reprennent leur rôle */
@media (max-width:1240px){
  .hf .barre{border-top:1px solid var(--hair);border-bottom:1px solid var(--hair)}
}

/* ------------------------------------------------- onglets et accordéons */
/* Les pastilles de la barre sont des ancres : elles gardent la couleur de
   l'étiquette, pas celle des liens. La section visée se décale sous l'en-tête
   collant et sous la barre, sinon son titre arrive caché derrière. */
.hf .seg a.tag,.hf .seg button.tag{color:var(--faint);text-decoration:none;cursor:pointer;
  font-family:inherit;transition:color .18s ease,border-color .18s ease}
.hf .seg a.tag:hover,.hf .seg button.tag:hover{color:var(--tx);border-color:var(--tx)}
.hf .seg a.tag.n,.hf .seg button.tag.n{border-color:color-mix(in oklab,var(--accent) 55%,transparent);color:var(--accent)}
.hf .sec[id]{scroll-margin-top:118px}
@media (prefers-reduced-motion:no-preference){html{scroll-behavior:smooth}}

/* Le champ de recherche : la carte reste la carte, l'input n'apporte que le texte. */
.hf .rech{color:var(--faint)}
.hf .rech input{flex:1;min-width:0;background:transparent;border:0;outline:0;padding:0;
  font-family:inherit;font-size:15px;color:var(--tx)}
.hf .rech input::placeholder{color:var(--faint)}
.hf .rech input::-webkit-search-cancel-button{-webkit-appearance:none;appearance:none}
.hf .rech:focus-within{border-color:var(--hair2)}

/* L'accordéon : fermé par défaut, la première de chaque groupe ouverte. Le signe
   vient d'ici et pas du markup, il ne peut donc pas mentir sur l'état. */
.hf .acc .q{cursor:pointer}
.hf .acc .q i::before{content:"+"}
.hf .acc.on .q i::before{content:"−"}
.hf .acc > p{display:none}
.hf .acc.on > p{display:block}

/* rien à afficher après un filtre ou une recherche */
.hf .vide{display:none;padding:26px 0;color:var(--faint);font-size:14.5px}
.hf .vide.on{display:block}
