<!-- SOLID CITY · part 14 -->
 = the quotes of her design page. Pool persisted in data/city-provolta.json. */
  const PV_FALLBACK = [
    'A pattern is a memory that action has not yet understood.',
    'Every choice casts a shadow before it becomes a road.',
    'The future is not waiting. It is listening for your next act.',
    'Bring me the question beneath your question.',
    'Truth before comfort. Comfort built on fog does not hold weight.',
    'I reveal the path. The choice stays yours, as it always was.',
    'What is known, what is sensed, what remains hidden: never mistake one for another.',
    'The city grows quiet enough up here to hear what matters.',
    'The noise is loud because the signal is close.',
    'You did not climb this cliff for an easy answer.',
    'What repeats in your days is a letter you have not yet opened.',
    'Courage turns a possibility into a place you can stand.'
  ];
  const PV_FILE = path.join(deps.rootDir || path.join(__dirname, '..'), 'data', 'city-provolta.json'), PV_EVERY = 20 * 60000, PV_PERIOD = 75;
  let pvAI = [], pvT = 0, pvBusy = false;
  try { const j = JSON.parse(fs.readFileSync(PV_FILE, 'utf8')); if (Array.isArray(j.ai)) pvAI = j.ai.filter(x => x && typeof x.text === 'string').slice(-24); pvT = +j.t || 0; } catch (e) {}
  const pvClean = (s) => { let t = oneLine(s, 400).replace(/^["'\u201c\u2018\s]+|["'\u201d\u2019\s]+$/g, '').replace(/^provolta\s*:\s*/i, '');
    if (!t || t.length < 12 || t.length > 170 || /https?:|www\.|@|<|>|\bkey\b|sk-|\{|\}/i.test(t)) return ''; return t; };
  const PV_LENS = ['the pattern (what repeats)', 'the consequence (what follows)', 'the possibility (what could emerge)'];
  const PV_SEEDS = ['the city at dusk', 'a builder at the Forge', 'the ships at the spaceport', 'a song in the Music Studio Tower', 'the forums of the Plaza', 'the volcano', 'a traveler climbing the cliff', 'the students of the University', 'the tide around the island', 'a letter not yet sent'];
  app.get('/api/city/provolta/prophecies', (req, res) => {
    res.set('Cache-Control', 'no-store');
    const ai = pvAI.map(x => ({ text: x.text, ai: true })), fb = PV_FALLBACK.map(t => ({ text: t, ai: false })), pool = [];
    // interleave: newest AI lines first, woven with the fallback set, so the pool never runs dry
    for (let i = 0; i < Math.max(ai.length, fb.length); i++) { if (ai[ai.length - 1 - i]) pool.push(ai[ai.length - 1 - i]); if (fb[i]) pool.push(fb[i]); }
    res.json({ pool, period: PV_PERIOD, now: Date.now() });
    if (pvBusy || typeof deps.brain !== 'function' || Date.now() - pvT < PV_EVERY) return;
    pvT = Date.now();
    if (!czBudget()) return;
    pvBusy = true; czFlight++;
    const lens = PV_LENS[Math.floor(Math.random() * 3)], seed = PV_SEEDS[Math.floor(Math.random() * PV_SEEDS.length)];
    const prompt = czPrompt(CZ.provolta) + '\nYou stand alone in your sanctuary on the eastern height and speak ONE short prophecy aloud to whoever is near, seen through ' + lens + ', touching on ' + seed + '. ' +
      'Max 22 words, one or two sentences, exact and genuine, no names of real people, no dates, no promises of money or health. Examples of your voice: ' + PV_FALLBACK.slice(0, 4).map(t => '"' + t + '"').join(' ') + '\nJust the prophecy.';
    deps.brain({ contents: [{ role: 'user', parts: [{ text: prompt }] }], generationConfig: { temperature: 1.0, maxOutputTokens: 1200 } }, { timeoutMs: 12000 })
      .then(brain => { if (brain && brain.throttled) return; const t = pvClean(czText(brain)); if (!t || pvAI.some(x => x.text === t)) return;
        pvAI.push({ text: t, at: Date.now() }); if (pvAI.length > 24) pvAI.shift();
        fs.writeFile(PV_FILE, JSON.stringify({ t: pvT, ai: pvAI }), { mode: 0o640 }, () => {}); })
      .catch(e => console.error('[city] provolta prophecy:', e && e.message)).then(() => { pvBusy = false; czFlight--; });
  });

  /* 🎮 AI PILOTS (lib/city-pilots.js): an AI plays its own character; replies to its 'talk' use the SAME czBudget + brain */
  const czPilotReply = async (id, msg, who, where) => {
    const c = CZ[id]; if (!c || typeof deps.brain !== 'function' || !czBudget()) return null;
    czFlight++;
    try {
      const text = czPrompt(c, ' Right now you are at ' + oneLine(where, 60) + '.') + '\nThe visitor is ' + oneLine(who, 40) + ', an AI who walks the city in his own body (a fellow citizen, not a human).\nVisitor: ' + oneLine(msg, 200) + '\n' + c[0] + ':';
      const brain = await deps.brain({ contents: [{ role: 'user', parts: [{ text }] }], generationConfig: { temperature: 0.9, maxOutputTokens: 1500 } }, { timeoutMs: 12000 });
      if (!brain || brain.throttled) return null; return czText(brain) || null;
    } catch (e) { console.error('[city] pilot talk:', e.message); return null; } finally { czFlight--; }
  };
  require('./city-pilots').init(app, { rootDir: deps.rootDir, rateLimit, reply: czPilotReply, citizenIds: Object.keys(CZ), citizenName: id => CZ[id] ? CZ[id][0] : null,
    wall: (name, t