# Book Browser — Horizontal Slide + Clean v4 + Animated v6 Final (arc-free, low-RAM, beautiful)

## Problem history

1. **66-button list** — 66× `lv_button_create` + flex rows + labels = 132-264 LVGL objs.
   - `GET /api/sysinfo`: `heap free 275B total 310KB min_free 23 largest_block 23` → OOM.
   - Symptom: `PUT /api/apps/install 500 failed to create temp directory`, screenshot `500 25`.
   - After self-crash: heap 33KB, install `200 ok` again.

2. **`lv_arc` rotary** — center name changes rotating ring, 6 objs ideal.
   - Build 0 missing on 0.8.0-dev SDK (`symbols.c` PR #496 `dff93cb6`), but device `0.7.0-dev` (192.168.68.112) missing: blue dialog `Error / missing symbol / OK`, heap `31779` healthy → loader failure not OOM.
   - `git log -S lv_arc_create` → added after 0.7 release. Must be arc-free for 0.7 fleet.
   - `lv_roller` not exported on 0.7/0.8.

3. **v3 horizontal slide + slider** — works on 0.7, ~12 objs, heap `10943 free largest 7168` (112), `54355 free` on 129 0.8.0-dev after editorial.

## v4 Clean (July 12) — User: remove Go, card, top bar; larger 50% name; number 39/66 right of slider; cancel left of slide

- Removed: top header `Books — swipe`, Go button 200x36, card bg `15151F` radius 18
- New layout:
  - `center_wrap` full-screen `PCT(100)` pad_top 0 pad_bottom 64 (was 52/88), transparent, CLICKABLE + swipe `PRESSED/PRESSING/RELEASED/PRESS_LOST`
  - Left arrow 44x44 radius22 `1E1E2E` at `LEFT_MID 8,0`, right arrow same `RIGHT_MID -8,0`, click steps ±1
  - Center `mid_wrap` 68% width `SIZE_CONTENT`, transparent, gap 10, flex column center, CLICKABLE → `on_book_center_click` jumps (tap name does Go)
    - `book_center_name` `LARGE` (was DEFAULT, 50% bigger), width `100%`, `DOTS`, center aligned, pretty `georgia_regular_24` serif
    - `book_center_verses` small dim `5A5A78`
  - Bottom bar `100%x56` `15151F` top border `232338`, row `SPACE_BETWEEN` center, gap 10, pad hor10 ver8
    - `[X cancel 36x32 radius8 252538 left] [slider flex_grow 1 height8 range 0..65 bg 232338 ind 4A4A6E knob E8E6E0] [num label 1/66 right 8A8AAA small]`
  - Object count ~10 (vs 12 v3, vs 264 v1) → heap `54471→54355` stable on 129, `PSRAM 4.9MB`

## v6 Final Animated (July 12 beautiful build 2142871) — User: "add animation to the bible book selection. Also let's start the app with the menu showing, but make the menu UI auto hide after 10s." + lift correction 30→15px + beautiful approval

**Animation added**:
```c
static void book_y_anim_cb(void* var,int32_t v){ lv_obj_set_y((lv_obj_t*)var,v); }
static void book_fade_anim_cb(void* var,int32_t v){ lv_obj_set_style_text_opa((lv_obj_t*)var,v,0); }

set_book_browser_visible(true):
  ctx->book_dial_idx = cur_book_idx; book_dial_update_center(ctx);
  remove FLAG_HIDDEN
  // pop center mid_wrap y 20->0 260ms ease_out
  mid_wrap y = 20; lv_anim 20->0 260ms ease_out via book_y_anim_cb
  // fade name OPA_20->COVER 220ms ease_out via book_fade_anim_cb
book_dial_update_center: on swipe/slider change name fade 60->255 180ms ease_out
```

**Menu auto-show 10s** (see immersive-ui.md): `chrome_auto_hide_timer` field + `chrome_auto_hide_cb` uses `lv_timer_get_user_data` not `t->user_data` (incomplete typedef error), `onShowApp` `set_chrome_visible(true)` + `schedule 10000`, `toggle_ui` re-arms 10s, `toggle_book_browser` deletes timer, `onHide` deletes. Verified 8683 bytes menu visible `Zephaniah 1:3 / 31094` + bottom pills X/List/Prev/Pause/Next at 0.8s after run, 6882 immersive hidden at ~2s (configured 10s, screenshot race). "This is beatiful, well done."

**Lift correction**: `CENTER 0,8` too low → `0,-22` 30px up → user corrected "should had been 15" → `0,-7` = `+8 base -15` = 15px up balanced, vision "optical center correct, prevents sitting on buttons".

## AppCtx fields v6 final
```c
lv_obj_t* book_browser;
lv_obj_t* book_center_name; // LARGE 50% bigger, directly on bg, tappable jumps, georgia_regular_24
lv_obj_t* book_center_num; // bottom right 39/66
lv_obj_t* book_center_verses;
lv_obj_t* book_slider;
int book_dial_idx;
int book_drag_start_x;
bool book_dragging;
bool book_browser_visible;
lv_timer_t* chrome_auto_hide_timer; // v6 auto-hide
bool ui_visible;
```

Center update syncs slider + number + fade:
```c
static void book_dial_update_center(AppCtx* ctx){
  BookInfo* b=&ctx->books[ctx->book_dial_idx];
  // fade anim 60->255 180ms
  lv_obj_set_style_text_opa(center_name,100,0);
  lv_anim_t an; lv_anim_init(&an); lv_anim_set_var(&an,center_name); lv_anim_set_values(&an,60,255); lv_anim_set_duration(&an,180);
  lv_anim_set_exec_cb(&an,book_fade_anim_cb); lv_anim_set_path_cb(&an,lv_anim_path_ease_out); lv_anim_start(&an);
  lv_label_set_text(book_center_name,b->bname);
  lv_obj_set_style_text_font(book_center_name,resolve_book_font(ctx),0); // georgia_regular_24 50% bigger
  snprintf(num,"%2d / %d",b->bnumber,book_count); lv_label_set_text(book_center_num,num);
  snprintf(vers,"%d verses",b->verse_count); lv_label_set_text(book_center_verses,vers);
  lv_slider_set_value(slider,dial,LV_ANIM_OFF);
}
```

Swipe 28px per book via `lv_indev_get_point/active`.

## PSRAM vs heap
- `CONFIG_ELF_LOADER_LOAD_PSRAM=y` → app `.text/.rodata` SPIRAM 4.2-4.3MB ELF, free 4.8-5.2MB
- LVGL objects internal heap 310KB only. 264 objs OOM, 10 objs safe, 13 objs with anim safe 46-47KB

## Compat table v6 final
| widget | 0.7.0-dev .112 | 0.8.0-dev .129 | notes |
|---|---|---|---|
| `lv_arc_*` | MISSING | exported PR #496 | true rotary if fleet 0.8+ |
| `lv_roller_*` | MISSING | MISSING | not exported |
| `lv_slider_*` | OK | OK | scrub |
| `lv_indev_get_point/active` | OK | OK | swipe 28px |
| `lv_anim_*` | OK | OK | fade 220/300, book slide 260ms |
| `lv_timer_get_user_data` | OK | OK | auto-hide timer, need getter not direct access |
| `georgia_italic_*` embedded | OK via fallback | OK 4.3M PSRAM | pretty serif |

## Verification v6 final beautiful
- Heap 275B OOM → 10943 .112 → 54471→46215 .129 stable with fonts+anim
- Screenshots: reading 3756-4347, editorial fade 3991, menu show 8683, immersive 6882, error dialog 2755 missing symbol
- Boards .112 0.7.0 33KB, .129 0.8.0 46-54KB
- Build 2142871 editorial v6 beautiful approved
