# Face DSL — Reference complete

Langage de description de cadrans pour OBD Dashboard.
Chaque fichier `.face` decrit un cadran complet : fond, variables, elements graphiques.

---

## Structure d'un fichier

```
@name "Nom du cadran"
@author "Auteur"
bg #000000

@var $ma_var = expression

# Commentaire
element arg1 arg2 ... prop:valeur prop:valeur

if condition {
  element ...
}
```

### Directives

| Directive | Description | Exemple |
|-----------|------------|---------|
| `@name "..."` | Nom du cadran | `@name "Classic Arc"` |
| `@author "..."` | Auteur | `@author "OBD Dash"` |
| `bg couleur` | Couleur de fond | `bg #000000` |
| `@var $nom = expr` | Variable calculee | `@var $psi = $raw * 0.145` |
| `# ...` | Commentaire (ignore) | `# Ceci est un commentaire` |

### Blocs conditionnels

```
if $zone==danger {
  circle 50 50 10 fill:#FF0000
  text "ALERTE" 50 50 size:8 bold color:#FF0000
}
```

Imbrication possible :
```
if $zone==danger {
  if $progress>0.95 {
    text "CRITIQUE" 50 50 size:10 bold color:#FF0000
  }
}
```

### Groupes

Les groupes organisent les elements sans condition. Utiles pour nommer, masquer ou copier un ensemble d'elements dans l'editeur.

```
group Fond {
  circle 50 50 45 fill:#111 stroke:#333 w:2
  arc 50 50 40 -225 270 stroke:#444 w:3
}

group Texte {
  text $value 50 42 size:16 bold color:#FFF
  text $unit 50 55 size:6 color:#888
}
```

Imbrication possible avec des conditionnels :
```
group Alertes {
  if $zone==danger {
    circle 50 50 46 stroke:#FF6B6B w:1
  }
}
```

> Les groupes sont purement structurels — ils n'affectent pas le rendu. Tous les enfants sont dessines normalement.

### Boucles (for)

Les boucles permettent de repeter des elements avec une variable qui change a chaque iteration.

```
for $i 0 360 step 30 {
  dot 50+cos($i)*40 50+sin($i)*40 2 fill:$accent
}
```

Syntaxe : `for $variable debut fin [step pas] { ... }`

- `$variable` : nom de la variable de boucle
- `debut` : valeur de depart (expression)
- `fin` : valeur de fin (inclusive, expression)
- `step pas` : optionnel, increment (defaut: 1, expression)

La variable de boucle est utilisable dans toutes les expressions des elements enfants.

Exemples :

```
# 12 points en cercle
for $i 0 11 {
  dot 50+cos($i*30)*40 50+sin($i*30)*40 1.5 fill:#FFFFFF
}

# Barres verticales avec opacite decroissante
for $x 10 90 step 10 {
  line $x 20 $x 80 stroke:$accent w:1 alpha:lerp(1, 0.1, $x/100)
}

# Anneaux concentriques (combinaison avec @var)
@var $count = 5
for $i 1 $count {
  circle 50 50 $i*8 stroke:$accent w:0.3 alpha:lerp(0.5, 0.1, $i/$count)
}
```

Imbrication possible avec d'autres blocs :
```
for $i 0 3 {
  for $j 0 3 {
    dot 20+$i*20 20+$j*20 2 fill:$accent
  }
}
```

> Limite de securite : maximum 1000 iterations par boucle. Si le pas est 0 ou dans la mauvaise direction, la boucle est ignoree.

---

## Systeme de coordonnees

Toutes les positions et tailles sont en **pourcentage** du canvas (0-100).

| Valeur | Signification |
|--------|--------------|
| `0` | Bord gauche / haut |
| `50` | Centre |
| `100` | Bord droit / bas |

Les angles sont en **degres** : 0 = droite (3h), 90 = bas (6h), sens horaire.
Convention commune : `-225` a `+45` couvre un arc de 270 degres (type compteur classique).

---

## Variables integrees

### Texte (pour l'element `text`)

| Variable | Description | Exemple |
|----------|------------|---------|
| `$value` | Valeur formatee avec decimales | `95`, `14.2` |
| `$unit` | Unite courante | `°C`, `kPa` |
| `$label` | Nom du capteur | `Huile`, `Turbo` |
| `$raw` | Valeur brute numerique | `95.0` |
| `$percent` | Pourcentage avec symbole | `65%` |
| `$min` | Minimum de la plage | `40` |
| `$max` | Maximum de la plage | `150` |

### Numerique (pour les expressions, @var, proprietes)

| Variable | Type | Plage | Description |
|----------|------|-------|-------------|
| `$progress` | float | 0.0 - 1.0 | Progression normalisee |
| `$percent` | float | 0 - 100 | Pourcentage |
| `$raw` | float | min - max | Valeur brute |
| `$min` | float | — | Minimum de la plage |
| `$max` | float | — | Maximum de la plage |
| `$whp` | float | 0.0 - 1.0 | Seuil warning haut (progress) |
| `$wlp` | float | 0.0 - 1.0 | Seuil warning bas (progress) |
| `$dhp` | float | 0.0 - 1.0 | Seuil danger haut (progress) |
| `$dlp` | float | 0.0 - 1.0 | Seuil danger bas (progress) |
| `$time` | float | 0 - 3600 | Temps en secondes (animation 60fps, modulo 1h) |

### Couleurs

| Variable | Description |
|----------|------------|
| `$accent` | Couleur accent du widget |
| `$zone_color` | Couleur selon zone (accent/jaune/rouge) |

### Zone

| Variable | Valeurs possibles |
|----------|------------------|
| `$zone` | `normal`, `warning`, `danger` |

### Variables multi-valeurs (donnees secondaires)

Quand un cadran est configure avec des donnees secondaires (multi-value), les variables suivantes sont automatiquement injectees pour chaque source supplementaire, ou `{key}` est le cle du WidgetType (ex: `oil_temp`, `rpm`, `boost`...) :

| Variable | Type | Description |
|----------|------|-------------|
| `$value-{key}` | texte | Valeur formatee |
| `$progress-{key}` | float | Progression 0.0-1.0 |
| `$raw-{key}` | float | Valeur brute |
| `$zone-{key}` | texte | normal/warning/danger |
| `$unit-{key}` | texte | Unite |
| `$label-{key}` | texte | Nom du capteur |
| `$accent-{key}` | couleur | Couleur accent |
| `$min-{key}` | float | Minimum de la plage |
| `$max-{key}` | float | Maximum de la plage |

**Variables indexees** : les memes variables sont aussi disponibles par position (1-based) pour les presets generiques :

| Variable | Equivalent |
|----------|------------|
| `$value-1` | `$value-{key}` de la 1ere donnee secondaire |
| `$progress-1` | `$progress-{key}` de la 1ere donnee secondaire |
| `$value-2` | `$value-{key}` de la 2eme donnee secondaire |
| ... | etc. |

**Exemple** : cadran RPM (principal) + temperature huile (secondaire) :
```
# Aiguille RPM (donnee principale, $value/$progress)
needle 50 50 34

# Texte temperature huile (donnee secondaire, par cle)
text $value-oil_temp 50 82 size:6 color:$accent-oil_temp

# Ou par index (equivalent si oil_temp est la 1ere donnee secondaire)
text $value-1 50 82 size:6 color:$accent-1
```

Ces variables sont disponibles dans l'editeur web (onglet Previsualisation > Donnees secondaires) et dans l'app Android (configuration du cadran > Donnees secondaires).

---

## Variables custom (@var)

Declarer des variables calculees a partir des donnees OBD :

```
@var $psi = $raw * 0.145
@var $bar = $raw * 0.01
@var $remaining = round(100 - $progress * 100)
```

Les variables peuvent **referencer d'autres variables** (resolues dans l'ordre de declaration) :

```
@var $celsius = $raw
@var $fahrenheit = $celsius * 1.8 + 32
```

Les variables custom sont utilisables :
- Comme **contenu texte** : `text $psi 50 50 size:16`
- Dans les **expressions numeriques** : `glow:$my_glow`
- Dans les **conditions** : `if $psi>20 { ... }`

---

## Fonctions mathematiques

Utilisables dans les expressions `@var` et dans les proprietes numeriques.

| Fonction | Description | Exemple |
|----------|------------|---------|
| `clamp(val, min, max)` | Limiter entre min et max | `clamp($progress, 0, 1)` |
| `min(a, b)` | Minimum | `min($raw, 100)` |
| `max(a, b)` | Maximum | `max($raw, 0)` |
| `abs(val)` | Valeur absolue | `abs($raw)` |
| `round(val)` | Arrondi entier | `round($progress * 100)` |
| `floor(val)` | Arrondi inferieur | `floor($raw)` |
| `ceil(val)` | Arrondi superieur | `ceil($raw)` |
| `lerp(a, b, t)` | Interpolation lineaire | `lerp(2, 16, $progress)` |
| `sin(deg)` | Sinus (en degres) | `sin($progress * 360)` |
| `cos(deg)` | Cosinus (en degres) | `cos($progress * 360)` |
| `mod(a, b)` | Modulo | `mod($raw, 10)` |
| `pow(a, b)` | Puissance | `pow($progress, 2)` |

### Operateurs

| Operateur | Description |
|-----------|------------|
| `+` `-` `*` `/` | Arithmetique standard |
| `( )` | Groupement |

### Exemples

```
@var $glow_size = lerp(2, 20, $progress)
@var $clamped = clamp($raw * 0.01, 0, 1)
@var $dot_size = lerp(1.5, 5, clamp(($dhp - $progress) / 0.2, 0, 1))
```

---

## Conditions

### Operateurs de comparaison

| Operateur | Description |
|-----------|------------|
| `==` | Egal (texte ou nombre) |
| `!=` | Different |
| `>` `<` `>=` `<=` | Comparaison numerique |

### Combinaisons

| Operateur | Description |
|-----------|------------|
| `&&` | ET logique |
| `\|\|` | OU logique |

### Exemples

```
if $zone==danger { ... }
if $progress>0.8 { ... }
if $zone==warning && $progress>0.85 { ... }
if $zone==danger || $progress>0.95 { ... }
```

### Condition inline (`iif`)

`iif(condition, valeur_si_vrai, valeur_si_faux)` permet d'utiliser une condition directement dans une expression ou une propriete, sans bloc `if`.

```
@var $color = iif($zone==danger,#FF0000,#00FF00)
@var $size = iif($progress>0.5,16,8)
text $value 50 50 size:$size color:$color
```

Imbrication possible :
```
@var $c = iif($zone==danger,#FF0000,iif($zone==warning,#FFD96B,#FFFFFF))
```

---

## Proprietes communes

Tous les elements supportent ces proprietes :

| Propriete | Type | Description |
|-----------|------|-------------|
| `alpha` | 0.0-1.0 | Opacite (0 = invisible, 1 = opaque) |
| `glow` | nombre | Taille de la lueur (en % du canvas) |
| `glow_color` | couleur | Couleur de la lueur (defaut : couleur du trait) |
| `blink` | nombre (ms) | Clignotement : alterne visible/invisible |

```
circle 50 50 40 stroke:#FF0000 w:2 alpha:0.5 glow:8 glow_color:#FF0000
text "DANGER" 50 50 size:10 bold color:#FF0000 blink:500
```

---

## Primitives graphiques

### Formes

#### `circle` — Cercle

```
circle cx cy rayon [props]
```

| Propriete | Type | Description |
|-----------|------|-------------|
| `fill` | couleur | Remplissage |
| `stroke` | couleur | Contour |
| `w` | nombre | Epaisseur contour |
| `alpha` | 0.0-1.0 | Opacite |
| `glow` | nombre | Taille lueur |
| `blink` | nombre (ms) | Clignotement |

#### `ellipse` — Ellipse

```
ellipse cx cy rx ry [props]
```

| Propriete | Type | Description |
|-----------|------|-------------|
| `fill` | couleur | Remplissage |
| `stroke` | couleur | Contour |
| `w` | nombre | Epaisseur contour |
| `rotation` | degres | Rotation |
| `alpha` | 0.0-1.0 | Opacite |
| `glow` | nombre | Taille lueur |
| `glow_color` | couleur | Couleur lueur |
| `blink` | nombre (ms) | Clignotement |

#### `rect` — Rectangle

```
rect x y largeur hauteur [props]
```

| Propriete | Type | Description |
|-----------|------|-------------|
| `fill` | couleur | Remplissage |
| `stroke` | couleur | Contour |
| `sw` | nombre | Epaisseur contour |
| `corner` | nombre | Arrondi des coins |
| `alpha` | 0.0-1.0 | Opacite |
| `blink` | nombre (ms) | Clignotement |

#### `line` — Ligne

```
line x1 y1 x2 y2 [props]
```

| Propriete | Type | Description |
|-----------|------|-------------|
| `stroke` | couleur | Couleur |
| `w` | nombre | Epaisseur |
| `cap` | round/butt/square | Terminaison |
| `dash` | "on,off" | Tirets (ex: `dash:4,2`) |
| `alpha` | 0.0-1.0 | Opacite |
| `blink` | nombre (ms) | Clignotement |

#### `polygon` — Polygone regulier

```
polygon cx cy rayon cotes [props]
```

| Propriete | Type | Description |
|-----------|------|-------------|
| `rotation` | degres | Rotation |
| `fill` | couleur | Remplissage |
| `stroke` | couleur | Contour |
| `w` | nombre | Epaisseur |
| `glow` | nombre | Lueur |
| `glow_color` | couleur | Couleur lueur |
| `alpha` | 0.0-1.0 | Opacite |
| `blink` | nombre (ms) | Clignotement |

#### `shape` — Forme libre

```
shape x1 y1 x2 y2 x3 y3 [x4 y4 ...] [props]
```

Polygone a sommets libres. Minimum 3 points (6 args), pas de limite superieure. Chaque paire d'arguments definit les coordonnees x y d'un sommet. Les sommets sont relies dans l'ordre et la forme est fermee automatiquement.

| Propriete | Type | Description |
|-----------|------|-------------|
| `fill` | couleur | Remplissage |
| `stroke` | couleur | Contour |
| `w` | nombre | Epaisseur contour |
| `glow` | nombre | Lueur |
| `glow_color` | couleur | Couleur lueur |
| `alpha` | 0.0-1.0 | Opacite |
| `blink` | nombre (ms) | Clignotement |

Exemples :

```
# Triangle
shape 20 20 80 20 50 80 fill:#FF0000

# Fleche (5 sommets)
shape 50 10 70 40 60 40 60 90 40 90 fill:#4FC3F7

# Losange avec contour
shape 50 10 90 50 50 90 10 50 stroke:#FFD700 w:2
```

#### `dot` — Point

```
dot cx cy rayon [props]
```

| Propriete | Type | Description |
|-----------|------|-------------|
| `fill` | couleur | Couleur |
| `glow` | nombre | Lueur |
| `glow_color` | couleur | Couleur lueur |
| `alpha` | 0.0-1.0 | Opacite |
| `blink` | nombre (ms) | Clignotement |

### Arcs & Anneaux

#### `arc` — Arc de cercle

```
arc cx cy rayon debut_deg balayage_deg [props]
```

| Propriete | Type | Description |
|-----------|------|-------------|
| `stroke` | couleur | Contour |
| `fill` | couleur | Remplissage (secteur) |
| `w` | nombre | Epaisseur |
| `cap` | round/butt/square | Terminaison |
| `corner` | 0-100 | Forme du trajet (0=carre, 100=rond) |
| `dash` | "on,off" | Tirets |
| `alpha` | 0.0-1.0 | Opacite |
| `glow` | nombre | Lueur |
| `blink` | nombre (ms) | Clignotement |

#### `ring` — Anneau

```
ring cx cy r_ext r_int debut_deg balayage_deg [props]
```

| Propriete | Type | Description |
|-----------|------|-------------|
| `fill` | couleur | Remplissage |
| `stroke` | couleur | Contour |
| `w` | nombre | Epaisseur contour |
| `corner` | 0-100 | Forme du trajet (0=carre, 100=rond) |
| `alpha` | 0.0-1.0 | Opacite |
| `blink` | nombre (ms) | Clignotement |

#### `gradient_ring` — Anneau degrade

```
gradient_ring cx cy r_ext r_int debut_deg balayage_deg segments [props]
```

| Propriete | Type | Description |
|-----------|------|-------------|
| `from` | couleur | Couleur debut |
| `to` | couleur | Couleur fin |
| `corner` | 0-100 | Forme du trajet (0=carre, 100=rond) |
| `alpha` | 0.0-1.0 | Opacite |
| `blink` | nombre (ms) | Clignotement |

### Texte

#### `text` — Texte

```
text contenu x y [props]
```

Le contenu peut etre une variable (`$value`), du texte entre guillemets (`"PSI"`), ou un mix.

| Propriete | Type | Description |
|-----------|------|-------------|
| `size` | nombre | Taille (% du canvas) |
| `color` | couleur | Couleur |
| `bold` | flag | Gras |
| `italic` | flag | Italique |
| `align` | center/left/right | Alignement |
| `font` | nom de police | Police (voir ci-dessous) |
| `glow` | nombre | Lueur |
| `glow_color` | couleur | Couleur lueur |
| `alpha` | 0.0-1.0 | Opacite |
| `blink` | nombre (ms) | Clignotement |

Polices disponibles : `sans-serif` (defaut), `orbitron`, `russo`, `teko`, `rajdhani`, `mono`, `audiowide`, `dseg7` (7-segments LCD), `barlow` (europeen condense), `saira` (racing condense), `play` (dashboard tech).

### Graduations

#### `ticks` — Graduations

```
ticks cx cy rayon nombre longueur [props]
```

| Propriete | Type | Description |
|-----------|------|-------------|
| `start` | degres | Angle debut (defaut: -225) |
| `sweep` | degres | Balayage (defaut: 270) |
| `stroke` | couleur | Couleur |
| `w` | nombre | Epaisseur |
| `corner` | 0-100 | Forme du trajet (0=carre, 100=rond) |
| `alpha` | 0.0-1.0 | Opacite |
| `blink` | nombre (ms) | Clignotement |

#### `sweep_ticks` — Graduations actives/inactives

Meme syntaxe que `ticks`, mais colore selon la progression.

| Propriete | Type | Description |
|-----------|------|-------------|
| `start` | degres | Angle debut |
| `sweep` | degres | Balayage |
| `on` | couleur | Couleur active |
| `off` | couleur | Couleur inactive |
| `w` | nombre | Epaisseur |
| `corner` | 0-100 | Forme du trajet (0=carre, 100=rond) |
| `alpha` | 0.0-1.0 | Opacite |
| `blink` | nombre (ms) | Clignotement |

### Progression (reagissent a `$progress`)

#### `progress_arc` — Arc de progression

```
progress_arc cx cy rayon debut_deg balayage_max_deg [props]
```

Se remplit de 0 a `balayage_max` selon `$progress`.

| Propriete | Type | Description |
|-----------|------|-------------|
| `stroke` | couleur | Couleur |
| `w` | nombre | Epaisseur |
| `cap` | round/butt/square | Terminaison |
| `corner` | 0-100 | Forme du trajet (0=carre, 100=rond) |
| `bg` | couleur | Fond (arc complet) |
| `glow` | nombre | Lueur |
| `glow_color` | couleur | Couleur lueur |
| `alpha` | 0.0-1.0 | Opacite |
| `blink` | nombre (ms) | Clignotement |

#### `progress_bar` — Barre de progression

```
progress_bar x y largeur hauteur [props]
```

| Propriete | Type | Description |
|-----------|------|-------------|
| `dir` | right/left/up/down | Direction |
| `fill` | couleur | Remplissage |
| `bg` | couleur | Fond |
| `corner` | nombre | Arrondi |
| `alpha` | 0.0-1.0 | Opacite |
| `blink` | nombre (ms) | Clignotement |

#### `progress_ring` — Anneau de progression

```
progress_ring cx cy r_ext r_int debut_deg balayage_max_deg [props]
```

| Propriete | Type | Description |
|-----------|------|-------------|
| `fill` | couleur | Remplissage |
| `bg` | couleur | Fond |
| `corner` | 0-100 | Forme du trajet (0=carre, 100=rond) |
| `alpha` | 0.0-1.0 | Opacite |
| `blink` | nombre (ms) | Clignotement |

#### `digital_bar` — Barre segmentee

```
digital_bar x y largeur hauteur segments ecart [props]
```

| Propriete | Type | Description |
|-----------|------|-------------|
| `fill` | couleur | Couleur active |
| `bg` | couleur | Couleur inactive |
| `corner` | nombre | Arrondi segments |
| `alpha` | 0.0-1.0 | Opacite |
| `blink` | nombre (ms) | Clignotement |

### Indicateurs (reagissent a `$progress`)

#### `needle` — Aiguille

```
needle cx cy longueur [props]
```

| Propriete | Type | Description |
|-----------|------|-------------|
| `from` | degres | Angle debut (defaut: -225) |
| `sweep` | degres | Balayage (defaut: 270) |
| `w` | nombre | Epaisseur |
| `color` | couleur | Couleur |
| `tail` | nombre | Longueur queue |
| `cap` | round/butt/square | Terminaison |
| `corner` | 0-100 | Forme du trajet (0=carre, 100=rond) |
| `dot` | nombre | Rayon point central |
| `glow` | nombre | Lueur |
| `glow_color` | couleur | Couleur lueur |
| `alpha` | 0.0-1.0 | Opacite |
| `blink` | nombre (ms) | Clignotement |

#### `value_dot` — Point orbitant

```
value_dot cx cy r_orbite debut_deg balayage_max_deg r_point [props]
```

| Propriete | Type | Description |
|-----------|------|-------------|
| `fill` | couleur | Couleur |
| `corner` | 0-100 | Forme du trajet (0=carre, 100=rond) |
| `glow` | nombre | Lueur |
| `glow_color` | couleur | Couleur lueur |
| `alpha` | 0.0-1.0 | Opacite |
| `blink` | nombre (ms) | Clignotement |

### Zones (colorees par seuils warning/danger)

#### `zone_arc` — Arc colore par zones

```
zone_arc cx cy rayon debut_deg balayage_deg epaisseur [props]
```

| Propriete | Type | Description |
|-----------|------|-------------|
| `normal` | couleur | Couleur zone normale |
| `warning` | couleur | Couleur zone warning |
| `danger` | couleur | Couleur zone danger |
| `corner` | 0-100 | Forme du trajet (0=carre, 100=rond) |
| `alpha` | 0.0-1.0 | Opacite |
| `blink` | nombre (ms) | Clignotement |

#### `zone_ring` — Anneau colore par zones

```
zone_ring cx cy r_ext r_int debut_deg balayage_deg [props]
```

Memes proprietes que `zone_arc` (`normal`, `warning`, `danger`, `corner`, `alpha`, `blink`).

---

## Couleurs nommees

| Nom | Valeur |
|-----|--------|
| `white` | `#FFFFFF` |
| `black` | `#000000` |
| `muted` | `#888888` |
| `warning` | `#FFD96B` |
| `danger` | `#FF6B6B` |
| `success` | `#4CAF50` |
| `red` | `#FF0000` |
| `green` | `#00FF00` |
| `blue` | `#0000FF` |
| `yellow` | `#FFFF00` |
| `cyan` | `#00FFFF` |
| `orange` | `#FF9800` |

Format hexadecimal : `#RGB`, `#RRGGBB`, ou `#AARRGGBB` (avec alpha).

---

## Variables dans n'importe quelle propriete

Toutes les proprietes numeriques (positions, tailles, opacites, epaisseurs...) acceptent des variables et expressions, pas seulement des nombres fixes.

Cela permet d'animer dynamiquement **toutes** les proprietes visuelles en fonction de la valeur OBD.

### Position dynamique

Deplacer un element en fonction de la valeur :

```
@var $text_y = lerp(80, 20, $progress)
text $value 50 $text_y size:22 bold color:#FFFFFF
```

Le texte glisse du bas vers le haut quand la valeur augmente.

### Taille reactive

```
@var $radius = lerp(10, 46, $progress)
circle 50 50 $radius fill:$accent alpha:0.2
progress_arc 50 50 $radius -90 360 stroke:$accent w:1.5
```

L'anneau grandit avec la valeur.

### Opacite dynamique

```
@var $fade = lerp(0.1, 1, $progress)
progress_arc 50 50 44 -225 270 stroke:$accent w:3 alpha:$fade
```

L'arc devient de plus en plus visible.

### Epaisseur variable

```
@var $thickness = lerp(0.5, 4, $progress)
progress_arc 50 50 44 -225 270 stroke:$accent w:$thickness cap:round
```

---

## Astuces avancees

### Conversion d'unites

```
@var $psi = $raw * 0.145
@var $bar = $raw * 0.01
text $psi 50 40 size:16 bold color:#FFFFFF
text "PSI" 60 40 size:6 color:#888888
```

### Design conditionnel total

Changer completement de design selon la zone :

```
if $zone==normal {
  text $value 50 50 size:28 bold color:#FFFFFF
}
if $zone==danger {
  rect 5 5 90 90 stroke:#FF6B6B sw:0.5
  text "DANGER" 50 30 size:8 bold color:#FF6B6B
  text $value 50 55 size:24 bold color:#FF6B6B
}
```

### Elements convergents

Faire converger des elements vers le centre :

```
@var $spread = lerp(44, 12, $progress)
circle 50 50 $spread stroke:$accent w:0.4
value_dot 50 50 $spread -90 360 2 fill:$accent
```

### Chaine de variables

Les variables peuvent referencer d'autres variables :

```
@var $celsius = $raw
@var $fahrenheit = $celsius * 1.8 + 32
@var $is_hot = clamp(($celsius - 80) / 20, 0, 1)
@var $alpha = lerp(0.2, 1, $is_hot)
```

### Barres coulissantes

```
@var $bar_x = lerp(5, 50, $progress)
line $bar_x 20 $bar_x 80 stroke:$accent w:2 alpha:0.3
```

---

## Animation avec $time

La variable `$time` fournit le temps en secondes (float, 0 a 3600, modulo 1h). Elle est mise a jour a 60fps et permet de creer des animations continues independantes de la valeur OBD.

### Rotation continue

```
@var $angle = mod($time * 60, 360)
polygon 50 50 20 6 rotation:$angle stroke:#4FC3F7 w:1
```

L'hexagone fait un tour complet toutes les 6 secondes.

### Pulsation

```
@var $pulse = sin($time * 180)
@var $r = lerp(38, 42, ($pulse + 1) / 2)
circle 50 50 $r stroke:$accent w:0.5 alpha:0.5
```

Le cercle pulse en continu (1 cycle par seconde).

### Points orbitants

```
@var $t = mod($time * 50, 360)
@var $ox = 50 + cos($t) * 30
@var $oy = 50 + sin($t) * 30
dot $ox $oy 2 fill:$accent glow:8 glow_color:$accent
```

Un point tourne autour du centre.

### Combinaison $time + $progress

`$time` peut etre combine avec `$progress` pour des animations qui reagissent a la valeur :

```
@var $speed = lerp(20, 120, $progress)
@var $angle = mod($time * $speed, 360)
@var $px = 50 + cos($angle) * 35
@var $py = 50 + sin($angle) * 35
dot $px $py 1.5 fill:$accent
```

Le point orbite plus vite quand la valeur augmente.
