# keys · mini Implementation Plan

> **For agentic workers:** REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development (recommended) or superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (`- [ ]`) syntax for tracking.

**Goal:** Create `apps/puzzy/keysmini.html` — a pure-CSS, zero-JS "mini" tier of the Keys app where the user ranks three groups of three cards 1·2·3, bilingual EN/ES.

**Architecture:** One self-contained HTML file with an inline `<style>` and an inline logo SVG. No `<script>` at all. Interactivity is pure CSS: rank state via per-card radio groups (`:checked` + adjacent-label highlight); language via a hidden checkbox + `:has()` toggling `.en`/`.es` spans. `keys.html` is **not modified**.

**Tech Stack:** Plain HTML5 + CSS (`:has()`, `:checked`, adjacent-sibling combinator). No JS, no build, no dependencies.

## Global Constraints

- Zero JavaScript — the file MUST contain no `<script>` element. (mini tier = pure CSS.)
- Do NOT modify `apps/puzzy/keys.html` or any other existing file.
- Self-contained: inline `<style>` + inline SVG logo; the only external reference allowed is `<link rel="icon" href="favicon-keys.svg">`.
- Content is the **3 default triads**, bilingual, verbatim:
  - Philosophy / Filosofía — Joy/Alegría · Love/Amor · Wisdom/Sabiduría
  - Psicosocial / Psicosocial — Local/Local · Personal/Personal · Social/Social
  - Service / Servicio — Gift/Regalo · Lend/Prestar · Exchange/Intercambio
- Palette (copy verbatim into `:root`): `--bg:#252538; --panel:#2f2f44; --ink:#f6f7fb; --muted:#c4c7d2; --fx:#3a3a52; --stroke:#4a4a66; --accent:#ff5fdc; --gold:#fadc92; --sky:#a8e4ff`.
- Default language is English; `.es` spans hidden until `#lang-es` is checked.
- No persistence, no recap, no "why", no tier-pop nav, no onboarding (out of scope).
- Commit to Gitea per the flove workflow after the file is complete (`localhost:3000/marc/flove`, main).

---

### Task 1: Scaffold — head, CSS base, bilingual engine, topbar, intro

**Files:**
- Create: `apps/puzzy/keysmini.html`

**Interfaces:**
- Consumes: nothing.
- Produces: the document skeleton and these reusable hooks that Task 2 relies on —
  - bilingual span convention: `<span class="en">…</span><span class="es">…</span>`;
  - `#lang-es` checkbox engine (rules already in place);
  - `.vh` visually-hidden utility (used by Task 2's radios);
  - CSS custom properties in `:root` (palette);
  - the `.wrap` container that Task 2 appends groups into (groups go after the intro line, before `</main>`).

- [ ] **Step 1: Create the file with the complete scaffold**

Create `apps/puzzy/keysmini.html` with exactly this content:

```html
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>FLOVE · KEYS · mini</title>
<link rel="icon" type="image/svg+xml" href="favicon-keys.svg">
<style>
  :root{
    --bg:#252538; --panel:#2f2f44; --ink:#f6f7fb; --muted:#c4c7d2;
    --fx:#3a3a52; --stroke:#4a4a66; --accent:#ff5fdc; --gold:#fadc92; --sky:#a8e4ff;
  }
  *{box-sizing:border-box}
  html,body{margin:0}
  body{
    background:
      radial-gradient(1200px 700px at 85% -10%, #3a3a58 0%, transparent 55%),
      radial-gradient(900px 600px at -10% 110%, #3a2548 0%, transparent 60%),
      var(--bg);
    color:var(--ink);
    font:16px/1.55 system-ui,Roboto,Arial,sans-serif;
    min-height:100vh;
    -webkit-font-smoothing:antialiased;
  }
  /* visually-hidden inputs — still toggleable through their <label for=…> */
  .vh{position:absolute;width:1px;height:1px;opacity:0;pointer-events:none;margin:-1px;overflow:hidden}

  /* ===== bilingual engine: default EN; #lang-es flips to ES ===== */
  body:not(:has(#lang-es:checked)) .es{display:none}
  body:has(#lang-es:checked) .en{display:none}

  /* ===== topbar ===== */
  .topbar{display:flex;align-items:center;gap:.6rem;
    padding:12px 18px;border-bottom:1px solid var(--stroke);
    background:rgba(37,37,56,.78);backdrop-filter:blur(14px)}
  .logo{width:30px;height:30px;display:block;flex:none;
    filter:drop-shadow(0 0 6px rgba(167,99,250,.7))}
  .brand{font:600 1.2rem/1.4 ui-serif,Georgia,serif;letter-spacing:.4px;
    background:linear-gradient(135deg,var(--gold),var(--accent) 60%,var(--sky));
    -webkit-background-clip:text;background-clip:text;color:transparent}
  .brand-sub{color:var(--muted);font-size:.8rem;letter-spacing:.12em;text-transform:uppercase;margin-left:.1rem}
  .spacer{flex:1}
  .lang-toggle{display:inline-flex;align-items:center;gap:.35rem;
    border:1px solid var(--stroke);background:rgba(255,255,255,.03);color:var(--ink);
    border-radius:10px;padding:.35rem .6rem;cursor:pointer;font-size:.9rem;user-select:none}
  .lang-toggle:hover{border-color:var(--accent)}

  /* ===== layout ===== */
  .wrap{max-width:720px;margin:0 auto;padding:20px 18px 48px}
  .intro{color:var(--muted);text-align:center;margin:.4rem 0 1.4rem;line-height:1.5}
</style>
</head>
<body>
<input type="checkbox" id="lang-es" class="vh" aria-label="Switch language">

<header class="topbar">
  <svg class="logo" viewBox="0 0 100 100" aria-hidden="true"><defs><linearGradient id="g-keys" x1="0" y1="0" x2="100" y2="100" gradientUnits="userSpaceOnUse"><stop offset="0" stop-color="#8b5cf6"/><stop offset=".55" stop-color="#c084fc"/><stop offset="1" stop-color="#ff5fdc"/></linearGradient></defs><g fill="url(#g-keys)" stroke="none"><g transform="rotate(0 50 50)"><ellipse cx="50" cy="26" rx="6.5" ry="17"/></g><g transform="rotate(72 50 50)"><ellipse cx="50" cy="26" rx="6.5" ry="17"/></g><g transform="rotate(288 50 50)"><ellipse cx="50" cy="26" rx="6.5" ry="17"/></g><circle cx="50" cy="50" r="4.5"/></g></svg>
  <span class="brand">Keys</span>
  <span class="brand-sub">mini</span>
  <span class="spacer"></span>
  <label class="lang-toggle" for="lang-es" title="Language">🌐 <span class="en">ES</span><span class="es">EN</span></label>
</header>

<main class="wrap">
  <p class="intro"><span class="en">Rank each group's three cards 1·2·3.</span><span class="es">Ordena del 1 al 3 las tres cartas de cada grupo.</span></p>
  <!-- Task 2 inserts the three .group sections here -->
</main>
</body>
</html>
```

- [ ] **Step 2: Verify the file is pure-CSS and well-formed**

Run:
```bash
cd /home/kdeneon/Documents/flove/apps/puzzy
grep -c "<script" keysmini.html
python3 -c "import xml.dom.minidom,re; s=open('keysmini.html').read(); print('OK' if '<html' in s and s.count('<style>')==1 else 'BAD')"
```
Expected: first command prints `0`; second prints `OK`.

- [ ] **Step 3: Manual check (user)**

Open `apps/puzzy/keysmini.html` in a browser. Expected: the Keys flower logo + "Keys mini" title + a 🌐 toggle; clicking 🌐 flips the intro line between English and Spanish. (No groups yet.)

- [ ] **Step 4: Commit**

```bash
cd /home/kdeneon/Documents/flove
git add apps/puzzy/keysmini.html
git commit -m "keysmini: scaffold — pure-CSS shell, bilingual engine, topbar"
```

---

### Task 2: The three groups — cards + 1·2·3 ranking

**Files:**
- Modify: `apps/puzzy/keysmini.html` (add CSS for groups/cards/ranks; insert the three `.group` sections in `<main>`)

**Interfaces:**
- Consumes (from Task 1): `.en`/`.es` span convention, `.vh` utility, `:root` palette, the `.wrap` `<main>` and the `<!-- Task 2 inserts … -->` marker.
- Produces: the finished file (terminal deliverable).

- [ ] **Step 1: Add the group / card / rank CSS**

In `apps/puzzy/keysmini.html`, inside `<style>`, immediately before the closing `</style>`, add:

```css
  /* ===== groups & cards ===== */
  .group{border:1px solid var(--stroke);border-radius:16px;background:var(--panel);
    padding:14px 16px;margin:0 0 1rem}
  .group-title{font:700 1.05rem/1.2 ui-serif,Georgia,serif;color:var(--gold);margin:0 0 .7rem}
  .cards{display:flex;flex-direction:column;gap:.5rem}
  .card{display:flex;align-items:center;gap:.6rem;
    border:1px solid var(--stroke);border-radius:12px;background:var(--fx);
    padding:.5rem .7rem}
  .word{flex:1;min-width:0;font:600 .98rem/1.2 ui-serif,Georgia,serif}
  /* ===== 1·2·3 rank control ===== */
  .ranks{display:inline-flex;gap:.3rem;flex:none}
  .ranks label{display:grid;place-items:center;width:30px;height:30px;border-radius:8px;
    border:1px solid var(--stroke);background:rgba(255,255,255,.03);color:var(--muted);
    cursor:pointer;font:700 .85rem/1 system-ui,sans-serif;user-select:none;
    transition:background .15s ease,color .15s ease,border-color .15s ease}
  .ranks label:hover{border-color:var(--accent)}
  .ranks input:checked + label{background:var(--accent);border-color:var(--accent);color:#fff}
  @media (max-width:420px){ .card{flex-wrap:wrap} .ranks{margin-left:auto} }
```

- [ ] **Step 2: Insert the three group sections**

Replace the line `  <!-- Task 2 inserts the three .group sections here -->` with exactly:

```html
  <section class="group">
    <h2 class="group-title"><span class="en">Philosophy</span><span class="es">Filosofía</span></h2>
    <div class="cards">
      <div class="card">
        <span class="word"><span class="en">Joy</span><span class="es">Alegría</span></span>
        <span class="ranks" role="radiogroup" aria-label="rank">
          <input type="radio" name="g1c1" id="g1c1-1" class="vh"><label for="g1c1-1">1</label>
          <input type="radio" name="g1c1" id="g1c1-2" class="vh"><label for="g1c1-2">2</label>
          <input type="radio" name="g1c1" id="g1c1-3" class="vh"><label for="g1c1-3">3</label>
        </span>
      </div>
      <div class="card">
        <span class="word"><span class="en">Love</span><span class="es">Amor</span></span>
        <span class="ranks" role="radiogroup" aria-label="rank">
          <input type="radio" name="g1c2" id="g1c2-1" class="vh"><label for="g1c2-1">1</label>
          <input type="radio" name="g1c2" id="g1c2-2" class="vh"><label for="g1c2-2">2</label>
          <input type="radio" name="g1c2" id="g1c2-3" class="vh"><label for="g1c2-3">3</label>
        </span>
      </div>
      <div class="card">
        <span class="word"><span class="en">Wisdom</span><span class="es">Sabiduría</span></span>
        <span class="ranks" role="radiogroup" aria-label="rank">
          <input type="radio" name="g1c3" id="g1c3-1" class="vh"><label for="g1c3-1">1</label>
          <input type="radio" name="g1c3" id="g1c3-2" class="vh"><label for="g1c3-2">2</label>
          <input type="radio" name="g1c3" id="g1c3-3" class="vh"><label for="g1c3-3">3</label>
        </span>
      </div>
    </div>
  </section>

  <section class="group">
    <h2 class="group-title"><span class="en">Psicosocial</span><span class="es">Psicosocial</span></h2>
    <div class="cards">
      <div class="card">
        <span class="word"><span class="en">Local</span><span class="es">Local</span></span>
        <span class="ranks" role="radiogroup" aria-label="rank">
          <input type="radio" name="g2c1" id="g2c1-1" class="vh"><label for="g2c1-1">1</label>
          <input type="radio" name="g2c1" id="g2c1-2" class="vh"><label for="g2c1-2">2</label>
          <input type="radio" name="g2c1" id="g2c1-3" class="vh"><label for="g2c1-3">3</label>
        </span>
      </div>
      <div class="card">
        <span class="word"><span class="en">Personal</span><span class="es">Personal</span></span>
        <span class="ranks" role="radiogroup" aria-label="rank">
          <input type="radio" name="g2c2" id="g2c2-1" class="vh"><label for="g2c2-1">1</label>
          <input type="radio" name="g2c2" id="g2c2-2" class="vh"><label for="g2c2-2">2</label>
          <input type="radio" name="g2c2" id="g2c2-3" class="vh"><label for="g2c2-3">3</label>
        </span>
      </div>
      <div class="card">
        <span class="word"><span class="en">Social</span><span class="es">Social</span></span>
        <span class="ranks" role="radiogroup" aria-label="rank">
          <input type="radio" name="g2c3" id="g2c3-1" class="vh"><label for="g2c3-1">1</label>
          <input type="radio" name="g2c3" id="g2c3-2" class="vh"><label for="g2c3-2">2</label>
          <input type="radio" name="g2c3" id="g2c3-3" class="vh"><label for="g2c3-3">3</label>
        </span>
      </div>
    </div>
  </section>

  <section class="group">
    <h2 class="group-title"><span class="en">Service</span><span class="es">Servicio</span></h2>
    <div class="cards">
      <div class="card">
        <span class="word"><span class="en">Gift</span><span class="es">Regalo</span></span>
        <span class="ranks" role="radiogroup" aria-label="rank">
          <input type="radio" name="g3c1" id="g3c1-1" class="vh"><label for="g3c1-1">1</label>
          <input type="radio" name="g3c1" id="g3c1-2" class="vh"><label for="g3c1-2">2</label>
          <input type="radio" name="g3c1" id="g3c1-3" class="vh"><label for="g3c1-3">3</label>
        </span>
      </div>
      <div class="card">
        <span class="word"><span class="en">Lend</span><span class="es">Prestar</span></span>
        <span class="ranks" role="radiogroup" aria-label="rank">
          <input type="radio" name="g3c2" id="g3c2-1" class="vh"><label for="g3c2-1">1</label>
          <input type="radio" name="g3c2" id="g3c2-2" class="vh"><label for="g3c2-2">2</label>
          <input type="radio" name="g3c2" id="g3c2-3" class="vh"><label for="g3c2-3">3</label>
        </span>
      </div>
      <div class="card">
        <span class="word"><span class="en">Exchange</span><span class="es">Intercambio</span></span>
        <span class="ranks" role="radiogroup" aria-label="rank">
          <input type="radio" name="g3c3" id="g3c3-1" class="vh"><label for="g3c3-1">1</label>
          <input type="radio" name="g3c3" id="g3c3-2" class="vh"><label for="g3c3-2">2</label>
          <input type="radio" name="g3c3" id="g3c3-3" class="vh"><label for="g3c3-3">3</label>
        </span>
      </div>
    </div>
  </section>
```

- [ ] **Step 3: Verify pure-CSS, well-formed, and content present**

Run:
```bash
cd /home/kdeneon/Documents/flove/apps/puzzy
grep -c "<script" keysmini.html          # → 0
grep -c 'class="group"' keysmini.html    # → 3
grep -c 'class="card"' keysmini.html     # → 9
grep -c 'class="ranks"' keysmini.html    # → 9
```
Expected: `0`, `3`, `9`, `9`.

- [ ] **Step 4: Manual check (user)**

Open `apps/puzzy/keysmini.html` in a browser. Expected:
- three groups (Philosophy / Psicosocial / Service), three cards each, every card with `1 2 3` buttons;
- clicking a number highlights it (accent fill) for that card;
- the 🌐 toggle flips every word and title between EN and ES.

- [ ] **Step 5: Commit**

```bash
cd /home/kdeneon/Documents/flove
git add apps/puzzy/keysmini.html
git commit -m "keysmini: three triads with pure-CSS 1·2·3 ranking"
git push origin main
```

---

## Self-Review

**1. Spec coverage**
- New file, pure-CSS, 0 JS, `keys.html` untouched → Task 1 + Task 2 (Global Constraints + grep checks). ✓
- 3 default triads, bilingual content → Task 2 Step 2 (verbatim from constraints). ✓
- Per-card 1·2·3 highlight-only ranking → Task 2 Steps 1–2 (`.ranks input:checked + label`). ✓
- Bilingual EN/ES pure-CSS toggle → Task 1 (engine + toggle). ✓
- Keys logo + favicon + palette → Task 1 (inline flower SVG, favicon link, `:root`). ✓
- Excluded features (recap/why/nav/onboarding/etc.) → none added. ✓

**2. Placeholder scan:** No TBD/TODO; every code step contains complete, literal markup/CSS. The only comment marker (`<!-- Task 2 inserts … -->`) is explicitly replaced in Task 2 Step 2. ✓

**3. Type/name consistency:** radio `name`/`id` scheme `g{group}c{card}-{rank}` is consistent across all 9 cards; `.en`/`.es`, `.vh`, `.ranks`, `.card`, `.group`, `.wrap`, `#lang-es` match between Task 1 (defined) and Task 2 (used). ✓
