/* @ds-bundle: {"format":4,"namespace":"EazyDesignSystem_019e08","components":[{"name":"EzButton","sourcePath":"components/EzButton/EzButton.jsx"}],"sourceHashes":{"components/EzButton/EzButton.jsx":"d9ee37b8d784","eazy-landing/doc-page.js":"62024d965071","eazy-landing/script.js":"79d70d9bff98","exports/eazy-math-diagnostic/app.js":"c2dbf692f7de","flashcards/Deck.jsx":"5797696c99cd","flashcards/Flashcard.jsx":"d89d2a57d2e5","flashcards/deck-data.js":"605ee8fc5290","flashcards/ios-frame.jsx":"d67eb3ffe562","flashcards/tweaks-panel.jsx":"a1107c630a56","quiz-game-export/QuizGameExport.jsx":"96b531136862","quiz-game-export/words.js":"35263fe45fb0","quiz-game-server/QuizGameServer.jsx":"590d586f60af","quiz-game/Game.standalone.jsx":"ccb27042040f","quiz-game/QuizGame.jsx":"57c1f54eb3c3","quiz-game/design-canvas.jsx":"c9095ef15594","quiz-game/dist/game.js":"0af452a8a961","quiz-game/dist/words.js":"35263fe45fb0","quiz-game/end-sketches.jsx":"344c4dbd2767","quiz-game/ios-frame.jsx":"911f9ccc95e7","quiz-game/words.js":"35263fe45fb0","quiz/Quiz.jsx":"eebec2992326","quiz/ios-frame.jsx":"d67eb3ffe562","quiz/quiz-data.js":"65c69e1a9cee","quiz/tweaks-panel.jsx":"a1107c630a56","role-game/RoleGame.jsx":"951d60cdd5d9","role-game/ios-frame.jsx":"d67eb3ffe562","role-game/levels.jsx":"50926fa55b23","role-game/levelup-sketches.jsx":"3eeab92f6555","role-game/levelup-variants.jsx":"90097990162b","role-game/questions.js":"7ccc83478f55","role-game/tweaks-panel.jsx":"a1107c630a56","tetri-psychometry-export/tetri-game.jsx":"0f0fbec59b26","tetri-psychometry-export/words.js":"35263fe45fb0","tetri-psychometry/TetriGame.jsx":"e3a6c86b8e20","tetri-psychometry/words.js":"35263fe45fb0","tetri-vocab/VocabGame.jsx":"818ad56f6fce","tetri-vocab/vocab-data.js":"704c9f66fcdf","ui_kits/flyer/FlyerBulletList.jsx":"c777714ad9ab","ui_kits/flyer/FlyerEventStamp.jsx":"51049c1d957d","ui_kits/flyer/FlyerFrame.jsx":"4657083a384b","ui_kits/flyer/FlyerHeadline.jsx":"7e70d6e424dc","ui_kits/flyer/FlyerLogoBlock.jsx":"226ec15611c3","ui_kits/web/BannerCTA.jsx":"c2cfe1aff5d6","ui_kits/web/CourseGrid.jsx":"3e5dd3062642","ui_kits/web/Footer.jsx":"ee1960cf5310","ui_kits/web/Hero.jsx":"39c9519cb9c6","ui_kits/web/Includes.jsx":"853a71769dcb","ui_kits/web/LeadForm.jsx":"56cd43f920cc","ui_kits/web/SiteHeader.jsx":"1cfdb3887752","word-game/design-canvas.jsx":"d3ddcf4241b9","workshop-followup/doc-page.js":"62024d965071","workshop-followup/habits-data.js":"4afdc952666e","workshop-followup/מקור-לעריכה/habits-data.js":"4afdc952666e"},"inlinedExternals":[],"unexposedExports":[]} */

(() => {

const __ds_ns = (window.EazyDesignSystem_019e08 = window.EazyDesignSystem_019e08 || {});

const __ds_scope = {};

(__ds_ns.__errors = __ds_ns.__errors || []);

// components/EzButton/EzButton.jsx
try { (() => {
/* global React */
const {
  useState
} = React;

/**
 * EzButton — the eazy brand button.
 * Solid fills only (no gradients), pill radius, Avigul display type.
 * Hover darkens the fill 8% per the brand spec; active presses to scale(.99).
 */
function EzButton({
  children,
  variant = "primary",
  type = "button",
  disabled = false,
  onClick
}) {
  const [hover, setHover] = useState(false);
  const [active, setActive] = useState(false);
  const base = {
    fontFamily: "var(--font-display, system-ui)",
    fontWeight: 700,
    fontSize: 16,
    lineHeight: 1,
    borderRadius: 999,
    padding: "12px 28px",
    cursor: disabled ? "not-allowed" : "pointer",
    opacity: disabled ? 0.4 : 1,
    border: 0,
    transition: "background .15s, color .15s, transform .08s",
    transform: active && !disabled ? "scale(.99)" : "none",
    outlineOffset: 2
  };
  const skins = {
    primary: {
      background: hover && !disabled ? "var(--ez-orange-deep)" : "var(--ez-orange)",
      color: "#fff"
    },
    secondary: {
      background: hover && !disabled ? "var(--ez-lavender-deep)" : "var(--ez-lavender)",
      color: hover && !disabled ? "#fff" : "#1d1a3a"
    },
    ghost: {
      background: hover && !disabled ? "var(--ez-ink)" : "transparent",
      color: hover && !disabled ? "#fff" : "var(--ez-ink)",
      border: "1.5px solid var(--ez-ink)",
      padding: "11px 26px"
    },
    link: {
      background: "transparent",
      color: hover && !disabled ? "var(--ez-orange-deep)" : "var(--ez-lavender-deep)",
      padding: "12px 0"
    }
  };
  return /*#__PURE__*/React.createElement("button", {
    type: type,
    disabled: disabled,
    onClick: onClick,
    onMouseEnter: () => setHover(true),
    onMouseLeave: () => {
      setHover(false);
      setActive(false);
    },
    onMouseDown: () => setActive(true),
    onMouseUp: () => setActive(false),
    style: {
      ...base,
      ...skins[variant]
    }
  }, children);
}
Object.assign(__ds_scope, { EzButton });
})(); } catch (e) { __ds_ns.__errors.push({ path: "components/EzButton/EzButton.jsx", error: String((e && e.message) || e) }); }

// eazy-landing/doc-page.js
try { (() => {
// @ds-adherence-ignore -- omelette starter scaffold (raw elements/hex/px by design)
/* BEGIN USAGE */
/**
 * <doc-page> — paged-document shell for printable HTML.
 *
 * On screen the document renders as a single continuous sheet on a desk
 * background (Google Docs' pageless view): you scroll one tall page card.
 * There is no manual page-splitting — write the whole document as normal
 * flow inside <doc-page> and the browser's print engine paginates it at
 * export.
 *
 * At print the component injects `@page { size: …; margin: 0 }` (which
 * leaves Chrome no margin box to draw its date/URL/page-count header in)
 * and moves the visual margin onto the sheet's own padding, so the printed
 * page has the same inset you see on screen. Standard break-hygiene rules
 * (`break-inside: avoid` on figures, code blocks, images and table rows;
 * `orphans/widows: 3`) are applied so paragraphs and groups split cleanly.
 * On screen and at print, headings default to `text-wrap: balance` and
 * body text (p, li, blockquote, figcaption) to `text-wrap: pretty`, so
 * the document avoids widowed/orphaned words; the defaults have zero
 * specificity, so any text-wrap you declare on those elements wins.
 *
 * Usage:
 *   <style>doc-page:not(:defined){visibility:hidden}</style>
 *   <doc-page size="letter" margin="0.75in">
 *     <h1>Title</h1>
 *     <p>…body…</p>
 *   </doc-page>
 *   <script src="doc-page.js"></script>
 *
 * Attributes:
 *   size    — letter | a4 | legal (default letter)
 *   width / height — explicit CSS lengths, override `size`
 *   margin  — printable inset on every page (default 0.75in)
 *
 * Running header/footer (optional): give an element `slot="header"` or
 * `slot="footer"` and it repeats on every printed page via
 * `position: fixed`. To keep body text from sliding under it, the
 * component prints inside a single-cell table whose <thead>/<tfoot> are
 * spacers sized to the header/footer height — browsers repeat thead/tfoot
 * on every page, so each sheet's content starts below the header and ends
 * above the footer. On screen the header/footer render once at the
 * top/bottom of the sheet.
 *
 * Author content as static HTML so the user can click-to-edit any text
 * directly. Do not set width/padding/background on the document body —
 * the component owns the sheet box.
 */
/* END USAGE */

(() => {
  const PAPER = {
    letter: ['8.5in', '11in'],
    a4: ['210mm', '297mm'],
    legal: ['8.5in', '14in']
  };
  const CSS_LENGTH = /^\d+(\.\d+)?(px|in|mm|cm|pt|pc)$/;
  const safeLen = (v, fb) => CSS_LENGTH.test((v || '').trim()) ? v.trim() : fb;
  const stylesheet = `
    :host {
      position: relative;
      display: block;
      min-height: 100vh;
      background: #ece8dd;
      padding: 48px 24px;
      box-sizing: border-box;
      font-family: -apple-system, BlinkMacSystemFont, "Helvetica Neue", Arial, sans-serif;
      --doc-page-w: 8.5in;
      --doc-page-h: 11in;
      --doc-page-margin: 0.75in;
      --doc-hdr-h: 0px;
      --doc-ftr-h: 0px;
    }
    .sheet {
      width: var(--doc-page-w);
      margin: 0 auto;
      background: #fff;
      box-shadow: 0 2px 14px rgba(20, 20, 19, 0.12);
      border-radius: 2px;
      box-sizing: border-box;
      padding: var(--doc-page-margin);
    }
    .frame { width: 100%; border-collapse: collapse; }
    .frame td, .frame th { padding: 0; text-align: left; font-weight: inherit; }
    .hdr-space { height: var(--doc-hdr-h); }
    .ftr-space { height: var(--doc-ftr-h); }
    ::slotted([slot="header"]),
    ::slotted([slot="footer"]) { display: block; box-sizing: border-box; }
    @media print {
      :host { background: none; padding: 0; min-height: 0; }
      .sheet {
        width: auto; margin: 0; box-shadow: none; border-radius: 0;
        padding: 0 var(--doc-page-margin);
      }
      /* The thead/tfoot spacers repeat on every page, so they carry the
       * vertical page margin (which the sheet's own padding cannot, since
       * that padding is consumed once on the first/last page). The running
       * header/footer are fixed inside that band. */
      .hdr-space { height: max(var(--doc-page-margin), calc(var(--doc-hdr-h) + 0.35in)); }
      .ftr-space { height: max(var(--doc-page-margin), calc(var(--doc-ftr-h) + 0.35in)); }
      ::slotted([slot="header"]) {
        position: fixed; top: 0; left: 0; right: 0; margin: 0;
        padding: calc(var(--doc-page-margin) * 0.45) var(--doc-page-margin) 0;
      }
      ::slotted([slot="footer"]) {
        position: fixed; bottom: 0; left: 0; right: 0; margin: 0;
        padding: 0 var(--doc-page-margin) calc(var(--doc-page-margin) * 0.45);
      }
    }
  `;
  class DocPage extends HTMLElement {
    static get observedAttributes() {
      return ['size', 'width', 'height', 'margin'];
    }
    constructor() {
      super();
      this._root = this.attachShadow({
        mode: 'open'
      });
      this._mo = typeof MutationObserver === 'function' ? new MutationObserver(() => this._scheduleMeasure()) : null;
    }
    get pageWidth() {
      const named = PAPER[(this.getAttribute('size') || '').toLowerCase()];
      return safeLen(this.getAttribute('width'), named ? named[0] : PAPER.letter[0]);
    }
    get pageHeight() {
      const named = PAPER[(this.getAttribute('size') || '').toLowerCase()];
      return safeLen(this.getAttribute('height'), named ? named[1] : PAPER.letter[1]);
    }
    get pageMargin() {
      return safeLen(this.getAttribute('margin'), '0.75in');
    }
    connectedCallback() {
      if (!this._sheet) this._render();
      this._syncSize();
      this._syncPrintPageRule();
      this._ensureTextWrapDefaults();
      if (this._mo) this._mo.observe(this, {
        subtree: true,
        childList: true,
        characterData: true,
        attributes: true
      });
      this._onResize = () => this._scheduleMeasure();
      window.addEventListener('resize', this._onResize);
      if (document.fonts && document.fonts.ready) {
        document.fonts.ready.then(() => this._scheduleMeasure());
      }
      this._scheduleMeasure();
    }
    disconnectedCallback() {
      window.removeEventListener('resize', this._onResize);
      if (this._mo) this._mo.disconnect();
      if (this._raf) {
        cancelAnimationFrame(this._raf);
        this._raf = null;
      }
      // Drop the head rules when the last doc-page leaves, so a deleted
      // document's @page geometry and text-wrap defaults can't apply to
      // whatever replaces it.
      if (!document.querySelector('doc-page')) {
        ['doc-page-print', 'doc-page-text-wrap'].forEach(id => {
          const tag = document.getElementById(id);
          if (tag) tag.remove();
        });
      }
    }
    attributeChangedCallback() {
      if (!this._sheet) return;
      this._syncSize();
      this._syncPrintPageRule();
      this._scheduleMeasure();
    }
    _render() {
      this._root.innerHTML = `
        <style>${stylesheet}</style>
        <style id="vars"></style>
        <div class="sheet" data-screen-label="Document">
          <table class="frame" role="presentation">
            <thead><tr><th><div class="hdr-space"><slot name="header"></slot></div></th></tr></thead>
            <tbody><tr><td class="body"><slot></slot></td></tr></tbody>
            <tfoot><tr><td><div class="ftr-space"><slot name="footer"></slot></div></td></tr></tfoot>
          </table>
        </div>`;
      this._sheet = this._root.querySelector('.sheet');
      this._vars = this._root.getElementById('vars');
    }

    /** Runtime sizing lives in a shadow <style> :host rule, never on the
     *  light-DOM host element, so serialize-persist can't write it back. */
    _syncSize(hdrH, ftrH) {
      this._vars.textContent = ':host{' + '--doc-page-w:' + this.pageWidth + ';' + '--doc-page-h:' + this.pageHeight + ';' + '--doc-page-margin:' + this.pageMargin + ';' + '--doc-hdr-h:' + (hdrH || 0) + 'px;' + '--doc-ftr-h:' + (ftrH || 0) + 'px}';
    }

    /** @page is a no-op inside shadow DOM, so the rule lives in <head>.
     *  Re-appended on every sync so it stays last in source order — the
     *  @page cascade is source-order per descriptor, so this rule wins
     *  over any other @page rule in the document. */
    _syncPrintPageRule() {
      const id = 'doc-page-print';
      let tag = document.getElementById(id);
      if (!tag) {
        tag = document.createElement('style');
        tag.id = id;
      }
      document.head.appendChild(tag);
      tag.textContent = '@page { size: ' + this.pageWidth + ' ' + this.pageHeight + '; margin: 0; } ' + '@media print { html, body { margin: 0 !important; padding: 0 !important; background: none !important; height: auto !important; overflow: visible !important; } ' + 'h1,h2,h3,h4,h5,h6 { break-after: avoid; } ' + 'figure,pre,blockquote,img,svg,tr { break-inside: avoid; } ' + 'p,li { orphans: 3; widows: 3; } ' + '* { -webkit-print-color-adjust: exact; print-color-adjust: exact; } ' + '*, *::before, *::after { animation-delay: -99s !important; animation-duration: .001s !important; ' + 'animation-iteration-count: 1 !important; animation-fill-mode: both !important; ' + 'animation-play-state: running !important; transition-duration: 0s !important; } }';
    }

    /** Typographic defaults for document text: balance headings, avoid
     *  widowed/orphaned words in body copy (browsers without text-wrap
     *  support drop the declarations). Zero-specificity via :where() so
     *  any text-wrap authored on those elements wins; document-level so the
     *  rules reach the slotted (light DOM) content — shadow styles can't.
     *  data-omelette-injected marks the tag for the host editor to strip
     *  at serialize, so it is never written back as authored source. */
    _ensureTextWrapDefaults() {
      if (document.getElementById('doc-page-text-wrap')) return;
      const tag = document.createElement('style');
      tag.id = 'doc-page-text-wrap';
      tag.setAttribute('data-omelette-injected', '');
      tag.textContent = ':where(h1,h2,h3,h4,h5,h6){text-wrap:balance}' + ':where(p,li,blockquote,figcaption){text-wrap:pretty}';
      document.head.appendChild(tag);
    }
    _scheduleMeasure() {
      if (this._raf) return;
      this._raf = requestAnimationFrame(() => {
        this._raf = null;
        this._measure();
      });
    }

    /** Slot heights feed the print spacers (--doc-hdr-h / --doc-ftr-h), so
     *  they re-measure on content mutation, resize, and font load. */
    _measure() {
      const hdr = this.querySelector(':scope > [slot="header"]');
      const ftr = this.querySelector(':scope > [slot="footer"]');
      this._syncSize(hdr ? hdr.offsetHeight : 0, ftr ? ftr.offsetHeight : 0);
    }
  }
  if (!customElements.get('doc-page')) {
    customElements.define('doc-page', DocPage);
  }
})();
})(); } catch (e) { __ds_ns.__errors.push({ path: "eazy-landing/doc-page.js", error: String((e && e.message) || e) }); }

// eazy-landing/script.js
try { (() => {
// ===== eazy landing — interactions =====
(function () {
  // Interactive Israel map — 42 branch pins
  var BRANCHES = [['קרית שמונה', 58, 7], ['נהריה', 40, 13], ['עכו', 42, 17], ['כרמיאל', 60, 16], ['צפת', 68, 14], ['טבריה', 72, 19], ['נצרת', 62, 23], ['עפולה', 60, 27], ['בית שאן', 78, 26], ['חיפה', 38, 25], ['הקריות', 44, 23], ['יקנעם', 52, 28], ['חדרה', 40, 33], ['נתניה', 34, 38], ['כפר סבא', 44, 40], ['רעננה', 40, 41], ['הרצליה', 34, 43], ['פתח תקווה', 46, 44], ['ראש העין', 52, 43], ['תל אביב', 30, 46], ['רמת גן', 36, 46], ['בני ברק', 38, 45], ['חולון', 30, 49], ['בת ים', 28, 50], ['ראשון לציון', 33, 51], ['רחובות', 36, 53], ['נס ציונה', 34, 52], ['מודיעין', 50, 50], ['ירושלים', 62, 52], ['בית שמש', 52, 54], ['אשדוד', 28, 55], ['אשקלון', 26, 60], ['קרית גת', 38, 60], ['יבנה', 32, 53], ['אריאל', 60, 45], ['באר שבע', 42, 68], ['אופקים', 34, 68], ['נתיבות', 32, 66], ['דימונה', 52, 72], ['ערד', 60, 72], ['קרית מלאכי', 32, 58], ['אילת', 46, 96]];
  var pinsHost = document.getElementById('mapPins');
  if (pinsHost) {
    var svg = '<svg viewBox="0 0 24 34"><path d="M12 0C5.4 0 0 5.3 0 11.9 0 20.5 12 34 12 34s12-13.5 12-22.1C24 5.3 18.6 0 12 0z" fill="#EA5F13"/><circle cx="12" cy="12" r="5" fill="#fff"/></svg>';
    BRANCHES.forEach(function (b) {
      var el = document.createElement('button');
      el.className = 'pin';
      el.type = 'button';
      el.style.left = b[1] + '%';
      el.style.top = b[2] + '%';
      el.setAttribute('aria-label', b[0]);
      el.innerHTML = '<span class="tip">' + b[0] + '</span><span class="dot">' + svg + '</span>';
      el.addEventListener('click', function (e) {
        e.preventDefault();
        document.querySelectorAll('.imap .pin.active').forEach(function (p) {
          p.classList.remove('active');
        });
        el.classList.add('active');
      });
      pinsHost.appendChild(el);
    });
    var bc = document.getElementById('branchCount');
    if (bc) bc.textContent = BRANCHES.length;
  }

  // Mobile nav toggle
  var t = document.getElementById('navToggle');
  var np = document.getElementById('navPurple');
  if (t && np) t.addEventListener('click', function () {
    np.classList.toggle('open');
  });

  // Team carousel
  var track = document.getElementById('teamTrack');
  var prev = document.getElementById('teamPrev');
  var next = document.getElementById('teamNext');
  if (track && prev && next) {
    var step = 206; // card width + gap
    // RTL: "next" (‹) moves to later cards = scroll left (negative)
    next.addEventListener('click', function () {
      track.scrollBy({
        left: -step * 2,
        behavior: 'smooth'
      });
    });
    prev.addEventListener('click', function () {
      track.scrollBy({
        left: step * 2,
        behavior: 'smooth'
      });
    });
  }

  // Testimonials dots reflect scroll (static demo — highlight on hover)
  var qs = document.querySelectorAll('.testi .q');
  var dots = document.querySelectorAll('.testi .dots i');
  qs.forEach(function (q, i) {
    q.addEventListener('mouseenter', function () {
      dots.forEach(function (d, j) {
        d.classList.toggle('on', i === j);
      });
    });
  });

  // Lead form
  var f = document.getElementById('leadForm');
  var ok = document.getElementById('leadOk');
  if (f) f.addEventListener('submit', function (e) {
    e.preventDefault();
    var name = document.getElementById('lname').value.trim();
    var phone = document.getElementById('lphone').value.trim();
    if (!name || !phone) {
      ok.textContent = 'נא למלא שם וטלפון.';
      ok.classList.add('show');
      return;
    }
    ok.textContent = 'תודה ' + name + '! ניצור איתך קשר בהקדם.';
    ok.classList.add('show');
    f.querySelector('.submit').textContent = 'נשלח ✓';
  });
})();
})(); } catch (e) { __ds_ns.__errors.push({ path: "eazy-landing/script.js", error: String((e && e.message) || e) }); }

// exports/eazy-math-diagnostic/app.js
try { (() => {
/* =========================================================================
   eazy — מסלול שברים: אבחון שברים ומשוואות
   ========================================================================= */

// small helper for fraction markup
const f = (a, b) => `<span class="frac"><span class="fr-n">${a}</span><span class="fr-d">${b}</span></span>`;
// convert inline "a⁄b" fraction-slash tokens (used in explanations) into classic stacked fractions
function stackFractions(html) {
  return html.replace(/([0-9A-Za-z()]+)\u2044([0-9A-Za-z()]+)/g, (m, n, d) => `<span class="frac"><span class="fr-n">${n}</span><span class="fr-d">${d}</span></span>`);
}
// wrap a math expression so it always renders left-to-right (minus left of number, exponent right of base)
const ltr = s => `<span class="ltr">${s}</span>`;

// ---- Questions ----
const QUESTIONS = [{
  topic: "ops",
  text: `כמה זה ${ltr(`${f(1, 4)} + ${f(2, 4)}`)} ?`,
  opts: [`${f(3, 4)}`, `${f(3, 8)}`, `${f(1, 2)}`, `${f(2, 8)}`],
  correct: 0,
  explain: `המכנה כבר משותף (4), אז פשוט מחברים את המונים: <span class="mono">1 + 2 = 3</span>, והמכנה נשאר 4. התוצאה: <b>3⁄4</b>.`
}, {
  topic: "ops",
  text: `כמה זה ${ltr(`${f(5, 6)} − ${f(1, 3)}`)} ?`,
  opts: [`${f(1, 2)}`, `${f(2, 3)}`, `${f(4, 9)}`, `${f(4, 3)}`],
  correct: 0,
  explain: `מוצאים מכנה משותף 6: <span class="mono">1⁄3 = 2⁄6</span>. עכשיו <span class="mono">5⁄6 − 2⁄6 = 3⁄6</span>, ומצמצמים ל־<b>1⁄2</b>.`
}, {
  topic: "reduce",
  text: `צמצמו את השבר ${f(12, 18)}`,
  opts: [`${f(2, 3)}`, `${f(3, 4)}`, `${f(6, 9)}`, `${f(4, 6)}`],
  correct: 0,
  explain: `מחפשים מספר שמחלק גם את 12 וגם את 18 — זה 6. <span class="mono">12÷6 = 2</span>, <span class="mono">18÷6 = 3</span>. התוצאה המצומצמת: <b>2⁄3</b>.`
}, {
  topic: "multdiv",
  text: `כמה זה ${ltr(`${f(2, 3)} × ${f(3, 5)}`)} ?`,
  opts: [`${f(2, 5)}`, `${f(5, 8)}`, `${f(6, 8)}`, `${f(5, 15)}`],
  correct: 0,
  explain: `בכפל שברים כופלים מונה במונה ומכנה במכנה: <span class="mono">2×3 = 6</span>, <span class="mono">3×5 = 15</span> → 6⁄15. מצמצמים ב־3 ומקבלים <b>2⁄5</b>.`
}, {
  topic: "multdiv",
  text: `כמה זה ${ltr(`${f(3, 4)} ÷ ${f(1, 2)}`)} ?`,
  opts: [`${f(3, 2)}`, `${f(3, 8)}`, `${f(1, 2)}`, `2`],
  correct: 0,
  explain: `בחילוק שברים הופכים את השבר השני וכופלים: <span class="mono">3⁄4 × 2⁄1 = 6⁄4</span>. מצמצמים ל־<b>3⁄2</b> (כלומר אחד וחצי).`
}, {
  topic: "simpleeq",
  text: `פתרו: ${ltr("4x − 3 = 17")}`,
  opts: [`x = 5`, `x = 6`, `x = 3.5`, `x = 4`],
  correct: 0,
  explain: `מעבירים אגף: <span class="mono">4x = 17 + 3 = 20</span>. מחלקים ב־4: <span class="mono">x = 20 ÷ 4 = 5</span>. אז <b>x = 5</b>.`
}, {
  topic: "compare",
  text: `מי גדול יותר — ${f(3, 5)} או ${f(5, 8)} ?`,
  opts: [`${f(5, 8)}`, `${f(3, 5)}`, `שווים`, `אי אפשר לדעת`],
  correct: 0,
  explain: `מביאים למכנה משותף 40: <span class="mono">3⁄5 = 24⁄40</span> ו־<span class="mono">5⁄8 = 25⁄40</span>. 25 גדול מ־24, לכן <b>5⁄8</b> גדול יותר.`
}, {
  topic: "compare",
  text: `מי הכי גדול מבין: ${f(2, 3)} , ${f(3, 4)} , ${f(4, 5)} ?`,
  opts: [`${f(4, 5)}`, `${f(3, 4)}`, `${f(2, 3)}`, `כולם שווים`],
  correct: 0,
  explain: `ככל שהשבר קרוב יותר לשלם, הוא גדול יותר. במכנה משותף 60: <span class="mono">2⁄3=40⁄60</span>, <span class="mono">3⁄4=45⁄60</span>, <span class="mono">4⁄5=48⁄60</span>. הגדול ביותר: <b>4⁄5</b>.`
}, {
  topic: "fraceq",
  text: `פתרו: ${ltr(`${f("x", 2)} + ${f("x", 4)} = 9`)}`,
  opts: [`x = 12`, `x = 6`, `x = 18`, `x = 3`],
  correct: 0,
  explain: `מכנה משותף 4: <span class="mono">2x⁄4 + x⁄4 = 3x⁄4</span>. אז <span class="mono">3x⁄4 = 9</span> → <span class="mono">3x = 36</span> → <b>x = 12</b>.`
}, {
  topic: "fraceq",
  text: `פתרו: ${ltr(`${f("(x + 1)", 3)} = 4`)}`,
  opts: [`x = 11`, `x = 12`, `x = 13`, `x = 3`],
  correct: 0,
  explain: `כופלים את שני האגפים ב־3: <span class="mono">x + 1 = 12</span>. מחסרים 1: <span class="mono">x = 11</span>. אז <b>x = 11</b>.`
}];

// ==== Quiz 2 — comparing fractions & inequalities ====
const Q2 = [{
  topic: "compare",
  text: `מי גדול יותר — ${f(3, 5)} או ${f(5, 8)} ?`,
  opts: [`${f(5, 8)}`, `${f(3, 5)}`, `שווים`, `אי אפשר לדעת`],
  correct: 0,
  explain: `מביאים למכנה משותף 40: <span class="mono">3⁄5 = 24⁄40</span> ו־<span class="mono">5⁄8 = 25⁄40</span>. 25 גדול מ־24, לכן <b>5⁄8</b> גדול יותר.`
}, {
  topic: "compare",
  text: `מי הכי גדול מבין: ${f(2, 3)} , ${f(3, 4)} , ${f(4, 5)} ?`,
  opts: [`${f(4, 5)}`, `${f(3, 4)}`, `${f(2, 3)}`, `כולם שווים`],
  correct: 0,
  explain: `ככל שהשבר קרוב יותר לשלם הוא גדול יותר. במכנה משותף 60: <span class="mono">2⁄3 = 40⁄60</span>, <span class="mono">3⁄4 = 45⁄60</span>, <span class="mono">4⁄5 = 48⁄60</span>. הגדול: <b>4⁄5</b>.`
}, {
  topic: "compare",
  text: `מי גדול יותר — ${f(4, 7)} או ${f(5, 9)} ?`,
  opts: [`${f(4, 7)}`, `${f(5, 9)}`, `שווים`, `אי אפשר לדעת`],
  correct: 0,
  explain: `מכנה משותף 63: <span class="mono">4⁄7 = 36⁄63</span> ו־<span class="mono">5⁄9 = 35⁄63</span>. 36 גדול מ־35, לכן <b>4⁄7</b> גדול יותר.`
}, {
  topic: "compare",
  text: `מי הכי קטן מבין: ${f(1, 2)} , ${f(2, 5)} , ${f(3, 8)} ?`,
  opts: [`${f(3, 8)}`, `${f(2, 5)}`, `${f(1, 2)}`, `כולם שווים`],
  correct: 0,
  explain: `במכנה משותף 40: <span class="mono">1⁄2 = 20⁄40</span>, <span class="mono">2⁄5 = 16⁄40</span>, <span class="mono">3⁄8 = 15⁄40</span>. הקטן ביותר: <b>3⁄8</b>.`
}, {
  topic: "inequal",
  text: `פתרו את האי-שוויון: ${ltr("x + 3 < 7")}`,
  opts: [`x < 4`, `x > 4`, `x < 10`, `x > 10`],
  correct: 0,
  explain: `מחסרים 3 משני האגפים: <span class="mono">x < 7 − 3</span>, כלומר <b>x < 4</b>.`
}, {
  topic: "inequal",
  text: `פתרו את האי-שוויון: ${ltr("2x > 10")}`,
  opts: [`x > 5`, `x < 5`, `x > 20`, `x = 5`],
  correct: 0,
  explain: `מחלקים ב־2 (מספר חיובי — הסימן נשאר): <span class="mono">x > 10 ÷ 2</span> → <b>x > 5</b>.`
}, {
  topic: "inequal",
  text: `פתרו את האי-שוויון: ${ltr("x − 2 ≥ 3")}`,
  opts: [`x ≥ 5`, `x ≤ 5`, `x ≥ 1`, `x > 5`],
  correct: 0,
  explain: `מוסיפים 2 לשני האגפים: <span class="mono">x ≥ 3 + 2</span> → <b>x ≥ 5</b>.`
}, {
  topic: "inequal",
  text: `פתרו את האי-שוויון: ${ltr("−x < −2")}`,
  opts: [`x > 2`, `x < 2`, `x < −2`, `x > −2`],
  correct: 0,
  explain: `כשמכפילים או מחלקים אי-שוויון במספר שלילי — הופכים את כיוון הסימן. כאן כופלים ב־(−1) ומקבלים <b>x > 2</b>.`
}];

// ==== Quiz 3 — percentages, powers & roots ====
const Q3 = [{
  topic: "percent",
  text: `כמה זה ${ltr("25%")} מתוך 80 ?`,
  opts: [`20`, `25`, `40`, `15`],
  correct: 0,
  explain: `25% הם רבע. <span class="mono">80 ÷ 4 = 20</span>. אז <b>20</b>.`
}, {
  topic: "percent",
  text: `15 הם כמה אחוזים מתוך 60 ?`,
  opts: [`25%`, `15%`, `40%`, `20%`],
  correct: 0,
  explain: `מחלקים ומכפילים ב־100: <span class="mono">15 ÷ 60 = 0.25</span> → <b>25%</b>.`
}, {
  topic: "percent",
  text: `מחיר ${ltr("200 ₪")} עלה ב־${ltr("10%")}. מה המחיר החדש ?`,
  opts: [`220 ₪`, `210 ₪`, `240 ₪`, `20 ₪`],
  correct: 0,
  explain: `10% מ־200 הם 20. מוסיפים: <span class="mono">200 + 20 = 220</span> ₪.`
}, {
  topic: "powers",
  text: `כמה זה ${ltr("2³ × 2²")} ?`,
  opts: [`32`, `16`, `64`, `20`],
  correct: 0,
  explain: `בכפל חזקות עם אותו בסיס מחברים את המעריכים: <span class="mono">2³⁺² = 2⁵ = 32</span>.`
}, {
  topic: "powers",
  text: `כמה זה ${ltr("(2³)²")} ?`,
  opts: [`64`, `32`, `128`, `12`],
  correct: 0,
  explain: `בחזקה של חזקה מכפילים את המעריכים: <span class="mono">2³ˣ² = 2⁶ = 64</span>.`
}, {
  topic: "powers",
  text: `כמה זה ${ltr("5⁰")} ?`,
  opts: [`1`, `0`, `5`, `אין פתרון`],
  correct: 0,
  explain: `כל מספר (שונה מ־0) בחזקת 0 שווה ל־<b>1</b>.`
}, {
  topic: "roots",
  text: `כמה זה ${ltr("√144")} ?`,
  opts: [`12`, `14`, `72`, `24`],
  correct: 0,
  explain: `מחפשים מספר שכפול עצמו נותן 144: <span class="mono">12 × 12 = 144</span>. אז <b>12</b>.`
}, {
  topic: "roots",
  text: `פשטו את השורש: ${ltr("√50")}`,
  opts: [`5√2`, `25√2`, `2√5`, `10`],
  correct: 0,
  explain: `מפרקים לגורם ריבועי: <span class="mono">√50 = √(25 × 2) = √25 × √2 = 5√2</span>.`
}];

// ==== Quiz 4 — absolute value, special products, factorial & power laws ====
const Q4 = [{
  topic: "abs",
  text: `כמה זה ${ltr("|−7|")} ?`,
  opts: [`7`, `−7`, `0`, `14`],
  correct: 0,
  explain: `ערך מוחלט הוא המרחק מ־0, ולכן תמיד אי-שלילי. אז <b>|−7| = 7</b>.`
}, {
  topic: "abs",
  text: `כמה זה ${ltr("|3 − 8|")} ?`,
  opts: [`5`, `−5`, `11`, `3`],
  correct: 0,
  explain: `קודם מחשבים בתוך הסימן: <span class="mono">3 − 8 = −5</span>, ואז <span class="mono">|−5| = 5</span>.`
}, {
  topic: "factorial",
  text: `כמה זה ${ltr("4!")} (עצרת) ?`,
  opts: [`24`, `12`, `16`, `10`],
  correct: 0,
  explain: `עצרת = מכפלת כל המספרים עד המספר: <span class="mono">4 × 3 × 2 × 1 = 24</span>.`
}, {
  topic: "factorial",
  text: `כמה זה ${ltr("5! ÷ 3!")} ?`,
  opts: [`20`, `2`, `60`, `120`],
  correct: 0,
  explain: `מצמצמים את העצרות: ${f("5!", "3!")} = <span class="mono">5 × 4 = 20</span>.`
}, {
  topic: "shortmult",
  text: `למה שווה ${ltr("(a + b)²")} ?`,
  opts: [`a² + 2ab + b²`, `a² + b²`, `a² − 2ab + b²`, `2a + 2b`],
  correct: 0,
  explain: `נוסחת הכפל המקוצר: <b>(a + b)² = a² + 2ab + b²</b>.`
}, {
  topic: "shortmult",
  text: `למה שווה ${ltr("(x + 3)(x − 3)")} ?`,
  opts: [`x² − 9`, `x² + 9`, `x² − 6`, `x² − 6x − 9`],
  correct: 0,
  explain: `הפרש ריבועים: <span class="mono">(x + 3)(x − 3) = x² − 3² = x² − 9</span>.`
}, {
  topic: "powerlaws",
  text: `כמה זה ${ltr("x⁵ ÷ x²")} ?`,
  opts: [`x³`, `x⁷`, `x¹⁰`, `x`],
  correct: 0,
  explain: `בחילוק חזקות עם אותו בסיס מחסרים את המעריכים: <span class="mono">x⁵⁻² = x³</span>.`
}, {
  topic: "powerlaws",
  text: `למה שווה ${ltr("x⁻²")} ?`,
  opts: [`${f(1, "x²")}`, `−x²`, `x²`, `−2x`],
  correct: 0,
  explain: `מעריך שלילי הופך למכנה: <b>x⁻² =</b> ${f(1, "x²")}.`
}];

// ---- Topic maps per quiz ----
const T1 = {
  ops: {
    name: "חיבור וחיסור שברים",
    tier: "foundation"
  },
  reduce: {
    name: "צמצום והרחבה",
    tier: "foundation"
  },
  multdiv: {
    name: "כפל וחילוק שברים",
    tier: "foundation"
  },
  simpleeq: {
    name: "משוואות פשוטות",
    tier: "foundation"
  },
  fraceq: {
    name: "משוואות עם שברים",
    tier: "advanced"
  }
};
const T2 = {
  compare: {
    name: "השוואת שברים",
    tier: "foundation"
  },
  inequal: {
    name: "אי-שוויונות",
    tier: "advanced"
  }
};
const T3 = {
  percent: {
    name: "אחוזים",
    tier: "foundation"
  },
  powers: {
    name: "חזקות",
    tier: "foundation"
  },
  roots: {
    name: "שורשים",
    tier: "advanced"
  }
};
const T4 = {
  abs: {
    name: "ערך מוחלט",
    tier: "foundation"
  },
  factorial: {
    name: "עצרת",
    tier: "foundation"
  },
  shortmult: {
    name: "כפל מקוצר",
    tier: "advanced"
  },
  powerlaws: {
    name: "חוקי חזקות",
    tier: "advanced"
  }
};

// ---- The 4 quizzes ----
const QUIZZES = [{
  name: "שברים ומשוואות",
  sub: "חיבור, חיסור, כפל, חילוק, צמצום ומשוואות",
  icon: "ph-function",
  color: "var(--ez-orange)",
  cls: "o",
  course: "תגבור 7.9",
  subject: "שברים ומשוואות",
  advancedName: "משוואות עם שברים",
  topics: T1,
  questions: QUESTIONS.filter(q => q.topic !== "compare")
}, {
  name: "השוואת שברים ואי-שוויונות",
  sub: "מי גדול יותר, סדר גדלים ופתרון אי-שוויונות",
  icon: "ph-arrows-left-right",
  color: "var(--game-blue)",
  cls: "b",
  course: "תגבור 7.9",
  subject: "השוואת שברים ואי-שוויונות",
  advancedName: "פתרון אי-שוויונות",
  topics: T2,
  questions: Q2
}, {
  name: "אחוזים, חזקות ושורשים",
  sub: "חישובי אחוזים, חוקי חזקות ושורשים",
  icon: "ph-percent",
  color: "var(--game-green)",
  cls: "g",
  course: "תגבור 8.9",
  subject: "אחוזים, חזקות ושורשים",
  advancedName: "שורשים",
  topics: T3,
  questions: Q3
}, {
  name: "ערך מוחלט, כפל מקוצר ועצרת",
  sub: "ערך מוחלט, נוסחאות כפל מקוצר, עצרת וחוקי חזקות",
  icon: "ph-math-operations",
  color: "var(--game-gold)",
  cls: "y",
  course: "תגבור 8.9",
  subject: "ערך מוחלט, כפל מקוצר ועצרת",
  advancedName: "כפל מקוצר וחוקי חזקות",
  topics: T4,
  questions: Q4
}];

// ---- State ----
const state = {
  quiz: null,
  qi: 0,
  i: 0,
  energy: 0,
  streak: 0,
  maxStreak: 0,
  answered: [],
  topicScore: {},
  session: null,
  results: [null, null, null, null] // per-quiz saved result for the summary
};
const ENERGY_BASE = 100;
const COMBO_STEP = 25; // +25 energy per streak level

// ---- Progress persistence (results + in-progress session) ----
const PROG_KEY = "eazy_frac_progress_v1";
function persist() {
  try {
    localStorage.setItem(PROG_KEY, JSON.stringify({
      results: state.results,
      session: state.session || null
    }));
  } catch (e) {}
}
function loadPersisted() {
  try {
    const raw = JSON.parse(localStorage.getItem(PROG_KEY));
    if (Array.isArray(raw) && raw.length === 4) {
      state.results = raw;
      return null;
    } // legacy format
    if (raw && Array.isArray(raw.results) && raw.results.length === 4) state.results = raw.results;
    if (raw && raw.session) return raw.session;
  } catch (e) {}
  return null;
}
function snapshot(phase) {
  return {
    phase,
    qi: state.qi,
    i: state.i,
    energy: state.energy,
    streak: state.streak,
    maxStreak: state.maxStreak,
    answered: state.answered,
    topicScore: state.topicScore
  };
}

// ---- DOM ----
const $ = id => document.getElementById(id);
const screens = {
  select: $("s-select"),
  summary: $("s-summary"),
  quiz: $("s-quiz"),
  result: $("s-result")
};
function show(name) {
  Object.values(screens).forEach(s => s.classList.remove("on"));
  screens[name].classList.add("on");
  window.scrollTo(0, 0);
}
function setSub(txt) {
  const el = document.querySelector(".gh-sub");
  if (el) el.textContent = txt;
}

// ---- Track init ----
function buildTrack() {
  const nodes = $("track-nodes");
  nodes.innerHTML = "";
  const n = state.quiz.questions.length;
  for (let k = 0; k < n; k++) {
    const d = document.createElement("div");
    d.className = "node";
    nodes.appendChild(d);
  }
}
function updateHUD() {
  const n = state.quiz.questions.length;
  $("hud-energy").textContent = state.energy;
  $("hud-streak").textContent = state.streak;
  $("hud-station").textContent = `${Math.min(state.i + 1, n)}/${n}`;
  const nodeEls = $("track-nodes").children;
  for (let k = 0; k < nodeEls.length; k++) {
    nodeEls[k].className = "node" + (k < state.i ? " done" : k === state.i ? " here" : "");
  }
  const pct = state.i / (n - 1);
  $("track-fill").style.width = state.i / n * 100 + "%";
  $("track-flyer").style.right = pct * 100 + "%";
}

// ---- Render question ----
let locked = false;
function renderQuestion() {
  const q = state.quiz.questions[state.i];
  const t = state.quiz.topics[q.topic];
  locked = false;
  $("q-topic-name").textContent = t.name;
  $("q-tier").textContent = t.tier === "foundation" ? "יסודות" : "מתקדם";
  $("q-text").innerHTML = q.text;
  const keys = ["1", "2", "3", "4"];
  const box = $("q-opts");
  box.innerHTML = "";
  q.opts.forEach((o, idx) => {
    const el = document.createElement("button");
    el.className = "opt";
    const heb = /[\u0590-\u05FF]/.test(o);
    el.innerHTML = `<span class="key">${keys[idx]}</span><span class="otext${heb ? "" : " ltr"}">${o}</span>`;
    el.onclick = () => choose(idx, el);
    box.appendChild(el);
  });

  // reset panel + buttons
  closePanel();
  $("btn-next").disabled = true;
  $("btn-next").innerHTML = state.i === state.quiz.questions.length - 1 ? 'לתוצאות <i class="ph ph-flag-checkered"></i>' : 'המשך <i class="ph ph-arrow-left"></i>';
  $("btn-explain").style.display = "inline-flex";
  updateHUD();
}

// ---- Panel helpers ----
function openPanel(kind, title, body, combo) {
  const p = $("q-panel");
  p.className = "panel open " + kind;
  $("q-panel-title").innerHTML = title;
  $("q-panel-body").innerHTML = stackFractions(body);
  const c = $("q-combo");
  if (combo) {
    c.style.display = "inline-flex";
    c.innerHTML = combo;
  } else {
    c.style.display = "none";
  }
}
function closePanel() {
  const p = $("q-panel");
  p.className = "panel";
  $("q-combo").style.display = "none";
}

// ---- Explain-me (hint, always available) ----
$("btn-explain").onclick = () => {
  const q = state.quiz.questions[state.i];
  const p = $("q-panel");
  if (p.classList.contains("open") && p.classList.contains("hint")) {
    closePanel();
    return;
  }
  openPanel("hint", '<i class="ph-fill ph-lightbulb"></i> הסבר · איך פותרים', q.explain);
};

// ---- Choose answer ----
function choose(idx, el) {
  if (locked) return;
  locked = true;
  const q = state.quiz.questions[state.i];
  const correct = idx === q.correct;
  state.answered[state.i] = {
    correct,
    chosen: idx
  };
  state.topicScore[q.topic].t += 1;
  if (correct) state.topicScore[q.topic].c += 1;

  // lock all options, mark correct/wrong
  const optEls = $("q-opts").children;
  for (let k = 0; k < optEls.length; k++) {
    optEls[k].classList.add("locked");
    optEls[k].onclick = null;
    if (k === q.correct) optEls[k].classList.add("correct");else if (k === idx) optEls[k].classList.add("wrong");else optEls[k].classList.add("dim");
  }
  if (correct) {
    state.streak += 1;
    state.maxStreak = Math.max(state.maxStreak, state.streak);
    const bonus = (state.streak - 1) * COMBO_STEP;
    const gain = ENERGY_BASE + bonus;
    state.energy += gain;
    let combo = "";
    if (state.streak >= 2) combo = `<i class="ph-fill ph-fire"></i> רצף ${state.streak}! בונוס +${bonus} אנרגיה`;
    openPanel("right", `<i class="ph-fill ph-check-circle"></i> יפה! +${gain} אנרגיה`, q.explain, combo);
  } else {
    state.streak = 0;
    openPanel("miss", '<i class="ph-fill ph-x-circle"></i> כמעט — ככה פותרים:', q.explain);
  }
  $("btn-explain").style.display = "none";
  $("btn-next").disabled = false;
  updateHUD();
  state.session = snapshot("quiz");
  persist();
}

// ---- Next ----
$("btn-next").onclick = () => {
  if (state.i < state.quiz.questions.length - 1) {
    state.i += 1;
    renderQuestion();
  } else {
    finish();
  }
};

// ---- Quiz selection / menu / summary ----
function resetRun() {
  state.i = 0;
  state.energy = 0;
  state.streak = 0;
  state.maxStreak = 0;
  state.answered = [];
  state.topicScore = {};
  Object.keys(state.quiz.topics).forEach(k => state.topicScore[k] = {
    c: 0,
    t: 0
  });
  $("r-mistakes").style.display = "none";
  $("r-next").style.display = "none";
}
function startQuiz(idx) {
  state.qi = idx;
  state.quiz = QUIZZES[idx];
  resetRun();
  setSub("לומדת מתמטיקה");
  $("hudwrap").style.display = "block";
  buildTrack();
  $("quizmeta").textContent = `${state.quiz.questions.length} שאלות · בין 3 ל-6 דקות`;
  renderQuestion();
  state.session = snapshot("quiz");
  persist();
  closeMenu();
  show("quiz");
}
function goHome() {
  $("hudwrap").style.display = "none";
  setSub("לומדת מתמטיקה");
  state.session = null;
  persist();
  closeMenu();
  show("select");
}
function goSummary() {
  $("hudwrap").style.display = "none";
  setSub("התמונה המלאה");
  state.session = null;
  persist();
  renderSummary();
  closeMenu();
  show("summary");
}

// ---- Build the select cards ----
function renderSelect() {
  const grid = $("quizgrid");
  grid.innerHTML = "";
  QUIZZES.forEach((q, i) => {
    const b = document.createElement("button");
    b.className = "qcard " + q.cls;
    b.style.setProperty("--qc", q.color);
    b.innerHTML = `<div class="qc-ic"><i class="ph-fill ${q.icon}"></i></div>` + `<div class="qc-name">${q.name}</div>` + `<div class="qc-course">${q.course}</div>`;
    b.onclick = () => startQuiz(i);
    grid.appendChild(b);
  });
}

// ---- Hamburger menu ----
function renderMenu() {
  const m = $("ghmenu");
  let html = `<button class="ghmi home" data-href="https://ezway.co.il"><i class="ph ph-house"></i> מסך הבית</button>` + `<button class="ghmi home" data-href="https://ezway.co.il/students"><i class="ph ph-student"></i> כניסת סטודנטים</button>` + `<button class="ghmi home" data-go="home"><i class="ph ph-rocket-launch"></i> מאיפה מתחילים</button>` + `<button class="ghmi home" data-go="summary"><i class="ph ph-chart-donut"></i> התמונה המלאה</button>` + `<div class="ghmsep"></div>`;
  QUIZZES.forEach((q, i) => {
    html += `<button class="ghmi" data-quiz="${i}" style="--qc:${q.color}"><span class="dot"></span> ${q.name}</button>`;
  });
  m.innerHTML = html;
  m.querySelectorAll("[data-quiz]").forEach(b => b.onclick = () => startQuiz(+b.dataset.quiz));
  m.querySelectorAll("[data-href]").forEach(b => b.onclick = () => {
    window.open(b.dataset.href, "_blank", "noopener");
    closeMenu();
  });
  m.querySelector('[data-go="home"]').onclick = goHome;
  m.querySelector('[data-go="summary"]').onclick = goSummary;
}
function openMenu() {
  $("ghmenu").hidden = false;
}
function closeMenu() {
  $("ghmenu").hidden = true;
}
document.querySelector(".gh-menu").onclick = e => {
  e.stopPropagation();
  const m = $("ghmenu");
  m.hidden ? openMenu() : closeMenu();
};
document.addEventListener("click", e => {
  const m = $("ghmenu");
  if (!m.hidden && !m.contains(e.target) && !e.target.closest(".gh-menu")) closeMenu();
});

// ---- Summary ("full picture") ----
function renderSummary() {
  const done = state.results.filter(Boolean).length;
  $("sum-lead").textContent = done === 0 ? "התמונה מתמלאת עם כל בוחן שתשלימו. פתרו קודם את התכנים — וכאן תראו בדיוק כמה חזקים אתם בכל תחום ומה עוד כדאי לחזק." : `השלמתם ${done} מתוך 4 הבחנים. התמונה מתמלאת — הנה מה שכבר נבדק ומה שנשאר לגלות.`;
  const pctDone = Math.round(done / QUIZZES.length * 100);
  $("sum-count").textContent = `${done}/${QUIZZES.length} בחנים הושלמו`;
  requestAnimationFrame(() => {
    $("sum-fill").style.width = pctDone + "%";
  });
  const list = $("sum-list");
  list.innerHTML = "";
  QUIZZES.forEach((q, i) => {
    const r = state.results[i];
    const row = document.createElement("div");
    row.className = "sumrow " + q.cls;
    row.style.setProperty("--qc", q.color);
    let stat, btnTxt;
    if (r) {
      const bandLbl = r.band === "full" ? "מומלץ תגבור מלא" : r.band === "advanced" ? "מומלץ החלק המתקדם" : "בשליטה יפה";
      stat = `<div class="sum-stat done">${r.correct}/${r.total} תשובות נכונות · ${bandLbl}</div>`;
      btnTxt = "שוב";
    } else {
      stat = `<div class="sum-stat todo">טרם בוצע · ${q.questions.length} שאלות</div>`;
      btnTxt = "התחל";
    }
    row.innerHTML = `<div class="sum-ic"><i class="ph-fill ${q.icon}"></i></div>` + `<div class="sum-b"><div class="sum-name">${q.name}</div>${stat}</div>` + `<button class="sum-go ${q.cls}">${btnTxt}</button>`;
    row.querySelector(".sum-go").onclick = () => startQuiz(i);
    list.appendChild(row);
  });
}
$("sum-home").onclick = goHome;

// ---- Finish + diagnosis ----
function finish() {
  updateHUD();
  const Q = state.quiz;
  let fC = 0,
    fT = 0,
    aC = 0,
    aT = 0;
  Object.keys(Q.topics).forEach(k => {
    const s = state.topicScore[k];
    if (Q.topics[k].tier === "foundation") {
      fC += s.c;
      fT += s.t;
    } else {
      aC += s.c;
      aT += s.t;
    }
  });
  const fPct = fT ? fC / fT : 1;
  const aPct = aT ? aC / aT : 1;
  const total = fC + aC,
    totalT = fT + aT;
  let band, rtitle, rbody, badgeColor, badgeIcon, headline;
  if (fPct < 0.7) {
    band = "full";
    headline = "בואו נבנה בסיס חזק";
    rtitle = `תגבור מלא — ${Q.subject} מהיסוד`;
    rbody = `בחלק הבסיסי של ${Q.subject} עדיין יש כמה פערים. כדאי להתחיל מהחלק שבונה את הבסיס — משם כל השאר נהיה הרבה יותר קל. זה בדיוק מה שהתגבור המלא עושה.`;
    badgeColor = "var(--ez-orange)";
    badgeIcon = "ph-stack";
  } else if (aPct < 0.75) {
    band = "advanced";
    headline = "הבסיס אצלכם — עכשיו למתקדם";
    rtitle = `החלק המתקדם — ${Q.advancedName}`;
    rbody = `את היסודות אתם שולטים יפה. הפערים מתמקדים בחלק המתקדם: ${Q.advancedName}. אין צורך בתגבור המלא — מספיק להצטרף לחלק המתקדם ולסגור בדיוק את מה שחסר.`;
    badgeColor = "var(--game-blue)";
    badgeIcon = "ph-trend-up";
  } else {
    band = "ready";
    headline = "אתם ממש מוכנים!";
    rtitle = "ריענון קצר בלבד — אתם בשליטה";
    rbody = `גם ביסודות וגם בחלק המתקדם הראיתם שליטה יפה ב${Q.subject}. אין צורך בתגבור מלא; ריענון ממוקד לפני המבחן יעשה את העבודה.`;
    badgeColor = "var(--ez-success)";
    badgeIcon = "ph-flag-checkered";
  }
  $("r-headline").textContent = headline;
  $("r-badge").style.background = badgeColor;
  $("r-badge").innerHTML = `<i class="ph-fill ${badgeIcon}"></i>`;
  $("r-score").innerHTML = `${total}/${totalT} תשובות נכונות · ${state.energy} אנרגיה · רצף שיא ${state.maxStreak}`;
  $("r-reco-title").textContent = rtitle;
  $("r-reco-body").textContent = rbody;

  // ---- topic map ----
  const mapEl = $("r-map");
  mapEl.innerHTML = "";
  const order = Object.keys(Q.topics);
  const topicPct = {};
  const groups = [{
    lab: "יסודות",
    keys: order.filter(k => Q.topics[k].tier === "foundation")
  }, {
    lab: "מתקדם",
    keys: order.filter(k => Q.topics[k].tier === "advanced")
  }];
  groups.forEach(g => {
    if (!g.keys.length) return;
    const gl = document.createElement("div");
    gl.className = "group-lab";
    gl.textContent = g.lab;
    mapEl.appendChild(gl);
    g.keys.forEach(k => {
      const s = state.topicScore[k];
      const pct = s.t ? Math.round(s.c / s.t * 100) : 0;
      topicPct[k] = pct;
      const cls = pct >= 100 ? "good" : pct >= 50 ? "mid" : "low";
      const tag = pct >= 100 ? "חזק" : pct >= 50 ? "כמעט" : "לחיזוק";
      const row = document.createElement("div");
      row.className = "bar " + cls;
      row.innerHTML = `<div class="brow"><span class="bname">${Q.topics[k].name}</span>` + `<span class="tag">${tag}</span></div>` + `<div class="btrack"><div class="bfill"></div></div>`;
      mapEl.appendChild(row);
      requestAnimationFrame(() => {
        setTimeout(() => {
          row.querySelector(".bfill").style.width = pct + "%";
        }, 60);
      });
    });
  });
  state.results[state.qi] = {
    correct: total,
    total: totalT,
    band: band,
    topics: topicPct
  };
  state.session = snapshot("result");
  persist();
  renderNext();
  show("result");
}

// ---- Next-topic suggestion ----
function renderNext() {
  const card = $("r-next");
  let nextIdx = -1;
  for (let s = 1; s < QUIZZES.length; s++) {
    const j = (state.qi + s) % QUIZZES.length;
    if (!state.results[j]) {
      nextIdx = j;
      break;
    }
  }
  if (nextIdx === -1) {
    card.className = "card nextcard";
    card.style.setProperty("--qc", "var(--ez-lavender-deep)");
    card.innerHTML = `<div class="nx-ic"><i class="ph-fill ph-check-circle"></i></div><div class="nx-b"><div class="nx-k">כל הכבוד!</div><div class="nx-t">סיימתם את כל 4 הבחנים</div></div><button class="nx-go" id="nx-btn"><i class="ph ph-chart-donut"></i> לתמונה המלאה</button>`;
    card.style.display = "";
    $("nx-btn").onclick = goSummary;
  } else {
    const nq = QUIZZES[nextIdx];
    card.className = "card nextcard " + nq.cls;
    card.style.setProperty("--qc", nq.color);
    card.innerHTML = `<div class="nx-ic"><i class="ph-fill ${nq.icon}"></i></div><div class="nx-b"><div class="nx-k">מוכנים להמשיך? הנושא הבא</div><div class="nx-t">${nq.name}</div></div><button class="nx-go" id="nx-btn">לנושא הבא <i class="ph ph-arrow-left"></i></button>`;
    card.style.display = "";
    $("nx-btn").onclick = () => startQuiz(nextIdx);
  }
}

// ---- Result nav actions ----
function toast(msg) {
  const t = $("toast");
  t.textContent = msg;
  t.classList.add("show");
  clearTimeout(t._t);
  t._t = setTimeout(() => t.classList.remove("show"), 2200);
}
function buildMistakes() {
  const list = $("r-mistakes-list");
  list.innerHTML = "";
  const wrong = [];
  state.quiz.questions.forEach((q, i) => {
    const a = state.answered[i];
    if (a && !a.correct) wrong.push(q);
  });
  if (!wrong.length) {
    list.innerHTML = '<div class="allgood">אין טעויות — כל הכבוד!</div>';
    return;
  }
  wrong.forEach(q => {
    const el = document.createElement("div");
    el.className = "mq";
    el.innerHTML = `<div class="mqt">${stackFractions(q.text)}</div><div class="mqe">${stackFractions(q.explain)}</div>`;
    list.appendChild(el);
  });
}
$("rb-review").onclick = () => {
  const card = $("r-mistakes");
  if (card.style.display === "none") {
    buildMistakes();
    card.style.display = "";
    window.scrollTo({
      top: card.getBoundingClientRect().top + window.scrollY - 90,
      behavior: "smooth"
    });
  } else {
    card.style.display = "none";
  }
};
$("rb-course").onclick = () => window.open("https://ezway.co.il", "_blank", "noopener");
$("rb-summary").onclick = goSummary;
$("rb-restart").onclick = restart;
function restart() {
  startQuiz(state.qi);
}

// ---- Init ----
function resumeSession(s) {
  state.qi = s.qi;
  state.quiz = QUIZZES[s.qi];
  if (!state.quiz) {
    goHome();
    return;
  }
  state.energy = s.energy || 0;
  state.streak = s.streak || 0;
  state.maxStreak = s.maxStreak || 0;
  state.answered = Array.isArray(s.answered) ? s.answered : [];
  state.topicScore = s.topicScore || {};
  Object.keys(state.quiz.topics).forEach(k => {
    if (!state.topicScore[k]) state.topicScore[k] = {
      c: 0,
      t: 0
    };
  });
  setSub("לומדת מתמטיקה");
  $("hudwrap").style.display = "block";
  $("quizmeta").textContent = `${state.quiz.questions.length} שאלות · בין 3 ל-6 דקות`;
  buildTrack();
  const answeredCount = state.answered.filter(Boolean).length;
  if (s.phase === "result" || answeredCount >= state.quiz.questions.length) {
    finish();
  } else {
    state.i = answeredCount;
    renderQuestion();
    show("quiz");
  }
}
const _sess = loadPersisted();
renderSelect();
renderMenu();
$("qc-summary").onclick = goSummary;
document.querySelector(".gh-logo").onclick = goHome;
if (_sess && _sess.phase) resumeSession(_sess);else goHome();

// ---- Loader: hide once the page + fonts are ready ----
(function () {
  function hideLoader() {
    var l = document.getElementById('loader');
    if (l) setTimeout(function () {
      l.classList.add('hidden');
    }, 250);
  }
  if (document.readyState === 'complete') hideLoader();else window.addEventListener('load', hideLoader);
})();
})(); } catch (e) { __ds_ns.__errors.push({ path: "exports/eazy-math-diagnostic/app.js", error: String((e && e.message) || e) }); }

// flashcards/Deck.jsx
try { (() => {
/* global React, FLASHCARD_DECK, Flashcard, SwipeCard, Icon, useTweaks, TweaksPanel, TweakSection, TweakRadio, TweakColor, TweakToggle */
const {
  useState: useStateD,
  useEffect: useEffectD,
  useMemo: useMemoD,
  useCallback: useCallbackD,
  useRef: useRefD
} = React;
const TWEAK_DEFAULTS = /*EDITMODE-BEGIN*/{
  "variant": "flip",
  "shuffle": false,
  "showCounter": true,
  "accent": "orange"
} /*EDITMODE-END*/;
function shuffleArr(arr) {
  const a = [...arr];
  for (let i = a.length - 1; i > 0; i--) {
    const j = Math.floor(Math.random() * (i + 1));
    [a[i], a[j]] = [a[j], a[i]];
  }
  return a;
}
function ZBackground() {
  return /*#__PURE__*/React.createElement("div", {
    className: "fc-z",
    "aria-hidden": true
  }, /*#__PURE__*/React.createElement("div", {
    className: "slash",
    style: {
      top: "-30px",
      right: "-8%",
      width: "62%",
      background: "var(--ez-lavender-soft)"
    }
  }), /*#__PURE__*/React.createElement("div", {
    className: "slash",
    style: {
      top: "55px",
      right: "18%",
      width: "68%",
      background: "var(--ez-lavender)",
      opacity: .35
    }
  }), /*#__PURE__*/React.createElement("div", {
    className: "slash",
    style: {
      bottom: "120px",
      right: "-8%",
      width: "78%",
      background: "var(--ez-lavender-soft)"
    }
  }), /*#__PURE__*/React.createElement("div", {
    className: "slash",
    style: {
      bottom: "60px",
      right: "30%",
      width: "60%",
      background: "var(--ez-lavender)",
      opacity: .25
    }
  }));
}
function Deck() {
  const [t, setTweak] = useTweaks(TWEAK_DEFAULTS);
  const [order, setOrder] = useStateD(() => FLASHCARD_DECK.map((_, i) => i));
  const [idx, setIdx] = useStateD(0);
  const [flipped, setFlipped] = useStateD(false);
  const [showAssoc, setShowAssoc] = useStateD(false);
  const [ratings, setRatings] = useStateD({}); // id -> "know"|"soso"|"miss"
  const [done, setDone] = useStateD(false);
  const [reviewMode, setReviewMode] = useStateD(false);

  // re-shuffle when tweak toggles
  useEffectD(() => {
    if (t.shuffle) setOrder(shuffleArr(FLASHCARD_DECK.map((_, i) => i)));else setOrder(FLASHCARD_DECK.map((_, i) => i));
  }, [t.shuffle]);

  // accent override (single CSS var)
  useEffectD(() => {
    const map = {
      orange: {
        o: "#F37327",
        od: "#D55B12",
        os: "#FBD9C2"
      },
      indigo: {
        o: "#3F4197",
        od: "#2A2C73",
        os: "#D5D6EC"
      },
      teal: {
        o: "#1F8A8A",
        od: "#10696B",
        os: "#CDE7E7"
      }
    };
    const c = map[t.accent] || map.orange;
    document.documentElement.style.setProperty("--ez-orange", c.o);
    document.documentElement.style.setProperty("--ez-orange-deep", c.od);
    document.documentElement.style.setProperty("--ez-orange-soft", c.os);
  }, [t.accent]);
  const total = order.length;
  const entry = total > 0 ? FLASHCARD_DECK[order[idx]] : null;
  const advance = useCallbackD(rating => {
    if (!entry) return;
    if (rating) setRatings(r => ({
      ...r,
      [entry.id]: rating
    }));
    if (idx + 1 >= total) {
      setDone(true);
    } else {
      setFlipped(false);
      setShowAssoc(false);
      setIdx(idx + 1);
    }
  }, [entry, idx, total]);
  const goBack = useCallbackD(() => {
    if (idx === 0) return;
    setFlipped(false);
    setShowAssoc(false);
    setIdx(idx - 1);
  }, [idx]);

  // keyboard shortcuts (still useful even if user said keyboard not required)
  useEffectD(() => {
    if (done) return;
    const onKey = e => {
      if (e.key === " " || e.key === "Enter") {
        e.preventDefault();
        setFlipped(f => !f);
      } else if (e.key === "ArrowRight") goBack(); // RTL: right = previous
      else if (e.key === "ArrowLeft") advance(null);else if (e.key === "1") advance("miss");else if (e.key === "2") advance("soso");else if (e.key === "3") advance("know");
    };
    window.addEventListener("keydown", onKey);
    return () => window.removeEventListener("keydown", onKey);
  }, [done, advance, goBack]);
  const restart = only => {
    if (only === "miss") {
      const missIds = Object.keys(ratings).filter(k => ratings[k] === "miss" || ratings[k] === "soso");
      const newOrder = FLASHCARD_DECK.map((e, i) => missIds.includes(e.id) ? i : -1).filter(i => i >= 0);
      setOrder(newOrder);
      setReviewMode(true);
    } else {
      setOrder(t.shuffle ? shuffleArr(FLASHCARD_DECK.map((_, i) => i)) : FLASHCARD_DECK.map((_, i) => i));
      setReviewMode(false);
    }
    setRatings({});
    setIdx(0);
    setFlipped(false);
    setShowAssoc(false);
    setDone(false);
  };
  const counts = useMemoD(() => {
    let know = 0,
      soso = 0,
      miss = 0;
    Object.values(ratings).forEach(v => {
      if (v === "know") know++;else if (v === "soso") soso++;else miss++;
    });
    return {
      know,
      soso,
      miss
    };
  }, [ratings]);
  return /*#__PURE__*/React.createElement("div", {
    className: "fc-app",
    "data-variant": t.variant
  }, /*#__PURE__*/React.createElement(ZBackground, null), /*#__PURE__*/React.createElement("div", {
    className: "fc-top"
  }, /*#__PURE__*/React.createElement("a", {
    href: "#",
    className: "logo",
    onClick: e => e.preventDefault()
  }, /*#__PURE__*/React.createElement("img", {
    src: "../assets/ez-icon.png",
    alt: "",
    style: {
      width: 32,
      height: 32,
      objectFit: "contain"
    }
  }), /*#__PURE__*/React.createElement("span", {
    className: "word"
  }, "eazy")), /*#__PURE__*/React.createElement("div", {
    className: "deck-name"
  }, reviewMode ? "חזרה על מילים שלא ידעתי" : "מילים לפסיכומטרי · יחידה 01"), !done && t.showCounter && entry && /*#__PURE__*/React.createElement("div", {
    className: "counter"
  }, idx + 1, " / ", total), /*#__PURE__*/React.createElement("button", {
    className: "icon-btn",
    title: "\u05E2\u05E8\u05D1\u05D1",
    onClick: () => setTweak("shuffle", !t.shuffle)
  }, /*#__PURE__*/React.createElement(Icon.shuffle, null)), /*#__PURE__*/React.createElement("button", {
    className: "icon-btn",
    title: "\u05D4\u05EA\u05D7\u05DC \u05DE\u05D7\u05D3\u05E9",
    onClick: () => restart()
  }, /*#__PURE__*/React.createElement(Icon.reset, null))), !done && /*#__PURE__*/React.createElement("div", {
    className: "fc-progress"
  }, /*#__PURE__*/React.createElement("div", {
    className: "fill",
    style: {
      width: `${idx / total * 100}%`
    }
  })), !done && entry && /*#__PURE__*/React.createElement(React.Fragment, null, /*#__PURE__*/React.createElement("div", {
    className: "fc-stage"
  }, /*#__PURE__*/React.createElement("div", {
    className: "fc-stage-inner"
  }, t.variant === "swipe" ? /*#__PURE__*/React.createElement(SwipeCard, {
    onSwipe: dir => advance(dir)
  }, /*#__PURE__*/React.createElement(Flashcard, {
    entry: entry,
    flipped: flipped,
    onFlip: () => setFlipped(f => !f),
    showAssoc: showAssoc,
    onToggleAssoc: () => setShowAssoc(true),
    variant: t.variant
  })) : /*#__PURE__*/React.createElement(Flashcard, {
    entry: entry,
    flipped: flipped,
    onFlip: () => setFlipped(f => !f),
    showAssoc: showAssoc,
    onToggleAssoc: () => setShowAssoc(true),
    variant: t.variant
  }))), /*#__PURE__*/React.createElement("div", {
    className: "fc-foot"
  }, t.variant !== "swipe" ? /*#__PURE__*/React.createElement(React.Fragment, null, flipped && /*#__PURE__*/React.createElement("div", {
    className: "fc-rating"
  }, /*#__PURE__*/React.createElement("button", {
    className: "fc-rate miss",
    onClick: () => advance("miss")
  }, /*#__PURE__*/React.createElement("span", {
    className: "glyph"
  }, "\u2715"), /*#__PURE__*/React.createElement("span", null, "\u05DC\u05D0 \u05D9\u05D3\u05E2\u05EA\u05D9"), /*#__PURE__*/React.createElement("span", {
    className: "sub"
  }, "\u05E0\u05D7\u05D6\u05D5\u05E8 \u05E2\u05DC \u05D4\u05DE\u05D9\u05DC\u05D4")), /*#__PURE__*/React.createElement("button", {
    className: "fc-rate soso",
    onClick: () => advance("soso")
  }, /*#__PURE__*/React.createElement("span", {
    className: "glyph"
  }, "~"), /*#__PURE__*/React.createElement("span", null, "\u05D7\u05E6\u05D9-\u05D7\u05E6\u05D9"), /*#__PURE__*/React.createElement("span", {
    className: "sub"
  }, "\u05E6\u05E8\u05D9\u05DA \u05EA\u05E8\u05D2\u05D5\u05DC \u05E0\u05D5\u05E1\u05E3")), /*#__PURE__*/React.createElement("button", {
    className: "fc-rate know",
    onClick: () => advance("know")
  }, /*#__PURE__*/React.createElement("span", {
    className: "glyph"
  }, "\u2713"), /*#__PURE__*/React.createElement("span", null, "\u05D9\u05D3\u05E2\u05EA\u05D9"), /*#__PURE__*/React.createElement("span", {
    className: "sub"
  }, "\u05E1\u05D2\u05D5\u05E8 \u05E2\u05DC \u05D4\u05DE\u05D9\u05DC\u05D4"))), !flipped && /*#__PURE__*/React.createElement("div", {
    className: "fc-rating",
    style: {
      gridTemplateColumns: "1fr"
    }
  }, /*#__PURE__*/React.createElement("button", {
    className: "fc-rate",
    style: {
      flexDirection: "row",
      justifyContent: "center",
      gap: 10
    },
    onClick: () => setFlipped(true)
  }, "\u05D7\u05E9\u05E4\u05D5 \u05D0\u05EA \u05D4\u05E4\u05D9\u05E8\u05D5\u05E9", /*#__PURE__*/React.createElement("span", {
    style: {
      fontFamily: "var(--font-mono)",
      fontSize: 11,
      color: "var(--ez-fg-3)"
    }
  }, "\xB7 \u05DE\u05E7\u05E9 \u05E8\u05D5\u05D5\u05D7"))), /*#__PURE__*/React.createElement("div", {
    style: {
      display: "flex",
      gap: 18,
      alignItems: "center"
    }
  }, /*#__PURE__*/React.createElement("button", {
    className: "skip",
    onClick: goBack,
    disabled: idx === 0,
    style: {
      opacity: idx === 0 ? .3 : 1
    }
  }, "\u2190 \u05D4\u05E7\u05D5\u05D3\u05DD"), /*#__PURE__*/React.createElement("button", {
    className: "skip",
    onClick: () => advance(null)
  }, "\u05D3\u05DC\u05D2 \u05DC\u05DE\u05D9\u05DC\u05D4 \u05D4\u05D1\u05D0\u05D4 \u2192"))) : /*#__PURE__*/React.createElement(React.Fragment, null, /*#__PURE__*/React.createElement("div", {
    style: {
      display: "flex",
      gap: 24,
      alignItems: "center",
      fontFamily: "var(--font-display)",
      fontWeight: 700,
      fontSize: 13
    }
  }, /*#__PURE__*/React.createElement("span", {
    style: {
      color: "var(--ez-orange-deep)"
    }
  }, "\u2190 \u05D4\u05D7\u05DC\u05D9\u05E7\u05D5 \u05D9\u05DE\u05D9\u05E0\u05D4: \u05DC\u05D0 \u05D9\u05D3\u05E2\u05EA\u05D9"), /*#__PURE__*/React.createElement("span", {
    style: {
      color: "#1B5C39"
    }
  }, "\u05D4\u05D7\u05DC\u05D9\u05E7\u05D5 \u05E9\u05DE\u05D0\u05DC\u05D4: \u05D9\u05D3\u05E2\u05EA\u05D9 \u2192")), /*#__PURE__*/React.createElement("div", {
    style: {
      display: "flex",
      gap: 18
    }
  }, /*#__PURE__*/React.createElement("button", {
    className: "skip",
    onClick: () => setFlipped(f => !f)
  }, "\u05D4\u05E4\u05DB\u05D5 \u05D0\u05EA \u05D4\u05DB\u05E8\u05D8\u05D9\u05E1\u05D9\u05D9\u05D4"), /*#__PURE__*/React.createElement("button", {
    className: "skip",
    onClick: goBack,
    disabled: idx === 0,
    style: {
      opacity: idx === 0 ? .3 : 1
    }
  }, "\u05D4\u05E7\u05D5\u05D3\u05DD"))))), done && /*#__PURE__*/React.createElement("div", {
    className: "fc-end"
  }, /*#__PURE__*/React.createElement("div", {
    className: "fc-end-card"
  }, /*#__PURE__*/React.createElement("div", {
    className: "check"
  }, "\u2713"), /*#__PURE__*/React.createElement("h2", null, "\u05E1\u05D9\u05D9\u05DE\u05EA\u05DD \u05D0\u05EA \u05D4\u05D9\u05D7\u05D9\u05D3\u05D4.", /*#__PURE__*/React.createElement("br", null), counts.know, " \u05DE\u05D9\u05DC\u05D9\u05DD \u05D1\u05DB\u05D9\u05E1."), /*#__PURE__*/React.createElement("div", {
    className: "sub"
  }, counts.miss + counts.soso > 0 ? `יש ${counts.miss + counts.soso} מילים שכדאי לחזור עליהן.` : "כל הכבוד — אין מילים שצריכות חזרה. ממשיכים ליחידה הבאה?"), /*#__PURE__*/React.createElement("div", {
    className: "stats"
  }, /*#__PURE__*/React.createElement("div", {
    className: "stat know"
  }, /*#__PURE__*/React.createElement("div", {
    className: "num"
  }, counts.know), /*#__PURE__*/React.createElement("div", {
    className: "label"
  }, "\u05D9\u05D3\u05E2\u05EA\u05D9")), /*#__PURE__*/React.createElement("div", {
    className: "stat soso"
  }, /*#__PURE__*/React.createElement("div", {
    className: "num"
  }, counts.soso), /*#__PURE__*/React.createElement("div", {
    className: "label"
  }, "\u05D7\u05E6\u05D9")), /*#__PURE__*/React.createElement("div", {
    className: "stat miss"
  }, /*#__PURE__*/React.createElement("div", {
    className: "num"
  }, counts.miss), /*#__PURE__*/React.createElement("div", {
    className: "label"
  }, "\u05DC\u05D0"))), /*#__PURE__*/React.createElement("div", {
    className: "actions"
  }, /*#__PURE__*/React.createElement("button", {
    className: "btn-primary",
    disabled: counts.miss + counts.soso === 0,
    onClick: () => restart("miss")
  }, "\u05D7\u05D9\u05D6\u05E8\u05D5 \u05E2\u05DC ", counts.miss + counts.soso, " \u05D4\u05DE\u05D9\u05DC\u05D9\u05DD \u05E9\u05DC\u05D0 \u05D9\u05D3\u05E2\u05EA\u05D9"), /*#__PURE__*/React.createElement("button", {
    className: "btn-ghost",
    onClick: () => restart()
  }, "\u05D4\u05EA\u05D7\u05D9\u05DC\u05D5 \u05D0\u05EA \u05D4\u05D9\u05D7\u05D9\u05D3\u05D4 \u05DE\u05D7\u05D3\u05E9")))), /*#__PURE__*/React.createElement(TweaksPanel, {
    title: "Tweaks"
  }, /*#__PURE__*/React.createElement(TweakSection, {
    title: "\u05D5\u05E8\u05D9\u05D0\u05E6\u05D9\u05D4"
  }, /*#__PURE__*/React.createElement(TweakRadio, {
    value: t.variant,
    onChange: v => setTweak("variant", v),
    options: [{
      value: "flip",
      label: "Flip"
    }, {
      value: "swipe",
      label: "Swipe"
    }, {
      value: "minimal",
      label: "Minimal"
    }]
  })), /*#__PURE__*/React.createElement(TweakSection, {
    title: "\u05E6\u05D1\u05E2 \u05DE\u05D1\u05D8\u05D0"
  }, /*#__PURE__*/React.createElement(TweakColor, {
    value: t.accent,
    onChange: v => setTweak("accent", v),
    options: [{
      value: "orange",
      color: "#F37327"
    }, {
      value: "indigo",
      color: "#3F4197"
    }, {
      value: "teal",
      color: "#1F8A8A"
    }]
  })), /*#__PURE__*/React.createElement(TweakSection, {
    title: "\u05D0\u05E4\u05E9\u05E8\u05D5\u05D9\u05D5\u05EA"
  }, /*#__PURE__*/React.createElement(TweakToggle, {
    label: "\u05E2\u05E8\u05D1\u05D1 \u05D0\u05EA \u05E1\u05D3\u05E8 \u05D4\u05DE\u05D9\u05DC\u05D9\u05DD",
    value: t.shuffle,
    onChange: v => setTweak("shuffle", v)
  }), /*#__PURE__*/React.createElement(TweakToggle, {
    label: "\u05D4\u05E6\u05D2 \u05DE\u05D5\u05E0\u05D4 \u05D4\u05EA\u05E7\u05D3\u05DE\u05D5\u05EA",
    value: t.showCounter,
    onChange: v => setTweak("showCounter", v)
  }))));
}
window.Deck = Deck;
})(); } catch (e) { __ds_ns.__errors.push({ path: "flashcards/Deck.jsx", error: String((e && e.message) || e) }); }

// flashcards/Flashcard.jsx
try { (() => {
function _extends() { return _extends = Object.assign ? Object.assign.bind() : function (n) { for (var e = 1; e < arguments.length; e++) { var t = arguments[e]; for (var r in t) ({}).hasOwnProperty.call(t, r) && (n[r] = t[r]); } return n; }, _extends.apply(null, arguments); }
/* global React, FLASHCARD_DECK */
const {
  useState,
  useEffect,
  useRef,
  useMemo,
  useCallback
} = React;

/* ---------- inline SVG icons (only the ones we need) ---------- */
const Icon = {
  speaker: p => /*#__PURE__*/React.createElement("svg", _extends({
    viewBox: "0 0 24 24",
    width: "20",
    height: "20",
    fill: "currentColor"
  }, p), /*#__PURE__*/React.createElement("path", {
    d: "M3 10v4a1 1 0 0 0 1 1h3l4 3.5a1 1 0 0 0 1.6-.8V6.3a1 1 0 0 0-1.6-.8L7 9H4a1 1 0 0 0-1 1Zm13.5-1.7a1 1 0 0 0-1.4 1.4 4 4 0 0 1 0 4.6 1 1 0 0 0 1.4 1.4 6 6 0 0 0 0-7.4Zm2.8-2.8a1 1 0 0 0-1.4 1.4 8 8 0 0 1 0 10.2 1 1 0 0 0 1.4 1.4 10 10 0 0 0 0-13Z"
  })),
  back: p => /*#__PURE__*/React.createElement("svg", _extends({
    viewBox: "0 0 24 24",
    width: "20",
    height: "20",
    fill: "none",
    stroke: "currentColor",
    strokeWidth: "2.2",
    strokeLinecap: "round",
    strokeLinejoin: "round"
  }, p), /*#__PURE__*/React.createElement("path", {
    d: "m15 18-6-6 6-6"
  })),
  shuffle: p => /*#__PURE__*/React.createElement("svg", _extends({
    viewBox: "0 0 24 24",
    width: "20",
    height: "20",
    fill: "none",
    stroke: "currentColor",
    strokeWidth: "2",
    strokeLinecap: "round",
    strokeLinejoin: "round"
  }, p), /*#__PURE__*/React.createElement("path", {
    d: "M16 3h5v5"
  }), /*#__PURE__*/React.createElement("path", {
    d: "M4 20 21 3"
  }), /*#__PURE__*/React.createElement("path", {
    d: "M21 16v5h-5"
  }), /*#__PURE__*/React.createElement("path", {
    d: "m15 15 6 6"
  }), /*#__PURE__*/React.createElement("path", {
    d: "M4 4l5 5"
  })),
  reset: p => /*#__PURE__*/React.createElement("svg", _extends({
    viewBox: "0 0 24 24",
    width: "20",
    height: "20",
    fill: "none",
    stroke: "currentColor",
    strokeWidth: "2",
    strokeLinecap: "round",
    strokeLinejoin: "round"
  }, p), /*#__PURE__*/React.createElement("path", {
    d: "M3 12a9 9 0 1 0 3-6.7L3 8"
  }), /*#__PURE__*/React.createElement("path", {
    d: "M3 3v5h5"
  })),
  sparkle: p => /*#__PURE__*/React.createElement("svg", _extends({
    viewBox: "0 0 24 24",
    width: "14",
    height: "14",
    fill: "currentColor"
  }, p), /*#__PURE__*/React.createElement("path", {
    d: "M12 2l1.5 5.5L19 9l-5.5 1.5L12 16l-1.5-5.5L5 9l5.5-1.5L12 2zM5 17l.7 2.3L8 20l-2.3.7L5 23l-.7-2.3L2 20l2.3-.7L5 17z"
  }))
};

/* ---------- speech ---------- */
function speak(text, onStart, onEnd) {
  if (!("speechSynthesis" in window)) {
    onEnd && onEnd();
    return;
  }
  try {
    window.speechSynthesis.cancel();
    const u = new SpeechSynthesisUtterance(text);
    u.lang = "en-US";
    u.rate = 0.92;
    u.pitch = 1;
    u.onstart = () => onStart && onStart();
    u.onend = () => onEnd && onEnd();
    u.onerror = () => onEnd && onEnd();
    window.speechSynthesis.speak(u);
  } catch (e) {
    onEnd && onEnd();
  }
}

/* ---------- card ---------- */
function Flashcard({
  entry,
  flipped,
  onFlip,
  showAssoc,
  onToggleAssoc,
  variant
}) {
  const [playing, setPlaying] = useState(false);
  const handleAudio = e => {
    e.stopPropagation();
    speak(entry.word, () => setPlaying(true), () => setPlaying(false));
  };
  if (variant === "minimal") {
    // No flip — both sides stack vertically; "flipped" means meaning is revealed
    return /*#__PURE__*/React.createElement("div", {
      className: "fc-card " + (flipped ? "flipped" : ""),
      onClick: onFlip
    }, /*#__PURE__*/React.createElement("div", {
      className: "fc-face front",
      style: {
        position: "relative",
        padding: "32px 28px 24px"
      }
    }, /*#__PURE__*/React.createElement("div", {
      className: "ribbon"
    }), /*#__PURE__*/React.createElement("button", {
      className: "audio " + (playing ? "playing" : ""),
      onClick: handleAudio,
      "aria-label": "\u05D4\u05E9\u05DE\u05E2 \u05DE\u05D9\u05DC\u05D4"
    }, /*#__PURE__*/React.createElement(Icon.speaker, null)), /*#__PURE__*/React.createElement("div", {
      className: "pos"
    }, entry.pos, " \xB7 ", /*#__PURE__*/React.createElement("span", {
      style: {
        fontFamily: "var(--font-mono)",
        fontWeight: 400
      }
    }, entry.ipa)), /*#__PURE__*/React.createElement("div", {
      className: "fc-word",
      style: {
        margin: "24px 0 16px"
      }
    }, entry.word), flipped && /*#__PURE__*/React.createElement("div", {
      className: "fc-meaning",
      style: {
        margin: 0,
        paddingTop: 16,
        borderTop: "1px solid var(--ez-line)",
        animation: "assocIn .3s"
      }
    }, /*#__PURE__*/React.createElement("div", {
      className: "heb"
    }, entry.heb), /*#__PURE__*/React.createElement("div", {
      className: "definition",
      dangerouslySetInnerHTML: {
        __html: entry.def
      }
    }), /*#__PURE__*/React.createElement("div", {
      style: {
        fontFamily: "var(--font-mono)",
        fontSize: 13,
        color: "var(--ez-fg-3)",
        direction: "ltr",
        textAlign: "left",
        borderInlineStart: "3px solid var(--ez-orange)",
        paddingInlineStart: 10
      }
    }, "\"", entry.example, "\""), showAssoc ? /*#__PURE__*/React.createElement("div", {
      className: "fc-assoc",
      style: {
        marginTop: 6
      }
    }, /*#__PURE__*/React.createElement("div", {
      className: "label"
    }, "\u05D0\u05E1\u05D5\u05E6\u05D9\u05D0\u05E6\u05D9\u05D4"), /*#__PURE__*/React.createElement("div", {
      className: "mnemonic",
      dangerouslySetInnerHTML: {
        __html: entry.mnemonic
      }
    }), /*#__PURE__*/React.createElement("div", {
      className: "body"
    }, entry.association)) : /*#__PURE__*/React.createElement("button", {
      className: "fc-assoc-toggle",
      onClick: e => {
        e.stopPropagation();
        onToggleAssoc();
      }
    }, /*#__PURE__*/React.createElement(Icon.sparkle, null), " \u05E6\u05E4\u05D5 \u05D1\u05D0\u05E1\u05D5\u05E6\u05D9\u05D0\u05E6\u05D9\u05D4")), !flipped && /*#__PURE__*/React.createElement("div", {
      style: {
        marginTop: "auto",
        textAlign: "center",
        fontFamily: "var(--font-mono)",
        fontSize: 12,
        color: "var(--ez-fg-3)"
      }
    }, "\u05DC\u05D7\u05E6\u05D5 \u05DC\u05D7\u05E9\u05D9\u05E4\u05EA \u05D4\u05E4\u05D9\u05E8\u05D5\u05E9")));
  }
  return /*#__PURE__*/React.createElement("div", {
    className: "fc-card " + (flipped ? "flipped" : ""),
    onClick: onFlip
  }, /*#__PURE__*/React.createElement("div", {
    className: "fc-face front"
  }, /*#__PURE__*/React.createElement("div", {
    className: "ribbon"
  }), /*#__PURE__*/React.createElement("button", {
    className: "audio " + (playing ? "playing" : ""),
    onClick: handleAudio,
    "aria-label": "\u05D4\u05E9\u05DE\u05E2 \u05DE\u05D9\u05DC\u05D4"
  }, /*#__PURE__*/React.createElement(Icon.speaker, null)), /*#__PURE__*/React.createElement("div", {
    className: "pos"
  }, entry.pos), /*#__PURE__*/React.createElement("div", {
    className: "fc-word"
  }, entry.word, /*#__PURE__*/React.createElement("span", {
    className: "ipa"
  }, entry.ipa)), /*#__PURE__*/React.createElement("div", {
    style: {
      textAlign: "center",
      fontFamily: "var(--font-mono)",
      fontSize: 12,
      color: "var(--ez-fg-3)"
    }
  }, "\u05DC\u05D7\u05E6\u05D5 \u05E2\u05DC \u05D4\u05DB\u05E8\u05D8\u05D9\u05E1\u05D9\u05D9\u05D4 \u05DC\u05D7\u05E9\u05D9\u05E4\u05D4")), /*#__PURE__*/React.createElement("div", {
    className: "fc-face back"
  }, /*#__PURE__*/React.createElement("div", {
    className: "ribbon"
  }), /*#__PURE__*/React.createElement("div", {
    className: "pos"
  }, entry.pos), /*#__PURE__*/React.createElement("div", {
    className: "fc-meaning"
  }, /*#__PURE__*/React.createElement("div", {
    className: "heb"
  }, entry.heb), /*#__PURE__*/React.createElement("div", {
    className: "definition",
    dangerouslySetInnerHTML: {
      __html: entry.def
    }
  }), /*#__PURE__*/React.createElement("div", {
    style: {
      fontFamily: "var(--font-mono)",
      fontSize: 13,
      color: "var(--ez-fg-3)",
      direction: "ltr",
      textAlign: "left",
      borderInlineStart: "3px solid var(--ez-orange)",
      paddingInlineStart: 10,
      marginTop: 4
    }
  }, "\"", entry.example, "\"")), showAssoc ? /*#__PURE__*/React.createElement("div", {
    className: "fc-assoc"
  }, /*#__PURE__*/React.createElement("div", {
    className: "label"
  }, "\u05D0\u05E1\u05D5\u05E6\u05D9\u05D0\u05E6\u05D9\u05D4"), /*#__PURE__*/React.createElement("div", {
    className: "mnemonic",
    dangerouslySetInnerHTML: {
      __html: entry.mnemonic
    }
  }), /*#__PURE__*/React.createElement("div", {
    className: "body"
  }, entry.association)) : /*#__PURE__*/React.createElement("button", {
    className: "fc-assoc-toggle",
    onClick: e => {
      e.stopPropagation();
      onToggleAssoc();
    }
  }, /*#__PURE__*/React.createElement(Icon.sparkle, null), " \u05E6\u05E4\u05D5 \u05D1\u05D0\u05E1\u05D5\u05E6\u05D9\u05D0\u05E6\u05D9\u05D4")));
}

/* ---------- swipe wrapper (variant=swipe) ---------- */
function SwipeCard({
  children,
  onSwipe
}) {
  const ref = useRef(null);
  const state = useRef({
    x: 0,
    dragging: false,
    startX: 0,
    startY: 0,
    axis: null
  });
  const onDown = e => {
    const p = e.touches ? e.touches[0] : e;
    state.current = {
      x: 0,
      dragging: true,
      startX: p.clientX,
      startY: p.clientY,
      axis: null
    };
    if (ref.current) ref.current.classList.add("dragging");
  };
  const onMove = e => {
    if (!state.current.dragging) return;
    const p = e.touches ? e.touches[0] : e;
    const dx = p.clientX - state.current.startX;
    const dy = p.clientY - state.current.startY;
    if (!state.current.axis) state.current.axis = Math.abs(dx) > Math.abs(dy) ? "x" : "y";
    if (state.current.axis !== "x") return;
    state.current.x = dx;
    if (ref.current) {
      ref.current.style.transform = `translateX(${dx}px) rotate(${dx / 30}deg)`;
      ref.current.style.opacity = String(1 - Math.min(Math.abs(dx) / 600, 0.4));
    }
  };
  const onUp = () => {
    if (!state.current.dragging) return;
    state.current.dragging = false;
    if (ref.current) ref.current.classList.remove("dragging");
    const dx = state.current.x;
    if (Math.abs(dx) > 100) {
      // direction: in RTL, swiping LEFT (negative dx) → "next/know", swiping RIGHT → "miss"
      // we'll keep simple: > 0 = miss (didn't know), < 0 = know
      const dir = dx > 0 ? "miss" : "know";
      if (ref.current) {
        ref.current.style.transition = "transform .35s cubic-bezier(.2,.7,.2,1), opacity .35s";
        ref.current.style.transform = `translateX(${dx > 0 ? "120%" : "-120%"}) rotate(${dx / 8}deg)`;
        ref.current.style.opacity = "0";
      }
      setTimeout(() => onSwipe && onSwipe(dir), 200);
    } else if (ref.current) {
      ref.current.style.transition = "transform .25s cubic-bezier(.2,.7,.2,1), opacity .25s";
      ref.current.style.transform = "";
      ref.current.style.opacity = "";
      setTimeout(() => {
        if (ref.current) ref.current.style.transition = "";
      }, 260);
    }
  };
  useEffect(() => {
    const el = ref.current;
    if (!el) return;
    const move = e => onMove(e);
    const up = () => onUp();
    window.addEventListener("mousemove", move);
    window.addEventListener("mouseup", up);
    window.addEventListener("touchmove", move, {
      passive: true
    });
    window.addEventListener("touchend", up);
    return () => {
      window.removeEventListener("mousemove", move);
      window.removeEventListener("mouseup", up);
      window.removeEventListener("touchmove", move);
      window.removeEventListener("touchend", up);
    };
  }, []);
  return /*#__PURE__*/React.createElement("div", {
    ref: ref,
    onMouseDown: onDown,
    onTouchStart: onDown,
    style: {
      willChange: "transform"
    }
  }, children);
}
window.Flashcard = Flashcard;
window.SwipeCard = SwipeCard;
window.Icon = Icon;
})(); } catch (e) { __ds_ns.__errors.push({ path: "flashcards/Flashcard.jsx", error: String((e && e.message) || e) }); }

// flashcards/deck-data.js
try { (() => {
/* global window */
// Curated psychometric-style high-utility English vocab list.
// Each entry includes:
//  - id, word
//  - pos (part of speech, in Hebrew)
//  - ipa (US pronunciation)
//  - heb: short Hebrew gloss
//  - def: longer Hebrew definition
//  - example: English usage in a sentence
//  - mnemonic: a Hebrew mnemonic / association
//  - association: a longer Hebrew context sentence
window.FLASHCARD_DECK = [{
  id: "enhance",
  word: "ENHANCE",
  pos: "פועל · verb",
  ipa: "/ɪnˈhæns/",
  heb: "להעצים, לשפר",
  def: "<strong>להוסיף ערך, לחזק או לשפר משהו קיים.</strong> מילה ניטרלית-חיובית — מתארת שיפור הדרגתי, לא שינוי קיצוני.",
  example: "These exercises will enhance your test-taking skills.",
  mnemonic: "EN-HANCE → \"בְּיָד\" (in-hand) — לוקחים מה שיש ביד ומשפרים אותו.",
  association: "תחשבו על Photoshop's \"Enhance\" — לוקחים תמונה רגילה ומשפרים אותה. זה לא יוצר משהו חדש מאפס; זה משפר את מה שכבר קיים."
}, {
  id: "mitigate",
  word: "MITIGATE",
  pos: "פועל · verb",
  ipa: "/ˈmɪtɪˌɡeɪt/",
  heb: "להקל, למתן",
  def: "<strong>להפחית את חומרת התוצאה השלילית של משהו.</strong> בא תמיד אחרי בעיה — ממתנים נזק, סיכון, כאב, השפעה.",
  example: "The new policy aims to mitigate the impact of climate change.",
  mnemonic: "MITI דומה ל-MEDI כמו ב-medicine. תרופה <em>מקלה</em> תסמינים.",
  association: "כשרואים MITIGATE — תמיד יש בעיה ברקע. אי-אפשר \"להמתין\" משהו טוב."
}, {
  id: "ambiguous",
  word: "AMBIGUOUS",
  pos: "תואר · adjective",
  ipa: "/æmˈbɪɡjuəs/",
  heb: "דו־משמעי, עמום",
  def: "<strong>שאפשר להבין אותו ביותר מדרך אחת.</strong> שלילי בדרך כלל — חוסר בהירות שגורם לבלבול. ההפך מ-clear.",
  example: "His answer was ambiguous — we couldn't tell if he agreed.",
  mnemonic: "AMBI = שניים (כמו ambidextrous, שתי ידיים) → שתי משמעויות.",
  association: "כל מילה שמתחילה ב-AMBI- מעידה על שניים: ambivalent (שתי רגשות), ambidextrous (שתי ידיים)."
}, {
  id: "advocate",
  word: "ADVOCATE",
  pos: "פועל / שם עצם",
  ipa: "/ˈædvəˌkeɪt/",
  heb: "לתמוך, להמליץ; תומך",
  def: "<strong>לדבר באופן פומבי בעד רעיון או בעד מישהו.</strong> שם עצם: מי שעושה זאת. הקונוטציה חיובית — תומך פעיל, לא רק מסכים.",
  example: "She is a strong advocate for educational reform.",
  mnemonic: "AD-VOCATE קשור ל-VOCAL (קולי). מי שמרים את הקול בעד משהו.",
  association: "בעברית \"עורך-דין\" באנגלית הוא advocate — בדיוק מי שמדבר בשם הלקוח."
}, {
  id: "scrutinize",
  word: "SCRUTINIZE",
  pos: "פועל · verb",
  ipa: "/ˈskruːtəˌnaɪz/",
  heb: "לבחון בקפדנות",
  def: "<strong>לבדוק משהו לעומק ובפרטי-פרטים.</strong> חזק יותר מ-examine — מרמז על חשדנות או על חיפוש פגמים.",
  example: "The auditor scrutinized every line of the report.",
  mnemonic: "SCRU- כמו \"סריקה\" — סורקים בעיניים שלוש פעמים.",
  association: "בודקים בכלל = check. בודקים בקפדנות = examine. בודקים עם זכוכית-מגדלת = scrutinize."
}, {
  id: "inevitable",
  word: "INEVITABLE",
  pos: "תואר · adjective",
  ipa: "/ɪˈnɛvɪtəbəl/",
  heb: "בלתי נמנע",
  def: "<strong>חייב לקרות, אי-אפשר למנוע.</strong> תיאור של ודאות מוחלטת לגבי העתיד. לא בהכרח דבר רע — אפשר \"בלתי נמנע ש...\" לטוב או לרע.",
  example: "With proper preparation, success becomes inevitable.",
  mnemonic: "IN (לא) + EVIT (להימנע) + ABLE (יכול) → לא יכול להימנע.",
  association: "המוות, המיסים, ויום ראשון בבוקר — these are inevitable."
}, {
  id: "diligent",
  word: "DILIGENT",
  pos: "תואר · adjective",
  ipa: "/ˈdɪlɪdʒənt/",
  heb: "חרוץ, שקדן",
  def: "<strong>שעובד בקפדנות, ברצינות ובהתמדה.</strong> הקונוטציה חיובית מאוד — לא רק עובד קשה אלא גם בקפידה.",
  example: "Diligent students review their notes after every class.",
  mnemonic: "DILI נשמע כמו \"דליל\" — מי שלא מוותר על אף פרט, גם הדק ביותר.",
  association: "תלמיד diligent הוא חלום של כל מורה — לא הכי חכם בכיתה, אבל בטוח הכי שקדן."
}, {
  id: "obsolete",
  word: "OBSOLETE",
  pos: "תואר · adjective",
  ipa: "/ˌɑbsəˈliːt/",
  heb: "מיושן, לא רלוונטי",
  def: "<strong>שעבר זמנו ויצא משימוש.</strong> טכנולוגיה ישנה, שיטה שכבר לא עובדת. שלילי — מרמז על חוסר תועלת בזמן הנוכחי.",
  example: "VHS tapes became obsolete with the rise of streaming.",
  mnemonic: "OBSOLETE → \"OB-סולט\" → סולת ישנה מתעבשת ויוצאת משימוש.",
  association: "הקלטת, הפלאפון בעל הכפתורים, האיירפודים בעלי החוט — all obsolete."
}, {
  id: "candid",
  word: "CANDID",
  pos: "תואר · adjective",
  ipa: "/ˈkændɪd/",
  heb: "כֵּן, ישיר, לא ערוך",
  def: "<strong>כֵּן ופתוח גם כשזה לא נוח, או צילום ספונטני שלא הוכן.</strong> חיובי — מילה של אמינות ושקיפות.",
  example: "I appreciate your candid feedback on my essay.",
  mnemonic: "CANDID נשמע כמו \"candle\" — נר שמאיר את כל מה שמסביב, בלי להסתיר.",
  association: "תמונת candid באינסטגרם = תמונה ספונטנית, לא מבוימת."
}, {
  id: "tenacious",
  word: "TENACIOUS",
  pos: "תואר · adjective",
  ipa: "/təˈneɪʃəs/",
  heb: "עיקש, דבק במטרה",
  def: "<strong>שמחזיק חזק במטרה ולא מוותר.</strong> חזק מ-determined — מרמז על כוח-רצון יוצא דופן בפני קושי.",
  example: "Her tenacious effort earned her a top score.",
  mnemonic: "TEN- כמו \"tenant\" (דייר שלא מוותר על הדירה) — מחזיק חזק.",
  association: "אם תקראו על מועמדים בראיונות עבודה — tenacious זאת תכונה שכל מנכ\"ל רוצה."
}];
})(); } catch (e) { __ds_ns.__errors.push({ path: "flashcards/deck-data.js", error: String((e && e.message) || e) }); }

// flashcards/ios-frame.jsx
try { (() => {
// iOS.jsx — Simplified iOS 26 (Liquid Glass) device frame
// Based on the iOS 26 UI Kit + Figma status bar spec. No assets, no deps.
// Exports: IOSDevice, IOSStatusBar, IOSNavBar, IOSGlassPill, IOSList, IOSListRow, IOSKeyboard

// ─────────────────────────────────────────────────────────────
// Status bar
// ─────────────────────────────────────────────────────────────
function IOSStatusBar({
  dark = false,
  time = '9:41'
}) {
  const c = dark ? '#fff' : '#000';
  return /*#__PURE__*/React.createElement("div", {
    style: {
      display: 'flex',
      gap: 154,
      alignItems: 'center',
      justifyContent: 'center',
      padding: '21px 24px 19px',
      boxSizing: 'border-box',
      position: 'relative',
      zIndex: 20,
      width: '100%'
    }
  }, /*#__PURE__*/React.createElement("div", {
    style: {
      flex: 1,
      height: 22,
      display: 'flex',
      alignItems: 'center',
      justifyContent: 'center',
      paddingTop: 1.5
    }
  }, /*#__PURE__*/React.createElement("span", {
    style: {
      fontFamily: '-apple-system, "SF Pro", system-ui',
      fontWeight: 590,
      fontSize: 17,
      lineHeight: '22px',
      color: c
    }
  }, time)), /*#__PURE__*/React.createElement("div", {
    style: {
      flex: 1,
      height: 22,
      display: 'flex',
      alignItems: 'center',
      justifyContent: 'center',
      gap: 7,
      paddingTop: 1,
      paddingRight: 1
    }
  }, /*#__PURE__*/React.createElement("svg", {
    width: "19",
    height: "12",
    viewBox: "0 0 19 12"
  }, /*#__PURE__*/React.createElement("rect", {
    x: "0",
    y: "7.5",
    width: "3.2",
    height: "4.5",
    rx: "0.7",
    fill: c
  }), /*#__PURE__*/React.createElement("rect", {
    x: "4.8",
    y: "5",
    width: "3.2",
    height: "7",
    rx: "0.7",
    fill: c
  }), /*#__PURE__*/React.createElement("rect", {
    x: "9.6",
    y: "2.5",
    width: "3.2",
    height: "9.5",
    rx: "0.7",
    fill: c
  }), /*#__PURE__*/React.createElement("rect", {
    x: "14.4",
    y: "0",
    width: "3.2",
    height: "12",
    rx: "0.7",
    fill: c
  })), /*#__PURE__*/React.createElement("svg", {
    width: "17",
    height: "12",
    viewBox: "0 0 17 12"
  }, /*#__PURE__*/React.createElement("path", {
    d: "M8.5 3.2C10.8 3.2 12.9 4.1 14.4 5.6L15.5 4.5C13.7 2.7 11.2 1.5 8.5 1.5C5.8 1.5 3.3 2.7 1.5 4.5L2.6 5.6C4.1 4.1 6.2 3.2 8.5 3.2Z",
    fill: c
  }), /*#__PURE__*/React.createElement("path", {
    d: "M8.5 6.8C9.9 6.8 11.1 7.3 12 8.2L13.1 7.1C11.8 5.9 10.2 5.1 8.5 5.1C6.8 5.1 5.2 5.9 3.9 7.1L5 8.2C5.9 7.3 7.1 6.8 8.5 6.8Z",
    fill: c
  }), /*#__PURE__*/React.createElement("circle", {
    cx: "8.5",
    cy: "10.5",
    r: "1.5",
    fill: c
  })), /*#__PURE__*/React.createElement("svg", {
    width: "27",
    height: "13",
    viewBox: "0 0 27 13"
  }, /*#__PURE__*/React.createElement("rect", {
    x: "0.5",
    y: "0.5",
    width: "23",
    height: "12",
    rx: "3.5",
    stroke: c,
    strokeOpacity: "0.35",
    fill: "none"
  }), /*#__PURE__*/React.createElement("rect", {
    x: "2",
    y: "2",
    width: "20",
    height: "9",
    rx: "2",
    fill: c
  }), /*#__PURE__*/React.createElement("path", {
    d: "M25 4.5V8.5C25.8 8.2 26.5 7.2 26.5 6.5C26.5 5.8 25.8 4.8 25 4.5Z",
    fill: c,
    fillOpacity: "0.4"
  }))));
}

// ─────────────────────────────────────────────────────────────
// Liquid glass pill — blur + tint + shine
// ─────────────────────────────────────────────────────────────
function IOSGlassPill({
  children,
  dark = false,
  style = {}
}) {
  return /*#__PURE__*/React.createElement("div", {
    style: {
      height: 44,
      minWidth: 44,
      borderRadius: 9999,
      position: 'relative',
      overflow: 'hidden',
      display: 'flex',
      alignItems: 'center',
      justifyContent: 'center',
      boxShadow: dark ? '0 2px 6px rgba(0,0,0,0.35), 0 6px 16px rgba(0,0,0,0.2)' : '0 1px 3px rgba(0,0,0,0.07), 0 3px 10px rgba(0,0,0,0.06)',
      ...style
    }
  }, /*#__PURE__*/React.createElement("div", {
    style: {
      position: 'absolute',
      inset: 0,
      borderRadius: 9999,
      backdropFilter: 'blur(12px) saturate(180%)',
      WebkitBackdropFilter: 'blur(12px) saturate(180%)',
      background: dark ? 'rgba(120,120,128,0.28)' : 'rgba(255,255,255,0.5)'
    }
  }), /*#__PURE__*/React.createElement("div", {
    style: {
      position: 'absolute',
      inset: 0,
      borderRadius: 9999,
      boxShadow: dark ? 'inset 1.5px 1.5px 1px rgba(255,255,255,0.15), inset -1px -1px 1px rgba(255,255,255,0.08)' : 'inset 1.5px 1.5px 1px rgba(255,255,255,0.7), inset -1px -1px 1px rgba(255,255,255,0.4)',
      border: dark ? '0.5px solid rgba(255,255,255,0.15)' : '0.5px solid rgba(0,0,0,0.06)'
    }
  }), /*#__PURE__*/React.createElement("div", {
    style: {
      position: 'relative',
      zIndex: 1,
      display: 'flex',
      alignItems: 'center',
      padding: '0 4px'
    }
  }, children));
}

// ─────────────────────────────────────────────────────────────
// Navigation bar — glass pills + large title
// ─────────────────────────────────────────────────────────────
function IOSNavBar({
  title = 'Title',
  dark = false,
  trailingIcon = true
}) {
  const muted = dark ? 'rgba(255,255,255,0.6)' : '#404040';
  const text = dark ? '#fff' : '#000';
  const pillIcon = content => /*#__PURE__*/React.createElement(IOSGlassPill, {
    dark: dark
  }, /*#__PURE__*/React.createElement("div", {
    style: {
      width: 36,
      height: 36,
      display: 'flex',
      alignItems: 'center',
      justifyContent: 'center'
    }
  }, content));
  return /*#__PURE__*/React.createElement("div", {
    style: {
      display: 'flex',
      flexDirection: 'column',
      gap: 10,
      paddingTop: 62,
      paddingBottom: 10,
      position: 'relative',
      zIndex: 5
    }
  }, /*#__PURE__*/React.createElement("div", {
    style: {
      display: 'flex',
      alignItems: 'center',
      justifyContent: 'space-between',
      padding: '0 16px'
    }
  }, pillIcon(/*#__PURE__*/React.createElement("svg", {
    width: "12",
    height: "20",
    viewBox: "0 0 12 20",
    fill: "none",
    style: {
      marginLeft: -1
    }
  }, /*#__PURE__*/React.createElement("path", {
    d: "M10 2L2 10l8 8",
    stroke: muted,
    strokeWidth: "2.5",
    strokeLinecap: "round",
    strokeLinejoin: "round"
  }))), trailingIcon && pillIcon(/*#__PURE__*/React.createElement("svg", {
    width: "22",
    height: "6",
    viewBox: "0 0 22 6"
  }, /*#__PURE__*/React.createElement("circle", {
    cx: "3",
    cy: "3",
    r: "2.5",
    fill: muted
  }), /*#__PURE__*/React.createElement("circle", {
    cx: "11",
    cy: "3",
    r: "2.5",
    fill: muted
  }), /*#__PURE__*/React.createElement("circle", {
    cx: "19",
    cy: "3",
    r: "2.5",
    fill: muted
  })))), /*#__PURE__*/React.createElement("div", {
    style: {
      padding: '0 16px',
      fontFamily: '-apple-system, system-ui',
      fontSize: 34,
      fontWeight: 700,
      lineHeight: '41px',
      color: text,
      letterSpacing: 0.4
    }
  }, title));
}

// ─────────────────────────────────────────────────────────────
// Grouped list (inset card, r:26) + row (52px)
// ─────────────────────────────────────────────────────────────
function IOSListRow({
  title,
  detail,
  icon,
  chevron = true,
  isLast = false,
  dark = false
}) {
  const text = dark ? '#fff' : '#000';
  const sec = dark ? 'rgba(235,235,245,0.6)' : 'rgba(60,60,67,0.6)';
  const ter = dark ? 'rgba(235,235,245,0.3)' : 'rgba(60,60,67,0.3)';
  const sep = dark ? 'rgba(84,84,88,0.65)' : 'rgba(60,60,67,0.12)';
  return /*#__PURE__*/React.createElement("div", {
    style: {
      display: 'flex',
      alignItems: 'center',
      minHeight: 52,
      padding: '0 16px',
      position: 'relative',
      fontFamily: '-apple-system, system-ui',
      fontSize: 17,
      letterSpacing: -0.43
    }
  }, icon && /*#__PURE__*/React.createElement("div", {
    style: {
      width: 30,
      height: 30,
      borderRadius: 7,
      background: icon,
      marginRight: 12,
      flexShrink: 0
    }
  }), /*#__PURE__*/React.createElement("div", {
    style: {
      flex: 1,
      color: text
    }
  }, title), detail && /*#__PURE__*/React.createElement("span", {
    style: {
      color: sec,
      marginRight: 6
    }
  }, detail), chevron && /*#__PURE__*/React.createElement("svg", {
    width: "8",
    height: "14",
    viewBox: "0 0 8 14",
    style: {
      flexShrink: 0
    }
  }, /*#__PURE__*/React.createElement("path", {
    d: "M1 1l6 6-6 6",
    stroke: ter,
    strokeWidth: "2",
    fill: "none",
    strokeLinecap: "round",
    strokeLinejoin: "round"
  })), !isLast && /*#__PURE__*/React.createElement("div", {
    style: {
      position: 'absolute',
      bottom: 0,
      right: 0,
      left: icon ? 58 : 16,
      height: 0.5,
      background: sep
    }
  }));
}
function IOSList({
  header,
  children,
  dark = false
}) {
  const hc = dark ? 'rgba(235,235,245,0.6)' : 'rgba(60,60,67,0.6)';
  const bg = dark ? '#1C1C1E' : '#fff';
  return /*#__PURE__*/React.createElement("div", null, header && /*#__PURE__*/React.createElement("div", {
    style: {
      fontFamily: '-apple-system, system-ui',
      fontSize: 13,
      color: hc,
      textTransform: 'uppercase',
      padding: '8px 36px 6px',
      letterSpacing: -0.08
    }
  }, header), /*#__PURE__*/React.createElement("div", {
    style: {
      background: bg,
      borderRadius: 26,
      margin: '0 16px',
      overflow: 'hidden'
    }
  }, children));
}

// ─────────────────────────────────────────────────────────────
// Device frame
// ─────────────────────────────────────────────────────────────
function IOSDevice({
  children,
  width = 402,
  height = 874,
  dark = false,
  title,
  keyboard = false
}) {
  return /*#__PURE__*/React.createElement("div", {
    style: {
      width,
      height,
      borderRadius: 48,
      overflow: 'hidden',
      position: 'relative',
      background: dark ? '#000' : '#F2F2F7',
      boxShadow: '0 40px 80px rgba(0,0,0,0.18), 0 0 0 1px rgba(0,0,0,0.12)',
      fontFamily: '-apple-system, system-ui, sans-serif',
      WebkitFontSmoothing: 'antialiased'
    }
  }, /*#__PURE__*/React.createElement("div", {
    style: {
      position: 'absolute',
      top: 11,
      left: '50%',
      transform: 'translateX(-50%)',
      width: 126,
      height: 37,
      borderRadius: 24,
      background: '#000',
      zIndex: 50
    }
  }), /*#__PURE__*/React.createElement("div", {
    style: {
      position: 'absolute',
      top: 0,
      left: 0,
      right: 0,
      zIndex: 10
    }
  }, /*#__PURE__*/React.createElement(IOSStatusBar, {
    dark: dark
  })), /*#__PURE__*/React.createElement("div", {
    style: {
      height: '100%',
      display: 'flex',
      flexDirection: 'column'
    }
  }, title !== undefined && /*#__PURE__*/React.createElement(IOSNavBar, {
    title: title,
    dark: dark
  }), /*#__PURE__*/React.createElement("div", {
    style: {
      flex: 1,
      overflow: 'auto'
    }
  }, children), keyboard && /*#__PURE__*/React.createElement(IOSKeyboard, {
    dark: dark
  })), /*#__PURE__*/React.createElement("div", {
    style: {
      position: 'absolute',
      bottom: 0,
      left: 0,
      right: 0,
      zIndex: 60,
      height: 34,
      display: 'flex',
      justifyContent: 'center',
      alignItems: 'flex-end',
      paddingBottom: 8,
      pointerEvents: 'none'
    }
  }, /*#__PURE__*/React.createElement("div", {
    style: {
      width: 139,
      height: 5,
      borderRadius: 100,
      background: dark ? 'rgba(255,255,255,0.7)' : 'rgba(0,0,0,0.25)'
    }
  })));
}

// ─────────────────────────────────────────────────────────────
// Keyboard — iOS 26 liquid glass
// ─────────────────────────────────────────────────────────────
function IOSKeyboard({
  dark = false
}) {
  const glyph = dark ? 'rgba(255,255,255,0.7)' : '#595959';
  const sugg = dark ? 'rgba(255,255,255,0.6)' : '#333';
  const keyBg = dark ? 'rgba(255,255,255,0.22)' : 'rgba(255,255,255,0.85)';

  // special-key icons
  const icons = {
    shift: /*#__PURE__*/React.createElement("svg", {
      width: "19",
      height: "17",
      viewBox: "0 0 19 17"
    }, /*#__PURE__*/React.createElement("path", {
      d: "M9.5 1L1 9.5h4.5V16h8V9.5H18L9.5 1z",
      fill: glyph
    })),
    del: /*#__PURE__*/React.createElement("svg", {
      width: "23",
      height: "17",
      viewBox: "0 0 23 17"
    }, /*#__PURE__*/React.createElement("path", {
      d: "M7 1h13a2 2 0 012 2v11a2 2 0 01-2 2H7l-6-7.5L7 1z",
      fill: "none",
      stroke: glyph,
      strokeWidth: "1.6",
      strokeLinejoin: "round"
    }), /*#__PURE__*/React.createElement("path", {
      d: "M10 5l7 7M17 5l-7 7",
      stroke: glyph,
      strokeWidth: "1.6",
      strokeLinecap: "round"
    })),
    ret: /*#__PURE__*/React.createElement("svg", {
      width: "20",
      height: "14",
      viewBox: "0 0 20 14"
    }, /*#__PURE__*/React.createElement("path", {
      d: "M18 1v6H4m0 0l4-4M4 7l4 4",
      fill: "none",
      stroke: "#fff",
      strokeWidth: "1.8",
      strokeLinecap: "round",
      strokeLinejoin: "round"
    }))
  };
  const key = (content, {
    w,
    flex,
    ret,
    fs = 25,
    k
  } = {}) => /*#__PURE__*/React.createElement("div", {
    key: k,
    style: {
      height: 42,
      borderRadius: 8.5,
      flex: flex ? 1 : undefined,
      width: w,
      minWidth: 0,
      background: ret ? '#08f' : keyBg,
      boxShadow: '0 1px 0 rgba(0,0,0,0.075)',
      display: 'flex',
      alignItems: 'center',
      justifyContent: 'center',
      fontFamily: '-apple-system, "SF Compact", system-ui',
      fontSize: fs,
      fontWeight: 458,
      color: ret ? '#fff' : glyph
    }
  }, content);
  const row = (keys, pad = 0) => /*#__PURE__*/React.createElement("div", {
    style: {
      display: 'flex',
      gap: 6.5,
      justifyContent: 'center',
      padding: `0 ${pad}px`
    }
  }, keys.map(l => key(l, {
    flex: true,
    k: l
  })));
  return /*#__PURE__*/React.createElement("div", {
    style: {
      position: 'relative',
      zIndex: 15,
      borderRadius: 27,
      overflow: 'hidden',
      padding: '11px 0 2px',
      display: 'flex',
      flexDirection: 'column',
      alignItems: 'center',
      boxShadow: dark ? '0 -2px 20px rgba(0,0,0,0.09)' : '0 -1px 6px rgba(0,0,0,0.018), 0 -3px 20px rgba(0,0,0,0.012)'
    }
  }, /*#__PURE__*/React.createElement("div", {
    style: {
      position: 'absolute',
      inset: 0,
      borderRadius: 27,
      backdropFilter: 'blur(12px) saturate(180%)',
      WebkitBackdropFilter: 'blur(12px) saturate(180%)',
      background: dark ? 'rgba(120,120,128,0.14)' : 'rgba(255,255,255,0.25)'
    }
  }), /*#__PURE__*/React.createElement("div", {
    style: {
      position: 'absolute',
      inset: 0,
      borderRadius: 27,
      boxShadow: dark ? 'inset 1.5px 1.5px 1px rgba(255,255,255,0.15)' : 'inset 1.5px 1.5px 1px rgba(255,255,255,0.7), inset -1px -1px 1px rgba(255,255,255,0.4)',
      border: dark ? '0.5px solid rgba(255,255,255,0.15)' : '0.5px solid rgba(0,0,0,0.06)',
      pointerEvents: 'none'
    }
  }), /*#__PURE__*/React.createElement("div", {
    style: {
      display: 'flex',
      gap: 20,
      alignItems: 'center',
      padding: '8px 22px 13px',
      width: '100%',
      boxSizing: 'border-box',
      position: 'relative'
    }
  }, ['"The"', 'the', 'to'].map((w, i) => /*#__PURE__*/React.createElement(React.Fragment, {
    key: i
  }, i > 0 && /*#__PURE__*/React.createElement("div", {
    style: {
      width: 1,
      height: 25,
      background: '#ccc',
      opacity: 0.3
    }
  }), /*#__PURE__*/React.createElement("div", {
    style: {
      flex: 1,
      textAlign: 'center',
      fontFamily: '-apple-system, system-ui',
      fontSize: 17,
      color: sugg,
      letterSpacing: -0.43,
      lineHeight: '22px'
    }
  }, w)))), /*#__PURE__*/React.createElement("div", {
    style: {
      display: 'flex',
      flexDirection: 'column',
      gap: 13,
      padding: '0 6.5px',
      width: '100%',
      boxSizing: 'border-box',
      position: 'relative'
    }
  }, row(['q', 'w', 'e', 'r', 't', 'y', 'u', 'i', 'o', 'p']), row(['a', 's', 'd', 'f', 'g', 'h', 'j', 'k', 'l'], 20), /*#__PURE__*/React.createElement("div", {
    style: {
      display: 'flex',
      gap: 14.25,
      alignItems: 'center'
    }
  }, key(icons.shift, {
    w: 45,
    k: 'shift'
  }), /*#__PURE__*/React.createElement("div", {
    style: {
      display: 'flex',
      gap: 6.5,
      flex: 1
    }
  }, ['z', 'x', 'c', 'v', 'b', 'n', 'm'].map(l => key(l, {
    flex: true,
    k: l
  }))), key(icons.del, {
    w: 45,
    k: 'del'
  })), /*#__PURE__*/React.createElement("div", {
    style: {
      display: 'flex',
      gap: 6,
      alignItems: 'center'
    }
  }, key('ABC', {
    w: 92.25,
    fs: 18,
    k: 'abc'
  }), key('', {
    flex: true,
    k: 'space'
  }), key(icons.ret, {
    w: 92.25,
    ret: true,
    k: 'ret'
  }))), /*#__PURE__*/React.createElement("div", {
    style: {
      height: 56,
      width: '100%',
      position: 'relative'
    }
  }));
}
Object.assign(window, {
  IOSDevice,
  IOSStatusBar,
  IOSNavBar,
  IOSGlassPill,
  IOSList,
  IOSListRow,
  IOSKeyboard
});
})(); } catch (e) { __ds_ns.__errors.push({ path: "flashcards/ios-frame.jsx", error: String((e && e.message) || e) }); }

// flashcards/tweaks-panel.jsx
try { (() => {
// tweaks-panel.jsx
// Reusable Tweaks shell + form-control helpers.
//
// Owns the host protocol (listens for __activate_edit_mode / __deactivate_edit_mode,
// posts __edit_mode_available / __edit_mode_set_keys / __edit_mode_dismissed) so
// individual prototypes don't re-roll it. Ships a consistent set of controls so you
// don't hand-draw <input type="range">, segmented radios, steppers, etc.
//
// Usage (in an HTML file that loads React + Babel):
//
//   const TWEAK_DEFAULTS = /*EDITMODE-BEGIN*/{
//     "primaryColor": "#D97757",
//     "palette": ["#D97757", "#29261b", "#f6f4ef"],
//     "fontSize": 16,
//     "density": "regular",
//     "dark": false
//   }/*EDITMODE-END*/;
//
//   function App() {
//     const [t, setTweak] = useTweaks(TWEAK_DEFAULTS);
//     return (
//       <div style={{ fontSize: t.fontSize, color: t.primaryColor }}>
//         Hello
//         <TweaksPanel>
//           <TweakSection label="Typography" />
//           <TweakSlider label="Font size" value={t.fontSize} min={10} max={32} unit="px"
//                        onChange={(v) => setTweak('fontSize', v)} />
//           <TweakRadio  label="Density" value={t.density}
//                        options={['compact', 'regular', 'comfy']}
//                        onChange={(v) => setTweak('density', v)} />
//           <TweakSection label="Theme" />
//           <TweakColor  label="Primary" value={t.primaryColor}
//                        options={['#D97757', '#2A6FDB', '#1F8A5B', '#7A5AE0']}
//                        onChange={(v) => setTweak('primaryColor', v)} />
//           <TweakColor  label="Palette" value={t.palette}
//                        options={[['#D97757', '#29261b', '#f6f4ef'],
//                                  ['#475569', '#0f172a', '#f1f5f9']]}
//                        onChange={(v) => setTweak('palette', v)} />
//           <TweakToggle label="Dark mode" value={t.dark}
//                        onChange={(v) => setTweak('dark', v)} />
//         </TweaksPanel>
//       </div>
//     );
//   }
//
// ─────────────────────────────────────────────────────────────────────────────

const __TWEAKS_STYLE = `
  .twk-panel{position:fixed;right:16px;bottom:16px;z-index:2147483646;width:280px;
    max-height:calc(100vh - 32px);display:flex;flex-direction:column;
    transform:scale(var(--dc-inv-zoom,1));transform-origin:bottom right;
    background:rgba(250,249,247,.78);color:#29261b;
    -webkit-backdrop-filter:blur(24px) saturate(160%);backdrop-filter:blur(24px) saturate(160%);
    border:.5px solid rgba(255,255,255,.6);border-radius:14px;
    box-shadow:0 1px 0 rgba(255,255,255,.5) inset,0 12px 40px rgba(0,0,0,.18);
    font:11.5px/1.4 ui-sans-serif,system-ui,-apple-system,sans-serif;overflow:hidden}
  .twk-hd{display:flex;align-items:center;justify-content:space-between;
    padding:10px 8px 10px 14px;cursor:move;user-select:none}
  .twk-hd b{font-size:12px;font-weight:600;letter-spacing:.01em}
  .twk-x{appearance:none;border:0;background:transparent;color:rgba(41,38,27,.55);
    width:22px;height:22px;border-radius:6px;cursor:default;font-size:13px;line-height:1}
  .twk-x:hover{background:rgba(0,0,0,.06);color:#29261b}
  .twk-body{padding:2px 14px 14px;display:flex;flex-direction:column;gap:10px;
    overflow-y:auto;overflow-x:hidden;min-height:0;
    scrollbar-width:thin;scrollbar-color:rgba(0,0,0,.15) transparent}
  .twk-body::-webkit-scrollbar{width:8px}
  .twk-body::-webkit-scrollbar-track{background:transparent;margin:2px}
  .twk-body::-webkit-scrollbar-thumb{background:rgba(0,0,0,.15);border-radius:4px;
    border:2px solid transparent;background-clip:content-box}
  .twk-body::-webkit-scrollbar-thumb:hover{background:rgba(0,0,0,.25);
    border:2px solid transparent;background-clip:content-box}
  .twk-row{display:flex;flex-direction:column;gap:5px}
  .twk-row-h{flex-direction:row;align-items:center;justify-content:space-between;gap:10px}
  .twk-lbl{display:flex;justify-content:space-between;align-items:baseline;
    color:rgba(41,38,27,.72)}
  .twk-lbl>span:first-child{font-weight:500}
  .twk-val{color:rgba(41,38,27,.5);font-variant-numeric:tabular-nums}

  .twk-sect{font-size:10px;font-weight:600;letter-spacing:.06em;text-transform:uppercase;
    color:rgba(41,38,27,.45);padding:10px 0 0}
  .twk-sect:first-child{padding-top:0}

  .twk-field{appearance:none;width:100%;height:26px;padding:0 8px;
    border:.5px solid rgba(0,0,0,.1);border-radius:7px;
    background:rgba(255,255,255,.6);color:inherit;font:inherit;outline:none}
  .twk-field:focus{border-color:rgba(0,0,0,.25);background:rgba(255,255,255,.85)}
  select.twk-field{padding-right:22px;
    background-image:url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='10' height='6' viewBox='0 0 10 6'><path fill='rgba(0,0,0,.5)' d='M0 0h10L5 6z'/></svg>");
    background-repeat:no-repeat;background-position:right 8px center}

  .twk-slider{appearance:none;-webkit-appearance:none;width:100%;height:4px;margin:6px 0;
    border-radius:999px;background:rgba(0,0,0,.12);outline:none}
  .twk-slider::-webkit-slider-thumb{-webkit-appearance:none;appearance:none;
    width:14px;height:14px;border-radius:50%;background:#fff;
    border:.5px solid rgba(0,0,0,.12);box-shadow:0 1px 3px rgba(0,0,0,.2);cursor:default}
  .twk-slider::-moz-range-thumb{width:14px;height:14px;border-radius:50%;
    background:#fff;border:.5px solid rgba(0,0,0,.12);box-shadow:0 1px 3px rgba(0,0,0,.2);cursor:default}

  .twk-seg{position:relative;display:flex;padding:2px;border-radius:8px;
    background:rgba(0,0,0,.06);user-select:none}
  .twk-seg-thumb{position:absolute;top:2px;bottom:2px;border-radius:6px;
    background:rgba(255,255,255,.9);box-shadow:0 1px 2px rgba(0,0,0,.12);
    transition:left .15s cubic-bezier(.3,.7,.4,1),width .15s}
  .twk-seg.dragging .twk-seg-thumb{transition:none}
  .twk-seg button{appearance:none;position:relative;z-index:1;flex:1;border:0;
    background:transparent;color:inherit;font:inherit;font-weight:500;min-height:22px;
    border-radius:6px;cursor:default;padding:4px 6px;line-height:1.2;
    overflow-wrap:anywhere}

  .twk-toggle{position:relative;width:32px;height:18px;border:0;border-radius:999px;
    background:rgba(0,0,0,.15);transition:background .15s;cursor:default;padding:0}
  .twk-toggle[data-on="1"]{background:#34c759}
  .twk-toggle i{position:absolute;top:2px;left:2px;width:14px;height:14px;border-radius:50%;
    background:#fff;box-shadow:0 1px 2px rgba(0,0,0,.25);transition:transform .15s}
  .twk-toggle[data-on="1"] i{transform:translateX(14px)}

  .twk-num{display:flex;align-items:center;height:26px;padding:0 0 0 8px;
    border:.5px solid rgba(0,0,0,.1);border-radius:7px;background:rgba(255,255,255,.6)}
  .twk-num-lbl{font-weight:500;color:rgba(41,38,27,.6);cursor:ew-resize;
    user-select:none;padding-right:8px}
  .twk-num input{flex:1;min-width:0;height:100%;border:0;background:transparent;
    font:inherit;font-variant-numeric:tabular-nums;text-align:right;padding:0 8px 0 0;
    outline:none;color:inherit;-moz-appearance:textfield}
  .twk-num input::-webkit-inner-spin-button,.twk-num input::-webkit-outer-spin-button{
    -webkit-appearance:none;margin:0}
  .twk-num-unit{padding-right:8px;color:rgba(41,38,27,.45)}

  .twk-btn{appearance:none;height:26px;padding:0 12px;border:0;border-radius:7px;
    background:rgba(0,0,0,.78);color:#fff;font:inherit;font-weight:500;cursor:default}
  .twk-btn:hover{background:rgba(0,0,0,.88)}
  .twk-btn.secondary{background:rgba(0,0,0,.06);color:inherit}
  .twk-btn.secondary:hover{background:rgba(0,0,0,.1)}

  .twk-swatch{appearance:none;-webkit-appearance:none;width:56px;height:22px;
    border:.5px solid rgba(0,0,0,.1);border-radius:6px;padding:0;cursor:default;
    background:transparent;flex-shrink:0}
  .twk-swatch::-webkit-color-swatch-wrapper{padding:0}
  .twk-swatch::-webkit-color-swatch{border:0;border-radius:5.5px}
  .twk-swatch::-moz-color-swatch{border:0;border-radius:5.5px}

  .twk-chips{display:flex;gap:6px}
  .twk-chip{position:relative;appearance:none;flex:1;min-width:0;height:46px;
    padding:0;border:0;border-radius:6px;overflow:hidden;cursor:default;
    box-shadow:0 0 0 .5px rgba(0,0,0,.12),0 1px 2px rgba(0,0,0,.06);
    transition:transform .12s cubic-bezier(.3,.7,.4,1),box-shadow .12s}
  .twk-chip:hover{transform:translateY(-1px);
    box-shadow:0 0 0 .5px rgba(0,0,0,.18),0 4px 10px rgba(0,0,0,.12)}
  .twk-chip[data-on="1"]{box-shadow:0 0 0 1.5px rgba(0,0,0,.85),
    0 2px 6px rgba(0,0,0,.15)}
  .twk-chip>span{position:absolute;top:0;bottom:0;right:0;width:34%;
    display:flex;flex-direction:column;box-shadow:-1px 0 0 rgba(0,0,0,.1)}
  .twk-chip>span>i{flex:1;box-shadow:0 -1px 0 rgba(0,0,0,.1)}
  .twk-chip>span>i:first-child{box-shadow:none}
  .twk-chip svg{position:absolute;top:6px;left:6px;width:13px;height:13px;
    filter:drop-shadow(0 1px 1px rgba(0,0,0,.3))}
`;

// ── useTweaks ───────────────────────────────────────────────────────────────
// Single source of truth for tweak values. setTweak persists via the host
// (__edit_mode_set_keys → host rewrites the EDITMODE block on disk).
function useTweaks(defaults) {
  const [values, setValues] = React.useState(defaults);
  // Accepts either setTweak('key', value) or setTweak({ key: value, ... }) so a
  // useState-style call doesn't write a "[object Object]" key into the persisted
  // JSON block.
  const setTweak = React.useCallback((keyOrEdits, val) => {
    const edits = typeof keyOrEdits === 'object' && keyOrEdits !== null ? keyOrEdits : {
      [keyOrEdits]: val
    };
    setValues(prev => ({
      ...prev,
      ...edits
    }));
    window.parent.postMessage({
      type: '__edit_mode_set_keys',
      edits
    }, '*');
    // Same-window signal so in-page listeners (deck-stage rail thumbnails)
    // can react — the parent message only reaches the host, not peers.
    window.dispatchEvent(new CustomEvent('tweakchange', {
      detail: edits
    }));
  }, []);
  return [values, setTweak];
}

// ── TweaksPanel ─────────────────────────────────────────────────────────────
// Floating shell. Registers the protocol listener BEFORE announcing
// availability — if the announce ran first, the host's activate could land
// before our handler exists and the toolbar toggle would silently no-op.
// The close button posts __edit_mode_dismissed so the host's toolbar toggle
// flips off in lockstep; the host echoes __deactivate_edit_mode back which
// is what actually hides the panel.
function TweaksPanel({
  title = 'Tweaks',
  noDeckControls = false,
  children
}) {
  const [open, setOpen] = React.useState(false);
  const dragRef = React.useRef(null);
  // Auto-inject a rail toggle when a <deck-stage> is on the page. The
  // toggle drives the deck's per-viewer _railVisible via window message;
  // state is mirrored from the same localStorage key the deck reads so
  // the control reflects reality across reloads. The mechanism is the
  // message — authors who want custom placement can post it directly
  // and pass noDeckControls to suppress this one.
  const hasDeckStage = React.useMemo(() => typeof document !== 'undefined' && !!document.querySelector('deck-stage'), []);
  // Hide the toggle until the host has actually enabled the rail (the
  // __omelette_rail_enabled window message, posted only when the
  // omelette_deck_rail_enabled flag is on for this user). The initial read
  // covers TweaksPanel mounting after the message already arrived; the
  // listener covers the common case of mounting first.
  const [railEnabled, setRailEnabled] = React.useState(() => hasDeckStage && !!document.querySelector('deck-stage')?._railEnabled);
  React.useEffect(() => {
    if (!hasDeckStage || railEnabled) return undefined;
    const onMsg = e => {
      if (e.data && e.data.type === '__omelette_rail_enabled') setRailEnabled(true);
    };
    window.addEventListener('message', onMsg);
    return () => window.removeEventListener('message', onMsg);
  }, [hasDeckStage, railEnabled]);
  const [railVisible, setRailVisible] = React.useState(() => {
    try {
      return localStorage.getItem('deck-stage.railVisible') !== '0';
    } catch (e) {
      return true;
    }
  });
  const toggleRail = on => {
    setRailVisible(on);
    window.postMessage({
      type: '__deck_rail_visible',
      on
    }, '*');
  };
  const offsetRef = React.useRef({
    x: 16,
    y: 16
  });
  const PAD = 16;
  const clampToViewport = React.useCallback(() => {
    const panel = dragRef.current;
    if (!panel) return;
    const w = panel.offsetWidth,
      h = panel.offsetHeight;
    const maxRight = Math.max(PAD, window.innerWidth - w - PAD);
    const maxBottom = Math.max(PAD, window.innerHeight - h - PAD);
    offsetRef.current = {
      x: Math.min(maxRight, Math.max(PAD, offsetRef.current.x)),
      y: Math.min(maxBottom, Math.max(PAD, offsetRef.current.y))
    };
    panel.style.right = offsetRef.current.x + 'px';
    panel.style.bottom = offsetRef.current.y + 'px';
  }, []);
  React.useEffect(() => {
    if (!open) return;
    clampToViewport();
    if (typeof ResizeObserver === 'undefined') {
      window.addEventListener('resize', clampToViewport);
      return () => window.removeEventListener('resize', clampToViewport);
    }
    const ro = new ResizeObserver(clampToViewport);
    ro.observe(document.documentElement);
    return () => ro.disconnect();
  }, [open, clampToViewport]);
  React.useEffect(() => {
    const onMsg = e => {
      const t = e?.data?.type;
      if (t === '__activate_edit_mode') setOpen(true);else if (t === '__deactivate_edit_mode') setOpen(false);
    };
    window.addEventListener('message', onMsg);
    window.parent.postMessage({
      type: '__edit_mode_available'
    }, '*');
    return () => window.removeEventListener('message', onMsg);
  }, []);
  const dismiss = () => {
    setOpen(false);
    window.parent.postMessage({
      type: '__edit_mode_dismissed'
    }, '*');
  };
  const onDragStart = e => {
    const panel = dragRef.current;
    if (!panel) return;
    const r = panel.getBoundingClientRect();
    const sx = e.clientX,
      sy = e.clientY;
    const startRight = window.innerWidth - r.right;
    const startBottom = window.innerHeight - r.bottom;
    const move = ev => {
      offsetRef.current = {
        x: startRight - (ev.clientX - sx),
        y: startBottom - (ev.clientY - sy)
      };
      clampToViewport();
    };
    const up = () => {
      window.removeEventListener('mousemove', move);
      window.removeEventListener('mouseup', up);
    };
    window.addEventListener('mousemove', move);
    window.addEventListener('mouseup', up);
  };
  if (!open) return null;
  return /*#__PURE__*/React.createElement(React.Fragment, null, /*#__PURE__*/React.createElement("style", null, __TWEAKS_STYLE), /*#__PURE__*/React.createElement("div", {
    ref: dragRef,
    className: "twk-panel",
    "data-noncommentable": "",
    style: {
      right: offsetRef.current.x,
      bottom: offsetRef.current.y
    }
  }, /*#__PURE__*/React.createElement("div", {
    className: "twk-hd",
    onMouseDown: onDragStart
  }, /*#__PURE__*/React.createElement("b", null, title), /*#__PURE__*/React.createElement("button", {
    className: "twk-x",
    "aria-label": "Close tweaks",
    onMouseDown: e => e.stopPropagation(),
    onClick: dismiss
  }, "\u2715")), /*#__PURE__*/React.createElement("div", {
    className: "twk-body"
  }, children, hasDeckStage && railEnabled && !noDeckControls && /*#__PURE__*/React.createElement(TweakSection, {
    label: "Deck"
  }, /*#__PURE__*/React.createElement(TweakToggle, {
    label: "Thumbnail rail",
    value: railVisible,
    onChange: toggleRail
  })))));
}

// ── Layout helpers ──────────────────────────────────────────────────────────

function TweakSection({
  label,
  children
}) {
  return /*#__PURE__*/React.createElement(React.Fragment, null, /*#__PURE__*/React.createElement("div", {
    className: "twk-sect"
  }, label), children);
}
function TweakRow({
  label,
  value,
  children,
  inline = false
}) {
  return /*#__PURE__*/React.createElement("div", {
    className: inline ? 'twk-row twk-row-h' : 'twk-row'
  }, /*#__PURE__*/React.createElement("div", {
    className: "twk-lbl"
  }, /*#__PURE__*/React.createElement("span", null, label), value != null && /*#__PURE__*/React.createElement("span", {
    className: "twk-val"
  }, value)), children);
}

// ── Controls ────────────────────────────────────────────────────────────────

function TweakSlider({
  label,
  value,
  min = 0,
  max = 100,
  step = 1,
  unit = '',
  onChange
}) {
  return /*#__PURE__*/React.createElement(TweakRow, {
    label: label,
    value: `${value}${unit}`
  }, /*#__PURE__*/React.createElement("input", {
    type: "range",
    className: "twk-slider",
    min: min,
    max: max,
    step: step,
    value: value,
    onChange: e => onChange(Number(e.target.value))
  }));
}
function TweakToggle({
  label,
  value,
  onChange
}) {
  return /*#__PURE__*/React.createElement("div", {
    className: "twk-row twk-row-h"
  }, /*#__PURE__*/React.createElement("div", {
    className: "twk-lbl"
  }, /*#__PURE__*/React.createElement("span", null, label)), /*#__PURE__*/React.createElement("button", {
    type: "button",
    className: "twk-toggle",
    "data-on": value ? '1' : '0',
    role: "switch",
    "aria-checked": !!value,
    onClick: () => onChange(!value)
  }, /*#__PURE__*/React.createElement("i", null)));
}
function TweakRadio({
  label,
  value,
  options,
  onChange
}) {
  const trackRef = React.useRef(null);
  const [dragging, setDragging] = React.useState(false);
  // The active value is read by pointer-move handlers attached for the lifetime
  // of a drag — ref it so a stale closure doesn't fire onChange for every move.
  const valueRef = React.useRef(value);
  valueRef.current = value;

  // Segments wrap mid-word once per-segment width runs out. The track is
  // ~248px (280 panel − 28 body pad − 4 seg pad), each button loses 12px
  // to its own padding, and 11.5px system-ui averages ~6.3px/char — so 2
  // options fit ~16 chars each, 3 fit ~10. Past that (or >3 options), fall
  // back to a dropdown rather than wrap.
  const labelLen = o => String(typeof o === 'object' ? o.label : o).length;
  const maxLen = options.reduce((m, o) => Math.max(m, labelLen(o)), 0);
  const fitsAsSegments = maxLen <= ({
    2: 16,
    3: 10
  }[options.length] ?? 0);
  if (!fitsAsSegments) {
    // <select> emits strings — map back to the original option value so the
    // fallback stays type-preserving (numbers, booleans) like the segment path.
    const resolve = s => {
      const m = options.find(o => String(typeof o === 'object' ? o.value : o) === s);
      return m === undefined ? s : typeof m === 'object' ? m.value : m;
    };
    return /*#__PURE__*/React.createElement(TweakSelect, {
      label: label,
      value: value,
      options: options,
      onChange: s => onChange(resolve(s))
    });
  }
  const opts = options.map(o => typeof o === 'object' ? o : {
    value: o,
    label: o
  });
  const idx = Math.max(0, opts.findIndex(o => o.value === value));
  const n = opts.length;
  const segAt = clientX => {
    const r = trackRef.current.getBoundingClientRect();
    const inner = r.width - 4;
    const i = Math.floor((clientX - r.left - 2) / inner * n);
    return opts[Math.max(0, Math.min(n - 1, i))].value;
  };
  const onPointerDown = e => {
    setDragging(true);
    const v0 = segAt(e.clientX);
    if (v0 !== valueRef.current) onChange(v0);
    const move = ev => {
      if (!trackRef.current) return;
      const v = segAt(ev.clientX);
      if (v !== valueRef.current) onChange(v);
    };
    const up = () => {
      setDragging(false);
      window.removeEventListener('pointermove', move);
      window.removeEventListener('pointerup', up);
    };
    window.addEventListener('pointermove', move);
    window.addEventListener('pointerup', up);
  };
  return /*#__PURE__*/React.createElement(TweakRow, {
    label: label
  }, /*#__PURE__*/React.createElement("div", {
    ref: trackRef,
    role: "radiogroup",
    onPointerDown: onPointerDown,
    className: dragging ? 'twk-seg dragging' : 'twk-seg'
  }, /*#__PURE__*/React.createElement("div", {
    className: "twk-seg-thumb",
    style: {
      left: `calc(2px + ${idx} * (100% - 4px) / ${n})`,
      width: `calc((100% - 4px) / ${n})`
    }
  }), opts.map(o => /*#__PURE__*/React.createElement("button", {
    key: o.value,
    type: "button",
    role: "radio",
    "aria-checked": o.value === value
  }, o.label))));
}
function TweakSelect({
  label,
  value,
  options,
  onChange
}) {
  return /*#__PURE__*/React.createElement(TweakRow, {
    label: label
  }, /*#__PURE__*/React.createElement("select", {
    className: "twk-field",
    value: value,
    onChange: e => onChange(e.target.value)
  }, options.map(o => {
    const v = typeof o === 'object' ? o.value : o;
    const l = typeof o === 'object' ? o.label : o;
    return /*#__PURE__*/React.createElement("option", {
      key: v,
      value: v
    }, l);
  })));
}
function TweakText({
  label,
  value,
  placeholder,
  onChange
}) {
  return /*#__PURE__*/React.createElement(TweakRow, {
    label: label
  }, /*#__PURE__*/React.createElement("input", {
    className: "twk-field",
    type: "text",
    value: value,
    placeholder: placeholder,
    onChange: e => onChange(e.target.value)
  }));
}
function TweakNumber({
  label,
  value,
  min,
  max,
  step = 1,
  unit = '',
  onChange
}) {
  const clamp = n => {
    if (min != null && n < min) return min;
    if (max != null && n > max) return max;
    return n;
  };
  const startRef = React.useRef({
    x: 0,
    val: 0
  });
  const onScrubStart = e => {
    e.preventDefault();
    startRef.current = {
      x: e.clientX,
      val: value
    };
    const decimals = (String(step).split('.')[1] || '').length;
    const move = ev => {
      const dx = ev.clientX - startRef.current.x;
      const raw = startRef.current.val + dx * step;
      const snapped = Math.round(raw / step) * step;
      onChange(clamp(Number(snapped.toFixed(decimals))));
    };
    const up = () => {
      window.removeEventListener('pointermove', move);
      window.removeEventListener('pointerup', up);
    };
    window.addEventListener('pointermove', move);
    window.addEventListener('pointerup', up);
  };
  return /*#__PURE__*/React.createElement("div", {
    className: "twk-num"
  }, /*#__PURE__*/React.createElement("span", {
    className: "twk-num-lbl",
    onPointerDown: onScrubStart
  }, label), /*#__PURE__*/React.createElement("input", {
    type: "number",
    value: value,
    min: min,
    max: max,
    step: step,
    onChange: e => onChange(clamp(Number(e.target.value)))
  }), unit && /*#__PURE__*/React.createElement("span", {
    className: "twk-num-unit"
  }, unit));
}

// Relative-luminance contrast pick — checkmarks drawn over a swatch need to
// read on both #111 and #fafafa without per-option configuration. Hex input
// only (#rgb / #rrggbb); named or rgb()/hsl() colors fall through to "light".
function __twkIsLight(hex) {
  const h = String(hex).replace('#', '');
  const x = h.length === 3 ? h.replace(/./g, c => c + c) : h.padEnd(6, '0');
  const n = parseInt(x.slice(0, 6), 16);
  if (Number.isNaN(n)) return true;
  const r = n >> 16 & 255,
    g = n >> 8 & 255,
    b = n & 255;
  return r * 299 + g * 587 + b * 114 > 148000;
}
const __TwkCheck = ({
  light
}) => /*#__PURE__*/React.createElement("svg", {
  viewBox: "0 0 14 14",
  "aria-hidden": "true"
}, /*#__PURE__*/React.createElement("path", {
  d: "M3 7.2 5.8 10 11 4.2",
  fill: "none",
  strokeWidth: "2.2",
  strokeLinecap: "round",
  strokeLinejoin: "round",
  stroke: light ? 'rgba(0,0,0,.78)' : '#fff'
}));

// TweakColor — curated color/palette picker. Each option is either a single
// hex string or an array of 1-5 hex strings; the card adapts — a lone color
// renders solid, a palette renders colors[0] as the hero (left ~2/3) with the
// rest stacked in a sharp column on the right. onChange emits the
// option in the shape it was passed (string stays string, array stays array).
// Without options it falls back to the native color input for back-compat.
function TweakColor({
  label,
  value,
  options,
  onChange
}) {
  if (!options || !options.length) {
    return /*#__PURE__*/React.createElement("div", {
      className: "twk-row twk-row-h"
    }, /*#__PURE__*/React.createElement("div", {
      className: "twk-lbl"
    }, /*#__PURE__*/React.createElement("span", null, label)), /*#__PURE__*/React.createElement("input", {
      type: "color",
      className: "twk-swatch",
      value: value,
      onChange: e => onChange(e.target.value)
    }));
  }
  // Native <input type=color> emits lowercase hex per the HTML spec, so
  // compare case-insensitively. String() guards JSON.stringify(undefined),
  // which returns the primitive undefined (no .toLowerCase).
  const key = o => String(JSON.stringify(o)).toLowerCase();
  const cur = key(value);
  return /*#__PURE__*/React.createElement(TweakRow, {
    label: label
  }, /*#__PURE__*/React.createElement("div", {
    className: "twk-chips",
    role: "radiogroup"
  }, options.map((o, i) => {
    const colors = Array.isArray(o) ? o : [o];
    const [hero, ...rest] = colors;
    const sup = rest.slice(0, 4);
    const on = key(o) === cur;
    return /*#__PURE__*/React.createElement("button", {
      key: i,
      type: "button",
      className: "twk-chip",
      role: "radio",
      "aria-checked": on,
      "data-on": on ? '1' : '0',
      "aria-label": colors.join(', '),
      title: colors.join(' · '),
      style: {
        background: hero
      },
      onClick: () => onChange(o)
    }, sup.length > 0 && /*#__PURE__*/React.createElement("span", null, sup.map((c, j) => /*#__PURE__*/React.createElement("i", {
      key: j,
      style: {
        background: c
      }
    }))), on && /*#__PURE__*/React.createElement(__TwkCheck, {
      light: __twkIsLight(hero)
    }));
  })));
}
function TweakButton({
  label,
  onClick,
  secondary = false
}) {
  return /*#__PURE__*/React.createElement("button", {
    type: "button",
    className: secondary ? 'twk-btn secondary' : 'twk-btn',
    onClick: onClick
  }, label);
}
Object.assign(window, {
  useTweaks,
  TweaksPanel,
  TweakSection,
  TweakRow,
  TweakSlider,
  TweakToggle,
  TweakRadio,
  TweakSelect,
  TweakText,
  TweakNumber,
  TweakColor,
  TweakButton
});
})(); } catch (e) { __ds_ns.__errors.push({ path: "flashcards/tweaks-panel.jsx", error: String((e && e.message) || e) }); }

// quiz-game-export/QuizGameExport.jsx
try { (() => {
/* global React, XLSX */
const {
  useState,
  useEffect,
  useRef,
  useCallback,
  useLayoutEffect,
  useMemo
} = React;

/* ---------- built-in sample dictionary ---------- */
const SAMPLE_DICT = [{
  en: "ENHANCE",
  he: "להעצים, לשפר",
  ipa: "/ɪnˈhæns/"
}, {
  en: "MITIGATE",
  he: "להקל, למתן",
  ipa: "/ˈmɪtɪˌɡeɪt/"
}, {
  en: "AMBIGUOUS",
  he: "דו-משמעי, עמום",
  ipa: "/æmˈbɪɡjuəs/"
}, {
  en: "ADVOCATE",
  he: "לתמוך, להמליץ",
  ipa: "/ˈædvəˌkeɪt/"
}, {
  en: "SCRUTINIZE",
  he: "לבחון בקפדנות",
  ipa: "/ˈskruːtəˌnaɪz/"
}, {
  en: "INEVITABLE",
  he: "בלתי נמנע",
  ipa: "/ɪˈnɛvɪtəbəl/"
}, {
  en: "DILIGENT",
  he: "חרוץ, שקדן",
  ipa: "/ˈdɪlɪdʒənt/"
}, {
  en: "OBSOLETE",
  he: "מיושן, יצא משימוש",
  ipa: "/ˌabsəˈliːt/"
}, {
  en: "CANDID",
  he: "הֵן, ישיר, ספונטני",
  ipa: "/ˈkændɪd/"
}, {
  en: "TENACIOUS",
  he: "עיקש, דבק במטרה",
  ipa: "/təˈneɪʃəs/"
}];
const STAGGER = [0, 40, 14, 56];
const DICT_STORAGE_KEY = "ez-mcq-dict-v2";
const DICT_NAME_KEY = "ez-mcq-dict-name-v2";
const MUTED_KEY = "ez-mcq-muted-v1";
const LB_KEY = "ez-mcq-leaderboard-v1";

/* ---------- sound engine (WebAudio FX + background music) ---------- */
const Sound = {
  ctx: null,
  muted: false,
  music: null,
  // <audio> element
  musicReady: false,
  init() {
    if (!this.ctx) {
      try {
        this.ctx = new (window.AudioContext || window.webkitAudioContext)();
      } catch (e) {}
    }
    if (this.ctx && this.ctx.state === 'suspended') this.ctx.resume();
    if (!this.music) {
      this.music = document.getElementById('bg-music');
      if (this.music) {
        this.music.volume = 0.35;
        this.music.loop = true;
        this.musicReady = true;
      }
    }
  },
  startMusic() {
    this.init();
    if (this.muted || !this.music) return;
    const p = this.music.play();
    if (p && p.catch) p.catch(() => {/* autoplay blocked — will start on next user gesture */});
  },
  stopMusic() {
    if (this.music) {
      this.music.pause();
    }
  },
  setMusicVolume(v) {
    if (this.music) this.music.volume = Math.max(0, Math.min(1, v));
  },
  setMuted(m) {
    this.muted = !!m;
    if (this.muted) this.stopMusic();else this.startMusic();
    try {
      localStorage.setItem(MUTED_KEY, this.muted ? '1' : '0');
    } catch (e) {}
  },
  beep(freq, duration, type = 'sine', gain = 0.15, delay = 0) {
    if (this.muted || !this.ctx) return;
    const t = this.ctx.currentTime + delay;
    const osc = this.ctx.createOscillator();
    const g = this.ctx.createGain();
    osc.type = type;
    osc.frequency.value = freq;
    g.gain.setValueAtTime(gain, t);
    g.gain.exponentialRampToValueAtTime(0.001, t + duration);
    osc.connect(g);
    g.connect(this.ctx.destination);
    osc.start(t);
    osc.stop(t + duration);
  },
  play(name) {
    if (this.muted) return;
    this.init();
    switch (name) {
      case 'shoot':
        this.beep(540, 0.06, 'square', 0.13);
        this.beep(220, 0.07, 'sawtooth', 0.10, 0.03);
        break;
      case 'hit':
        /* punchier explosion: low thump + bright chord + bell tail */
        this.beep(80, 0.10, 'square', 0.22);
        this.beep(523, 0.10, 'square', 0.16, 0.04);
        this.beep(784, 0.12, 'square', 0.14, 0.10);
        this.beep(1047, 0.22, 'triangle', 0.16, 0.18);
        this.beep(1568, 0.30, 'sine', 0.12, 0.30);
        break;
      case 'miss':
        /* descending "wha-wha" buzzer — clearly distinct from a hit */
        this.beep(440, 0.10, 'square', 0.20);
        this.beep(330, 0.14, 'square', 0.20, 0.10);
        this.beep(220, 0.30, 'sawtooth', 0.22, 0.22);
        this.beep(150, 0.45, 'triangle', 0.20, 0.45);
        break;
      case 'lifegain':
        /* sparkle: ascending major arpeggio */
        this.beep(659, 0.10, 'triangle', 0.18);
        this.beep(880, 0.10, 'triangle', 0.18, 0.10);
        this.beep(1175, 0.10, 'triangle', 0.18, 0.20);
        this.beep(1568, 0.32, 'sine', 0.20, 0.30);
        break;
      case 'fifty':
        /* two-note chime */
        this.beep(880, 0.10, 'sine', 0.15);
        this.beep(1320, 0.18, 'sine', 0.16, 0.10);
        break;
      case 'levelup':
        this.beep(523, 0.10, 'triangle', 0.18);
        this.beep(659, 0.10, 'triangle', 0.18, 0.10);
        this.beep(784, 0.10, 'triangle', 0.18, 0.20);
        this.beep(1047, 0.32, 'sine', 0.20, 0.30);
        break;
      case 'tick':
        this.beep(720, 0.08, 'sine', 0.10);
        break;
      case 'go':
        this.beep(1200, 0.30, 'triangle', 0.22);
        break;
      case 'streak':
        this.beep(880, 0.08, 'sine', 0.13);
        this.beep(1320, 0.10, 'sine', 0.14, 0.08);
        break;
      case 'gameover':
        this.beep(440, 0.20, 'sine', 0.15);
        this.beep(330, 0.24, 'sine', 0.15, 0.20);
        this.beep(220, 0.50, 'sine', 0.18, 0.45);
        break;
    }
  }
};
try {
  Sound.muted = localStorage.getItem(MUTED_KEY) === '1';
} catch (e) {}

/* ---------- leaderboard ---------- */
function getLeaderboard() {
  try {
    return JSON.parse(localStorage.getItem(LB_KEY) || '[]');
  } catch (e) {
    return [];
  }
}
function addToLeaderboard(name, score) {
  const lb = getLeaderboard();
  lb.push({
    name: (name || "אנונימי").slice(0, 20),
    score,
    date: new Date().toISOString()
  });
  lb.sort((a, b) => b.score - a.score);
  try {
    localStorage.setItem(LB_KEY, JSON.stringify(lb.slice(0, 5)));
  } catch (e) {}
  return lb.slice(0, 5);
}
function qualifiesForLeaderboard(score) {
  if (score <= 0) return false;
  const lb = getLeaderboard();
  if (lb.length < 5) return true;
  return score > lb[lb.length - 1].score;
}

/* ---------- dictionary helpers ---------- */
function shuffleArr(a) {
  const x = [...a];
  for (let i = x.length - 1; i > 0; i--) {
    const j = Math.floor(Math.random() * (i + 1));
    [x[i], x[j]] = [x[j], x[i]];
  }
  return x;
}
function buildQuestion(dict, correctIdx) {
  const correct = dict[correctIdx];
  const correctMeaning = normalizeMeaning(correct.he);

  // Build pool excluding correct answer AND entries that share the same meaning.
  // This prevents duplicate Hebrew translations from appearing as distractors
  // (e.g. when the same meaning is split across two English words).
  const pool = dict.map((entry, i) => ({
    entry,
    i,
    key: normalizeMeaning(entry.he)
  })).filter(({
    i,
    key
  }) => i !== correctIdx && key !== correctMeaning);

  // Pick 3 distractors with distinct meanings from each other too.
  const shuffled = shuffleArr(pool);
  const picked = [];
  const seenMeanings = new Set([correctMeaning]);
  for (const {
    entry,
    key
  } of shuffled) {
    if (seenMeanings.has(key)) continue;
    seenMeanings.add(key);
    picked.push(entry);
    if (picked.length === 3) break;
  }

  // Fallback: if the dict is too small / too many duplicates, allow same-key duplicates
  // just so we always have 4 options.
  while (picked.length < 3) {
    const fillers = shuffleArr(pool).filter(p => !picked.includes(p.entry));
    if (fillers.length === 0) break;
    picked.push(fillers[0].entry);
  }
  const options = shuffleArr([correct.he, ...picked.map(d => d.he)]);
  return {
    en: String(correct.en).toUpperCase(),
    ipa: correct.ipa || "",
    correct: correct.he,
    options
  };
}

// Normalize a meaning string so "להאריך / להרחיב" and "להאריך, להרחיב" collide,
// and casing/whitespace differences don't matter.
function normalizeMeaning(s) {
  return String(s || "").toLowerCase().replace(/[\/,،]/g, " ") // treat /, comma, arabic comma as separators
  .replace(/\s+/g, " ").replace(/[״"׳'.…]/g, "").trim();
}
function parseSpreadsheet(file) {
  return new Promise((resolve, reject) => {
    const reader = new FileReader();
    reader.onerror = () => reject(new Error("לא מצליח לקרוא את הקובץ"));
    reader.onload = e => {
      try {
        if (typeof XLSX === "undefined") {
          reject(new Error("תוכנת הפיענוח לא נטענה. רענן דף ונסה שוב."));
          return;
        }
        const data = new Uint8Array(e.target.result);
        const wb = XLSX.read(data, {
          type: "array"
        });
        const sheet = wb.Sheets[wb.SheetNames[0]];
        const rows = XLSX.utils.sheet_to_json(sheet, {
          header: 1,
          blankrows: false
        });
        if (!rows.length) {
          reject(new Error("הקובץ ריק"));
          return;
        }
        const firstB = String(rows[0][1] || "").trim().toLowerCase();
        const looksLikeHeader = /english|word|מילה|אנגלית/.test(firstB) || /פירוש|תרגום|עברית/.test(String(rows[0][2] || ""));
        const start = looksLikeHeader ? 1 : 0;
        const entries = [];
        for (let i = start; i < rows.length; i++) {
          const en = String(rows[i][1] || "").trim(); // column B
          const he = String(rows[i][2] || "").trim(); // column C
          if (en && he) entries.push({
            en,
            he,
            ipa: ""
          });
        }
        if (entries.length < 4) {
          reject(new Error("צריך לפחות 4 מילים בקובץ"));
          return;
        }
        resolve(entries);
      } catch (err) {
        reject(err);
      }
    };
    reader.readAsArrayBuffer(file);
  });
}

/* ──────────────────────────────────────────────
   Polished SVG illustrations
   ────────────────────────────────────────────── */

function RocketSVG() {
  const stroke = "#2A2155";
  const strokeW = 3.5;
  return /*#__PURE__*/React.createElement("svg", {
    className: "frame",
    viewBox: "0 0 620 150",
    preserveAspectRatio: "none",
    "aria-hidden": true
  }, /*#__PURE__*/React.createElement("defs", null, /*#__PURE__*/React.createElement("linearGradient", {
    id: "bodyG",
    x1: "0",
    y1: "0",
    x2: "0",
    y2: "1"
  }, /*#__PURE__*/React.createElement("stop", {
    offset: "0",
    stopColor: "#FFFFFF"
  }), /*#__PURE__*/React.createElement("stop", {
    offset: ".6",
    stopColor: "#F5F3F8"
  }), /*#__PURE__*/React.createElement("stop", {
    offset: "1",
    stopColor: "#C9C7CF"
  })), /*#__PURE__*/React.createElement("linearGradient", {
    id: "bodyG-hit",
    x1: "0",
    y1: "0",
    x2: "0",
    y2: "1"
  }, /*#__PURE__*/React.createElement("stop", {
    offset: "0",
    stopColor: "#FFE6CB"
  }), /*#__PURE__*/React.createElement("stop", {
    offset: ".5",
    stopColor: "#F37327"
  }), /*#__PURE__*/React.createElement("stop", {
    offset: "1",
    stopColor: "#A93C08"
  })), /*#__PURE__*/React.createElement("linearGradient", {
    id: "bodyG-miss",
    x1: "0",
    y1: "0",
    x2: "0",
    y2: "1"
  }, /*#__PURE__*/React.createElement("stop", {
    offset: "0",
    stopColor: "#D7D5DC"
  }), /*#__PURE__*/React.createElement("stop", {
    offset: "1",
    stopColor: "#9A98A4"
  })), /*#__PURE__*/React.createElement("linearGradient", {
    id: "bodyG-correct",
    x1: "0",
    y1: "0",
    x2: "0",
    y2: "1"
  }, /*#__PURE__*/React.createElement("stop", {
    offset: "0",
    stopColor: "#BDF0D3"
  }), /*#__PURE__*/React.createElement("stop", {
    offset: "1",
    stopColor: "#3FA76C"
  })), /*#__PURE__*/React.createElement("linearGradient", {
    id: "tipG",
    x1: "0",
    y1: "0",
    x2: "0",
    y2: "1"
  }, /*#__PURE__*/React.createElement("stop", {
    offset: "0",
    stopColor: "#FFB36B"
  }), /*#__PURE__*/React.createElement("stop", {
    offset: ".55",
    stopColor: "#F37327"
  }), /*#__PURE__*/React.createElement("stop", {
    offset: "1",
    stopColor: "#B94A0C"
  })), /*#__PURE__*/React.createElement("linearGradient", {
    id: "finG",
    x1: "0",
    y1: "0",
    x2: "0",
    y2: "1"
  }, /*#__PURE__*/React.createElement("stop", {
    offset: "0",
    stopColor: "#FFB36B"
  }), /*#__PURE__*/React.createElement("stop", {
    offset: ".5",
    stopColor: "#F37327"
  }), /*#__PURE__*/React.createElement("stop", {
    offset: "1",
    stopColor: "#A0410B"
  })), /*#__PURE__*/React.createElement("radialGradient", {
    id: "flameG",
    cx: "50%",
    cy: "50%",
    r: "55%"
  }, /*#__PURE__*/React.createElement("stop", {
    offset: "0",
    stopColor: "#FFF7CE"
  }), /*#__PURE__*/React.createElement("stop", {
    offset: ".4",
    stopColor: "#FFD23F"
  }), /*#__PURE__*/React.createElement("stop", {
    offset: ".85",
    stopColor: "#F37327"
  }), /*#__PURE__*/React.createElement("stop", {
    offset: "1",
    stopColor: "#B94A0C"
  }))), /*#__PURE__*/React.createElement("g", null, /*#__PURE__*/React.createElement("path", {
    d: "M 525,40 Q 555,52 580,32 Q 568,55 595,55 Q 575,68 610,72 Q 575,80 615,90 Q 575,92 600,108 Q 570,100 588,118 Q 555,100 580,118 Q 555,98 525,110 Z",
    fill: "url(#flameG)",
    stroke: stroke,
    strokeWidth: strokeW,
    strokeLinejoin: "round"
  }), /*#__PURE__*/React.createElement("path", {
    d: "M 530,55 Q 555,55 570,42 Q 568,62 585,68 Q 565,75 582,82 Q 565,88 580,100 Q 558,92 568,110 Q 545,95 530,100 Z",
    fill: "#FFF7CE",
    opacity: ".95"
  })), /*#__PURE__*/React.createElement("path", {
    d: "M 470,42 Q 488,18 540,2 Q 540,30 520,46 Q 500,52 470,42 Z",
    fill: "url(#finG)",
    stroke: stroke,
    strokeWidth: strokeW,
    strokeLinejoin: "round"
  }), /*#__PURE__*/React.createElement("path", {
    d: "M 495,28 Q 515,18 532,12",
    stroke: "#fff",
    strokeOpacity: ".6",
    strokeWidth: "3",
    fill: "none",
    strokeLinecap: "round"
  }), /*#__PURE__*/React.createElement("path", {
    d: "M 470,108 Q 488,132 540,148 Q 540,120 520,104 Q 500,98 470,108 Z",
    fill: "url(#finG)",
    stroke: stroke,
    strokeWidth: strokeW,
    strokeLinejoin: "round"
  }), /*#__PURE__*/React.createElement("path", {
    d: "M 495,122 Q 515,132 532,138",
    stroke: "#fff",
    strokeOpacity: ".45",
    strokeWidth: "3",
    fill: "none",
    strokeLinecap: "round"
  }), /*#__PURE__*/React.createElement("path", {
    className: "body-fill",
    d: "M 40,75 Q 70,16 165,16 L 530,16 Q 560,16 560,38 L 560,112 Q 560,134 530,134 L 165,134 Q 70,134 40,75 Z",
    fill: "url(#bodyG)",
    stroke: stroke,
    strokeWidth: strokeW,
    strokeLinejoin: "round"
  }), /*#__PURE__*/React.createElement("path", {
    d: "M 40,75 Q 70,16 165,16 L 175,16 Q 110,30 90,75 Q 110,120 175,134 L 165,134 Q 70,134 40,75 Z",
    fill: "url(#tipG)",
    stroke: stroke,
    strokeWidth: strokeW,
    strokeLinejoin: "round"
  }), /*#__PURE__*/React.createElement("path", {
    d: "M 70,52 Q 90,38 120,42",
    stroke: "#fff",
    strokeOpacity: ".7",
    strokeWidth: "4",
    fill: "none",
    strokeLinecap: "round"
  }), /*#__PURE__*/React.createElement("path", {
    d: "M 195,30 Q 360,24 510,32",
    stroke: "#fff",
    strokeOpacity: ".95",
    strokeWidth: "5",
    fill: "none",
    strokeLinecap: "round"
  }), /*#__PURE__*/React.createElement("path", {
    d: "M 170,124 Q 360,140 520,126",
    stroke: "#1A1530",
    strokeOpacity: ".09",
    strokeWidth: "6",
    fill: "none",
    strokeLinecap: "round"
  }), /*#__PURE__*/React.createElement("circle", {
    cx: "125",
    cy: "48",
    r: "2.5",
    fill: "#fff"
  }));
}
function BurstSVG() {
  return /*#__PURE__*/React.createElement("svg", {
    viewBox: "0 0 140 140",
    "aria-hidden": true
  }, /*#__PURE__*/React.createElement("defs", null, /*#__PURE__*/React.createElement("radialGradient", {
    id: "boom",
    cx: "50%",
    cy: "50%",
    r: "50%"
  }, /*#__PURE__*/React.createElement("stop", {
    offset: "0%",
    stopColor: "#FFF7E6"
  }), /*#__PURE__*/React.createElement("stop", {
    offset: "35%",
    stopColor: "#FFB061"
  }), /*#__PURE__*/React.createElement("stop", {
    offset: "70%",
    stopColor: "#F37327"
  }), /*#__PURE__*/React.createElement("stop", {
    offset: "100%",
    stopColor: "rgba(213,90,18,0)"
  }))), /*#__PURE__*/React.createElement("circle", {
    cx: "70",
    cy: "70",
    r: "48",
    fill: "url(#boom)"
  }), /*#__PURE__*/React.createElement("g", {
    stroke: "#FFB061",
    strokeWidth: "3",
    strokeLinecap: "round",
    fill: "none"
  }, /*#__PURE__*/React.createElement("line", {
    x1: "70",
    y1: "14",
    x2: "70",
    y2: "32"
  }), /*#__PURE__*/React.createElement("line", {
    x1: "70",
    y1: "108",
    x2: "70",
    y2: "126"
  }), /*#__PURE__*/React.createElement("line", {
    x1: "14",
    y1: "70",
    x2: "32",
    y2: "70"
  }), /*#__PURE__*/React.createElement("line", {
    x1: "108",
    y1: "70",
    x2: "126",
    y2: "70"
  }), /*#__PURE__*/React.createElement("line", {
    x1: "28",
    y1: "28",
    x2: "42",
    y2: "42"
  }), /*#__PURE__*/React.createElement("line", {
    x1: "98",
    y1: "98",
    x2: "112",
    y2: "112"
  }), /*#__PURE__*/React.createElement("line", {
    x1: "28",
    y1: "112",
    x2: "42",
    y2: "98"
  }), /*#__PURE__*/React.createElement("line", {
    x1: "98",
    y1: "42",
    x2: "112",
    y2: "28"
  })), /*#__PURE__*/React.createElement("circle", {
    cx: "70",
    cy: "70",
    r: "18",
    fill: "#FFF7E6"
  }));
}
function CannonBase() {
  return /*#__PURE__*/React.createElement("svg", {
    className: "base",
    viewBox: "0 0 280 240",
    "aria-hidden": true
  }, /*#__PURE__*/React.createElement("defs", null, /*#__PURE__*/React.createElement("linearGradient", {
    id: "domeG",
    x1: "0",
    y1: "0",
    x2: "0",
    y2: "1"
  }, /*#__PURE__*/React.createElement("stop", {
    offset: "0",
    stopColor: "#FFA362"
  }), /*#__PURE__*/React.createElement("stop", {
    offset: "0.5",
    stopColor: "#F37327"
  }), /*#__PURE__*/React.createElement("stop", {
    offset: "1",
    stopColor: "#A93C08"
  })), /*#__PURE__*/React.createElement("linearGradient", {
    id: "tracksG",
    x1: "0",
    y1: "0",
    x2: "0",
    y2: "1"
  }, /*#__PURE__*/React.createElement("stop", {
    offset: "0",
    stopColor: "#2A2547"
  }), /*#__PURE__*/React.createElement("stop", {
    offset: "1",
    stopColor: "#0A0820"
  })), /*#__PURE__*/React.createElement("linearGradient", {
    id: "metalG",
    x1: "0",
    y1: "0",
    x2: "0",
    y2: "1"
  }, /*#__PURE__*/React.createElement("stop", {
    offset: "0",
    stopColor: "#3a3358"
  }), /*#__PURE__*/React.createElement("stop", {
    offset: "1",
    stopColor: "#15102B"
  }))), /*#__PURE__*/React.createElement("ellipse", {
    cx: "140",
    cy: "226",
    rx: "120",
    ry: "10",
    fill: "rgba(0,0,0,.45)"
  }), /*#__PURE__*/React.createElement("path", {
    d: "M 20,168 L 260,168 L 250,216 L 30,216 Z",
    fill: "url(#tracksG)",
    stroke: "#000",
    strokeWidth: "1"
  }), Array.from({
    length: 12
  }).map((_, i) => /*#__PURE__*/React.createElement("rect", {
    key: i,
    x: 32 + i * 18,
    y: "174",
    width: "12",
    height: "36",
    rx: "2",
    fill: "#3a3358"
  })), [58, 98, 138, 178, 218].map((cx, i) => /*#__PURE__*/React.createElement("g", {
    key: i
  }, /*#__PURE__*/React.createElement("circle", {
    cx: cx,
    cy: "200",
    r: "13",
    fill: "#0A0820"
  }), /*#__PURE__*/React.createElement("circle", {
    cx: cx,
    cy: "200",
    r: "10",
    fill: "#3a3358",
    stroke: "#5a5470",
    strokeWidth: "2"
  }), /*#__PURE__*/React.createElement("circle", {
    cx: cx,
    cy: "200",
    r: "3",
    fill: "#5a5470"
  }))), /*#__PURE__*/React.createElement("path", {
    d: "M 30,140 L 250,140 L 260,168 L 20,168 Z",
    fill: "#1A1530"
  }), /*#__PURE__*/React.createElement("rect", {
    x: "36",
    y: "146",
    width: "208",
    height: "3",
    fill: "rgba(255,255,255,.1)",
    rx: "1"
  }), [60, 100, 140, 180, 220].map((cx, i) => /*#__PURE__*/React.createElement("circle", {
    key: i,
    cx: cx,
    cy: "156",
    r: "3",
    fill: "#5a5470"
  })), /*#__PURE__*/React.createElement("path", {
    d: "M 70,140 Q 140,40 210,140 Z",
    fill: "url(#domeG)"
  }), /*#__PURE__*/React.createElement("path", {
    d: "M 85,128 Q 110,76 138,68",
    stroke: "rgba(255,255,255,.45)",
    strokeWidth: "4",
    fill: "none",
    strokeLinecap: "round"
  }), /*#__PURE__*/React.createElement("ellipse", {
    cx: "140",
    cy: "138",
    rx: "74",
    ry: "10",
    fill: "#0A0820"
  }), /*#__PURE__*/React.createElement("ellipse", {
    cx: "140",
    cy: "135",
    rx: "74",
    ry: "10",
    fill: "#1A1530"
  }), /*#__PURE__*/React.createElement("ellipse", {
    cx: "140",
    cy: "134",
    rx: "68",
    ry: "6",
    fill: "#3a3358"
  }), /*#__PURE__*/React.createElement("path", {
    d: "M 75,138 Q 140,52 205,138",
    stroke: "rgba(0,0,0,.18)",
    strokeWidth: "1",
    fill: "none"
  }), /*#__PURE__*/React.createElement("g", {
    transform: "translate(170 96)"
  }, /*#__PURE__*/React.createElement("rect", {
    x: "-18",
    y: "-18",
    width: "36",
    height: "36",
    rx: "6",
    fill: "#fff"
  }), /*#__PURE__*/React.createElement("rect", {
    x: "-12",
    y: "-12",
    width: "24",
    height: "6",
    fill: "#F37327"
  }), /*#__PURE__*/React.createElement("rect", {
    x: "-12",
    y: "-3",
    width: "16",
    height: "6",
    fill: "#F37327"
  }), /*#__PURE__*/React.createElement("rect", {
    x: "-12",
    y: "6",
    width: "24",
    height: "6",
    fill: "#F37327"
  })), /*#__PURE__*/React.createElement("line", {
    x1: "100",
    y1: "80",
    x2: "92",
    y2: "36",
    stroke: "#1A1530",
    strokeWidth: "2"
  }), /*#__PURE__*/React.createElement("circle", {
    cx: "92",
    cy: "34",
    r: "3",
    fill: "#F33F3F"
  }), /*#__PURE__*/React.createElement("circle", {
    cx: "62",
    cy: "156",
    r: "6",
    fill: "#FFE6A8"
  }), /*#__PURE__*/React.createElement("circle", {
    cx: "62",
    cy: "156",
    r: "3",
    fill: "#FFF"
  }));
}
function CannonBarrel() {
  return /*#__PURE__*/React.createElement("svg", {
    viewBox: "0 0 220 60",
    "aria-hidden": true
  }, /*#__PURE__*/React.createElement("defs", null, /*#__PURE__*/React.createElement("linearGradient", {
    id: "barG",
    x1: "0",
    y1: "0",
    x2: "0",
    y2: "1"
  }, /*#__PURE__*/React.createElement("stop", {
    offset: "0",
    stopColor: "#3a3358"
  }), /*#__PURE__*/React.createElement("stop", {
    offset: "0.5",
    stopColor: "#1A1530"
  }), /*#__PURE__*/React.createElement("stop", {
    offset: "1",
    stopColor: "#0A0820"
  })), /*#__PURE__*/React.createElement("linearGradient", {
    id: "muzzleG",
    x1: "0",
    y1: "0",
    x2: "0",
    y2: "1"
  }, /*#__PURE__*/React.createElement("stop", {
    offset: "0",
    stopColor: "#5a5470"
  }), /*#__PURE__*/React.createElement("stop", {
    offset: "1",
    stopColor: "#2A2547"
  }))), /*#__PURE__*/React.createElement("rect", {
    x: "14",
    y: "22",
    width: "36",
    height: "20",
    rx: "4",
    fill: "#1A1530"
  }), /*#__PURE__*/React.createElement("rect", {
    x: "14",
    y: "22",
    width: "36",
    height: "3",
    fill: "rgba(255,255,255,.18)"
  }), /*#__PURE__*/React.createElement("rect", {
    x: "40",
    y: "26",
    width: "150",
    height: "12",
    rx: "4",
    fill: "url(#barG)"
  }), /*#__PURE__*/React.createElement("rect", {
    x: "42",
    y: "27",
    width: "146",
    height: "2",
    rx: "1",
    fill: "rgba(255,255,255,.25)"
  }), /*#__PURE__*/React.createElement("rect", {
    x: "184",
    y: "22",
    width: "22",
    height: "20",
    rx: "3",
    fill: "url(#muzzleG)"
  }), /*#__PURE__*/React.createElement("rect", {
    x: "188",
    y: "26",
    width: "2",
    height: "12",
    fill: "#0A0820"
  }), /*#__PURE__*/React.createElement("rect", {
    x: "194",
    y: "26",
    width: "2",
    height: "12",
    fill: "#0A0820"
  }), /*#__PURE__*/React.createElement("rect", {
    x: "200",
    y: "26",
    width: "2",
    height: "12",
    fill: "#0A0820"
  }), /*#__PURE__*/React.createElement("rect", {
    x: "22",
    y: "14",
    width: "6",
    height: "10",
    fill: "#1A1530"
  }), /*#__PURE__*/React.createElement("circle", {
    cx: "25",
    cy: "13",
    r: "3",
    fill: "#F33F3F"
  }));
}
function Mountains() {
  return /*#__PURE__*/React.createElement("div", {
    className: "gm-horizon"
  }, /*#__PURE__*/React.createElement("svg", {
    viewBox: "0 0 1600 240",
    preserveAspectRatio: "none",
    "aria-hidden": true
  }, /*#__PURE__*/React.createElement("path", {
    d: "M0,150 L120,90 L240,130 L380,70 L520,118 L660,82 L800,124 L940,86 L1080,128 L1220,94 L1360,126 L1500,90 L1600,118 L1600,240 L0,240 Z",
    fill: "#B6B1E0"
  }), /*#__PURE__*/React.createElement("path", {
    d: "M0,200 L160,140 L300,180 L440,118 L580,158 L720,128 L860,168 L1000,134 L1140,170 L1280,140 L1420,176 L1560,148 L1600,164 L1600,240 L0,240 Z",
    fill: "#8E89C8"
  })));
}
function SkyZ() {
  return /*#__PURE__*/React.createElement("div", {
    className: "gm-sky-z",
    "aria-hidden": true
  }, /*#__PURE__*/React.createElement("div", {
    className: "z",
    style: {
      top: "6%",
      left: "8%",
      width: "26%",
      background: "rgba(255,255,255,.65)"
    }
  }), /*#__PURE__*/React.createElement("div", {
    className: "z",
    style: {
      top: "10%",
      left: "46%",
      width: "20%",
      background: "rgba(255,255,255,.5)"
    }
  }), /*#__PURE__*/React.createElement("div", {
    className: "z",
    style: {
      top: "18%",
      left: "22%",
      width: "14%",
      background: "rgba(255,255,255,.35)"
    }
  }), /*#__PURE__*/React.createElement("div", {
    className: "z",
    style: {
      top: "26%",
      left: "62%",
      width: "22%",
      background: "rgba(255,255,255,.4)"
    }
  }));
}
function Heart({
  lost
}) {
  return /*#__PURE__*/React.createElement("svg", {
    viewBox: "0 0 24 24",
    className: lost ? "lost" : ""
  }, /*#__PURE__*/React.createElement("path", {
    fill: "#F33F3F",
    d: "M12 21s-7.5-4.7-9.6-9.5C.9 7.7 3.5 4 7.2 4c2 0 3.6 1 4.8 2.6C13.2 5 14.8 4 16.8 4c3.7 0 6.3 3.7 4.8 7.5C19.5 16.3 12 21 12 21z"
  }));
}
const I = {
  pause: () => /*#__PURE__*/React.createElement("svg", {
    viewBox: "0 0 24 24",
    width: "16",
    height: "16",
    fill: "currentColor"
  }, /*#__PURE__*/React.createElement("path", {
    d: "M9 5h2v14H9zM13 5h2v14h-2z"
  })),
  speaker: () => /*#__PURE__*/React.createElement("svg", {
    viewBox: "0 0 24 24",
    width: "18",
    height: "18",
    fill: "currentColor"
  }, /*#__PURE__*/React.createElement("path", {
    d: "M3 10v4a1 1 0 0 0 1 1h3l4 3.5a1 1 0 0 0 1.6-.8V6.3a1 1 0 0 0-1.6-.8L7 9H4a1 1 0 0 0-1 1Z"
  })),
  speakerMute: () => /*#__PURE__*/React.createElement("svg", {
    viewBox: "0 0 24 24",
    width: "18",
    height: "18",
    fill: "none",
    stroke: "currentColor",
    strokeWidth: "2.2",
    strokeLinecap: "round",
    strokeLinejoin: "round"
  }, /*#__PURE__*/React.createElement("path", {
    d: "M3 10v4a1 1 0 0 0 1 1h3l4 3.5a1 1 0 0 0 1.6-.8V6.3a1 1 0 0 0-1.6-.8L7 9H4a1 1 0 0 0-1 1Z",
    fill: "currentColor",
    stroke: "none"
  }), /*#__PURE__*/React.createElement("path", {
    d: "M16 8l5 5M21 8l-5 5"
  })),
  expand: () => /*#__PURE__*/React.createElement("svg", {
    viewBox: "0 0 24 24",
    width: "18",
    height: "18",
    fill: "none",
    stroke: "currentColor",
    strokeWidth: "2.2",
    strokeLinecap: "round",
    strokeLinejoin: "round"
  }, /*#__PURE__*/React.createElement("path", {
    d: "M4 9V4h5M20 9V4h-5M4 15v5h5M20 15v5h-5"
  })),
  home: () => /*#__PURE__*/React.createElement("svg", {
    viewBox: "0 0 24 24",
    width: "20",
    height: "20",
    fill: "none",
    stroke: "currentColor",
    strokeWidth: "2.2",
    strokeLinecap: "round",
    strokeLinejoin: "round"
  }, /*#__PURE__*/React.createElement("path", {
    d: "M3 11l9-8 9 8"
  }), /*#__PURE__*/React.createElement("path", {
    d: "M5 10v10h14V10"
  }), /*#__PURE__*/React.createElement("path", {
    d: "M10 20v-6h4v6"
  })),
  trophy: () => /*#__PURE__*/React.createElement("svg", {
    viewBox: "0 0 24 24",
    width: "22",
    height: "22",
    fill: "none",
    stroke: "currentColor",
    strokeWidth: "2.2",
    strokeLinecap: "round",
    strokeLinejoin: "round"
  }, /*#__PURE__*/React.createElement("path", {
    d: "M8 21h8M12 17v4M7 4h10v5a5 5 0 0 1-10 0V4z"
  }), /*#__PURE__*/React.createElement("path", {
    d: "M7 6H4v2a3 3 0 0 0 3 3M17 6h3v2a3 3 0 0 1-3 3"
  }))
};
function ScopeIcon() {
  return /*#__PURE__*/React.createElement("svg", {
    viewBox: "0 0 32 32",
    fill: "none",
    stroke: "#F37327",
    strokeWidth: "2.2"
  }, /*#__PURE__*/React.createElement("circle", {
    cx: "16",
    cy: "16",
    r: "11"
  }), /*#__PURE__*/React.createElement("path", {
    d: "M16 2v6 M16 24v6 M2 16h6 M24 16h6",
    strokeLinecap: "round"
  }), /*#__PURE__*/React.createElement("circle", {
    cx: "16",
    cy: "16",
    r: "2",
    fill: "#F37327",
    stroke: "none"
  }));
}

/* ──────────────────────────────────────────────
   Stage scaler: fits 1600×900 into viewport, letterboxing.
   ────────────────────────────────────────────── */
function useStageScale(designW, designH) {
  const [scale, setScale] = useState(1);
  useLayoutEffect(() => {
    const recalc = () => {
      const w = window.innerWidth;
      const h = window.innerHeight;
      setScale(Math.min(w / designW, h / designH));
    };
    recalc();
    window.addEventListener("resize", recalc);
    return () => window.removeEventListener("resize", recalc);
  }, [designW, designH]);
  return scale;
}

/* ──────────────────────────────────────────────
   Upload screen — load Excel/CSV
   ────────────────────────────────────────────── */
function UploadScreen({
  onLoad
}) {
  const [drag, setDrag] = useState(false);
  const [err, setErr] = useState(null);
  const [busy, setBusy] = useState(false);
  const inputRef = useRef(null);
  const handle = useCallback(async file => {
    if (!file) return;
    setErr(null);
    setBusy(true);
    try {
      const entries = await parseSpreadsheet(file);
      onLoad(entries, file.name);
    } catch (e) {
      setErr(e.message || "שגיאה בקריאת הקובץ");
    } finally {
      setBusy(false);
    }
  }, [onLoad]);
  const onDrop = e => {
    e.preventDefault();
    setDrag(false);
    const f = e.dataTransfer?.files?.[0];
    if (f) handle(f);
  };
  return /*#__PURE__*/React.createElement("div", {
    className: "gm-app gm-up-app"
  }, /*#__PURE__*/React.createElement("div", {
    className: "gm-up-wrap"
  }, /*#__PURE__*/React.createElement("div", {
    className: "gm-up-card"
  }, /*#__PURE__*/React.createElement("div", {
    className: "gm-up-eye"
  }, "eazy \xB7 \u05DE\u05E9\u05D7\u05E7 \u05DE\u05D9\u05DC\u05D9\u05DD"), /*#__PURE__*/React.createElement("h1", {
    className: "gm-up-h1"
  }, "\u05D8\u05E2\u05E0\u05D5 \u05DE\u05D9\u05DC\u05D5\u05DF \u05DC\u05DE\u05E9\u05D7\u05E7."), /*#__PURE__*/React.createElement("p", {
    className: "gm-up-sub"
  }, "\u05E7\u05D5\u05D1\u05E5 Excel \u05D0\u05D5 CSV. \u05E2\u05DE\u05D5\u05D3\u05D4 B = \u05DE\u05D9\u05DC\u05D4 \u05D1\u05D0\u05E0\u05D2\u05DC\u05D9\u05EA, \u05E2\u05DE\u05D5\u05D3\u05D4 C = \u05E4\u05D9\u05E8\u05D5\u05E9 \u05D1\u05E2\u05D1\u05E8\u05D9\u05EA. \u05E0\u05D1\u05D7\u05E8 \u05D1\u05DB\u05DC \u05E1\u05D9\u05D1\u05D5\u05D1 4 \u05DE\u05D9\u05DC\u05D9\u05DD: \u05D0\u05D7\u05EA \u05D4\u05E0\u05DB\u05D5\u05E0\u05D4, \u05E9\u05DC\u05D5\u05E9 \u05D0\u05D7\u05E8\u05D5\u05EA \u05DE\u05D4\u05DE\u05D9\u05DC\u05D5\u05DF \u05DB\u05DE\u05E1\u05D9\u05D7\u05D9\u05DD."), /*#__PURE__*/React.createElement("div", {
    className: "gm-dropzone " + (drag ? "drag" : ""),
    onClick: () => inputRef.current?.click(),
    onDragOver: e => {
      e.preventDefault();
      setDrag(true);
    },
    onDragLeave: () => setDrag(false),
    onDrop: onDrop
  }, /*#__PURE__*/React.createElement("div", {
    className: "gm-dz-icon"
  }, /*#__PURE__*/React.createElement("svg", {
    viewBox: "0 0 32 32",
    width: "42",
    height: "42",
    fill: "none",
    stroke: "#F37327",
    strokeWidth: "2",
    strokeLinecap: "round",
    strokeLinejoin: "round"
  }, /*#__PURE__*/React.createElement("path", {
    d: "M16 4v18"
  }), /*#__PURE__*/React.createElement("path", {
    d: "M9 11l7-7 7 7"
  }), /*#__PURE__*/React.createElement("path", {
    d: "M4 26h24"
  }))), /*#__PURE__*/React.createElement("div", {
    className: "gm-dz-title"
  }, "\u05D2\u05E8\u05E8\u05D5 \u05DC\u05DB\u05D0\u05DF \u05D0\u05D5 \u05DC\u05D7\u05E6\u05D5"), /*#__PURE__*/React.createElement("div", {
    className: "gm-dz-sub"
  }, ".xlsx / .xls / .csv"), /*#__PURE__*/React.createElement("input", {
    ref: inputRef,
    type: "file",
    accept: ".xlsx,.xls,.csv,application/vnd.ms-excel,application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",
    style: {
      display: "none"
    },
    onChange: e => handle(e.target.files[0])
  })), busy && /*#__PURE__*/React.createElement("div", {
    className: "gm-up-info"
  }, "\u05E7\u05D5\u05E8\u05D0\u05D9 \u05D0\u05EA \u05D4\u05E7\u05D5\u05D1\u05E5\u2026"), err && /*#__PURE__*/React.createElement("div", {
    className: "gm-up-err"
  }, err), /*#__PURE__*/React.createElement("div", {
    className: "gm-up-or"
  }, "\u2014 \u05D0\u05D5 \u2014"), /*#__PURE__*/React.createElement("button", {
    className: "gm-up-btn-ghost",
    onClick: () => onLoad(SAMPLE_DICT, "מילון לדוגמה")
  }, "\u05D4\u05EA\u05D7\u05D9\u05DC\u05D5 \u05E2\u05DD \u05DE\u05D9\u05DC\u05D5\u05DF \u05D3\u05D5\u05D2\u05DE\u05D4 (", SAMPLE_DICT.length, " \u05DE\u05D9\u05DC\u05D9\u05DD)"), /*#__PURE__*/React.createElement("div", {
    className: "gm-up-format"
  }, /*#__PURE__*/React.createElement("div", {
    className: "gm-fmt-title"
  }, "\u05E4\u05D5\u05E8\u05DE\u05D8 \u05D4\u05E7\u05D5\u05D1\u05E5:"), /*#__PURE__*/React.createElement("table", null, /*#__PURE__*/React.createElement("thead", null, /*#__PURE__*/React.createElement("tr", null, /*#__PURE__*/React.createElement("th", null, "A"), /*#__PURE__*/React.createElement("th", null, "B \u2014 English"), /*#__PURE__*/React.createElement("th", null, "C \u2014 \u05E2\u05D1\u05E8\u05D9\u05EA"))), /*#__PURE__*/React.createElement("tbody", null, /*#__PURE__*/React.createElement("tr", null, /*#__PURE__*/React.createElement("td", null, "1"), /*#__PURE__*/React.createElement("td", {
    dir: "ltr"
  }, "enhance"), /*#__PURE__*/React.createElement("td", null, "\u05DC\u05D4\u05E2\u05E6\u05D9\u05DD, \u05DC\u05E9\u05E4\u05E8")), /*#__PURE__*/React.createElement("tr", null, /*#__PURE__*/React.createElement("td", null, "2"), /*#__PURE__*/React.createElement("td", {
    dir: "ltr"
  }, "mitigate"), /*#__PURE__*/React.createElement("td", null, "\u05DC\u05D4\u05E7\u05DC, \u05DC\u05DE\u05EA\u05DF")), /*#__PURE__*/React.createElement("tr", null, /*#__PURE__*/React.createElement("td", null, "3"), /*#__PURE__*/React.createElement("td", {
    dir: "ltr"
  }, "ambiguous"), /*#__PURE__*/React.createElement("td", null, "\u05D3\u05D5-\u05DE\u05E9\u05DE\u05E2\u05D9")))), /*#__PURE__*/React.createElement("div", {
    className: "gm-fmt-note"
  }, "\u05E9\u05D5\u05E8\u05EA \u05DB\u05D5\u05EA\u05E8\u05EA \u05EA\u05D6\u05D5\u05D4\u05D4 \u05D0\u05D5\u05D8\u05D5\u05DE\u05D8\u05D9\u05EA. \u05E2\u05DE\u05D5\u05D3\u05D4 A \u05DE\u05EA\u05E2\u05DC\u05DE\u05D9\u05DD \u05DE\u05DE\u05E0\u05D4 (\u05DE\u05E1\u05E4\u05D5\u05E8 / \u05DE\u05D6\u05D4\u05D4).")))));
}

/* ──────────────────────────────────────────────
   Intro screen — first thing the user sees
   ───────────────────────────────────────────── */
function IntroScreen({
  onStart,
  toggleFullscreen,
  muted,
  toggleMute
}) {
  const scale = useStageScale(1600, 900);
  return /*#__PURE__*/React.createElement("div", {
    className: "gm-app"
  }, /*#__PURE__*/React.createElement("div", {
    className: "gm-stage gm-intro-stage",
    style: {
      "--gm-scale": scale
    }
  }, /*#__PURE__*/React.createElement(SkyZ, null), /*#__PURE__*/React.createElement(Mountains, null), /*#__PURE__*/React.createElement("div", {
    className: "gm-ground"
  }), /*#__PURE__*/React.createElement("div", {
    className: "gm-hud-brand"
  }, /*#__PURE__*/React.createElement("img", {
    src: "assets/ez-icon.png",
    alt: ""
  }), /*#__PURE__*/React.createElement("span", null, "eazy")), /*#__PURE__*/React.createElement("div", {
    className: "gm-cannon gm-intro-cannon"
  }, /*#__PURE__*/React.createElement(CannonBase, null), /*#__PURE__*/React.createElement("div", {
    className: "barrel-wrap"
  }, /*#__PURE__*/React.createElement("svg", {
    style: {
      position: "absolute",
      width: "220px",
      height: "60px",
      top: "-30px",
      left: "-30px",
      transformOrigin: "30px 30px",
      transform: `rotate(-22deg)`,
      overflow: "visible"
    },
    viewBox: "0 0 220 60"
  }, /*#__PURE__*/React.createElement("defs", null, /*#__PURE__*/React.createElement("linearGradient", {
    id: "barG3",
    x1: "0",
    y1: "0",
    x2: "0",
    y2: "1"
  }, /*#__PURE__*/React.createElement("stop", {
    offset: "0",
    stopColor: "#3a3358"
  }), /*#__PURE__*/React.createElement("stop", {
    offset: "0.5",
    stopColor: "#1A1530"
  }), /*#__PURE__*/React.createElement("stop", {
    offset: "1",
    stopColor: "#0A0820"
  })), /*#__PURE__*/React.createElement("linearGradient", {
    id: "muzzleG3",
    x1: "0",
    y1: "0",
    x2: "0",
    y2: "1"
  }, /*#__PURE__*/React.createElement("stop", {
    offset: "0",
    stopColor: "#5a5470"
  }), /*#__PURE__*/React.createElement("stop", {
    offset: "1",
    stopColor: "#2A2547"
  }))), /*#__PURE__*/React.createElement("rect", {
    x: "14",
    y: "22",
    width: "36",
    height: "20",
    rx: "4",
    fill: "#1A1530"
  }), /*#__PURE__*/React.createElement("rect", {
    x: "14",
    y: "22",
    width: "36",
    height: "3",
    fill: "rgba(255,255,255,.18)"
  }), /*#__PURE__*/React.createElement("rect", {
    x: "40",
    y: "26",
    width: "150",
    height: "12",
    rx: "4",
    fill: "url(#barG3)"
  }), /*#__PURE__*/React.createElement("rect", {
    x: "42",
    y: "27",
    width: "146",
    height: "2",
    rx: "1",
    fill: "rgba(255,255,255,.25)"
  }), /*#__PURE__*/React.createElement("rect", {
    x: "184",
    y: "22",
    width: "22",
    height: "20",
    rx: "3",
    fill: "url(#muzzleG3)"
  }), /*#__PURE__*/React.createElement("rect", {
    x: "188",
    y: "26",
    width: "2",
    height: "12",
    fill: "#0A0820"
  }), /*#__PURE__*/React.createElement("rect", {
    x: "194",
    y: "26",
    width: "2",
    height: "12",
    fill: "#0A0820"
  }), /*#__PURE__*/React.createElement("rect", {
    x: "200",
    y: "26",
    width: "2",
    height: "12",
    fill: "#0A0820"
  }), /*#__PURE__*/React.createElement("rect", {
    x: "22",
    y: "14",
    width: "6",
    height: "10",
    fill: "#1A1530"
  }), /*#__PURE__*/React.createElement("circle", {
    cx: "25",
    cy: "13",
    r: "3",
    fill: "#F33F3F"
  })))), /*#__PURE__*/React.createElement("div", {
    className: "gm-intro-text"
  }, /*#__PURE__*/React.createElement("div", {
    className: "gm-intro-eye"
  }, "\u05DE\u05E9\u05D7\u05E7 \u05D0\u05E0\u05D2\u05DC\u05D9\u05EA \u05DE\u05D1\u05D9\u05EA eazy"), /*#__PURE__*/React.createElement("h1", {
    className: "gm-intro-title"
  }, "\u05EA\u05D5\u05EA\u05D7 \u05DE\u05D9\u05DC\u05D9\u05DD", /*#__PURE__*/React.createElement("span", {
    className: "dot"
  }, ".")), /*#__PURE__*/React.createElement("p", {
    className: "gm-intro-lead"
  }, "\u05DC\u05E8\u05E9\u05D5\u05EA\u05DA \u05EA\u05D5\u05EA\u05D7 \u05DE\u05D9\u05DC\u05D9\u05DD \u05D5\u05D4\u05D9\u05D3\u05E2 \u05E9\u05DC\u05DA \u05D1\u05D0\u05E0\u05D2\u05DC\u05D9\u05EA."), /*#__PURE__*/React.createElement("p", {
    className: "gm-intro-body"
  }, "\u05D1\u05EA\u05D7\u05EA\u05D9\u05EA \u05DE\u05D5\u05E4\u05D9\u05E2\u05D4 \u05DE\u05D9\u05DC\u05D4 \u05D1\u05D0\u05E0\u05D2\u05DC\u05D9\u05EA. \u05DE\u05DB\u05D5\u05D5\u05E0\u05D9\u05DD \u05D0\u05DC \u05D4\u05E4\u05D9\u05E8\u05D5\u05E9 \u05D4\u05DE\u05EA\u05D0\u05D9\u05DD \u05D5\u05DE\u05E9\u05DE\u05D9\u05D3\u05D9\u05DD \u05D0\u05EA \u05D4\u05D8\u05D9\u05DC \u05DC\u05E4\u05E0\u05D9 \u05E9\u05D9\u05D2\u05D9\u05E2 \u05D0\u05DC\u05D9\u05DA. \u05D1\u05D4\u05E6\u05DC\u05D7\u05D4!")), /*#__PURE__*/React.createElement("button", {
    className: "gm-intro-cta",
    onClick: onStart
  }, /*#__PURE__*/React.createElement("span", null, "\u05DC\u05D4\u05EA\u05D7\u05D9\u05DC!"), /*#__PURE__*/React.createElement("svg", {
    viewBox: "0 0 24 24",
    width: "28",
    height: "28",
    fill: "none",
    stroke: "currentColor",
    strokeWidth: "2.6",
    strokeLinecap: "round",
    strokeLinejoin: "round"
  }, /*#__PURE__*/React.createElement("path", {
    d: "M19 12H5"
  }), /*#__PURE__*/React.createElement("path", {
    d: "M12 19l-7-7 7-7"
  }))), /*#__PURE__*/React.createElement("div", {
    className: "gm-foot-actions"
  }, /*#__PURE__*/React.createElement("button", {
    className: "foot-btn",
    onClick: () => {
      try {
        window.top.location.href = "https://www.ezway.co.il";
      } catch (e) {
        window.open("https://www.ezway.co.il", "_top");
      }
    },
    title: "\u05D0\u05EA\u05E8 \u05D4\u05D1\u05D9\u05EA"
  }, /*#__PURE__*/React.createElement(I.home, null)), /*#__PURE__*/React.createElement("button", {
    className: "foot-btn",
    onClick: toggleFullscreen,
    title: "\u05DE\u05E1\u05DA \u05DE\u05DC\u05D0"
  }, /*#__PURE__*/React.createElement(I.expand, null)), /*#__PURE__*/React.createElement("button", {
    className: "foot-btn" + (muted ? " muted" : ""),
    onClick: toggleMute,
    title: muted ? "השמע צלילים" : "השתק צלילים"
  }, muted ? /*#__PURE__*/React.createElement(I.speakerMute, null) : /*#__PURE__*/React.createElement(I.speaker, null)))));
}
function EndScreen({
  score,
  missedWords,
  onRestart
}) {
  const [submitted, setSubmitted] = useState(false);
  const [name, setName] = useState("");
  const [board, setBoard] = useState(() => getLeaderboard());
  const [showLb, setShowLb] = useState(false);
  const qualifies = qualifiesForLeaderboard(score) && !submitted;
  const submitName = () => {
    const newBoard = addToLeaderboard(name.trim() || "אנונימי", score);
    setBoard(newBoard);
    setSubmitted(true);
    setShowLb(true); // auto-open to show new ranking
  };
  return /*#__PURE__*/React.createElement("div", {
    className: "gm-app gm-end-app"
  }, /*#__PURE__*/React.createElement("div", {
    className: "gm-end-wrap"
  }, /*#__PURE__*/React.createElement("div", {
    className: "gm-end-card"
  }, /*#__PURE__*/React.createElement("div", {
    className: "gm-end-header"
  }, /*#__PURE__*/React.createElement("div", {
    className: "gm-end-eye"
  }, "\u05E1\u05D5\u05E3 \u05E1\u05D9\u05D1\u05D5\u05D1"), /*#__PURE__*/React.createElement("div", {
    className: "gm-end-brand"
  }, /*#__PURE__*/React.createElement("img", {
    src: "assets/ez-icon.png",
    alt: ""
  }), /*#__PURE__*/React.createElement("span", null, "eazy"))), /*#__PURE__*/React.createElement("h1", {
    className: "gm-end-h1"
  }, /*#__PURE__*/React.createElement("span", null, "\u05D4\u05E9\u05D2\u05EA"), /*#__PURE__*/React.createElement("span", {
    className: "num"
  }, score), /*#__PURE__*/React.createElement("span", null, "\u05E0\u05E7\u05D5\u05D3\u05D5\u05EA."), /*#__PURE__*/React.createElement("span", {
    className: "trail"
  }, missedWords.length > 0 ? "אלו המילים שפספסת:" : "כל הכבוד — לא פספסת אף מילה!")), missedWords.length > 0 && /*#__PURE__*/React.createElement("div", {
    className: "gm-end-list"
  }, missedWords.map((w, i) => /*#__PURE__*/React.createElement("div", {
    key: i,
    className: "gm-end-row"
  }, /*#__PURE__*/React.createElement("div", {
    className: "gm-end-en"
  }, String(w.en).toUpperCase()), /*#__PURE__*/React.createElement("div", {
    className: "gm-end-divider"
  }), /*#__PURE__*/React.createElement("div", {
    className: "gm-end-he"
  }, w.he)))), qualifies && /*#__PURE__*/React.createElement("div", {
    className: "gm-lb-prompt"
  }, /*#__PURE__*/React.createElement("span", null, /*#__PURE__*/React.createElement(I.trophy, null), " \u05E0\u05DB\u05E0\u05E1\u05EA \u05DC\u05D8\u05D1\u05DC\u05EA \u05D4\u05E9\u05D9\u05D0\u05D9\u05DD!  \u05D0\u05D9\u05DA \u05DC\u05E7\u05E8\u05D5\u05D0 \u05DC\u05DA?"), /*#__PURE__*/React.createElement("input", {
    className: "gm-lb-input",
    type: "text",
    placeholder: "\u05D4\u05E9\u05DD \u05E9\u05DC\u05DA",
    value: name,
    onChange: e => setName(e.target.value),
    onKeyDown: e => e.key === 'Enter' && submitName(),
    maxLength: 20,
    autoFocus: true
  }), /*#__PURE__*/React.createElement("button", {
    className: "gm-lb-save",
    onClick: submitName
  }, "\u05E9\u05DE\u05D5\u05E8")), /*#__PURE__*/React.createElement("div", {
    className: "gm-end-buttons"
  }, /*#__PURE__*/React.createElement("button", {
    className: "gm-end-cta secondary",
    onClick: () => setShowLb(true)
  }, /*#__PURE__*/React.createElement(I.trophy, null), /*#__PURE__*/React.createElement("span", null, "\u05D8\u05D1\u05DC\u05EA \u05D4\u05E9\u05D9\u05D0\u05D9\u05DD")), /*#__PURE__*/React.createElement("button", {
    className: "gm-end-cta",
    onClick: onRestart
  }, /*#__PURE__*/React.createElement("span", {
    className: "cta-icon",
    "aria-hidden": true
  }, /*#__PURE__*/React.createElement("svg", {
    viewBox: "0 0 36 24",
    fill: "none"
  }, /*#__PURE__*/React.createElement("ellipse", {
    cx: "12",
    cy: "20",
    rx: "11",
    ry: "3",
    fill: "rgba(0,0,0,.25)"
  }), /*#__PURE__*/React.createElement("path", {
    d: "M 4,17 Q 8,8 14,8 L 14,17 Z",
    fill: "#fff"
  }), /*#__PURE__*/React.createElement("rect", {
    x: "13",
    y: "9",
    width: "20",
    height: "7",
    rx: "2",
    fill: "#fff"
  }), /*#__PURE__*/React.createElement("rect", {
    x: "30",
    y: "7",
    width: "5",
    height: "11",
    rx: "1.5",
    fill: "#fff"
  }))), /*#__PURE__*/React.createElement("span", null, "\u05D9\u05D5\u05E6\u05D0\u05D9\u05DD \u05DC\u05E1\u05D9\u05D1\u05D5\u05D1 \u05E0\u05D5\u05E1\u05E3 \u05E2\u05DD \u05D4\u05EA\u05D5\u05EA\u05D7?"))))), showLb && /*#__PURE__*/React.createElement("div", {
    className: "gm-lb-modal",
    onClick: () => setShowLb(false)
  }, /*#__PURE__*/React.createElement("div", {
    className: "gm-lb-modal-card",
    onClick: e => e.stopPropagation()
  }, /*#__PURE__*/React.createElement("button", {
    className: "gm-lb-close",
    onClick: () => setShowLb(false),
    "aria-label": "\u05E1\u05D2\u05D5\u05E8"
  }, "\xD7"), /*#__PURE__*/React.createElement("div", {
    className: "gm-lb-title"
  }, /*#__PURE__*/React.createElement(I.trophy, null), /*#__PURE__*/React.createElement("span", null, "\u05D8\u05D1\u05DC\u05EA \u05D4\u05E9\u05D9\u05D0\u05D9\u05DD")), board.length === 0 ? /*#__PURE__*/React.createElement("div", {
    className: "gm-lb-empty"
  }, "\u05E2\u05D3\u05D9\u05D9\u05DF \u05D0\u05D9\u05DF \u05E9\u05D9\u05D0\u05D9\u05DD. \u05D0\u05EA\u05D4 \u05D9\u05DB\u05D5\u05DC \u05DC\u05D4\u05D9\u05D5\u05EA \u05D4\u05E8\u05D0\u05E9\u05D5\u05DF.") : /*#__PURE__*/React.createElement("ol", {
    className: "gm-lb-list"
  }, board.map((entry, i) => /*#__PURE__*/React.createElement("li", {
    key: i,
    className: "gm-lb-row " + (submitted && entry.score === score && entry.name === (name.trim() || "אנונימי") ? "you" : "")
  }, /*#__PURE__*/React.createElement("span", {
    className: "rank"
  }, i + 1), /*#__PURE__*/React.createElement("span", {
    className: "name"
  }, entry.name), /*#__PURE__*/React.createElement("span", {
    className: "pts"
  }, entry.score)))))));
}

/* ──────────────────────────────────────────────
   Game
   ────────────────────────────────────────────── */
function QuizGameExport() {
  const [started, setStarted] = useState(false);
  const [dict, setDict] = useState(null);
  const [dictName, setDictName] = useState("");
  const [used, setUsed] = useState([]);
  const [missed, setMissed] = useState([]);
  const [question, setQuestion] = useState(null);
  const [lives, setLives] = useState(3);
  const [score, setScore] = useState(0);
  const [aimed, setAimed] = useState(null);
  const [resolved, setResolved] = useState({});
  const [angle, setAngle] = useState(-18);
  const [shot, setShot] = useState(null);
  const [toast, setToast] = useState(null);
  const [missFx, setMissFx] = useState(false);
  const [recoil, setRecoil] = useState(false);
  const [levelUp, setLevelUp] = useState(false);
  const [muted, setMuted] = useState(Sound.muted);
  // lifelines & bonuses
  const [fiftyAvailable, setFiftyAvailable] = useState(true);
  const [hiddenIdx, setHiddenIdx] = useState(() => new Set());
  const [kitState, setKitState] = useState(null);
  const prevQuestionEnRef = useRef(null);
  const prevLevelRef = useRef(0);
  const stageRef = useRef(null);
  const cannonRef = useRef(null);
  const rocketRefs = useRef([]);
  const scale = useStageScale(1600, 900);

  // ── level system: every 15 questions speeds up + raises points ──
  const level = Math.floor(used.length / 15);
  const rocketDur = Math.max(8, 22 - level * 3); // seconds, min 8s
  const pointsPerHit = 200 + level * 100;
  useEffect(() => {
    if (level > prevLevelRef.current && used.length > 0) {
      setLevelUp(true);
      const t = setTimeout(() => setLevelUp(false), 2600);
      prevLevelRef.current = level;
      return () => clearTimeout(t);
    }
    prevLevelRef.current = level;
  }, [level, used.length]);

  // mouse-tracking aim when idle
  useEffect(() => {
    const stage = stageRef.current;
    const cannon = cannonRef.current;
    if (!stage || !cannon) return;
    const onMove = ev => {
      if (aimed !== null) return; // a shot is in flight
      if (isRoundOver) return;
      const sR = stage.getBoundingClientRect();
      const cR = cannon.getBoundingClientRect();
      const mx = (ev.clientX - sR.left) / scale;
      const my = (ev.clientY - sR.top) / scale;
      const fromX = (cR.left - sR.left + cR.width * 0.5) / scale;
      const fromY = (cR.top - sR.top + cR.height * 0.42) / scale;
      let ang = Math.atan2(my - fromY, mx - fromX) * (180 / Math.PI);
      // clamp barrel rotation
      if (ang < -55) ang = -55;
      if (ang > 20) ang = 20;
      setAngle(ang);
    };
    stage.addEventListener("mousemove", onMove);
    return () => stage.removeEventListener("mousemove", onMove);
  }, [aimed, isRoundOver, scale]);

  // fullscreen toggle — also locks orientation to landscape on mobile
  const toggleFullscreen = useCallback(() => {
    try {
      const target = window.frameElement ? window.frameElement : document.documentElement;
      const doc = window.frameElement ? window.parent.document : document;
      const isFs = doc.fullscreenElement || doc.webkitFullscreenElement;
      if (!isFs) {
        const req = target.requestFullscreen || target.webkitRequestFullscreen || target.mozRequestFullScreen || target.msRequestFullscreen;
        if (req) {
          const p = req.call(target);
          // attempt to lock landscape on mobile devices
          if (p && p.then) {
            p.then(() => {
              try {
                if (screen.orientation && screen.orientation.lock) {
                  screen.orientation.lock('landscape').catch(() => {});
                }
              } catch (e) {}
            }).catch(() => {});
          } else {
            try {
              if (screen.orientation && screen.orientation.lock) {
                screen.orientation.lock('landscape').catch(() => {});
              }
            } catch (e) {}
          }
        }
      } else {
        try {
          if (screen.orientation && screen.orientation.unlock) screen.orientation.unlock();
        } catch (e) {}
        const exit = doc.exitFullscreen || doc.webkitExitFullscreen || doc.mozCancelFullScreen || doc.msExitFullscreen;
        if (exit) exit.call(doc);
      }
    } catch (e) {/* permission blocked in iframe — silent */}
  }, []);

  // mute toggle — controls both background music and sound FX
  const toggleMute = useCallback(() => {
    const next = !Sound.muted;
    Sound.setMuted(next);
    setMuted(next);
  }, []);

  // hydrate dictionary — bundled words.js takes precedence over localStorage
  useEffect(() => {
    if (window.GAME_DICTIONARY && Array.isArray(window.GAME_DICTIONARY) && window.GAME_DICTIONARY.length >= 4) {
      setDict(window.GAME_DICTIONARY);
      setDictName("מילון המשחק");
      return;
    }
    try {
      const raw = localStorage.getItem(DICT_STORAGE_KEY);
      if (raw) {
        const arr = JSON.parse(raw);
        if (Array.isArray(arr) && arr.length >= 4) {
          setDict(arr);
          setDictName(localStorage.getItem(DICT_NAME_KEY) || "");
        }
      }
    } catch (e) {}
  }, []);

  // draw a question whenever dict changes or used grows
  useEffect(() => {
    if (!dict) return;
    const available = dict.map((_, i) => i).filter(i => !used.includes(i));
    if (available.length === 0) {
      setQuestion(null);
      return;
    }
    const correctIdx = available[Math.floor(Math.random() * available.length)];
    setQuestion({
      ...buildQuestion(dict, correctIdx),
      correctDictIdx: correctIdx
    });
  }, [dict, used]);
  const loadDict = useCallback((entries, name) => {
    setDict(entries);
    setDictName(name);
    setUsed([]);
    setMissed([]);
    setLives(3);
    setScore(0);
    setResolved({});
    setAimed(null);
    try {
      localStorage.setItem(DICT_STORAGE_KEY, JSON.stringify(entries));
      localStorage.setItem(DICT_NAME_KEY, name);
    } catch (e) {}
  }, []);
  const resetDict = useCallback(() => {
    setDict(null);
    setDictName("");
    setUsed([]);
    setMissed([]);
    setLives(3);
    setScore(0);
    setResolved({});
    setAimed(null);
    setQuestion(null);
    try {
      localStorage.removeItem(DICT_STORAGE_KEY);
      localStorage.removeItem(DICT_NAME_KEY);
    } catch (e) {}
  }, []);
  const restartGame = useCallback(() => {
    setUsed([]);
    setMissed([]);
    setLives(3);
    setScore(0);
    setResolved({});
    setAimed(null);
    setFiftyAvailable(true);
    setHiddenIdx(new Set());
    setKitState(null);
    prevLevelRef.current = 0;
    Sound.startMusic();
  }, []);
  const correctIdx = question ? question.options.indexOf(question.correct) : -1;
  const isRoundOver = resolved[correctIdx] === "hit" || lives <= 0;

  // Reset 50/50 hidden distractors whenever a new question appears;
  // every 8th question, drop a first-aid kit (if not full lives + not already showing).
  useEffect(() => {
    if (!question) return;
    if (prevQuestionEnRef.current !== question.en) {
      setHiddenIdx(new Set());
      prevQuestionEnRef.current = question.en;
      if (used.length > 0 && used.length % 8 === 0 && !kitState && lives < 3) {
        setKitState({
          id: Date.now()
        });
      }
    }
  }, [question, used.length, lives, kitState]);

  // 50/50 lifeline: hide 2 of the 3 wrong distractors
  const useFifty = useCallback(() => {
    if (!fiftyAvailable || !question || isRoundOver) return;
    const wrongs = question.options.map((_, i) => i).filter(i => i !== correctIdx);
    const toHide = shuffleArr(wrongs).slice(0, 2);
    setHiddenIdx(new Set(toHide));
    setFiftyAvailable(false);
    Sound.play('fifty');
  }, [fiftyAvailable, question, correctIdx, isRoundOver]);

  // Shooting the first-aid kit grants a life back
  const onKitHit = useCallback(() => {
    if (!kitState) return;
    setLives(l => Math.min(3, l + 1));
    setKitState(null);
    Sound.play('lifegain');
    setToast({
      kind: "win",
      text: "+1 לב · תיק עזרה ראשונה!"
    });
    setTimeout(() => setToast(null), 1800);
  }, [kitState]);

  // Kit auto-vanishes if not shot in time
  useEffect(() => {
    if (!kitState) return;
    const t = setTimeout(() => setKitState(null), 9000);
    return () => clearTimeout(t);
  }, [kitState]);
  const nextQuestion = useCallback(() => {
    if (!question) return;
    setUsed(u => [...u, question.correctDictIdx]);
    setResolved({});
    setAimed(null);
    setAngle(-18);
  }, [question]);
  const onTarget = useCallback(i => {
    if (!question) return;
    if (hiddenIdx.has(i)) return;
    if (resolved[i] || isRoundOver || aimed !== null) return;
    setAimed(i);
    Sound.play('shoot');
    const stage = stageRef.current;
    const cannon = cannonRef.current;
    const target = rocketRefs.current[i];
    if (!stage || !cannon || !target) return;
    const sR = stage.getBoundingClientRect();
    const cR = cannon.getBoundingClientRect();
    const tR = target.getBoundingClientRect();
    const fromX = (cR.left - sR.left + cR.width * 0.5) / scale;
    const fromY = (cR.top - sR.top + cR.height * 0.42) / scale;
    const toX = (tR.left - sR.left + 70) / scale;
    const toY = (tR.top - sR.top + tR.height * 0.5) / scale;
    const ang = Math.atan2(toY - fromY, toX - fromX) * (180 / Math.PI);
    setAngle(ang);
    setTimeout(() => {
      setShot({
        fromX,
        fromY,
        toX,
        toY
      });
      setTimeout(() => {
        const correct = i === correctIdx;
        setResolved(r => ({
          ...r,
          [i]: correct ? "hit" : "missed"
        }));
        if (correct) {
          setScore(s => s + pointsPerHit);
          Sound.play('hit');
          setToast({
            kind: "win",
            text: `פגיעה ישירה. +${pointsPerHit}`
          });
        } else {
          setLives(l => Math.max(0, l - 1));
          setMissed(m => m.includes(question.correctDictIdx) ? m : [...m, question.correctDictIdx]);
          setMissFx(true);
          setTimeout(() => setMissFx(false), 5400);
          setRecoil(true);
          setTimeout(() => setRecoil(false), 500);
          Sound.play('miss');
          setToast({
            kind: "lose",
            text: "פספסת — לב אחד נפל"
          });
          setTimeout(() => {
            setResolved(r => ({
              ...r,
              [correctIdx]: r[correctIdx] || "correct-after"
            }));
          }, 700);
        }
        setShot(null);
        setAimed(null);
        setTimeout(() => setToast(null), 1800);
        // auto-advance to next question
        setTimeout(() => {
          setUsed(u => [...u, question.correctDictIdx]);
          setResolved({});
          setAimed(null);
          setAngle(-18);
        }, correct ? 1400 : 5600);
      }, 380);
    }, 340);
  }, [resolved, isRoundOver, aimed, correctIdx, scale, question, pointsPerHit, hiddenIdx]);

  // Rocket reaches the cannon zone = wrong answer
  const onTravelEnd = useCallback((i, e) => {
    if (e.animationName !== "rocketTravel") return;
    if (!question || resolved[i] || isRoundOver) return;
    setLives(l => Math.max(0, l - 1));
    setMissed(m => m.includes(question.correctDictIdx) ? m : [...m, question.correctDictIdx]);
    setResolved(r => ({
      ...r,
      [i]: "missed",
      [correctIdx]: r[correctIdx] || "correct-after"
    }));
    setMissFx(true);
    setTimeout(() => setMissFx(false), 5400);
    Sound.play('miss');
    setToast({
      kind: "lose",
      text: "הטיל הגיע — לב אחד נפל"
    });
    setTimeout(() => setToast(null), 1800);
    setTimeout(() => {
      setUsed(u => [...u, question.correctDictIdx]);
      setResolved({});
      setAimed(null);
      setAngle(-18);
    }, 5600);
  }, [question, resolved, isRoundOver, correctIdx]);
  let shotEl = null;
  if (shot) {
    const dx = shot.toX - shot.fromX;
    const dy = shot.toY - shot.fromY;
    shotEl = /*#__PURE__*/React.createElement("div", {
      className: "gm-shot active",
      style: {
        left: shot.fromX,
        top: shot.fromY,
        animation: "shotFly .4s linear forwards",
        "--dx": `${dx}px`,
        "--dy": `${dy}px`
      }
    });
  }

  // ── intro first ──
  if (!started) return /*#__PURE__*/React.createElement(IntroScreen, {
    onStart: () => {
      setStarted(true);
      Sound.startMusic();
    },
    toggleFullscreen: toggleFullscreen,
    muted: muted,
    toggleMute: toggleMute
  });

  // ── no dict yet — only shown if bundled words.js missing AND no localStorage ──
  if (!dict) return /*#__PURE__*/React.createElement(UploadScreen, {
    onLoad: loadDict
  });

  // ── game over (lives exhausted) ──
  if (lives <= 0) {
    const missedWords = missed.map(idx => dict[idx]).filter(Boolean);
    return /*#__PURE__*/React.createElement(EndScreen, {
      score: score,
      missedWords: missedWords,
      onRestart: restartGame
    });
  }

  // ── dict exhausted ──
  if (!question) {
    return /*#__PURE__*/React.createElement("div", {
      className: "gm-app gm-up-app"
    }, /*#__PURE__*/React.createElement("div", {
      className: "gm-up-wrap"
    }, /*#__PURE__*/React.createElement("div", {
      className: "gm-up-card"
    }, /*#__PURE__*/React.createElement("div", {
      className: "gm-up-eye"
    }, "\u05E1\u05D9\u05D9\u05DE\u05EA\u05DD \u05D0\u05EA \u05D4\u05DE\u05D9\u05DC\u05D5\u05DF"), /*#__PURE__*/React.createElement("h1", {
      className: "gm-up-h1"
    }, used.length, " \u05DE\u05D9\u05DC\u05D9\u05DD \xB7 ", score, " \u05E0\u05E7\u05D5\u05D3\u05D5\u05EA"), /*#__PURE__*/React.createElement("p", {
      className: "gm-up-sub"
    }, "\u05E2\u05D1\u05E8\u05EA \u05E2\u05DC \u05DB\u05DC \u05D4\u05DE\u05D9\u05DC\u05D9\u05DD \u05D1\u05DE\u05D9\u05DC\u05D5\u05DF \"", dictName, "\". \u05DE\u05D4 \u05D4\u05DC\u05D0\u05D4?"), /*#__PURE__*/React.createElement("button", {
      className: "gm-up-btn",
      onClick: () => {
        setUsed([]);
        setLives(3);
        setScore(0);
      }
    }, "\u05E1\u05D9\u05D1\u05D5\u05D1 \u05E0\u05D5\u05E1\u05E3 \u05E2\u05DD \u05D0\u05D5\u05EA\u05DD \u05DE\u05D9\u05DC\u05D9\u05DD"), /*#__PURE__*/React.createElement("button", {
      className: "gm-up-btn-ghost",
      onClick: resetDict
    }, "\u05D8\u05E2\u05E0\u05D5 \u05DE\u05D9\u05DC\u05D5\u05DF \u05D0\u05D7\u05E8"))));
  }
  return /*#__PURE__*/React.createElement("div", {
    className: "gm-app"
  }, /*#__PURE__*/React.createElement("div", {
    className: "gm-stage",
    ref: stageRef,
    style: {
      "--gm-scale": scale,
      "--rocket-duration": `${rocketDur}s`
    }
  }, /*#__PURE__*/React.createElement(SkyZ, null), /*#__PURE__*/React.createElement(Mountains, null), /*#__PURE__*/React.createElement("div", {
    className: "gm-ground"
  }), /*#__PURE__*/React.createElement("div", {
    className: "gm-hud-brand"
  }, /*#__PURE__*/React.createElement("img", {
    src: "assets/ez-icon.png",
    alt: ""
  }), /*#__PURE__*/React.createElement("span", null, "eazy")), /*#__PURE__*/React.createElement("div", {
    className: "gm-hud"
  }, /*#__PURE__*/React.createElement("div", {
    className: "chip hearts"
  }, [0, 1, 2].map(i => /*#__PURE__*/React.createElement(Heart, {
    key: i,
    lost: i >= lives
  }))), /*#__PURE__*/React.createElement("div", {
    className: "chip score"
  }, /*#__PURE__*/React.createElement("span", {
    className: "label"
  }, "\u05E0\u05D9\u05E7\u05D5\u05D3"), /*#__PURE__*/React.createElement("span", null, score)), /*#__PURE__*/React.createElement("div", {
    className: "spacer"
  })), /*#__PURE__*/React.createElement("div", {
    className: "gm-word"
  }, /*#__PURE__*/React.createElement("div", {
    className: "en"
  }, question.en)), /*#__PURE__*/React.createElement("div", {
    className: "gm-foot-actions"
  }, /*#__PURE__*/React.createElement("button", {
    className: "foot-btn",
    onClick: () => {
      try {
        window.top.location.href = "https://www.ezway.co.il";
      } catch (e) {
        window.open("https://www.ezway.co.il", "_top");
      }
    },
    title: "\u05D0\u05EA\u05E8 \u05D4\u05D1\u05D9\u05EA"
  }, /*#__PURE__*/React.createElement(I.home, null)), /*#__PURE__*/React.createElement("button", {
    className: "foot-btn",
    onClick: toggleFullscreen,
    title: "\u05DE\u05E1\u05DA \u05DE\u05DC\u05D0"
  }, /*#__PURE__*/React.createElement(I.expand, null)), /*#__PURE__*/React.createElement("button", {
    className: "foot-btn lifeline" + (fiftyAvailable ? "" : " used"),
    onClick: useFifty,
    disabled: !fiftyAvailable,
    title: fiftyAvailable ? "גלגל הצלה 50/50" : "כבר השתמשת ב-50/50"
  }, /*#__PURE__*/React.createElement("span", {
    className: "fifty-text"
  }, "50", /*#__PURE__*/React.createElement("br", null), "50")), /*#__PURE__*/React.createElement("button", {
    className: "foot-btn" + (muted ? " muted" : ""),
    onClick: toggleMute,
    title: muted ? "השמע צלילים" : "השתק צלילים"
  }, muted ? /*#__PURE__*/React.createElement(I.speakerMute, null) : /*#__PURE__*/React.createElement(I.speaker, null))), /*#__PURE__*/React.createElement("div", {
    className: "gm-rockets"
  }, question.options.map((opt, i) => {
    const state = resolved[i];
    let cls = "gm-rocket";
    if (aimed === i) cls += " aiming";
    if (state === "hit") cls += " hit";else if (state === "missed") cls += " missed";else if (state === "correct-after") cls += " correct-after";
    const paused = isRoundOver || aimed === i || resolved[i] && resolved[i] !== "correct-after"; // correct-after keeps drifting
    const hidden = hiddenIdx.has(i);
    return /*#__PURE__*/React.createElement("div", {
      key: `${question.en}-${i}`,
      className: "gm-rocket-travel" + (paused ? " paused" : "") + (hidden ? " hidden5050" : ""),
      style: {
        animationDelay: `${-i * 1.5}s`
      },
      onAnimationEnd: e => onTravelEnd(i, e)
    }, /*#__PURE__*/React.createElement("div", {
      ref: el => rocketRefs.current[i] = el,
      className: cls,
      style: {
        "--mr": STAGGER[i] + "px"
      },
      onClick: () => onTarget(i)
    }, /*#__PURE__*/React.createElement(RocketSVG, null), /*#__PURE__*/React.createElement("div", {
      className: "label"
    }, opt), /*#__PURE__*/React.createElement("div", {
      className: "gm-burst"
    }, /*#__PURE__*/React.createElement(BurstSVG, null))));
  })), /*#__PURE__*/React.createElement("div", {
    className: "gm-cannon" + (recoil ? " recoil" : ""),
    ref: cannonRef
  }, /*#__PURE__*/React.createElement(CannonBase, null), /*#__PURE__*/React.createElement("div", {
    className: "barrel-wrap"
  }, /*#__PURE__*/React.createElement("svg", {
    style: {
      position: "absolute",
      width: "220px",
      height: "60px",
      top: "-30px",
      left: "-30px",
      transformOrigin: "30px 30px",
      transform: `rotate(${angle}deg)`,
      transition: "transform .08s linear",
      overflow: "visible"
    },
    viewBox: "0 0 220 60"
  }, /*#__PURE__*/React.createElement("defs", null, /*#__PURE__*/React.createElement("linearGradient", {
    id: "barG2",
    x1: "0",
    y1: "0",
    x2: "0",
    y2: "1"
  }, /*#__PURE__*/React.createElement("stop", {
    offset: "0",
    stopColor: "#3a3358"
  }), /*#__PURE__*/React.createElement("stop", {
    offset: "0.5",
    stopColor: "#1A1530"
  }), /*#__PURE__*/React.createElement("stop", {
    offset: "1",
    stopColor: "#0A0820"
  })), /*#__PURE__*/React.createElement("linearGradient", {
    id: "muzzleG2",
    x1: "0",
    y1: "0",
    x2: "0",
    y2: "1"
  }, /*#__PURE__*/React.createElement("stop", {
    offset: "0",
    stopColor: "#5a5470"
  }), /*#__PURE__*/React.createElement("stop", {
    offset: "1",
    stopColor: "#2A2547"
  }))), /*#__PURE__*/React.createElement("rect", {
    x: "14",
    y: "22",
    width: "36",
    height: "20",
    rx: "4",
    fill: "#1A1530"
  }), /*#__PURE__*/React.createElement("rect", {
    x: "14",
    y: "22",
    width: "36",
    height: "3",
    fill: "rgba(255,255,255,.18)"
  }), /*#__PURE__*/React.createElement("rect", {
    x: "40",
    y: "26",
    width: "150",
    height: "12",
    rx: "4",
    fill: "url(#barG2)"
  }), /*#__PURE__*/React.createElement("rect", {
    x: "42",
    y: "27",
    width: "146",
    height: "2",
    rx: "1",
    fill: "rgba(255,255,255,.25)"
  }), /*#__PURE__*/React.createElement("rect", {
    x: "184",
    y: "22",
    width: "22",
    height: "20",
    rx: "3",
    fill: "url(#muzzleG2)"
  }), /*#__PURE__*/React.createElement("rect", {
    x: "188",
    y: "26",
    width: "2",
    height: "12",
    fill: "#0A0820"
  }), /*#__PURE__*/React.createElement("rect", {
    x: "194",
    y: "26",
    width: "2",
    height: "12",
    fill: "#0A0820"
  }), /*#__PURE__*/React.createElement("rect", {
    x: "200",
    y: "26",
    width: "2",
    height: "12",
    fill: "#0A0820"
  }), /*#__PURE__*/React.createElement("rect", {
    x: "22",
    y: "14",
    width: "6",
    height: "10",
    fill: "#1A1530"
  }), /*#__PURE__*/React.createElement("circle", {
    cx: "25",
    cy: "13",
    r: "3",
    fill: "#F33F3F"
  })))), shotEl, kitState && /*#__PURE__*/React.createElement("div", {
    className: "gm-kit-travel",
    key: kitState.id,
    onAnimationEnd: () => setKitState(null)
  }, /*#__PURE__*/React.createElement("button", {
    className: "gm-kit",
    onClick: onKitHit,
    title: "\u05D9\u05E8\u05D4 \u05D1\u05EA\u05D9\u05E7 \u05DC\u05E2\u05D5\u05D3 \u05DC\u05D1!"
  }, /*#__PURE__*/React.createElement("svg", {
    viewBox: "0 0 120 110",
    "aria-hidden": true
  }, /*#__PURE__*/React.createElement("defs", null, /*#__PURE__*/React.createElement("linearGradient", {
    id: "kitG",
    x1: "0",
    y1: "0",
    x2: "0",
    y2: "1"
  }, /*#__PURE__*/React.createElement("stop", {
    offset: "0",
    stopColor: "#FFFFFF"
  }), /*#__PURE__*/React.createElement("stop", {
    offset: "1",
    stopColor: "#E8E6F0"
  })), /*#__PURE__*/React.createElement("linearGradient", {
    id: "kitHandleG",
    x1: "0",
    y1: "0",
    x2: "0",
    y2: "1"
  }, /*#__PURE__*/React.createElement("stop", {
    offset: "0",
    stopColor: "#3a3358"
  }), /*#__PURE__*/React.createElement("stop", {
    offset: "1",
    stopColor: "#1A1530"
  }))), /*#__PURE__*/React.createElement("ellipse", {
    cx: "60",
    cy: "102",
    rx: "42",
    ry: "5",
    fill: "rgba(0,0,0,.3)"
  }), /*#__PURE__*/React.createElement("rect", {
    x: "44",
    y: "8",
    width: "32",
    height: "14",
    rx: "3",
    fill: "url(#kitHandleG)",
    stroke: "#0A0820",
    strokeWidth: "2"
  }), /*#__PURE__*/React.createElement("rect", {
    x: "48",
    y: "14",
    width: "24",
    height: "8",
    rx: "2",
    fill: "rgba(255,255,255,.15)"
  }), /*#__PURE__*/React.createElement("rect", {
    x: "14",
    y: "22",
    width: "92",
    height: "76",
    rx: "8",
    fill: "url(#kitG)",
    stroke: "#0A0820",
    strokeWidth: "2.5"
  }), /*#__PURE__*/React.createElement("rect", {
    x: "52",
    y: "34",
    width: "16",
    height: "52",
    rx: "2",
    fill: "#DC2626"
  }), /*#__PURE__*/React.createElement("rect", {
    x: "34",
    y: "52",
    width: "52",
    height: "16",
    rx: "2",
    fill: "#DC2626"
  }), /*#__PURE__*/React.createElement("rect", {
    x: "20",
    y: "28",
    width: "80",
    height: "3",
    rx: "1.5",
    fill: "rgba(255,255,255,.5)"
  }), /*#__PURE__*/React.createElement("rect", {
    x: "56",
    y: "20",
    width: "8",
    height: "6",
    fill: "#3a3358"
  })), /*#__PURE__*/React.createElement("div", {
    className: "gm-kit-label"
  }, "+1 \u05DC\u05D1"))), missFx && /*#__PURE__*/React.createElement("div", {
    className: "gm-miss-jam",
    "aria-hidden": true
  }, /*#__PURE__*/React.createElement("svg", {
    viewBox: "0 0 1600 900",
    preserveAspectRatio: "none"
  }, /*#__PURE__*/React.createElement("defs", null, /*#__PURE__*/React.createElement("linearGradient", {
    id: "jamG",
    x1: "0",
    y1: "0",
    x2: "0",
    y2: "1"
  }, /*#__PURE__*/React.createElement("stop", {
    offset: "0",
    stopColor: "#7C170F",
    stopOpacity: ".95"
  }), /*#__PURE__*/React.createElement("stop", {
    offset: ".35",
    stopColor: "#9C1E16",
    stopOpacity: ".92"
  }), /*#__PURE__*/React.createElement("stop", {
    offset: ".75",
    stopColor: "#B5251B",
    stopOpacity: ".88"
  }), /*#__PURE__*/React.createElement("stop", {
    offset: ".94",
    stopColor: "#C72A1F",
    stopOpacity: ".84"
  }), /*#__PURE__*/React.createElement("stop", {
    offset: ".95",
    stopColor: "#C72A1F",
    stopOpacity: "0"
  }), /*#__PURE__*/React.createElement("stop", {
    offset: "1",
    stopColor: "#C72A1F",
    stopOpacity: "0"
  })), /*#__PURE__*/React.createElement("linearGradient", {
    id: "curtainG",
    x1: "0",
    y1: "0",
    x2: "0",
    y2: "1"
  }, /*#__PURE__*/React.createElement("stop", {
    offset: "0",
    stopColor: "#8E1A12",
    stopOpacity: ".95"
  }), /*#__PURE__*/React.createElement("stop", {
    offset: ".5",
    stopColor: "#A8201A",
    stopOpacity: ".92"
  }), /*#__PURE__*/React.createElement("stop", {
    offset: ".9",
    stopColor: "#B5251B",
    stopOpacity: ".90"
  }), /*#__PURE__*/React.createElement("stop", {
    offset: "1",
    stopColor: "#7C170F",
    stopOpacity: ".95"
  })), /*#__PURE__*/React.createElement("filter", {
    id: "jamBlur",
    x: "-3%",
    y: "-3%",
    width: "106%",
    height: "106%"
  }, /*#__PURE__*/React.createElement("feGaussianBlur", {
    stdDeviation: ".8"
  }))), /*#__PURE__*/React.createElement("path", {
    className: "jam-splat",
    d: "M 0 0 L 1600 0 L 1600 180 C 1540 220 1490 175 1440 200 C 1380 230 1330 175 1280 215 C 1230 245 1180 185 1130 225 C 1080 255 1030 200 980 230 C 930 265 880 195 830 240 C 780 275 730 215 680 245 C 630 280 580 210 530 250 C 480 280 430 220 380 260 C 330 290 280 225 230 265 C 180 295 130 230 80 270 C 50 290 30 250 0 275 Z",
    fill: "url(#jamG)",
    filter: "url(#jamBlur)"
  }), [
  // x1, x2 define the horizontal span; depth = how far below the splat band; delay = stagger
  {
    x1: 0,
    x2: 360,
    depth: 540,
    delay: 0.05,
    dur: 2.4
  }, {
    x1: 280,
    x2: 660,
    depth: 460,
    delay: 0.45,
    dur: 2.6
  }, {
    x1: 580,
    x2: 940,
    depth: 580,
    delay: 0.20,
    dur: 2.5
  }, {
    x1: 860,
    x2: 1220,
    depth: 500,
    delay: 0.65,
    dur: 2.4
  }, {
    x1: 1140,
    x2: 1480,
    depth: 560,
    delay: 0.30,
    dur: 2.6
  }, {
    x1: 1400,
    x2: 1600,
    depth: 480,
    delay: 0.55,
    dur: 2.5
  }].map((c, i) => {
    const topY = 175;
    const bottomY = topY + c.depth;
    // wavy bottom edge — 3 peaks/valleys for irregularity
    const span = c.x2 - c.x1;
    const p1 = c.x1 + span * 0.20;
    const p2 = c.x1 + span * 0.45;
    const p3 = c.x1 + span * 0.72;
    const dip = c.depth * 0.18;
    const path = `
                  M ${c.x1} ${topY}
                  L ${c.x2} ${topY}
                  L ${c.x2} ${bottomY - dip * 0.6}
                  C ${c.x2 - 40} ${bottomY + dip * 0.4}, ${p3 + 40} ${bottomY - dip}, ${p3} ${bottomY + dip * 0.6}
                  C ${p3 - 40} ${bottomY + dip * 1.2}, ${p2 + 50} ${bottomY - dip * 0.8}, ${p2} ${bottomY + dip * 0.3}
                  C ${p2 - 50} ${bottomY + dip * 0.9}, ${p1 + 40} ${bottomY - dip * 0.5}, ${p1} ${bottomY + dip * 0.5}
                  C ${p1 - 40} ${bottomY + dip * 1.1}, ${c.x1 + 40} ${bottomY - dip * 0.3}, ${c.x1} ${bottomY - dip * 0.4}
                  Z
                `;
    return /*#__PURE__*/React.createElement("path", {
      key: i,
      className: "jam-curtain",
      d: path,
      fill: "url(#curtainG)",
      filter: "url(#jamBlur)",
      style: {
        animationDelay: `${c.delay}s`,
        animationDuration: `${c.dur}s`
      }
    });
  }))), levelUp && /*#__PURE__*/React.createElement("div", {
    className: "gm-levelup"
  }, /*#__PURE__*/React.createElement("div", {
    className: "gm-levelup-title"
  }, "\u05E2\u05DC\u05D9\u05EA \u05E9\u05DC\u05D1!"), /*#__PURE__*/React.createElement("div", {
    className: "gm-levelup-sub"
  }, "\u05D4\u05D8\u05D9\u05DC\u05D9\u05DD \u05DE\u05D4\u05D9\u05E8\u05D9\u05DD \u05D9\u05D5\u05EA\u05E8 \xB7 +", pointsPerHit, " \u05DC\u05DB\u05DC \u05EA\u05E9\u05D5\u05D1\u05D4 \u05E0\u05DB\u05D5\u05E0\u05D4")), toast && /*#__PURE__*/React.createElement("div", {
    className: "gm-toast " + toast.kind
  }, /*#__PURE__*/React.createElement("span", {
    className: "dot"
  }), toast.text), /*#__PURE__*/React.createElement("style", null, `
          @keyframes shotFly {
            from { transform: translate(-50%, -50%) translate(0, 0); opacity: 1; }
            to   { transform: translate(-50%, -50%) translate(var(--dx, 0px), var(--dy, 0px)); opacity: 1; }
          }
        `)));
}
window.Game = QuizGameExport;
})(); } catch (e) { __ds_ns.__errors.push({ path: "quiz-game-export/QuizGameExport.jsx", error: String((e && e.message) || e) }); }

// quiz-game-export/words.js
try { (() => {
/* eazy · משחק תותח־מילים — מילון המשחק
   ─────────────────────────────────────────────────────────────
   זהו הדטה־בייס של המשחק. לכל שורה:
     en — המילה באנגלית
     he — הפירוש בעברית
   המשחק יטען את הרשימה הזו אוטומטית בכל מכשיר, ללא צורך בהעלאה.

   להוסיף/לערוך מילים — פשוט ערוך את הקובץ הזה ושמור.
   מספר הערכים הנוכחי: 637
*/
window.GAME_DICTIONARY = [{
  en: "a fortnight ago",
  he: "לפני שבועיים"
}, {
  en: "abduct",
  he: "לחטוף"
}, {
  en: "abolish",
  he: "לבטל"
}, {
  en: "accelerate",
  he: "להאיץ"
}, {
  en: "accent",
  he: "מבטא"
}, {
  en: "access",
  he: "גישה"
}, {
  en: "acclaim",
  he: "הכרה / הוקרה"
}, {
  en: "ache",
  he: "כאב / לכאוב"
}, {
  en: "activity",
  he: "פעילות"
}, {
  en: "acute",
  he: "חריף"
}, {
  en: "admiration",
  he: "הערצה"
}, {
  en: "admission process",
  he: "תהליך ההרשמה"
}, {
  en: "advertisement",
  he: "פרסומת"
}, {
  en: "adviser",
  he: "יועץ"
}, {
  en: "affirmative action",
  he: "העדפה מתקנת"
}, {
  en: "ague",
  he: "צמרמורת / קדחת"
}, {
  en: "aid",
  he: "עזרה"
}, {
  en: "ailment",
  he: "מחלה"
}, {
  en: "aimed at",
  he: "המכוון אל..."
}, {
  en: "alert",
  he: "כוננות"
}, {
  en: "allegation",
  he: "האשמה"
}, {
  en: "allegedly",
  he: "לכאורה"
}, {
  en: "ally",
  he: "בעל ברית"
}, {
  en: "along with",
  he: "לצד"
}, {
  en: "along side",
  he: "לצד / ליד"
}, {
  en: "ambassador",
  he: "שגריר"
}, {
  en: "ambiguous",
  he: "מעורפל"
}, {
  en: "ambition",
  he: "שאיפה"
}, {
  en: "ambitious",
  he: "שאפתן"
}, {
  en: "amnesia",
  he: "שכחה / נשייה"
}, {
  en: "ample",
  he: "הרבה / שפע"
}, {
  en: "analyze",
  he: "לנתח"
}, {
  en: "animosity",
  he: "עוינות"
}, {
  en: "annihilation",
  he: "השמדה מוחלטת"
}, {
  en: "anniversary",
  he: "יום השנה"
}, {
  en: "annoyance",
  he: "מטרד"
}, {
  en: "annulment",
  he: "ביטול נישואין"
}, {
  en: "anonymous",
  he: "אלמוני"
}, {
  en: "anthem",
  he: "המנון"
}, {
  en: "anticipation",
  he: "ציפייה"
}, {
  en: "anxious",
  he: "עצבני / מודאג"
}, {
  en: "any given moment",
  he: "כל רגע נתון"
}, {
  en: "apology",
  he: "התנצלות"
}, {
  en: "appear",
  he: "מופיע"
}, {
  en: "appliance",
  he: "כלי/מתקן"
}, {
  en: "application",
  he: "בקשה לקבלה"
}, {
  en: "approve",
  he: "לאשר"
}, {
  en: "arena",
  he: "זירה / מגרש"
}, {
  en: "argument",
  he: "ויכוח / טיעון"
}, {
  en: "arrogance",
  he: "שחצנות"
}, {
  en: "assessment",
  he: "הערכה"
}, {
  en: "associate",
  he: "עמית / שותף"
}, {
  en: "assumption",
  he: "הנחה"
}, {
  en: "astonishment",
  he: "תדהמה"
}, {
  en: "attack",
  he: "התקפה"
}, {
  en: "attendance",
  he: "נוכחות"
}, {
  en: "attention",
  he: "תשומת לב"
}, {
  en: "attribution",
  he: "ייחוס / תכונה"
}, {
  en: "awe-inspiring",
  he: "מעורר השתאות"
}, {
  en: "bark",
  he: "לנבוח"
}, {
  en: "barrier",
  he: "מחסום, סייג"
}, {
  en: "beforehand",
  he: "מראש"
}, {
  en: "bench",
  he: "ספסל"
}, {
  en: "beneficial",
  he: "מועיל / מיטיב"
}, {
  en: "beneficiary",
  he: "המוטב / הנהנה"
}, {
  en: "benefit",
  he: "להרוויח"
}, {
  en: "benign",
  he: "שפיר"
}, {
  en: "bequeath",
  he: "להוריש"
}, {
  en: "bereavement",
  he: "אבל / שכול"
}, {
  en: "bigotry",
  he: "גזענות"
}, {
  en: "birth",
  he: "לידה / ללדת"
}, {
  en: "blink",
  he: "מצמוץ"
}, {
  en: "blizzard",
  he: "סופה / סערה"
}, {
  en: "block",
  he: "לחסום"
}, {
  en: "board",
  he: "מועצה / לוח"
}, {
  en: "boldly",
  he: "באופן נועז"
}, {
  en: "bone-marrow",
  he: "מוח עצם"
}, {
  en: "border",
  he: "גבול / גבולי"
}, {
  en: "boredom",
  he: "שעמום"
}, {
  en: "boundless",
  he: "חסר גבולות"
}, {
  en: "brash",
  he: "פזיז / נמהר"
}, {
  en: "breast",
  he: "שד / חזה"
}, {
  en: "briefing",
  he: "תדריך"
}, {
  en: "brisk",
  he: "בחטף / במהרה"
}, {
  en: "broadcast",
  he: "לשדר / שידור"
}, {
  en: "broker",
  he: "מתווך / סוכן"
}, {
  en: "budget",
  he: "תקציב"
}, {
  en: "bulks",
  he: "כמויות גדולות"
}, {
  en: "buried",
  he: "קבור"
}, {
  en: "campaign",
  he: "מסע בחירות"
}, {
  en: "canal",
  he: "תעלה"
}, {
  en: "cancel",
  he: "לבטל"
}, {
  en: "candidate",
  he: "מועמד"
}, {
  en: "capsized",
  he: "מתהפך / מתבטל"
}, {
  en: "captions",
  he: "כתוביות"
}, {
  en: "capture",
  he: "ללכוד / לשבות"
}, {
  en: "careful consideration",
  he: "מחשבה מרובה"
}, {
  en: "cargo",
  he: "מטען"
}, {
  en: "cell",
  he: "תא"
}, {
  en: "cemeteries",
  he: "בתי קברות"
}, {
  en: "centric",
  he: "מרכזי"
}, {
  en: "chairman",
  he: "יו\"ר"
}, {
  en: "challenge",
  he: "אתגר"
}, {
  en: "charity",
  he: "צדקה"
}, {
  en: "charming",
  he: "מקסים"
}, {
  en: "chauvinistic",
  he: "שוביניסטי"
}, {
  en: "chronic illness",
  he: "מחלה כרונית"
}, {
  en: "circulated",
  he: "סבב / נפוץ"
}, {
  en: "civil",
  he: "אזרחי"
}, {
  en: "clarify",
  he: "להבהיר / לחדד"
}, {
  en: "clash",
  he: "עימות"
}, {
  en: "classified material",
  he: "חומר מסווג"
}, {
  en: "classify",
  he: "לסווג / למיין"
}, {
  en: "classified",
  he: "מסווג"
}, {
  en: "cloning",
  he: "לשכפל"
}, {
  en: "coach",
  he: "מאמן"
}, {
  en: "coating",
  he: "ציפוי"
}, {
  en: "coercion",
  he: "כפייה"
}, {
  en: "cognition",
  he: "תפישה"
}, {
  en: "colleague",
  he: "עמית"
}, {
  en: "collision",
  he: "התנגשות"
}, {
  en: "come to a halt",
  he: "לעצור / לחדול"
}, {
  en: "come to light",
  he: "נודע / הופיע"
}, {
  en: "comet",
  he: "כוכב שביט"
}, {
  en: "comfort",
  he: "הטבה / נוחיות"
}, {
  en: "commitment",
  he: "מחויבות"
}, {
  en: "committed to",
  he: "מסור ל..."
}, {
  en: "committee",
  he: "ועדה"
}, {
  en: "companion",
  he: "בן זוג / שותף"
}, {
  en: "compel",
  he: "לאלץ / לכפות"
}, {
  en: "complaint",
  he: "תלונה"
}, {
  en: "comprehensive",
  he: "מקיף וכוללני"
}, {
  en: "compromise",
  he: "להתפשר / לסכן"
}, {
  en: "compulsive",
  he: "כפייתי"
}, {
  en: "concentration",
  he: "ריכוז"
}, {
  en: "conditioning",
  he: "התניה"
}, {
  en: "confess",
  he: "להתוודות"
}, {
  en: "confronted",
  he: "מעומת למול"
}, {
  en: "connection",
  he: "קשר"
}, {
  en: "conniving",
  he: "תככן וחתרן"
}, {
  en: "conquest",
  he: "כיבוש"
}, {
  en: "consecutive",
  he: "רציף / רצוף"
}, {
  en: "considering",
  he: "בהתחשב"
}, {
  en: "consortium",
  he: "תאגיד"
}, {
  en: "construct",
  he: "לבנות"
}, {
  en: "continent",
  he: "יבשת"
}, {
  en: "continuity",
  he: "המשכיות"
}, {
  en: "continuously",
  he: "מתמשך"
}, {
  en: "contradiction",
  he: "סתירה"
}, {
  en: "contrary to",
  he: "בניגוד ל..."
}, {
  en: "conviction",
  he: "הרשעה / שכנוע"
}, {
  en: "convince",
  he: "לשכנע"
}, {
  en: "copyrights",
  he: "זכויות יוצרים"
}, {
  en: "coral",
  he: "אלמוג"
}, {
  en: "correspondent",
  he: "מתכתב / כתב"
}, {
  en: "co-star",
  he: "כוכב משנה"
}, {
  en: "counterfeit",
  he: "מזויף"
}, {
  en: "county judge",
  he: "שופט מחוזי"
}, {
  en: "courage",
  he: "אומץ"
}, {
  en: "court ruling",
  he: "פסיקת ביהמ\"ש"
}, {
  en: "cover story",
  he: "סיפור שער"
}, {
  en: "covert operation",
  he: "מבצע חשאי"
}, {
  en: "covertly",
  he: "בחשאיות"
}, {
  en: "covet",
  he: "לחמוד"
}, {
  en: "creativity",
  he: "יצירתיות"
}, {
  en: "credential",
  he: "מסמך / אישור"
}, {
  en: "credible",
  he: "מהימן / אמין"
}, {
  en: "crime prevention",
  he: "מניעת פשע"
}, {
  en: "crops",
  he: "יבולים"
}, {
  en: "crusade",
  he: "מסע צלב"
}, {
  en: "cumbersome",
  he: "מסורבל"
}, {
  en: "curse",
  he: "קללה"
}, {
  en: "debased",
  he: "פוגע / מעליב"
}, {
  en: "debut",
  he: "סרט ביכורים"
}, {
  en: "deceitfulness",
  he: "מרמה והונאה"
}, {
  en: "decentralized",
  he: "דה-צנטרליסטי"
}, {
  en: "decisive",
  he: "החלטי / מכריע"
}, {
  en: "debrief",
  he: "לתחקר"
}, {
  en: "decipher",
  he: "לפענח"
}, {
  en: "deduction",
  he: "דדוקציה"
}, {
  en: "defeat",
  he: "מפלה"
}, {
  en: "defect",
  he: "פגם / \"דפקט\""
}, {
  en: "defendant",
  he: "הנאשם"
}, {
  en: "defended",
  he: "הגן על..."
}, {
  en: "deform",
  he: "לעוות צורה"
}, {
  en: "defrost",
  he: "להפשיר"
}, {
  en: "denounce",
  he: "לגנות"
}, {
  en: "density",
  he: "צפיפות"
}, {
  en: "deny",
  he: "להכחיש"
}, {
  en: "depict",
  he: "לתאר"
}, {
  en: "deportation",
  he: "גירוש"
}, {
  en: "depression",
  he: "שפל"
}, {
  en: "descendant",
  he: "צאצא"
}, {
  en: "desirable",
  he: "נחשק"
}, {
  en: "deterrence",
  he: "הרתעה"
}, {
  en: "detest",
  he: "לתעב / לשנוא"
}, {
  en: "devastatingly",
  he: "באופן הרסני"
}, {
  en: "diminutive",
  he: "מקטין / זעיר"
}, {
  en: "disarray",
  he: "תוהו ובוהו"
}, {
  en: "discipline",
  he: "משמעת"
}, {
  en: "disclose",
  he: "לחשוף / לגלות"
}, {
  en: "disclosure",
  he: "חשיפה"
}, {
  en: "discount",
  he: "הנחה"
}, {
  en: "discovery",
  he: "תגלית"
}, {
  en: "disgusted",
  he: "נגעל"
}, {
  en: "disqualify",
  he: "לפסול"
}, {
  en: "disrupt",
  he: "להפריע"
}, {
  en: "distinguish",
  he: "להבחין"
}, {
  en: "distribute",
  he: "לחלק / להפיץ"
}, {
  en: "district",
  he: "מחוז / אזור"
}, {
  en: "disturbance",
  he: "הפרעה"
}, {
  en: "diver",
  he: "צוללן"
}, {
  en: "divulge",
  he: "לחשוף"
}, {
  en: "documentation",
  he: "תיעוד"
}, {
  en: "dodge",
  he: "להתחמק"
}, {
  en: "domain",
  he: "תחום"
}, {
  en: "dominated",
  he: "נשלט"
}, {
  en: "dormant",
  he: "רדום"
}, {
  en: "dosage",
  he: "מינון"
}, {
  en: "dot",
  he: "נקודה"
}, {
  en: "draw back",
  he: "לסגת / להירתע"
}, {
  en: "eager",
  he: "להוט"
}, {
  en: "earnest",
  he: "רציני"
}, {
  en: "echo",
  he: "הד"
}, {
  en: "editor",
  he: "עורך"
}, {
  en: "editorial",
  he: "מאמר מערכת"
}, {
  en: "educate",
  he: "לחנך"
}, {
  en: "efficient",
  he: "יעיל"
}, {
  en: "effort",
  he: "מאמץ / ניסיון"
}, {
  en: "elderly",
  he: "קשיש"
}, {
  en: "embezzle",
  he: "למעול / מעילה"
}, {
  en: "embrace",
  he: "לחבק"
}, {
  en: "emigrate",
  he: "להגר / לרדת"
}, {
  en: "employee",
  he: "עובד שכיר"
}, {
  en: "enclosure",
  he: "סגירת שטח"
}, {
  en: "encouragement",
  he: "עידוד"
}, {
  en: "endeavor",
  he: "מאמץ"
}, {
  en: "endorsement",
  he: "תמיכה / חסות"
}, {
  en: "enhance",
  he: "להרחיב"
}, {
  en: "enrollment",
  he: "הרשמה"
}, {
  en: "enthusiasm",
  he: "התלהבות"
}, {
  en: "eruption",
  he: "התפרצות"
}, {
  en: "espionage",
  he: "ריגול"
}, {
  en: "establishment",
  he: "מוסד / ממסד"
}, {
  en: "ethical",
  he: "אתי / מוסרי"
}, {
  en: "evaluation",
  he: "הערכה"
}, {
  en: "eventful",
  he: "מלא אירועים"
}, {
  en: "evolution",
  he: "אבולוציה"
}, {
  en: "excessive",
  he: "מוגזם"
}, {
  en: "excuse",
  he: "תירוץ"
}, {
  en: "expose",
  he: "לחשוף"
}, {
  en: "extend",
  he: "להאריך"
}, {
  en: "extensive",
  he: "מקיף"
}, {
  en: "extinction",
  he: "הכחדה"
}, {
  en: "facial features",
  he: "תווי פנים"
}, {
  en: "factor",
  he: "גורם"
}, {
  en: "faculty",
  he: "פקולטה"
}, {
  en: "fancy",
  he: "מהודר"
}, {
  en: "fan",
  he: "אוהד / מניפה"
}, {
  en: "favor",
  he: "טובה / העדפה"
}, {
  en: "feminine",
  he: "נשי"
}, {
  en: "ferocious",
  he: "פראי / אכזר"
}, {
  en: "ferociously",
  he: "באכזריות"
}, {
  en: "fertility",
  he: "פוריות"
}, {
  en: "feud",
  he: "משטמה"
}, {
  en: "fidelity",
  he: "נאמנות"
}, {
  en: "first aid",
  he: "עזרה ראשונה"
}, {
  en: "fixture",
  he: "משהו קבוע"
}, {
  en: "flat",
  he: "שטוח / דירה"
}, {
  en: "flaw",
  he: "חסרון / פגם"
}, {
  en: "flexibility",
  he: "גמישות"
}, {
  en: "foe",
  he: "אויב"
}, {
  en: "forge",
  he: "לזייף"
}, {
  en: "forming",
  he: "מייסדים"
}, {
  en: "fortify",
  he: "לבצר / לחזק"
}, {
  en: "foster",
  he: "לטפח / לאמץ"
}, {
  en: "found",
  he: "לייסד / להקים"
}, {
  en: "fraud",
  he: "הונאה / מרמה"
}, {
  en: "frown",
  he: "להזעיף פנים"
}, {
  en: "fruitful",
  he: "פורה"
}, {
  en: "frustrated",
  he: "מתוסכל"
}, {
  en: "function",
  he: "תפקוד"
}, {
  en: "fundamental",
  he: "בסיסי / יסודי"
}, {
  en: "furious",
  he: "זועם / \"רותח\""
}, {
  en: "gag order",
  he: "צו איסור פרסום"
}, {
  en: "gap",
  he: "פער"
}, {
  en: "genetic information",
  he: "מידע גנטי"
}, {
  en: "genuine",
  he: "מקורי / אמיתי"
}, {
  en: "get under way",
  he: "לצאת לדרך"
}, {
  en: "giant",
  he: "ענק"
}, {
  en: "glance",
  he: "מבט חטוף"
}, {
  en: "glimpse",
  he: "הצצה רגעית"
}, {
  en: "global economy",
  he: "כלכלה עולמית"
}, {
  en: "gown",
  he: "שמלה / חלוק"
}, {
  en: "graduate degree",
  he: "תואר אקדמאי"
}, {
  en: "greed",
  he: "תאוות בצע"
}, {
  en: "grief",
  he: "יגון"
}, {
  en: "guarded",
  he: "שמור"
}, {
  en: "guidance",
  he: "הנחיה"
}, {
  en: "gulf",
  he: "מפרץ"
}, {
  en: "halt",
  he: "לעצור / לחדול"
}, {
  en: "handcuffs",
  he: "אזיקים"
}, {
  en: "handy",
  he: "יעיל"
}, {
  en: "harbor",
  he: "נמל"
}, {
  en: "hearing",
  he: "שימוע / שומע"
}, {
  en: "heir",
  he: "יורש"
}, {
  en: "hint",
  he: "רמז"
}, {
  en: "holocaust survivor",
  he: "ניצול שואה"
}, {
  en: "honorable",
  he: "מכובד"
}, {
  en: "hopefulness",
  he: "מלא תקווה"
}, {
  en: "hostage",
  he: "בן ערובה"
}, {
  en: "hostile",
  he: "עוין"
}, {
  en: "hostility",
  he: "עוינות"
}, {
  en: "humidity",
  he: "לחות"
}, {
  en: "humiliation",
  he: "השפלה / בושה"
}, {
  en: "identical",
  he: "זהה"
}, {
  en: "identity",
  he: "זהות"
}, {
  en: "ignoring",
  he: "להתעלם"
}, {
  en: "ill-fated",
  he: "מסתיים בכי רע"
}, {
  en: "image",
  he: "תמונה / דמות"
}, {
  en: "imaginable",
  he: "ניתן לדמיון"
}, {
  en: "immunity",
  he: "חסינות"
}, {
  en: "impede",
  he: "להאט / להפריע"
}, {
  en: "implant",
  he: "לשתול"
}, {
  en: "imply",
  he: "לרמוז"
}, {
  en: "imprison",
  he: "לכלוא / לאסור"
}, {
  en: "improbable",
  he: "בלתי סביר"
}, {
  en: "in accordance",
  he: "בהתאם ל..."
}, {
  en: "in contradiction",
  he: "בסתירה"
}, {
  en: "incapable",
  he: "לא מסוגל"
}, {
  en: "incautious",
  he: "בלתי זהיר"
}, {
  en: "incentive",
  he: "תמריץ"
}, {
  en: "incident",
  he: "תקרית"
}, {
  en: "inclination",
  he: "נטייה ל..."
}, {
  en: "in common",
  he: "במשותף"
}, {
  en: "incompatible",
  he: "בלתי מתאים"
}, {
  en: "incompetence",
  he: "חוסר יכולת"
}, {
  en: "inconceivable",
  he: "בלתי נתפש"
}, {
  en: "indication",
  he: "אינדיקציה"
}, {
  en: "indicator",
  he: "אינדיקטור"
}, {
  en: "indictment",
  he: "כתב אישום"
}, {
  en: "infant",
  he: "תינוק קטן"
}, {
  en: "infectious",
  he: "מדבק"
}, {
  en: "infer",
  he: "להסיק / להבין"
}, {
  en: "infinitesimal",
  he: "מזערי"
}, {
  en: "inherent",
  he: "טבוע"
}, {
  en: "inheritance",
  he: "ירושה"
}, {
  en: "initial",
  he: "ראשוני"
}, {
  en: "initiate",
  he: "ליזום"
}, {
  en: "insanity",
  he: "שיגעון"
}, {
  en: "insect",
  he: "חרק"
}, {
  en: "inspiration",
  he: "השראה"
}, {
  en: "institution",
  he: "מוסד"
}, {
  en: "insufferable",
  he: "בלתי נסבל"
}, {
  en: "insufficient",
  he: "בלתי מספק"
}, {
  en: "insurance evaluators",
  he: "שמאי ביטוח"
}, {
  en: "insurance policy",
  he: "פוליסת ביטוח"
}, {
  en: "insure",
  he: "להבטיח"
}, {
  en: "integrity",
  he: "יושר / אמינות"
}, {
  en: "intelligence officer",
  he: "קצין מודיעין"
}, {
  en: "intended effect",
  he: "אפקט מיועד"
}, {
  en: "intent",
  he: "כוונה"
}, {
  en: "interaction",
  he: "אינטראקציה"
}, {
  en: "interrogation",
  he: "חקירה"
}, {
  en: "investigation",
  he: "חקירה (בלשית)"
}, {
  en: "investor",
  he: "משקיע"
}, {
  en: "invincible",
  he: "בלתי מנוצח"
}, {
  en: "invisible",
  he: "בלתי נראה"
}, {
  en: "invitation",
  he: "הזמנה"
}, {
  en: "isolate",
  he: "לבודד / לנתק"
}, {
  en: "isolationism",
  he: "בדלנות"
}, {
  en: "issue a declaration",
  he: "לפרסם הצהרה"
}, {
  en: "journey",
  he: "מסע"
}, {
  en: "judgment",
  he: "יכולת שיפוט"
}, {
  en: "jump-start",
  he: "להתניע"
}, {
  en: "justify",
  he: "להצדיק"
}, {
  en: "kidnapping",
  he: "חטיפה"
}, {
  en: "lab",
  he: "מעבדה"
}, {
  en: "lap",
  he: "הקפה / ירך"
}, {
  en: "launch",
  he: "להשיק / לשגר"
}, {
  en: "lavishly",
  he: "בהידור"
}, {
  en: "lawyer",
  he: "עורך דין"
}, {
  en: "layoffs",
  he: "פיטורין"
}, {
  en: "lecture",
  he: "הרצאה"
}, {
  en: "legacy",
  he: "מורשת"
}, {
  en: "lethal",
  he: "קטלני"
}, {
  en: "likeness",
  he: "דמיון"
}, {
  en: "limitation",
  he: "מגבלה"
}, {
  en: "line of research",
  he: "קו מחקרי"
}, {
  en: "link",
  he: "קשר"
}, {
  en: "loathe",
  he: "מתעב"
}, {
  en: "makes sense",
  he: "נשמע הגיוני"
}, {
  en: "malfunction",
  he: "תקלה"
}, {
  en: "management position",
  he: "תפקיד ניהולי"
}, {
  en: "mandatory",
  he: "חובה"
}, {
  en: "manner",
  he: "אופן"
}, {
  en: "marginal element",
  he: "גורם שולי"
}, {
  en: "markedly",
  he: "באופן ניכר"
}, {
  en: "masculine",
  he: "גברי"
}, {
  en: "massacre",
  he: "טבח"
}, {
  en: "meager",
  he: "זעום"
}, {
  en: "meaningless",
  he: "חסר משמעות"
}, {
  en: "means of deterrence",
  he: "אמצעי הרתעה"
}, {
  en: "mediator",
  he: "מתווך"
}, {
  en: "mediocre",
  he: "בינוני"
}, {
  en: "meek",
  he: "חלש / קלוש"
}, {
  en: "meet these goals",
  he: "לעמוד ביעדים"
}, {
  en: "mental",
  he: "נפשי / מנטאלי"
}, {
  en: "merger",
  he: "איחוד / מיזוג"
}, {
  en: "meticulous",
  he: "קפדני ודקדקני"
}, {
  en: "middleman",
  he: "מתווך"
}, {
  en: "mild",
  he: "מתון"
}, {
  en: "minister",
  he: "שר"
}, {
  en: "minute",
  he: "זעיר / דקה"
}, {
  en: "miracle",
  he: "נס"
}, {
  en: "misconception",
  he: "תפישה שגויה"
}, {
  en: "misinterpret",
  he: "לפרש לא נכון"
}, {
  en: "missionary",
  he: "מיסיונר"
}, {
  en: "moral question",
  he: "שאלה מוסרית"
}, {
  en: "mortal danger",
  he: "סכנת חיים"
}, {
  en: "motion",
  he: "תנועה"
}, {
  en: "motive",
  he: "מניע"
}, {
  en: "mutual",
  he: "הדדי"
}, {
  en: "mysteriousness",
  he: "מסתוריות"
}, {
  en: "mystical",
  he: "מיסטי"
}, {
  en: "mystify",
  he: "לערפל"
}, {
  en: "naive",
  he: "נאיבי / תמים"
}, {
  en: "narcissist",
  he: "נרקיסיסט"
}, {
  en: "navigate",
  he: "לנווט"
}, {
  en: "nerve cell",
  he: "תא עצב"
}, {
  en: "neutral",
  he: "נייטראלי"
}, {
  en: "next of kin",
  he: "קרוב משפחה"
}, {
  en: "nightmare",
  he: "סיוט"
}, {
  en: "novel",
  he: "חדשני"
}, {
  en: "novelist",
  he: "סופר"
}, {
  en: "obligation",
  he: "התחייבות"
}, {
  en: "offspring",
  he: "צאצא"
}, {
  en: "ongoing",
  he: "מתמשך"
}, {
  en: "oppose",
  he: "להתנגד ל..."
}, {
  en: "opposite",
  he: "הפוך"
}, {
  en: "oppression",
  he: "דיכוי"
}, {
  en: "oral",
  he: "בעל פה"
}, {
  en: "orbit",
  he: "מסלול היקפי"
}, {
  en: "originates from",
  he: "נובע מ..."
}, {
  en: "outcome",
  he: "תוצאה"
}, {
  en: "overshadow",
  he: "להאפיל"
}, {
  en: "overt",
  he: "גלוי, פומבי"
}, {
  en: "overwhelmed",
  he: "המום"
}, {
  en: "pamper",
  he: "לפנק"
}, {
  en: "parade",
  he: "מצעד / להצעיד"
}, {
  en: "paralyze",
  he: "לשתק"
}, {
  en: "participant",
  he: "משתתף"
}, {
  en: "particle",
  he: "חלקיק"
}, {
  en: "pave",
  he: "לסלול"
}, {
  en: "peacefulness",
  he: "שקט ושלווה"
}, {
  en: "penetration",
  he: "חדירה"
}, {
  en: "percent",
  he: "אחוז"
}, {
  en: "perception",
  he: "תפישה"
}, {
  en: "persist",
  he: "להתמיד"
}, {
  en: "personnel",
  he: "כוח אדם"
}, {
  en: "persuasion",
  he: "שכנוע"
}, {
  en: "phase",
  he: "שלב"
}, {
  en: "pipeline",
  he: "צינור"
}, {
  en: "plagiarism",
  he: "גניבה ספרותית"
}, {
  en: "plain",
  he: "פשוט / ברור"
}, {
  en: "plaintiff",
  he: "תובע / מאשים"
}, {
  en: "planet",
  he: "כוכב לכת"
}, {
  en: "plea",
  he: "טענה"
}, {
  en: "pledge",
  he: "התחייבות"
}, {
  en: "plenty",
  he: "שפע"
}, {
  en: "point out",
  he: "לציין"
}, {
  en: "pollute",
  he: "לזהם"
}, {
  en: "popular belief",
  he: "אמונה מקובלת"
}, {
  en: "port",
  he: "נמל"
}, {
  en: "precaution",
  he: "אמצעי זהירות"
}, {
  en: "precious",
  he: "יקר"
}, {
  en: "precisely",
  he: "בדיוק"
}, {
  en: "preclude",
  he: "להוציא מהכלל"
}, {
  en: "preference",
  he: "העדפה"
}, {
  en: "premise",
  he: "הנחת יסוד"
}, {
  en: "preparation",
  he: "הכנה"
}, {
  en: "preserved bodies",
  he: "גופות משומרות"
}, {
  en: "prestigious",
  he: "יוקרתי"
}, {
  en: "probable successor",
  he: "יורש אפשרי"
}, {
  en: "probation",
  he: "תקופת מבחן"
}, {
  en: "probe",
  he: "סקירה מעמיקה"
}, {
  en: "profit",
  he: "להרוויח"
}, {
  en: "projected",
  he: "צפוי / מתוכנן"
}, {
  en: "prolonged",
  he: "מוארך / ממושך"
}, {
  en: "prominent",
  he: "בולט"
}, {
  en: "promotion",
  he: "קידום"
}, {
  en: "pronunciation",
  he: "היגוי / מבטא"
}, {
  en: "prophecy",
  he: "נבואה"
}, {
  en: "proponent",
  he: "תומך"
}, {
  en: "proposal",
  he: "הצעה"
}, {
  en: "prosperity",
  he: "שגשוג ורווחה"
}, {
  en: "protest",
  he: "מחאה / הפגנה"
}, {
  en: "punishment",
  he: "עונש / ענישה"
}, {
  en: "purify",
  he: "לטהר"
}, {
  en: "purloined material",
  he: "חומר \"מושאל\""
}, {
  en: "purposeful",
  he: "מלא כוונה"
}, {
  en: "pursuit",
  he: "מרדף"
}, {
  en: "puzzled",
  he: "תמוה"
}, {
  en: "qualified",
  he: "מתאים / מוסמך"
}, {
  en: "quarter",
  he: "רבע"
}, {
  en: "quiz",
  he: "בוחן / חידון"
}, {
  en: "racism",
  he: "גזענות"
}, {
  en: "racist",
  he: "גזען"
}, {
  en: "radiation",
  he: "קרינה"
}, {
  en: "reaction",
  he: "תגובה"
}, {
  en: "reasonable",
  he: "סביר / הגיוני"
}, {
  en: "reassembled",
  he: "מורכב מחדש"
}, {
  en: "rebuttal",
  he: "הפרכה"
}, {
  en: "recipe",
  he: "מתכון"
}, {
  en: "rectify",
  he: "לתקן"
}, {
  en: "refuel",
  he: "לתדלק מחדש"
}, {
  en: "regardless",
  he: "ללא קשר"
}, {
  en: "regime",
  he: "משטר"
}, {
  en: "regiment",
  he: "גדוד"
}, {
  en: "region",
  he: "אזור / תחום"
}, {
  en: "reinforce",
  he: "לתגבר / לחזק"
}, {
  en: "reluctance",
  he: "חוסר רצון"
}, {
  en: "remarkable",
  he: "ראוי לציון"
}, {
  en: "remorse",
  he: "חרטה / צער"
}, {
  en: "reprehensible",
  he: "ראוי לגינוי"
}, {
  en: "reptile",
  he: "זוחל"
}, {
  en: "requester",
  he: "המבקש"
}, {
  en: "residency",
  he: "מקום מגורים"
}, {
  en: "respiration",
  he: "נשימה"
}, {
  en: "restoration",
  he: "שחזור"
}, {
  en: "restore",
  he: "לשחזר"
}, {
  en: "retirement",
  he: "פרישה"
}, {
  en: "reveal",
  he: "לחשוף / לגלות"
}, {
  en: "review",
  he: "לבדוק שנית"
}, {
  en: "revive",
  he: "להחיות"
}, {
  en: "revolutionize",
  he: "לחולל מהפיכה"
}, {
  en: "role",
  he: "תפקיד"
}, {
  en: "root",
  he: "שורש"
}, {
  en: "routine",
  he: "רוטינה / שגרה"
}, {
  en: "rural",
  he: "כפרי"
}, {
  en: "sacred",
  he: "קדוש"
}, {
  en: "satellite",
  he: "לוויין"
}, {
  en: "scatter",
  he: "לפזר / להתפזר"
}, {
  en: "scenario",
  he: "תרחיש"
}, {
  en: "schooling",
  he: "חינוך"
}, {
  en: "scroll",
  he: "מגילה"
}, {
  en: "self-preservation",
  he: "שימור עצמי"
}, {
  en: "self-restraint",
  he: "שליטה עצמית"
}, {
  en: "semi",
  he: "למחצה"
}, {
  en: "seminar",
  he: "סמינר"
}, {
  en: "sensible",
  he: "הגיוני"
}, {
  en: "sensuous",
  he: "חושני"
}, {
  en: "serenity",
  he: "שלווה"
}, {
  en: "server",
  he: "שרת מחשב"
}, {
  en: "session",
  he: "פגישה /סדנא"
}, {
  en: "shortage",
  he: "מחסור"
}, {
  en: "similarly",
  he: "באופן דומה"
}, {
  en: "simulate",
  he: "לדמות"
}, {
  en: "site",
  he: "אתר"
}, {
  en: "skinny",
  he: "רזה מאוד"
}, {
  en: "sleepiness",
  he: "ישנוניות"
}, {
  en: "slim",
  he: "רזה / קלוש"
}, {
  en: "slips of the tongue",
  he: "מעידות בלשון"
}, {
  en: "sober",
  he: "פיכח"
}, {
  en: "software patches",
  he: "טלאי תוכנה"
}, {
  en: "sought after",
  he: "מחפשים אחריו"
}, {
  en: "specialist",
  he: "מומחה"
}, {
  en: "specialize",
  he: "מתמחה ב..."
}, {
  en: "spectator",
  he: "צופה"
}, {
  en: "spokesperson",
  he: "דובר"
}, {
  en: "spokeswoman",
  he: "דוברת"
}, {
  en: "sporadic",
  he: "בלתי סדיר"
}, {
  en: "spot",
  he: "נקודה"
}, {
  en: "squeeze",
  he: "ללחוץ / למחוץ"
}, {
  en: "stage",
  he: "שלב"
}, {
  en: "stakes",
  he: "סיכונים"
}, {
  en: "stand",
  he: "לעמוד / יציע"
}, {
  en: "startling",
  he: "מפתיע / מדהים"
}, {
  en: "stems from",
  he: "נובע מ..."
}, {
  en: "stock",
  he: "מניה בורסאית"
}, {
  en: "stomach",
  he: "קיבה / בטן"
}, {
  en: "storm",
  he: "סופה / סערה"
}, {
  en: "straight-forward",
  he: "ישיר"
}, {
  en: "strict",
  he: "נוקשה / קפדני"
}, {
  en: "suburban",
  he: "פרברי"
}, {
  en: "superstition",
  he: "אמונה טפלה"
}, {
  en: "supervision",
  he: "פיקוח"
}, {
  en: "surface variance",
  he: "משתנה חיצוני"
}, {
  en: "surrogate mother",
  he: "אם פונדקאית"
}, {
  en: "suspended",
  he: "מושעה / מושהה"
}, {
  en: "tantalizing",
  he: "מרגש / מרעיד"
}, {
  en: "tempt fate",
  he: "להתגרות בגורל"
}, {
  en: "testify",
  he: "להעיד"
}, {
  en: "testimony",
  he: "עדות"
}, {
  en: "therapy",
  he: "תרפיה / טיפול"
}, {
  en: "tide",
  he: "גאות ושפל"
}, {
  en: "timeliness",
  he: "דייקנות"
}, {
  en: "tool",
  he: "כלי"
}, {
  en: "topic",
  he: "הנושא"
}, {
  en: "topple",
  he: "למוטט"
}, {
  en: "tournament",
  he: "טורניר"
}, {
  en: "trade-offs",
  he: "החלפות"
}, {
  en: "traditional",
  he: "מסורתי"
}, {
  en: "traitorous",
  he: "בוגדני"
}, {
  en: "tranquility",
  he: "שלווה"
}, {
  en: "transaction",
  he: "עסקה"
}, {
  en: "transfer",
  he: "להעביר"
}, {
  en: "translucent",
  he: "מעט שקוף"
}, {
  en: "transparent",
  he: "שקוף / ברור"
}, {
  en: "tremendous",
  he: "עצום"
}, {
  en: "trend",
  he: "אופנה"
}, {
  en: "trial and error",
  he: "ניסוי וטעייה"
}, {
  en: "truthfully",
  he: "בכנות"
}, {
  en: "unbearable",
  he: "בלתי נסבל"
}, {
  en: "under dispute",
  he: "נתון במחלוקת"
}, {
  en: "undeterred",
  he: "לא נרתע מ..."
}, {
  en: "unravel",
  he: "לחשוף"
}, {
  en: "unstable",
  he: "בלתי יציב"
}, {
  en: "usable",
  he: "ניתן לשימוש"
}, {
  en: "vacancy",
  he: "מקום פנוי"
}, {
  en: "varies",
  he: "משתנה"
}, {
  en: "vast majority",
  he: "הרוב המוחלט"
}, {
  en: "veil",
  he: "הינומה"
}, {
  en: "violate",
  he: "להפר"
}, {
  en: "voyage",
  he: "מסע"
}, {
  en: "wage",
  he: "שכר / משכורת"
}, {
  en: "want of understanding",
  he: "העדר הבנה"
}, {
  en: "waver",
  he: "לוותר"
}, {
  en: "will",
  he: "רצון / צוואה"
}, {
  en: "willingness",
  he: "מוכנות"
}, {
  en: "wiped out",
  he: "למחוק"
}, {
  en: "work ethic",
  he: "מוסר עבודה"
}, {
  en: "worship",
  he: "לסגוד ל..."
}, {
  en: "wrapped up",
  he: "עטוף"
}, {
  en: "wrist",
  he: "פרק יד"
}, {
  en: "yearn",
  he: "להשתוקק"
}, {
  en: "youth",
  he: "נעורים"
}];
})(); } catch (e) { __ds_ns.__errors.push({ path: "quiz-game-export/words.js", error: String((e && e.message) || e) }); }

// quiz-game-server/QuizGameServer.jsx
try { (() => {
/* global React, XLSX */
const {
  useState,
  useEffect,
  useRef,
  useCallback,
  useLayoutEffect,
  useMemo
} = React;

/* ---------- built-in sample dictionary ---------- */
const SAMPLE_DICT = [{
  en: "ENHANCE",
  he: "להעצים, לשפר",
  ipa: "/ɪnˈhæns/"
}, {
  en: "MITIGATE",
  he: "להקל, למתן",
  ipa: "/ˈmɪtɪˌɡeɪt/"
}, {
  en: "AMBIGUOUS",
  he: "דו-משמעי, עמום",
  ipa: "/æmˈbɪɡjuəs/"
}, {
  en: "ADVOCATE",
  he: "לתמוך, להמליץ",
  ipa: "/ˈædvəˌkeɪt/"
}, {
  en: "SCRUTINIZE",
  he: "לבחון בקפדנות",
  ipa: "/ˈskruːtəˌnaɪz/"
}, {
  en: "INEVITABLE",
  he: "בלתי נמנע",
  ipa: "/ɪˈnɛvɪtəbəl/"
}, {
  en: "DILIGENT",
  he: "חרוץ, שקדן",
  ipa: "/ˈdɪlɪdʒənt/"
}, {
  en: "OBSOLETE",
  he: "מיושן, יצא משימוש",
  ipa: "/ˌabsəˈliːt/"
}, {
  en: "CANDID",
  he: "הֵן, ישיר, ספונטני",
  ipa: "/ˈkændɪd/"
}, {
  en: "TENACIOUS",
  he: "עיקש, דבק במטרה",
  ipa: "/təˈneɪʃəs/"
}];
const STAGGER = [0, 40, 14, 56];
const DICT_STORAGE_KEY = "ez-mcq-dict-v2";
const DICT_NAME_KEY = "ez-mcq-dict-name-v2";
const MUTED_KEY = "ez-mcq-muted-v1";
const LB_KEY = "ez-mcq-leaderboard-v1";

/* ---------- sound engine (WebAudio FX + background music) ---------- */
const Sound = {
  ctx: null,
  muted: false,
  music: null,
  // <audio> element
  musicReady: false,
  init() {
    if (!this.ctx) {
      try {
        this.ctx = new (window.AudioContext || window.webkitAudioContext)();
      } catch (e) {}
    }
    if (this.ctx && this.ctx.state === 'suspended') this.ctx.resume();
    if (!this.music) {
      this.music = document.getElementById('bg-music');
      if (this.music) {
        this.music.volume = 0.35;
        this.music.loop = true;
        this.musicReady = true;
      }
    }
  },
  startMusic() {
    this.init();
    if (this.muted || !this.music) return;
    const p = this.music.play();
    if (p && p.catch) p.catch(() => {/* autoplay blocked — will start on next user gesture */});
  },
  stopMusic() {
    if (this.music) {
      this.music.pause();
    }
  },
  setMusicVolume(v) {
    if (this.music) this.music.volume = Math.max(0, Math.min(1, v));
  },
  setMuted(m) {
    this.muted = !!m;
    if (this.muted) this.stopMusic();else this.startMusic();
    try {
      localStorage.setItem(MUTED_KEY, this.muted ? '1' : '0');
    } catch (e) {}
  },
  beep(freq, duration, type = 'sine', gain = 0.15, delay = 0) {
    if (this.muted || !this.ctx) return;
    const t = this.ctx.currentTime + delay;
    const osc = this.ctx.createOscillator();
    const g = this.ctx.createGain();
    osc.type = type;
    osc.frequency.value = freq;
    g.gain.setValueAtTime(gain, t);
    g.gain.exponentialRampToValueAtTime(0.001, t + duration);
    osc.connect(g);
    g.connect(this.ctx.destination);
    osc.start(t);
    osc.stop(t + duration);
  },
  play(name) {
    if (this.muted) return;
    this.init();
    switch (name) {
      case 'shoot':
        this.beep(540, 0.06, 'square', 0.13);
        this.beep(220, 0.07, 'sawtooth', 0.10, 0.03);
        break;
      case 'hit':
        /* punchier explosion: low thump + bright chord + bell tail */
        this.beep(80, 0.10, 'square', 0.22);
        this.beep(523, 0.10, 'square', 0.16, 0.04);
        this.beep(784, 0.12, 'square', 0.14, 0.10);
        this.beep(1047, 0.22, 'triangle', 0.16, 0.18);
        this.beep(1568, 0.30, 'sine', 0.12, 0.30);
        break;
      case 'miss':
        /* descending "wha-wha" buzzer — clearly distinct from a hit */
        this.beep(440, 0.10, 'square', 0.20);
        this.beep(330, 0.14, 'square', 0.20, 0.10);
        this.beep(220, 0.30, 'sawtooth', 0.22, 0.22);
        this.beep(150, 0.45, 'triangle', 0.20, 0.45);
        break;
      case 'lifegain':
        /* sparkle: ascending major arpeggio */
        this.beep(659, 0.10, 'triangle', 0.18);
        this.beep(880, 0.10, 'triangle', 0.18, 0.10);
        this.beep(1175, 0.10, 'triangle', 0.18, 0.20);
        this.beep(1568, 0.32, 'sine', 0.20, 0.30);
        break;
      case 'fifty':
        /* two-note chime */
        this.beep(880, 0.10, 'sine', 0.15);
        this.beep(1320, 0.18, 'sine', 0.16, 0.10);
        break;
      case 'levelup':
        this.beep(523, 0.10, 'triangle', 0.18);
        this.beep(659, 0.10, 'triangle', 0.18, 0.10);
        this.beep(784, 0.10, 'triangle', 0.18, 0.20);
        this.beep(1047, 0.32, 'sine', 0.20, 0.30);
        break;
      case 'tick':
        this.beep(720, 0.08, 'sine', 0.10);
        break;
      case 'go':
        this.beep(1200, 0.30, 'triangle', 0.22);
        break;
      case 'streak':
        this.beep(880, 0.08, 'sine', 0.13);
        this.beep(1320, 0.10, 'sine', 0.14, 0.08);
        break;
      case 'gameover':
        this.beep(440, 0.20, 'sine', 0.15);
        this.beep(330, 0.24, 'sine', 0.15, 0.20);
        this.beep(220, 0.50, 'sine', 0.18, 0.45);
        break;
    }
  }
};
try {
  Sound.muted = localStorage.getItem(MUTED_KEY) === '1';
} catch (e) {}

/* ---------- leaderboard ---------- */
function getLeaderboard() {
  try {
    return JSON.parse(localStorage.getItem(LB_KEY) || '[]');
  } catch (e) {
    return [];
  }
}
function addToLeaderboard(name, score) {
  const lb = getLeaderboard();
  lb.push({
    name: (name || "אנונימי").slice(0, 20),
    score,
    date: new Date().toISOString()
  });
  lb.sort((a, b) => b.score - a.score);
  try {
    localStorage.setItem(LB_KEY, JSON.stringify(lb.slice(0, 5)));
  } catch (e) {}
  return lb.slice(0, 5);
}
function qualifiesForLeaderboard(score) {
  if (score <= 0) return false;
  const lb = getLeaderboard();
  if (lb.length < 5) return true;
  return score > lb[lb.length - 1].score;
}

/* ---------- dictionary helpers ---------- */
function shuffleArr(a) {
  const x = [...a];
  for (let i = x.length - 1; i > 0; i--) {
    const j = Math.floor(Math.random() * (i + 1));
    [x[i], x[j]] = [x[j], x[i]];
  }
  return x;
}
function buildQuestion(dict, correctIdx) {
  const correct = dict[correctIdx];
  const correctMeaning = normalizeMeaning(correct.he);

  // Build pool excluding correct answer AND entries that share the same meaning.
  // This prevents duplicate Hebrew translations from appearing as distractors
  // (e.g. when the same meaning is split across two English words).
  const pool = dict.map((entry, i) => ({
    entry,
    i,
    key: normalizeMeaning(entry.he)
  })).filter(({
    i,
    key
  }) => i !== correctIdx && key !== correctMeaning);

  // Pick 3 distractors with distinct meanings from each other too.
  const shuffled = shuffleArr(pool);
  const picked = [];
  const seenMeanings = new Set([correctMeaning]);
  for (const {
    entry,
    key
  } of shuffled) {
    if (seenMeanings.has(key)) continue;
    seenMeanings.add(key);
    picked.push(entry);
    if (picked.length === 3) break;
  }

  // Fallback: if the dict is too small / too many duplicates, allow same-key duplicates
  // just so we always have 4 options.
  while (picked.length < 3) {
    const fillers = shuffleArr(pool).filter(p => !picked.includes(p.entry));
    if (fillers.length === 0) break;
    picked.push(fillers[0].entry);
  }
  const options = shuffleArr([correct.he, ...picked.map(d => d.he)]);
  return {
    en: String(correct.en).toUpperCase(),
    ipa: correct.ipa || "",
    correct: correct.he,
    options
  };
}

// Normalize a meaning string so "להאריך / להרחיב" and "להאריך, להרחיב" collide,
// and casing/whitespace differences don't matter.
function normalizeMeaning(s) {
  return String(s || "").toLowerCase().replace(/[\/,،]/g, " ") // treat /, comma, arabic comma as separators
  .replace(/\s+/g, " ").replace(/[״"׳'.…]/g, "").trim();
}
function parseSpreadsheet(file) {
  return new Promise((resolve, reject) => {
    const reader = new FileReader();
    reader.onerror = () => reject(new Error("לא מצליח לקרוא את הקובץ"));
    reader.onload = e => {
      try {
        if (typeof XLSX === "undefined") {
          reject(new Error("תוכנת הפיענוח לא נטענה. רענן דף ונסה שוב."));
          return;
        }
        const data = new Uint8Array(e.target.result);
        const wb = XLSX.read(data, {
          type: "array"
        });
        const sheet = wb.Sheets[wb.SheetNames[0]];
        const rows = XLSX.utils.sheet_to_json(sheet, {
          header: 1,
          blankrows: false
        });
        if (!rows.length) {
          reject(new Error("הקובץ ריק"));
          return;
        }
        const firstB = String(rows[0][1] || "").trim().toLowerCase();
        const looksLikeHeader = /english|word|מילה|אנגלית/.test(firstB) || /פירוש|תרגום|עברית/.test(String(rows[0][2] || ""));
        const start = looksLikeHeader ? 1 : 0;
        const entries = [];
        for (let i = start; i < rows.length; i++) {
          const en = String(rows[i][1] || "").trim(); // column B
          const he = String(rows[i][2] || "").trim(); // column C
          if (en && he) entries.push({
            en,
            he,
            ipa: ""
          });
        }
        if (entries.length < 4) {
          reject(new Error("צריך לפחות 4 מילים בקובץ"));
          return;
        }
        resolve(entries);
      } catch (err) {
        reject(err);
      }
    };
    reader.readAsArrayBuffer(file);
  });
}

/* ──────────────────────────────────────────────
   Polished SVG illustrations
   ────────────────────────────────────────────── */

function RocketSVG({
  isBoss
}) {
  const stroke = "#2A2155";
  const strokeW = 3.5;

  // ── Regular rockets ── use the curated reference artwork embedded as a
  // PNG. Replacing the SVG with the bitmap matches the source illustration
  // pixel-for-pixel; state-based color shifts (hit / missed / correct) come
  // from CSS filters applied to .gm-rocket via `.rocket-img`.
  if (!isBoss) {
    return /*#__PURE__*/React.createElement("svg", {
      className: "frame",
      viewBox: "0 0 620 150",
      preserveAspectRatio: "none",
      "aria-hidden": true
    }, /*#__PURE__*/React.createElement("image", {
      className: "rocket-img",
      href: "rocket-cropped.png",
      xlinkHref: "rocket-cropped.png",
      x: "0",
      y: "0",
      width: "620",
      height: "150",
      preserveAspectRatio: "none"
    }));
  }

  // ── BOSS rocket ── still drawn fully in SVG so the red gradient body,
  // shark-fins and multi-lick flame stay intact (per the user's request).
  return /*#__PURE__*/React.createElement("svg", {
    className: "frame",
    viewBox: "0 0 620 150",
    preserveAspectRatio: "none",
    "aria-hidden": true
  }, /*#__PURE__*/React.createElement("defs", null, /*#__PURE__*/React.createElement("linearGradient", {
    id: "bodyG",
    x1: "0",
    y1: "0",
    x2: "0",
    y2: "1"
  }, /*#__PURE__*/React.createElement("stop", {
    offset: "0",
    stopColor: "#FFFFFF"
  }), /*#__PURE__*/React.createElement("stop", {
    offset: ".6",
    stopColor: "#F5F3F8"
  }), /*#__PURE__*/React.createElement("stop", {
    offset: "1",
    stopColor: "#C9C7CF"
  })), /*#__PURE__*/React.createElement("linearGradient", {
    id: "bodyG-hit",
    x1: "0",
    y1: "0",
    x2: "0",
    y2: "1"
  }, /*#__PURE__*/React.createElement("stop", {
    offset: "0",
    stopColor: "#FFE6CB"
  }), /*#__PURE__*/React.createElement("stop", {
    offset: ".5",
    stopColor: "#F37327"
  }), /*#__PURE__*/React.createElement("stop", {
    offset: "1",
    stopColor: "#A93C08"
  })), /*#__PURE__*/React.createElement("linearGradient", {
    id: "bodyG-miss",
    x1: "0",
    y1: "0",
    x2: "0",
    y2: "1"
  }, /*#__PURE__*/React.createElement("stop", {
    offset: "0",
    stopColor: "#D7D5DC"
  }), /*#__PURE__*/React.createElement("stop", {
    offset: "1",
    stopColor: "#9A98A4"
  })), /*#__PURE__*/React.createElement("linearGradient", {
    id: "bodyG-correct",
    x1: "0",
    y1: "0",
    x2: "0",
    y2: "1"
  }, /*#__PURE__*/React.createElement("stop", {
    offset: "0",
    stopColor: "#BDF0D3"
  }), /*#__PURE__*/React.createElement("stop", {
    offset: "1",
    stopColor: "#3FA76C"
  })), /*#__PURE__*/React.createElement("linearGradient", {
    id: "bodyG-boss",
    x1: "0",
    y1: "0",
    x2: "0",
    y2: "1"
  }, /*#__PURE__*/React.createElement("stop", {
    offset: "0",
    stopColor: "#FCA5A5"
  }), /*#__PURE__*/React.createElement("stop", {
    offset: ".5",
    stopColor: "#DC2626"
  }), /*#__PURE__*/React.createElement("stop", {
    offset: "1",
    stopColor: "#7F1D1D"
  })), /*#__PURE__*/React.createElement("linearGradient", {
    id: "tipG-boss",
    x1: "0",
    y1: "0",
    x2: "0",
    y2: "1"
  }, /*#__PURE__*/React.createElement("stop", {
    offset: "0",
    stopColor: "#FCD34D"
  }), /*#__PURE__*/React.createElement("stop", {
    offset: ".55",
    stopColor: "#DC2626"
  }), /*#__PURE__*/React.createElement("stop", {
    offset: "1",
    stopColor: "#7F1D1D"
  })), /*#__PURE__*/React.createElement("linearGradient", {
    id: "tipG",
    x1: "0",
    y1: "0",
    x2: "0",
    y2: "1"
  }, /*#__PURE__*/React.createElement("stop", {
    offset: "0",
    stopColor: "#FFB36B"
  }), /*#__PURE__*/React.createElement("stop", {
    offset: ".55",
    stopColor: "#F37327"
  }), /*#__PURE__*/React.createElement("stop", {
    offset: "1",
    stopColor: "#B94A0C"
  })), /*#__PURE__*/React.createElement("linearGradient", {
    id: "finG",
    x1: "0",
    y1: "0",
    x2: "0",
    y2: "1"
  }, /*#__PURE__*/React.createElement("stop", {
    offset: "0",
    stopColor: "#FFB36B"
  }), /*#__PURE__*/React.createElement("stop", {
    offset: ".5",
    stopColor: "#F37327"
  }), /*#__PURE__*/React.createElement("stop", {
    offset: "1",
    stopColor: "#A0410B"
  })), /*#__PURE__*/React.createElement("radialGradient", {
    id: "flameG",
    cx: "50%",
    cy: "50%",
    r: "55%"
  }, /*#__PURE__*/React.createElement("stop", {
    offset: "0",
    stopColor: "#FFF7CE"
  }), /*#__PURE__*/React.createElement("stop", {
    offset: ".4",
    stopColor: "#FFD23F"
  }), /*#__PURE__*/React.createElement("stop", {
    offset: ".85",
    stopColor: "#F37327"
  }), /*#__PURE__*/React.createElement("stop", {
    offset: "1",
    stopColor: "#B94A0C"
  }))), /*#__PURE__*/React.createElement("g", null, /*#__PURE__*/React.createElement("path", {
    d: "M 525,40 Q 555,52 580,32 Q 568,55 595,55 Q 575,68 610,72 Q 575,80 615,90 Q 575,92 600,108 Q 570,100 588,118 Q 555,100 580,118 Q 555,98 525,110 Z",
    fill: "url(#flameG)",
    stroke: stroke,
    strokeWidth: strokeW,
    strokeLinejoin: "round"
  }), /*#__PURE__*/React.createElement("path", {
    d: "M 530,55 Q 555,55 570,42 Q 568,62 585,68 Q 565,75 582,82 Q 565,88 580,100 Q 558,92 568,110 Q 545,95 530,100 Z",
    fill: "#FFF7CE",
    opacity: ".95"
  })), /*#__PURE__*/React.createElement("path", {
    d: "M 470,42 Q 488,18 540,2 Q 540,30 520,46 Q 500,52 470,42 Z",
    fill: "url(#finG)",
    stroke: stroke,
    strokeWidth: strokeW,
    strokeLinejoin: "round"
  }), /*#__PURE__*/React.createElement("path", {
    d: "M 495,28 Q 515,18 532,12",
    stroke: "#fff",
    strokeOpacity: ".6",
    strokeWidth: "3",
    fill: "none",
    strokeLinecap: "round"
  }), /*#__PURE__*/React.createElement("path", {
    d: "M 470,108 Q 488,132 540,148 Q 540,120 520,104 Q 500,98 470,108 Z",
    fill: "url(#finG)",
    stroke: stroke,
    strokeWidth: strokeW,
    strokeLinejoin: "round"
  }), /*#__PURE__*/React.createElement("path", {
    d: "M 495,122 Q 515,132 532,138",
    stroke: "#fff",
    strokeOpacity: ".45",
    strokeWidth: "3",
    fill: "none",
    strokeLinecap: "round"
  }), /*#__PURE__*/React.createElement("path", {
    className: "body-fill",
    d: "M 40,75 Q 70,16 165,16 L 530,16 Q 560,16 560,38 L 560,112 Q 560,134 530,134 L 165,134 Q 70,134 40,75 Z",
    fill: "url(#bodyG)",
    stroke: stroke,
    strokeWidth: strokeW,
    strokeLinejoin: "round"
  }), /*#__PURE__*/React.createElement("path", {
    className: "tip-fill",
    d: "M 40,75 Q 70,16 165,16 L 175,16 Q 110,30 90,75 Q 110,120 175,134 L 165,134 Q 70,134 40,75 Z",
    fill: "url(#tipG)",
    stroke: stroke,
    strokeWidth: strokeW,
    strokeLinejoin: "round"
  }), /*#__PURE__*/React.createElement("path", {
    d: "M 70,52 Q 90,38 120,42",
    stroke: "#fff",
    strokeOpacity: ".7",
    strokeWidth: "4",
    fill: "none",
    strokeLinecap: "round"
  }), /*#__PURE__*/React.createElement("path", {
    d: "M 195,30 Q 360,24 510,32",
    stroke: "#fff",
    strokeOpacity: ".95",
    strokeWidth: "5",
    fill: "none",
    strokeLinecap: "round"
  }), /*#__PURE__*/React.createElement("path", {
    d: "M 170,124 Q 360,140 520,126",
    stroke: "#1A1530",
    strokeOpacity: ".09",
    strokeWidth: "6",
    fill: "none",
    strokeLinecap: "round"
  }), /*#__PURE__*/React.createElement("circle", {
    cx: "125",
    cy: "48",
    r: "2.5",
    fill: "#fff"
  }));
}
function BurstSVG() {
  return /*#__PURE__*/React.createElement("svg", {
    viewBox: "0 0 140 140",
    "aria-hidden": true
  }, /*#__PURE__*/React.createElement("defs", null, /*#__PURE__*/React.createElement("radialGradient", {
    id: "boom",
    cx: "50%",
    cy: "50%",
    r: "50%"
  }, /*#__PURE__*/React.createElement("stop", {
    offset: "0%",
    stopColor: "#FFF7E6"
  }), /*#__PURE__*/React.createElement("stop", {
    offset: "35%",
    stopColor: "#FFB061"
  }), /*#__PURE__*/React.createElement("stop", {
    offset: "70%",
    stopColor: "#F37327"
  }), /*#__PURE__*/React.createElement("stop", {
    offset: "100%",
    stopColor: "rgba(213,90,18,0)"
  }))), /*#__PURE__*/React.createElement("circle", {
    cx: "70",
    cy: "70",
    r: "48",
    fill: "url(#boom)"
  }), /*#__PURE__*/React.createElement("g", {
    stroke: "#FFB061",
    strokeWidth: "3",
    strokeLinecap: "round",
    fill: "none"
  }, /*#__PURE__*/React.createElement("line", {
    x1: "70",
    y1: "14",
    x2: "70",
    y2: "32"
  }), /*#__PURE__*/React.createElement("line", {
    x1: "70",
    y1: "108",
    x2: "70",
    y2: "126"
  }), /*#__PURE__*/React.createElement("line", {
    x1: "14",
    y1: "70",
    x2: "32",
    y2: "70"
  }), /*#__PURE__*/React.createElement("line", {
    x1: "108",
    y1: "70",
    x2: "126",
    y2: "70"
  }), /*#__PURE__*/React.createElement("line", {
    x1: "28",
    y1: "28",
    x2: "42",
    y2: "42"
  }), /*#__PURE__*/React.createElement("line", {
    x1: "98",
    y1: "98",
    x2: "112",
    y2: "112"
  }), /*#__PURE__*/React.createElement("line", {
    x1: "28",
    y1: "112",
    x2: "42",
    y2: "98"
  }), /*#__PURE__*/React.createElement("line", {
    x1: "98",
    y1: "42",
    x2: "112",
    y2: "28"
  })), /*#__PURE__*/React.createElement("circle", {
    cx: "70",
    cy: "70",
    r: "18",
    fill: "#FFF7E6"
  }));
}
function CannonBase() {
  return /*#__PURE__*/React.createElement("svg", {
    className: "base",
    viewBox: "0 0 280 240",
    "aria-hidden": true
  }, /*#__PURE__*/React.createElement("defs", null, /*#__PURE__*/React.createElement("linearGradient", {
    id: "domeG",
    x1: "0",
    y1: "0",
    x2: "0",
    y2: "1"
  }, /*#__PURE__*/React.createElement("stop", {
    offset: "0",
    stopColor: "#FFA362"
  }), /*#__PURE__*/React.createElement("stop", {
    offset: "0.5",
    stopColor: "#F37327"
  }), /*#__PURE__*/React.createElement("stop", {
    offset: "1",
    stopColor: "#A93C08"
  })), /*#__PURE__*/React.createElement("linearGradient", {
    id: "tracksG",
    x1: "0",
    y1: "0",
    x2: "0",
    y2: "1"
  }, /*#__PURE__*/React.createElement("stop", {
    offset: "0",
    stopColor: "#2A2547"
  }), /*#__PURE__*/React.createElement("stop", {
    offset: "1",
    stopColor: "#0A0820"
  })), /*#__PURE__*/React.createElement("linearGradient", {
    id: "metalG",
    x1: "0",
    y1: "0",
    x2: "0",
    y2: "1"
  }, /*#__PURE__*/React.createElement("stop", {
    offset: "0",
    stopColor: "#3a3358"
  }), /*#__PURE__*/React.createElement("stop", {
    offset: "1",
    stopColor: "#15102B"
  }))), /*#__PURE__*/React.createElement("ellipse", {
    cx: "140",
    cy: "226",
    rx: "120",
    ry: "10",
    fill: "rgba(0,0,0,.45)"
  }), /*#__PURE__*/React.createElement("path", {
    d: "M 20,168 L 260,168 L 250,216 L 30,216 Z",
    fill: "url(#tracksG)",
    stroke: "#000",
    strokeWidth: "1"
  }), Array.from({
    length: 12
  }).map((_, i) => /*#__PURE__*/React.createElement("rect", {
    key: i,
    x: 32 + i * 18,
    y: "174",
    width: "12",
    height: "36",
    rx: "2",
    fill: "#3a3358"
  })), [58, 98, 138, 178, 218].map((cx, i) => /*#__PURE__*/React.createElement("g", {
    key: i
  }, /*#__PURE__*/React.createElement("circle", {
    cx: cx,
    cy: "200",
    r: "13",
    fill: "#0A0820"
  }), /*#__PURE__*/React.createElement("circle", {
    cx: cx,
    cy: "200",
    r: "10",
    fill: "#3a3358",
    stroke: "#5a5470",
    strokeWidth: "2"
  }), /*#__PURE__*/React.createElement("circle", {
    cx: cx,
    cy: "200",
    r: "3",
    fill: "#5a5470"
  }))), /*#__PURE__*/React.createElement("path", {
    d: "M 30,140 L 250,140 L 260,168 L 20,168 Z",
    fill: "#1A1530"
  }), /*#__PURE__*/React.createElement("rect", {
    x: "36",
    y: "146",
    width: "208",
    height: "3",
    fill: "rgba(255,255,255,.1)",
    rx: "1"
  }), [60, 100, 140, 180, 220].map((cx, i) => /*#__PURE__*/React.createElement("circle", {
    key: i,
    cx: cx,
    cy: "156",
    r: "3",
    fill: "#5a5470"
  })), /*#__PURE__*/React.createElement("path", {
    d: "M 70,140 Q 140,40 210,140 Z",
    fill: "url(#domeG)"
  }), /*#__PURE__*/React.createElement("path", {
    d: "M 85,128 Q 110,76 138,68",
    stroke: "rgba(255,255,255,.45)",
    strokeWidth: "4",
    fill: "none",
    strokeLinecap: "round"
  }), /*#__PURE__*/React.createElement("ellipse", {
    cx: "140",
    cy: "138",
    rx: "74",
    ry: "10",
    fill: "#0A0820"
  }), /*#__PURE__*/React.createElement("ellipse", {
    cx: "140",
    cy: "135",
    rx: "74",
    ry: "10",
    fill: "#1A1530"
  }), /*#__PURE__*/React.createElement("ellipse", {
    cx: "140",
    cy: "134",
    rx: "68",
    ry: "6",
    fill: "#3a3358"
  }), /*#__PURE__*/React.createElement("path", {
    d: "M 75,138 Q 140,52 205,138",
    stroke: "rgba(0,0,0,.18)",
    strokeWidth: "1",
    fill: "none"
  }), /*#__PURE__*/React.createElement("g", {
    transform: "translate(170 96)"
  }, /*#__PURE__*/React.createElement("rect", {
    x: "-20",
    y: "-20",
    width: "40",
    height: "40",
    rx: "7",
    fill: "#fff"
  }), /*#__PURE__*/React.createElement("image", {
    href: "ez-icon.png",
    x: "-17",
    y: "-17",
    width: "34",
    height: "34"
  })), /*#__PURE__*/React.createElement("line", {
    x1: "100",
    y1: "80",
    x2: "92",
    y2: "36",
    stroke: "#1A1530",
    strokeWidth: "2"
  }), /*#__PURE__*/React.createElement("circle", {
    cx: "92",
    cy: "34",
    r: "3",
    fill: "#F33F3F"
  }), /*#__PURE__*/React.createElement("circle", {
    cx: "62",
    cy: "156",
    r: "6",
    fill: "#FFE6A8"
  }), /*#__PURE__*/React.createElement("circle", {
    cx: "62",
    cy: "156",
    r: "3",
    fill: "#FFF"
  }));
}
function CannonBarrel() {
  return /*#__PURE__*/React.createElement("svg", {
    viewBox: "0 0 220 60",
    "aria-hidden": true
  }, /*#__PURE__*/React.createElement("defs", null, /*#__PURE__*/React.createElement("linearGradient", {
    id: "barG",
    x1: "0",
    y1: "0",
    x2: "0",
    y2: "1"
  }, /*#__PURE__*/React.createElement("stop", {
    offset: "0",
    stopColor: "#3a3358"
  }), /*#__PURE__*/React.createElement("stop", {
    offset: "0.5",
    stopColor: "#1A1530"
  }), /*#__PURE__*/React.createElement("stop", {
    offset: "1",
    stopColor: "#0A0820"
  })), /*#__PURE__*/React.createElement("linearGradient", {
    id: "muzzleG",
    x1: "0",
    y1: "0",
    x2: "0",
    y2: "1"
  }, /*#__PURE__*/React.createElement("stop", {
    offset: "0",
    stopColor: "#5a5470"
  }), /*#__PURE__*/React.createElement("stop", {
    offset: "1",
    stopColor: "#2A2547"
  }))), /*#__PURE__*/React.createElement("rect", {
    x: "14",
    y: "22",
    width: "36",
    height: "20",
    rx: "4",
    fill: "#1A1530"
  }), /*#__PURE__*/React.createElement("rect", {
    x: "14",
    y: "22",
    width: "36",
    height: "3",
    fill: "rgba(255,255,255,.18)"
  }), /*#__PURE__*/React.createElement("rect", {
    x: "40",
    y: "26",
    width: "150",
    height: "12",
    rx: "4",
    fill: "url(#barG)"
  }), /*#__PURE__*/React.createElement("rect", {
    x: "42",
    y: "27",
    width: "146",
    height: "2",
    rx: "1",
    fill: "rgba(255,255,255,.25)"
  }), /*#__PURE__*/React.createElement("rect", {
    x: "184",
    y: "22",
    width: "22",
    height: "20",
    rx: "3",
    fill: "url(#muzzleG)"
  }), /*#__PURE__*/React.createElement("rect", {
    x: "188",
    y: "26",
    width: "2",
    height: "12",
    fill: "#0A0820"
  }), /*#__PURE__*/React.createElement("rect", {
    x: "194",
    y: "26",
    width: "2",
    height: "12",
    fill: "#0A0820"
  }), /*#__PURE__*/React.createElement("rect", {
    x: "200",
    y: "26",
    width: "2",
    height: "12",
    fill: "#0A0820"
  }), /*#__PURE__*/React.createElement("rect", {
    x: "22",
    y: "14",
    width: "6",
    height: "10",
    fill: "#1A1530"
  }), /*#__PURE__*/React.createElement("circle", {
    cx: "25",
    cy: "13",
    r: "3",
    fill: "#F33F3F"
  }));
}
function Mountains() {
  return /*#__PURE__*/React.createElement("div", {
    className: "gm-horizon"
  }, /*#__PURE__*/React.createElement("svg", {
    viewBox: "0 0 1600 240",
    preserveAspectRatio: "none",
    "aria-hidden": true
  }, /*#__PURE__*/React.createElement("path", {
    d: "M0,150 L120,90 L240,130 L380,70 L520,118 L660,82 L800,124 L940,86 L1080,128 L1220,94 L1360,126 L1500,90 L1600,118 L1600,240 L0,240 Z",
    fill: "#B6B1E0"
  }), /*#__PURE__*/React.createElement("path", {
    d: "M0,200 L160,140 L300,180 L440,118 L580,158 L720,128 L860,168 L1000,134 L1140,170 L1280,140 L1420,176 L1560,148 L1600,164 L1600,240 L0,240 Z",
    fill: "#8E89C8"
  })));
}
function SkyZ() {
  return /*#__PURE__*/React.createElement("div", {
    className: "gm-sky-z",
    "aria-hidden": true
  }, /*#__PURE__*/React.createElement("div", {
    className: "z",
    style: {
      top: "6%",
      left: "8%",
      width: "26%",
      background: "rgba(255,255,255,.65)"
    }
  }), /*#__PURE__*/React.createElement("div", {
    className: "z",
    style: {
      top: "10%",
      left: "46%",
      width: "20%",
      background: "rgba(255,255,255,.5)"
    }
  }), /*#__PURE__*/React.createElement("div", {
    className: "z",
    style: {
      top: "18%",
      left: "22%",
      width: "14%",
      background: "rgba(255,255,255,.35)"
    }
  }), /*#__PURE__*/React.createElement("div", {
    className: "z",
    style: {
      top: "26%",
      left: "62%",
      width: "22%",
      background: "rgba(255,255,255,.4)"
    }
  }));
}
function Heart({
  lost
}) {
  return /*#__PURE__*/React.createElement("svg", {
    viewBox: "0 0 24 24",
    className: lost ? "lost" : ""
  }, /*#__PURE__*/React.createElement("path", {
    fill: "#F33F3F",
    d: "M12 21s-7.5-4.7-9.6-9.5C.9 7.7 3.5 4 7.2 4c2 0 3.6 1 4.8 2.6C13.2 5 14.8 4 16.8 4c3.7 0 6.3 3.7 4.8 7.5C19.5 16.3 12 21 12 21z"
  }));
}
const I = {
  pause: () => /*#__PURE__*/React.createElement("svg", {
    viewBox: "0 0 24 24",
    width: "16",
    height: "16",
    fill: "currentColor"
  }, /*#__PURE__*/React.createElement("path", {
    d: "M9 5h2v14H9zM13 5h2v14h-2z"
  })),
  speaker: () => /*#__PURE__*/React.createElement("svg", {
    viewBox: "0 0 24 24",
    width: "18",
    height: "18",
    fill: "currentColor"
  }, /*#__PURE__*/React.createElement("path", {
    d: "M3 10v4a1 1 0 0 0 1 1h3l4 3.5a1 1 0 0 0 1.6-.8V6.3a1 1 0 0 0-1.6-.8L7 9H4a1 1 0 0 0-1 1Z"
  })),
  speakerMute: () => /*#__PURE__*/React.createElement("svg", {
    viewBox: "0 0 24 24",
    width: "18",
    height: "18",
    fill: "none",
    stroke: "currentColor",
    strokeWidth: "2.2",
    strokeLinecap: "round",
    strokeLinejoin: "round"
  }, /*#__PURE__*/React.createElement("path", {
    d: "M3 10v4a1 1 0 0 0 1 1h3l4 3.5a1 1 0 0 0 1.6-.8V6.3a1 1 0 0 0-1.6-.8L7 9H4a1 1 0 0 0-1 1Z",
    fill: "currentColor",
    stroke: "none"
  }), /*#__PURE__*/React.createElement("path", {
    d: "M16 8l5 5M21 8l-5 5"
  })),
  expand: () => /*#__PURE__*/React.createElement("svg", {
    viewBox: "0 0 24 24",
    width: "18",
    height: "18",
    fill: "none",
    stroke: "currentColor",
    strokeWidth: "2.2",
    strokeLinecap: "round",
    strokeLinejoin: "round"
  }, /*#__PURE__*/React.createElement("path", {
    d: "M4 9V4h5M20 9V4h-5M4 15v5h5M20 15v5h-5"
  })),
  home: () => /*#__PURE__*/React.createElement("svg", {
    viewBox: "0 0 24 24",
    width: "20",
    height: "20",
    fill: "none",
    stroke: "currentColor",
    strokeWidth: "2.2",
    strokeLinecap: "round",
    strokeLinejoin: "round"
  }, /*#__PURE__*/React.createElement("path", {
    d: "M3 11l9-8 9 8"
  }), /*#__PURE__*/React.createElement("path", {
    d: "M5 10v10h14V10"
  }), /*#__PURE__*/React.createElement("path", {
    d: "M10 20v-6h4v6"
  })),
  trophy: () => /*#__PURE__*/React.createElement("svg", {
    viewBox: "0 0 24 24",
    width: "22",
    height: "22",
    fill: "none",
    stroke: "currentColor",
    strokeWidth: "2.2",
    strokeLinecap: "round",
    strokeLinejoin: "round"
  }, /*#__PURE__*/React.createElement("path", {
    d: "M8 21h8M12 17v4M7 4h10v5a5 5 0 0 1-10 0V4z"
  }), /*#__PURE__*/React.createElement("path", {
    d: "M7 6H4v2a3 3 0 0 0 3 3M17 6h3v2a3 3 0 0 1-3 3"
  }))
};
function ScopeIcon() {
  return /*#__PURE__*/React.createElement("svg", {
    viewBox: "0 0 32 32",
    fill: "none",
    stroke: "#F37327",
    strokeWidth: "2.2"
  }, /*#__PURE__*/React.createElement("circle", {
    cx: "16",
    cy: "16",
    r: "11"
  }), /*#__PURE__*/React.createElement("path", {
    d: "M16 2v6 M16 24v6 M2 16h6 M24 16h6",
    strokeLinecap: "round"
  }), /*#__PURE__*/React.createElement("circle", {
    cx: "16",
    cy: "16",
    r: "2",
    fill: "#F37327",
    stroke: "none"
  }));
}

/* ──────────────────────────────────────────────
   Stage scaler: fits 1600×900 into viewport, letterboxing.
   ────────────────────────────────────────────── */
function useStageScale(designW, designH) {
  const [scale, setScale] = useState(1);
  useLayoutEffect(() => {
    const recalc = () => {
      const w = window.innerWidth;
      const h = window.innerHeight;
      setScale(Math.min(w / designW, h / designH));
    };
    recalc();
    window.addEventListener("resize", recalc);
    return () => window.removeEventListener("resize", recalc);
  }, [designW, designH]);
  return scale;
}

/* ──────────────────────────────────────────────
   Upload screen — load Excel/CSV
   ────────────────────────────────────────────── */
function UploadScreen({
  onLoad
}) {
  const [drag, setDrag] = useState(false);
  const [err, setErr] = useState(null);
  const [busy, setBusy] = useState(false);
  const inputRef = useRef(null);
  const handle = useCallback(async file => {
    if (!file) return;
    setErr(null);
    setBusy(true);
    try {
      const entries = await parseSpreadsheet(file);
      onLoad(entries, file.name);
    } catch (e) {
      setErr(e.message || "שגיאה בקריאת הקובץ");
    } finally {
      setBusy(false);
    }
  }, [onLoad]);
  const onDrop = e => {
    e.preventDefault();
    setDrag(false);
    const f = e.dataTransfer?.files?.[0];
    if (f) handle(f);
  };
  return /*#__PURE__*/React.createElement("div", {
    className: "gm-app gm-up-app"
  }, /*#__PURE__*/React.createElement("div", {
    className: "gm-up-wrap"
  }, /*#__PURE__*/React.createElement("div", {
    className: "gm-up-card"
  }, /*#__PURE__*/React.createElement("div", {
    className: "gm-up-eye"
  }, /*#__PURE__*/React.createElement("span", {
    className: "brand-eazy"
  }, "eazy"), " \xB7 \u05DE\u05E9\u05D7\u05E7 \u05DE\u05D9\u05DC\u05D9\u05DD"), /*#__PURE__*/React.createElement("h1", {
    className: "gm-up-h1"
  }, "\u05D8\u05E2\u05E0\u05D5 \u05DE\u05D9\u05DC\u05D5\u05DF \u05DC\u05DE\u05E9\u05D7\u05E7."), /*#__PURE__*/React.createElement("p", {
    className: "gm-up-sub"
  }, "\u05E7\u05D5\u05D1\u05E5 Excel \u05D0\u05D5 CSV. \u05E2\u05DE\u05D5\u05D3\u05D4 B = \u05DE\u05D9\u05DC\u05D4 \u05D1\u05D0\u05E0\u05D2\u05DC\u05D9\u05EA, \u05E2\u05DE\u05D5\u05D3\u05D4 C = \u05E4\u05D9\u05E8\u05D5\u05E9 \u05D1\u05E2\u05D1\u05E8\u05D9\u05EA. \u05E0\u05D1\u05D7\u05E8 \u05D1\u05DB\u05DC \u05E1\u05D9\u05D1\u05D5\u05D1 4 \u05DE\u05D9\u05DC\u05D9\u05DD: \u05D0\u05D7\u05EA \u05D4\u05E0\u05DB\u05D5\u05E0\u05D4, \u05E9\u05DC\u05D5\u05E9 \u05D0\u05D7\u05E8\u05D5\u05EA \u05DE\u05D4\u05DE\u05D9\u05DC\u05D5\u05DF \u05DB\u05DE\u05E1\u05D9\u05D7\u05D9\u05DD."), /*#__PURE__*/React.createElement("div", {
    className: "gm-dropzone " + (drag ? "drag" : ""),
    onClick: () => inputRef.current?.click(),
    onDragOver: e => {
      e.preventDefault();
      setDrag(true);
    },
    onDragLeave: () => setDrag(false),
    onDrop: onDrop
  }, /*#__PURE__*/React.createElement("div", {
    className: "gm-dz-icon"
  }, /*#__PURE__*/React.createElement("svg", {
    viewBox: "0 0 32 32",
    width: "42",
    height: "42",
    fill: "none",
    stroke: "#F37327",
    strokeWidth: "2",
    strokeLinecap: "round",
    strokeLinejoin: "round"
  }, /*#__PURE__*/React.createElement("path", {
    d: "M16 4v18"
  }), /*#__PURE__*/React.createElement("path", {
    d: "M9 11l7-7 7 7"
  }), /*#__PURE__*/React.createElement("path", {
    d: "M4 26h24"
  }))), /*#__PURE__*/React.createElement("div", {
    className: "gm-dz-title"
  }, "\u05D2\u05E8\u05E8\u05D5 \u05DC\u05DB\u05D0\u05DF \u05D0\u05D5 \u05DC\u05D7\u05E6\u05D5"), /*#__PURE__*/React.createElement("div", {
    className: "gm-dz-sub"
  }, ".xlsx / .xls / .csv"), /*#__PURE__*/React.createElement("input", {
    ref: inputRef,
    type: "file",
    accept: ".xlsx,.xls,.csv,application/vnd.ms-excel,application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",
    style: {
      display: "none"
    },
    onChange: e => handle(e.target.files[0])
  })), busy && /*#__PURE__*/React.createElement("div", {
    className: "gm-up-info"
  }, "\u05E7\u05D5\u05E8\u05D0\u05D9 \u05D0\u05EA \u05D4\u05E7\u05D5\u05D1\u05E5\u2026"), err && /*#__PURE__*/React.createElement("div", {
    className: "gm-up-err"
  }, err), /*#__PURE__*/React.createElement("div", {
    className: "gm-up-or"
  }, "\u2014 \u05D0\u05D5 \u2014"), /*#__PURE__*/React.createElement("button", {
    className: "gm-up-btn-ghost",
    onClick: () => onLoad(SAMPLE_DICT, "מילון לדוגמה")
  }, "\u05D4\u05EA\u05D7\u05D9\u05DC\u05D5 \u05E2\u05DD \u05DE\u05D9\u05DC\u05D5\u05DF \u05D3\u05D5\u05D2\u05DE\u05D4 (", SAMPLE_DICT.length, " \u05DE\u05D9\u05DC\u05D9\u05DD)"), /*#__PURE__*/React.createElement("div", {
    className: "gm-up-format"
  }, /*#__PURE__*/React.createElement("div", {
    className: "gm-fmt-title"
  }, "\u05E4\u05D5\u05E8\u05DE\u05D8 \u05D4\u05E7\u05D5\u05D1\u05E5:"), /*#__PURE__*/React.createElement("table", null, /*#__PURE__*/React.createElement("thead", null, /*#__PURE__*/React.createElement("tr", null, /*#__PURE__*/React.createElement("th", null, "A"), /*#__PURE__*/React.createElement("th", null, "B \u2014 English"), /*#__PURE__*/React.createElement("th", null, "C \u2014 \u05E2\u05D1\u05E8\u05D9\u05EA"))), /*#__PURE__*/React.createElement("tbody", null, /*#__PURE__*/React.createElement("tr", null, /*#__PURE__*/React.createElement("td", null, "1"), /*#__PURE__*/React.createElement("td", {
    dir: "ltr"
  }, "enhance"), /*#__PURE__*/React.createElement("td", null, "\u05DC\u05D4\u05E2\u05E6\u05D9\u05DD, \u05DC\u05E9\u05E4\u05E8")), /*#__PURE__*/React.createElement("tr", null, /*#__PURE__*/React.createElement("td", null, "2"), /*#__PURE__*/React.createElement("td", {
    dir: "ltr"
  }, "mitigate"), /*#__PURE__*/React.createElement("td", null, "\u05DC\u05D4\u05E7\u05DC, \u05DC\u05DE\u05EA\u05DF")), /*#__PURE__*/React.createElement("tr", null, /*#__PURE__*/React.createElement("td", null, "3"), /*#__PURE__*/React.createElement("td", {
    dir: "ltr"
  }, "ambiguous"), /*#__PURE__*/React.createElement("td", null, "\u05D3\u05D5-\u05DE\u05E9\u05DE\u05E2\u05D9")))), /*#__PURE__*/React.createElement("div", {
    className: "gm-fmt-note"
  }, "\u05E9\u05D5\u05E8\u05EA \u05DB\u05D5\u05EA\u05E8\u05EA \u05EA\u05D6\u05D5\u05D4\u05D4 \u05D0\u05D5\u05D8\u05D5\u05DE\u05D8\u05D9\u05EA. \u05E2\u05DE\u05D5\u05D3\u05D4 A \u05DE\u05EA\u05E2\u05DC\u05DE\u05D9\u05DD \u05DE\u05DE\u05E0\u05D4 (\u05DE\u05E1\u05E4\u05D5\u05E8 / \u05DE\u05D6\u05D4\u05D4).")))));
}

/* ──────────────────────────────────────────────
   Intro screen — first thing the user sees
   ───────────────────────────────────────────── */
function IntroScreen({
  onStart,
  toggleFullscreen,
  muted,
  toggleMute
}) {
  const scale = useStageScale(1600, 900);
  // Combined handler: enter fullscreen on the user's tap (must come from a
  // gesture) and then start the round. Failures are non-fatal — we still
  // start the game even if the browser blocks fullscreen.
  const startAndFullscreen = () => {
    try {
      const el = document.documentElement;
      const req = el.requestFullscreen || el.webkitRequestFullscreen || el.msRequestFullscreen;
      if (req && !document.fullscreenElement && !document.webkitFullscreenElement) {
        const p = req.call(el);
        if (p && typeof p.catch === 'function') p.catch(() => {});
      }
    } catch (e) {}
    onStart();
  };
  return /*#__PURE__*/React.createElement("div", {
    className: "gm-app"
  }, /*#__PURE__*/React.createElement("div", {
    className: "gm-stage gm-intro-stage",
    style: {
      "--gm-scale": scale
    }
  }, /*#__PURE__*/React.createElement(SkyZ, null), /*#__PURE__*/React.createElement(Mountains, null), /*#__PURE__*/React.createElement("div", {
    className: "gm-ground"
  }), /*#__PURE__*/React.createElement("div", {
    className: "gm-hud-brand"
  }, /*#__PURE__*/React.createElement("img", {
    src: "ez-icon.png",
    alt: ""
  }), /*#__PURE__*/React.createElement("span", {
    className: "brand-eazy"
  }, "eazy")), /*#__PURE__*/React.createElement("div", {
    className: "gm-cannon gm-intro-cannon"
  }, /*#__PURE__*/React.createElement(CannonBase, null), /*#__PURE__*/React.createElement("div", {
    className: "barrel-wrap"
  }, /*#__PURE__*/React.createElement("svg", {
    style: {
      position: "absolute",
      width: "220px",
      height: "60px",
      top: "-30px",
      left: "-30px",
      transformOrigin: "30px 30px",
      transform: `rotate(-22deg)`,
      overflow: "visible"
    },
    viewBox: "0 0 220 60"
  }, /*#__PURE__*/React.createElement("defs", null, /*#__PURE__*/React.createElement("linearGradient", {
    id: "barG3",
    x1: "0",
    y1: "0",
    x2: "0",
    y2: "1"
  }, /*#__PURE__*/React.createElement("stop", {
    offset: "0",
    stopColor: "#3a3358"
  }), /*#__PURE__*/React.createElement("stop", {
    offset: "0.5",
    stopColor: "#1A1530"
  }), /*#__PURE__*/React.createElement("stop", {
    offset: "1",
    stopColor: "#0A0820"
  })), /*#__PURE__*/React.createElement("linearGradient", {
    id: "muzzleG3",
    x1: "0",
    y1: "0",
    x2: "0",
    y2: "1"
  }, /*#__PURE__*/React.createElement("stop", {
    offset: "0",
    stopColor: "#5a5470"
  }), /*#__PURE__*/React.createElement("stop", {
    offset: "1",
    stopColor: "#2A2547"
  }))), /*#__PURE__*/React.createElement("rect", {
    x: "14",
    y: "22",
    width: "36",
    height: "20",
    rx: "4",
    fill: "#1A1530"
  }), /*#__PURE__*/React.createElement("rect", {
    x: "14",
    y: "22",
    width: "36",
    height: "3",
    fill: "rgba(255,255,255,.18)"
  }), /*#__PURE__*/React.createElement("rect", {
    x: "40",
    y: "26",
    width: "150",
    height: "12",
    rx: "4",
    fill: "url(#barG3)"
  }), /*#__PURE__*/React.createElement("rect", {
    x: "42",
    y: "27",
    width: "146",
    height: "2",
    rx: "1",
    fill: "rgba(255,255,255,.25)"
  }), /*#__PURE__*/React.createElement("rect", {
    x: "184",
    y: "22",
    width: "22",
    height: "20",
    rx: "3",
    fill: "url(#muzzleG3)"
  }), /*#__PURE__*/React.createElement("rect", {
    x: "188",
    y: "26",
    width: "2",
    height: "12",
    fill: "#0A0820"
  }), /*#__PURE__*/React.createElement("rect", {
    x: "194",
    y: "26",
    width: "2",
    height: "12",
    fill: "#0A0820"
  }), /*#__PURE__*/React.createElement("rect", {
    x: "200",
    y: "26",
    width: "2",
    height: "12",
    fill: "#0A0820"
  }), /*#__PURE__*/React.createElement("rect", {
    x: "22",
    y: "14",
    width: "6",
    height: "10",
    fill: "#1A1530"
  }), /*#__PURE__*/React.createElement("circle", {
    cx: "25",
    cy: "13",
    r: "3",
    fill: "#F33F3F"
  })))), /*#__PURE__*/React.createElement("div", {
    className: "gm-intro-text"
  }, /*#__PURE__*/React.createElement("div", {
    className: "gm-intro-eye"
  }, "\u05DE\u05E9\u05D7\u05E7 \u05D0\u05E0\u05D2\u05DC\u05D9\u05EA \u05DE\u05D1\u05D9\u05EA ", /*#__PURE__*/React.createElement("span", {
    className: "en brand-eazy"
  }, "eazy")), /*#__PURE__*/React.createElement("h1", {
    className: "gm-intro-title"
  }, "\u05EA\u05D5\u05EA\u05D7 \u05DE\u05D9\u05DC\u05D9\u05DD", /*#__PURE__*/React.createElement("span", {
    className: "dot"
  }, ".")), /*#__PURE__*/React.createElement("p", {
    className: "gm-intro-lead"
  }, "\u05E2\u05D5\u05DE\u05D3\u05D9\u05DD \u05DC\u05E8\u05E9\u05D5\u05EA\u05DB\u05DD \u05EA\u05D5\u05EA\u05D7 \u05DE\u05D9\u05DC\u05D9\u05DD \u05D5\u05D4\u05D9\u05D3\u05E2 \u05E9\u05DC\u05DB\u05DD \u05D1\u05D0\u05E0\u05D2\u05DC\u05D9\u05EA."), /*#__PURE__*/React.createElement("p", {
    className: "gm-intro-body"
  }, "\u05D1\u05EA\u05D7\u05EA\u05D9\u05EA \u05D4\u05DE\u05E1\u05DA \u05DE\u05D5\u05E4\u05D9\u05E2\u05D4 \u05DE\u05D9\u05DC\u05D4 \u05D1\u05D0\u05E0\u05D2\u05DC\u05D9\u05EA. \u05D6\u05D4\u05D5 \u05D0\u05EA \u05D4\u05D8\u05D9\u05DC \u05E2\u05DD \u05D4\u05E4\u05D9\u05E8\u05D5\u05E9 \u05D4\u05DE\u05EA\u05D0\u05D9\u05DD \u05D5\u05EA\u05DC\u05D7\u05E6\u05D5 \u05E2\u05DC\u05D9\u05D5.", /*#__PURE__*/React.createElement("br", null), "\u05DB\u05DB\u05DC \u05E9\u05E2\u05D5\u05E0\u05D9\u05DD \u05DE\u05D4\u05E8 \u05D9\u05D5\u05EA\u05E8, \u05E6\u05D5\u05D1\u05E8\u05D9\u05DD \u05D9\u05D5\u05EA\u05E8 \u05E0\u05E7\u05D5\u05D3\u05D5\u05EA. \u05D1\u05D4\u05E6\u05DC\u05D7\u05D4!")), /*#__PURE__*/React.createElement("button", {
    className: "gm-intro-cta",
    onClick: startAndFullscreen
  }, /*#__PURE__*/React.createElement("span", null, "\u05DC\u05D4\u05EA\u05D7\u05D9\u05DC \u05DC\u05E9\u05D7\u05E7"), /*#__PURE__*/React.createElement("svg", {
    viewBox: "0 0 24 24",
    width: "28",
    height: "28",
    fill: "none",
    stroke: "currentColor",
    strokeWidth: "2.6",
    strokeLinecap: "round",
    strokeLinejoin: "round"
  }, /*#__PURE__*/React.createElement("path", {
    d: "M19 12H5"
  }), /*#__PURE__*/React.createElement("path", {
    d: "M12 19l-7-7 7-7"
  }))), /*#__PURE__*/React.createElement("div", {
    className: "gm-foot-actions"
  }, /*#__PURE__*/React.createElement("button", {
    className: "foot-btn",
    onClick: () => {
      try {
        window.top.location.href = "https://www.ezway.co.il";
      } catch (e) {
        window.open("https://www.ezway.co.il", "_top");
      }
    },
    title: "\u05D0\u05EA\u05E8 \u05D4\u05D1\u05D9\u05EA"
  }, /*#__PURE__*/React.createElement(I.home, null)), /*#__PURE__*/React.createElement("button", {
    className: "foot-btn",
    onClick: toggleFullscreen,
    title: "\u05DE\u05E1\u05DA \u05DE\u05DC\u05D0"
  }, /*#__PURE__*/React.createElement(I.expand, null)), /*#__PURE__*/React.createElement("button", {
    className: "foot-btn" + (muted ? " muted" : ""),
    onClick: toggleMute,
    title: muted ? "השמע צלילים" : "השתק צלילים"
  }, muted ? /*#__PURE__*/React.createElement(I.speakerMute, null) : /*#__PURE__*/React.createElement(I.speaker, null)))));
}
function EndScreen({
  score,
  missedWords,
  onRestart
}) {
  const [submitted, setSubmitted] = useState(false);
  const [name, setName] = useState("");
  const [board, setBoard] = useState(() => getLeaderboard());
  const [showLb, setShowLb] = useState(false);
  const qualifies = qualifiesForLeaderboard(score) && !submitted;
  const submitName = () => {
    const newBoard = addToLeaderboard(name.trim() || "אנונימי", score);
    setBoard(newBoard);
    setSubmitted(true);
    setShowLb(true); // auto-open to show new ranking
  };
  return /*#__PURE__*/React.createElement("div", {
    className: "gm-app gm-end-app"
  }, /*#__PURE__*/React.createElement("div", {
    className: "gm-end-hud"
  }, /*#__PURE__*/React.createElement("button", {
    className: "gm-end-home",
    onClick: () => {
      try {
        window.top.location.href = "https://www.ezway.co.il";
      } catch (e) {
        window.open("https://www.ezway.co.il", "_top");
      }
    },
    title: "\u05D0\u05EA\u05E8 \u05D4\u05D1\u05D9\u05EA",
    "aria-label": "\u05DC\u05D0\u05EA\u05E8 eazy"
  }, /*#__PURE__*/React.createElement(I.home, null)), /*#__PURE__*/React.createElement("div", {
    className: "gm-end-brand"
  }, /*#__PURE__*/React.createElement("img", {
    src: "ez-icon.png",
    alt: ""
  }), /*#__PURE__*/React.createElement("span", {
    className: "brand-eazy"
  }, "eazy"))), /*#__PURE__*/React.createElement("div", {
    className: "gm-end-score"
  }, /*#__PURE__*/React.createElement("div", {
    className: "gm-end-score-text"
  }, /*#__PURE__*/React.createElement("div", {
    className: "gm-end-eye"
  }, "\u05E1\u05D5\u05E3 \u05E1\u05D9\u05D1\u05D5\u05D1", /*#__PURE__*/React.createElement("span", {
    className: "dot"
  }, ".")), /*#__PURE__*/React.createElement("div", {
    className: "gm-end-line"
  }, /*#__PURE__*/React.createElement("span", null, "\u05D4\u05E9\u05D2\u05EA"), /*#__PURE__*/React.createElement("span", {
    className: "num"
  }, score), /*#__PURE__*/React.createElement("span", null, "\u05E0\u05E7\u05D5\u05D3\u05D5\u05EA."))), qualifies ? /*#__PURE__*/React.createElement("div", {
    className: "gm-lb-prompt"
  }, /*#__PURE__*/React.createElement("div", {
    className: "gm-lb-prompt-eye"
  }, /*#__PURE__*/React.createElement(I.trophy, null), " \u05E0\u05DB\u05E0\u05E1\u05EA \u05DC\u05D8\u05D1\u05DC\u05EA \u05D4\u05E9\u05D9\u05D0\u05D9\u05DD!"), /*#__PURE__*/React.createElement("div", {
    className: "gm-lb-prompt-row"
  }, /*#__PURE__*/React.createElement("input", {
    className: "gm-lb-input",
    type: "text",
    placeholder: "\u05D4\u05E9\u05DD \u05E9\u05DC\u05DA",
    value: name,
    onChange: e => setName(e.target.value),
    onKeyDown: e => e.key === 'Enter' && submitName(),
    maxLength: 20,
    autoFocus: true
  }), /*#__PURE__*/React.createElement("button", {
    className: "gm-lb-save",
    onClick: submitName
  }, "\u05E9\u05DE\u05D5\u05E8"))) : /*#__PURE__*/React.createElement("button", {
    className: "gm-end-cta secondary gm-end-lb-btn",
    onClick: () => setShowLb(true)
  }, /*#__PURE__*/React.createElement(I.trophy, null), /*#__PURE__*/React.createElement("span", null, "\u05D8\u05D1\u05DC\u05EA \u05D4\u05E9\u05D9\u05D0\u05D9\u05DD"))), /*#__PURE__*/React.createElement("div", {
    className: "gm-end-vrule"
  }), /*#__PURE__*/React.createElement("div", {
    className: "gm-end-list-wrap"
  }, missedWords.length > 0 ? /*#__PURE__*/React.createElement(React.Fragment, null, /*#__PURE__*/React.createElement("div", {
    className: "gm-end-list-eye"
  }, "\u05D0\u05DC\u05D5 \u05D4\u05DE\u05D9\u05DC\u05D9\u05DD \u05E9\u05E4\u05E1\u05E4\u05E1\u05EA"), /*#__PURE__*/React.createElement("div", {
    className: "gm-end-list"
  }, missedWords.map((w, i) => /*#__PURE__*/React.createElement("div", {
    key: i,
    className: "gm-end-row"
  }, /*#__PURE__*/React.createElement("span", {
    className: "gm-end-en"
  }, String(w.en).toUpperCase()), /*#__PURE__*/React.createElement("span", {
    className: "gm-end-he"
  }, w.he))))) : /*#__PURE__*/React.createElement("div", {
    className: "gm-end-no-miss"
  }, /*#__PURE__*/React.createElement("span", {
    className: "hi"
  }, "\u05DB\u05DC \u05D4\u05DB\u05D1\u05D5\u05D3", /*#__PURE__*/React.createElement("span", {
    className: "dot"
  }, "!")), /*#__PURE__*/React.createElement("span", {
    className: "lo"
  }, "\u05DC\u05D0 \u05E4\u05E1\u05E4\u05E1\u05EA \u05D0\u05E3 \u05DE\u05D9\u05DC\u05D4.")), /*#__PURE__*/React.createElement("button", {
    className: "gm-end-cta gm-end-restart",
    onClick: onRestart
  }, /*#__PURE__*/React.createElement("span", null, "\u05D9\u05D5\u05E6\u05D0\u05D9\u05DD \u05DC\u05E1\u05D9\u05D1\u05D5\u05D1 \u05E0\u05D5\u05E1\u05E3 \u05E2\u05DD \u05D4\u05EA\u05D5\u05EA\u05D7?"), /*#__PURE__*/React.createElement("span", {
    className: "cta-arrow",
    "aria-hidden": true
  }, "\u203A"))), showLb && /*#__PURE__*/React.createElement("div", {
    className: "gm-lb-modal",
    onClick: () => setShowLb(false)
  }, /*#__PURE__*/React.createElement("div", {
    className: "gm-lb-modal-card",
    onClick: e => e.stopPropagation()
  }, /*#__PURE__*/React.createElement("button", {
    className: "gm-lb-close",
    onClick: () => setShowLb(false),
    "aria-label": "\u05E1\u05D2\u05D5\u05E8"
  }, "\xD7"), /*#__PURE__*/React.createElement("div", {
    className: "gm-lb-title"
  }, /*#__PURE__*/React.createElement(I.trophy, null), /*#__PURE__*/React.createElement("span", null, "\u05D8\u05D1\u05DC\u05EA \u05D4\u05E9\u05D9\u05D0\u05D9\u05DD")), board.length === 0 ? /*#__PURE__*/React.createElement("div", {
    className: "gm-lb-empty"
  }, "\u05E2\u05D3\u05D9\u05D9\u05DF \u05D0\u05D9\u05DF \u05E9\u05D9\u05D0\u05D9\u05DD. \u05D0\u05EA\u05D4 \u05D9\u05DB\u05D5\u05DC \u05DC\u05D4\u05D9\u05D5\u05EA \u05D4\u05E8\u05D0\u05E9\u05D5\u05DF.") : /*#__PURE__*/React.createElement("ol", {
    className: "gm-lb-list"
  }, board.map((entry, i) => /*#__PURE__*/React.createElement("li", {
    key: i,
    className: "gm-lb-row " + (submitted && entry.score === score && entry.name === (name.trim() || "אנונימי") ? "you" : "")
  }, /*#__PURE__*/React.createElement("span", {
    className: "rank"
  }, i + 1), /*#__PURE__*/React.createElement("span", {
    className: "name"
  }, entry.name), /*#__PURE__*/React.createElement("span", {
    className: "pts"
  }, entry.score)))))));
}

/* ──────────────────────────────────────────────
   Game
   ────────────────────────────────────────────── */
function QuizGameServer() {
  const [started, setStarted] = useState(false);
  const [dict, setDict] = useState(null);
  const [dictName, setDictName] = useState("");
  const [used, setUsed] = useState([]);
  const [missed, setMissed] = useState([]);
  const [question, setQuestion] = useState(null);
  const [lives, setLives] = useState(3);
  const [score, setScore] = useState(0);
  const [aimed, setAimed] = useState(null);
  const [resolved, setResolved] = useState({});
  const [angle, setAngle] = useState(-18);
  const [shot, setShot] = useState(null);
  const [toast, setToast] = useState(null);
  const [missFx, setMissFx] = useState(false);
  const [recoil, setRecoil] = useState(false);
  const [levelUpInfo, setLevelUpInfo] = useState(null);
  const [audioUnlocked, setAudioUnlocked] = useState(false);
  const [autoSpeakEnabled, setAutoSpeakEnabled] = useState(true);
  // streak (consecutive correct answers), and the last time a streak bonus
  // fired — combo bonuses are gated to once per 5 minutes so they stay rare.
  const [streak, setStreak] = useState(0);
  const lastBonusTimeRef = useRef(0);
  const questionStartRef = useRef(Date.now());
  const [muted, setMuted] = useState(Sound.muted);
  // lifelines & bonuses
  const [fiftyAvailable, setFiftyAvailable] = useState(true);
  const [hiddenIdx, setHiddenIdx] = useState(() => new Set());
  const [kitState, setKitState] = useState(null);
  const prevQuestionEnRef = useRef(null);
  const prevLevelRef = useRef(0);
  const stageRef = useRef(null);
  const cannonRef = useRef(null);
  const rocketRefs = useRef([]);
  const scale = useStageScale(1600, 900);

  // ── level system: every 15 questions speeds up + raises points ──
  const level = Math.floor(used.length / 15);
  const rocketDur = Math.max(8, 22 - level * 3); // seconds, min 8s
  const pointsPerHit = 200 + level * 100;
  useEffect(() => {
    if (level > prevLevelRef.current && used.length > 0) {
      setLevelUpInfo({
        sub: `הטילים מהירים יותר · +${pointsPerHit} לכל תשובה נכונה`
      });
      const t = setTimeout(() => setLevelUpInfo(null), 2600);
      prevLevelRef.current = level;
      return () => clearTimeout(t);
    }
    prevLevelRef.current = level;
  }, [level, used.length, pointsPerHit]);

  // ── BOSS question + audio unlock ──
  // The 6th question (after 5 normal answers) is a one-time BOSS round. Hitting
  // it unlocks the per-word speaker icon for the rest of the run.
  const isBoss = used.length === 5 && !audioUnlocked;

  // Speak the current English word via the browser's SpeechSynthesis. Works
  // regardless of the game's mute toggle (those are SFX/music; this is content).
  const speakWord = useCallback(text => {
    if (!text) return;
    try {
      const synth = window.speechSynthesis;
      if (!synth) return;
      synth.cancel();
      const u = new SpeechSynthesisUtterance(String(text));
      u.lang = 'en-US';
      u.rate = 0.85;
      u.pitch = 1.0;
      u.volume = 1.0;
      // Prefer a real English voice if the browser has finished loading them.
      try {
        const voices = synth.getVoices ? synth.getVoices() : [];
        const en = voices.find(v => /^en[-_]/i.test(v.lang)) || voices.find(v => /english/i.test(v.name));
        if (en) u.voice = en;
      } catch (e) {}
      synth.speak(u);
    } catch (e) {/* ignore — TTS just won't fire */}
  }, []);

  // After the BOSS is beaten and audio is unlocked, auto-speak every new word.
  // Three independent guards: the audio must be unlocked (boss beaten), the
  // user must have opted in at the level-up screen, and the master sound
  // toggle must be unmuted.
  useEffect(() => {
    if (!audioUnlocked) return;
    if (!autoSpeakEnabled) return;
    if (muted) return;
    if (!question?.en) return;
    // Small delay so the new word has time to render and any in-flight SFX
    // (hit/levelup) doesn't compete with the TTS.
    const t = setTimeout(() => speakWord(question.en), 350);
    return () => clearTimeout(t);
  }, [audioUnlocked, autoSpeakEnabled, muted, question?.en, speakWord]);

  // mouse-tracking aim when idle
  useEffect(() => {
    const stage = stageRef.current;
    const cannon = cannonRef.current;
    if (!stage || !cannon) return;
    const onMove = ev => {
      if (aimed !== null) return; // a shot is in flight
      if (isRoundOver) return;
      const sR = stage.getBoundingClientRect();
      const cR = cannon.getBoundingClientRect();
      const mx = (ev.clientX - sR.left) / scale;
      const my = (ev.clientY - sR.top) / scale;
      const fromX = (cR.left - sR.left + cR.width * 0.5) / scale;
      const fromY = (cR.top - sR.top + cR.height * 0.42) / scale;
      let ang = Math.atan2(my - fromY, mx - fromX) * (180 / Math.PI);
      // clamp barrel rotation
      if (ang < -55) ang = -55;
      if (ang > 20) ang = 20;
      setAngle(ang);
    };
    stage.addEventListener("mousemove", onMove);
    return () => stage.removeEventListener("mousemove", onMove);
  }, [aimed, isRoundOver, scale]);

  // fullscreen toggle — also locks orientation to landscape on mobile
  const toggleFullscreen = useCallback(() => {
    try {
      const target = window.frameElement ? window.frameElement : document.documentElement;
      const doc = window.frameElement ? window.parent.document : document;
      const isFs = doc.fullscreenElement || doc.webkitFullscreenElement;
      if (!isFs) {
        const req = target.requestFullscreen || target.webkitRequestFullscreen || target.mozRequestFullScreen || target.msRequestFullscreen;
        if (req) {
          const p = req.call(target);
          // attempt to lock landscape on mobile devices
          if (p && p.then) {
            p.then(() => {
              try {
                if (screen.orientation && screen.orientation.lock) {
                  screen.orientation.lock('landscape').catch(() => {});
                }
              } catch (e) {}
            }).catch(() => {});
          } else {
            try {
              if (screen.orientation && screen.orientation.lock) {
                screen.orientation.lock('landscape').catch(() => {});
              }
            } catch (e) {}
          }
        }
      } else {
        try {
          if (screen.orientation && screen.orientation.unlock) screen.orientation.unlock();
        } catch (e) {}
        const exit = doc.exitFullscreen || doc.webkitExitFullscreen || doc.mozCancelFullScreen || doc.msExitFullscreen;
        if (exit) exit.call(doc);
      }
    } catch (e) {/* permission blocked in iframe — silent */}
  }, []);

  // mute toggle — controls background music, sound FX, AND (after the BOSS
  // unlock) the per-word audio. This is the single source of truth for any
  // sound coming out of the game.
  const toggleMute = useCallback(() => {
    const next = !Sound.muted;
    Sound.setMuted(next);
    setMuted(next);
    if (next) {
      // muting → stop any in-flight TTS immediately
      try {
        window.speechSynthesis?.cancel();
      } catch (e) {}
    }
  }, []);

  // hydrate dictionary — bundled words.js takes precedence over localStorage
  useEffect(() => {
    if (window.GAME_DICTIONARY && Array.isArray(window.GAME_DICTIONARY) && window.GAME_DICTIONARY.length >= 4) {
      setDict(window.GAME_DICTIONARY);
      setDictName("מילון המשחק");
      return;
    }
    try {
      const raw = localStorage.getItem(DICT_STORAGE_KEY);
      if (raw) {
        const arr = JSON.parse(raw);
        if (Array.isArray(arr) && arr.length >= 4) {
          setDict(arr);
          setDictName(localStorage.getItem(DICT_NAME_KEY) || "");
        }
      }
    } catch (e) {}
  }, []);

  // draw a question whenever dict changes or used grows
  useEffect(() => {
    if (!dict) return;
    const available = dict.map((_, i) => i).filter(i => !used.includes(i));
    if (available.length === 0) {
      setQuestion(null);
      return;
    }
    const correctIdx = available[Math.floor(Math.random() * available.length)];
    setQuestion({
      ...buildQuestion(dict, correctIdx),
      correctDictIdx: correctIdx
    });
  }, [dict, used]);
  const loadDict = useCallback((entries, name) => {
    setDict(entries);
    setDictName(name);
    setUsed([]);
    setMissed([]);
    setLives(3);
    setScore(0);
    setResolved({});
    setAimed(null);
    try {
      localStorage.setItem(DICT_STORAGE_KEY, JSON.stringify(entries));
      localStorage.setItem(DICT_NAME_KEY, name);
    } catch (e) {}
  }, []);
  const resetDict = useCallback(() => {
    setDict(null);
    setDictName("");
    setUsed([]);
    setMissed([]);
    setLives(3);
    setScore(0);
    setResolved({});
    setAimed(null);
    setQuestion(null);
    try {
      localStorage.removeItem(DICT_STORAGE_KEY);
      localStorage.removeItem(DICT_NAME_KEY);
    } catch (e) {}
  }, []);
  const restartGame = useCallback(() => {
    setUsed([]);
    setMissed([]);
    setLives(3);
    setScore(0);
    setResolved({});
    setAimed(null);
    setFiftyAvailable(true);
    setHiddenIdx(new Set());
    setKitState(null);
    setAudioUnlocked(false);
    setAutoSpeakEnabled(true);
    setLevelUpInfo(null);
    setStreak(0);
    lastBonusTimeRef.current = 0;
    questionStartRef.current = Date.now();
    prevLevelRef.current = 0;
    Sound.startMusic();
  }, []);
  const correctIdx = question ? question.options.indexOf(question.correct) : -1;
  const isRoundOver = resolved[correctIdx] === "hit" || lives <= 0;

  // Reset 50/50 hidden distractors whenever a new question appears;
  // every 8th question, drop a first-aid kit (if not full lives + not already showing).
  useEffect(() => {
    if (!question) return;
    if (prevQuestionEnRef.current !== question.en) {
      setHiddenIdx(new Set());
      prevQuestionEnRef.current = question.en;
      // Stamp the new question's start time so the speed bonus can be computed
      // when the user finally shoots.
      questionStartRef.current = Date.now();
      if (used.length > 0 && used.length % 8 === 0 && !kitState && lives < 3) {
        setKitState({
          id: Date.now()
        });
      }
    }
  }, [question, used.length, lives, kitState]);

  // 50/50 lifeline: hide 2 of the 3 wrong distractors
  const useFifty = useCallback(() => {
    if (!fiftyAvailable || !question || isRoundOver) return;
    const wrongs = question.options.map((_, i) => i).filter(i => i !== correctIdx);
    const toHide = shuffleArr(wrongs).slice(0, 2);
    setHiddenIdx(new Set(toHide));
    setFiftyAvailable(false);
    Sound.play('fifty');
  }, [fiftyAvailable, question, correctIdx, isRoundOver]);

  // Shooting the first-aid kit grants a life back
  const onKitHit = useCallback(() => {
    if (!kitState) return;
    setLives(l => Math.min(3, l + 1));
    setKitState(null);
    Sound.play('lifegain');
    setToast({
      kind: "win",
      text: "+1 לב · תיק עזרה ראשונה!"
    });
    setTimeout(() => setToast(null), 1800);
  }, [kitState]);

  // Kit auto-vanishes if not shot in time
  useEffect(() => {
    if (!kitState) return;
    const t = setTimeout(() => setKitState(null), 9000);
    return () => clearTimeout(t);
  }, [kitState]);
  const nextQuestion = useCallback(() => {
    if (!question) return;
    setUsed(u => [...u, question.correctDictIdx]);
    setResolved({});
    setAimed(null);
    setAngle(-18);
  }, [question]);
  const onTarget = useCallback(i => {
    if (!question) return;
    if (hiddenIdx.has(i)) return;
    if (resolved[i] || isRoundOver || aimed !== null) return;
    setAimed(i);
    Sound.play('shoot');
    const stage = stageRef.current;
    const cannon = cannonRef.current;
    const target = rocketRefs.current[i];
    if (!stage || !cannon || !target) return;
    const sR = stage.getBoundingClientRect();
    const cR = cannon.getBoundingClientRect();
    const tR = target.getBoundingClientRect();
    const fromX = (cR.left - sR.left + cR.width * 0.5) / scale;
    const fromY = (cR.top - sR.top + cR.height * 0.42) / scale;
    const toX = (tR.left - sR.left + 70) / scale;
    const toY = (tR.top - sR.top + tR.height * 0.5) / scale;
    const ang = Math.atan2(toY - fromY, toX - fromX) * (180 / Math.PI);
    setAngle(ang);
    setTimeout(() => {
      setShot({
        fromX,
        fromY,
        toX,
        toY
      });
      setTimeout(() => {
        const correct = i === correctIdx;
        const isBossHit = isBoss && correct;
        setResolved(r => ({
          ...r,
          [i]: correct ? "hit" : "missed"
        }));
        if (correct) {
          // ── speed bonus: faster hits earn more points (linear 2× → 1×) ──
          const effectiveDur = isBoss ? rocketDur * 0.8 : rocketDur;
          const elapsed = (Date.now() - questionStartRef.current) / 1000;
          const speedMult = Math.max(1, Math.min(2, 2 - elapsed / Math.max(1, effectiveDur)));

          // ── streak bonus: every 5 in a row unlocks a special — but a special
          // bonus fires at most once per 5 minutes so it stays meaningful. ──
          const newStreak = streak + 1;
          const now = Date.now();
          const cooldownPassed = now - lastBonusTimeRef.current >= 5 * 60 * 1000;
          let comboMult = 1,
            comboBonus = 0,
            comboLabel = null;
          if (newStreak >= 5 && newStreak % 5 === 0 && cooldownPassed) {
            if (newStreak >= 20) {
              comboMult = 3;
              comboLabel = `סטריק ${newStreak} ✦ ×3 ניקוד`;
            } else if (newStreak >= 10) {
              comboMult = 2;
              comboLabel = `סטריק ${newStreak} ✦ ×2 ניקוד`;
            } else {
              comboBonus = 500;
              comboLabel = `סטריק ${newStreak} ✦ +500 בונוס`;
            }
            lastBonusTimeRef.current = now;
          }
          const basePoints = isBossHit ? 500 : pointsPerHit;
          const points = Math.round(basePoints * speedMult * comboMult) + comboBonus;
          setScore(s => s + points);
          setStreak(newStreak);
          Sound.play(comboLabel ? 'levelup' : 'hit');
          if (comboLabel) {
            setToast({
              kind: "win",
              text: `${comboLabel} · +${points}`
            });
          } else {
            const speedTag = speedMult >= 1.7 ? "מהיר! " : speedMult >= 1.35 ? "יפה! " : "";
            setToast({
              kind: "win",
              text: `${speedTag}פגיעה ישירה +${points}`
            });
          }
          // BOSS pass → unlock the per-word audio, show a custom level-up overlay.
          // The overlay has its own continue buttons so we DON'T auto-advance here.
          if (isBossHit) {
            setAudioUnlocked(true);
            Sound.play('levelup');
            setTimeout(() => {
              setLevelUpInfo({
                mode: 'audio',
                sub: 'מעכשיו אפשר גם לשמוע כל מילה באנגלית.'
              });
            }, 500);
          }
        } else {
          setStreak(0);
          setLives(l => Math.max(0, l - 1));
          setMissed(m => m.includes(question.correctDictIdx) ? m : [...m, question.correctDictIdx]);
          setMissFx(true);
          setTimeout(() => setMissFx(false), 5400);
          setRecoil(true);
          setTimeout(() => setRecoil(false), 500);
          Sound.play('miss');
          setToast({
            kind: "lose",
            text: "פספסת — לב אחד נפל"
          });
          setTimeout(() => {
            setResolved(r => ({
              ...r,
              [correctIdx]: r[correctIdx] || "correct-after"
            }));
          }, 700);
        }
        setShot(null);
        setAimed(null);
        setTimeout(() => setToast(null), 1800);
        // auto-advance to next question — skipped for the BOSS hit (the
        // unlock overlay's "Continue" button handles that)
        if (!isBossHit) {
          setTimeout(() => {
            setUsed(u => [...u, question.correctDictIdx]);
            setResolved({});
            setAimed(null);
            setAngle(-18);
          }, correct ? 1400 : 5600);
        }
      }, 380);
    }, 340);
  }, [resolved, isRoundOver, aimed, correctIdx, scale, question, pointsPerHit, hiddenIdx, isBoss, rocketDur, streak]);

  // Rocket reaches the cannon zone = wrong answer
  const onTravelEnd = useCallback((i, e) => {
    if (e.animationName !== "rocketTravel") return;
    // Hard guard: once the correct rocket is resolved (hit, missed, or
    // revealed-after), no other rocket of the same round can deduct another
    // life. Without this, multiple rockets reaching the line in a row burned
    // through every heart in one round.
    if (!question || resolved[i] || isRoundOver || resolved[correctIdx]) return;
    setStreak(0);
    setLives(l => Math.max(0, l - 1));
    setMissed(m => m.includes(question.correctDictIdx) ? m : [...m, question.correctDictIdx]);
    setResolved(r => ({
      ...r,
      [i]: "missed",
      [correctIdx]: r[correctIdx] || "correct-after"
    }));
    setMissFx(true);
    setTimeout(() => setMissFx(false), 5400);
    Sound.play('miss');
    setToast({
      kind: "lose",
      text: "הטיל הגיע — לב אחד נפל"
    });
    setTimeout(() => setToast(null), 1800);
    setTimeout(() => {
      setUsed(u => [...u, question.correctDictIdx]);
      setResolved({});
      setAimed(null);
      setAngle(-18);
    }, 5600);
  }, [question, resolved, isRoundOver, correctIdx]);
  let shotEl = null;
  if (shot) {
    const dx = shot.toX - shot.fromX;
    const dy = shot.toY - shot.fromY;
    shotEl = /*#__PURE__*/React.createElement("div", {
      className: "gm-shot active",
      style: {
        left: shot.fromX,
        top: shot.fromY,
        animation: "shotFly .4s linear forwards",
        "--dx": `${dx}px`,
        "--dy": `${dy}px`
      }
    });
  }

  // ── intro first ──
  if (!started) return /*#__PURE__*/React.createElement(IntroScreen, {
    onStart: () => {
      setStarted(true);
      Sound.startMusic();
      // Prime SpeechSynthesis on user gesture so iOS will let later auto-speaks fire.
      // Also kicks the browser to start loading its voice list.
      try {
        const s = window.speechSynthesis;
        if (s) {
          const primer = new SpeechSynthesisUtterance(' ');
          primer.volume = 0;
          primer.rate = 1;
          s.speak(primer);
          s.getVoices?.();
        }
      } catch (e) {}
    },
    toggleFullscreen: toggleFullscreen,
    muted: muted,
    toggleMute: toggleMute
  });

  // ── no dict yet — only shown if bundled words.js missing AND no localStorage ──
  if (!dict) return /*#__PURE__*/React.createElement(UploadScreen, {
    onLoad: loadDict
  });

  // ── game over (lives exhausted) ──
  if (lives <= 0) {
    const missedWords = missed.map(idx => dict[idx]).filter(Boolean);
    return /*#__PURE__*/React.createElement(EndScreen, {
      score: score,
      missedWords: missedWords,
      onRestart: restartGame
    });
  }

  // ── dict exhausted ──
  if (!question) {
    return /*#__PURE__*/React.createElement("div", {
      className: "gm-app gm-up-app"
    }, /*#__PURE__*/React.createElement("div", {
      className: "gm-up-wrap"
    }, /*#__PURE__*/React.createElement("div", {
      className: "gm-up-card"
    }, /*#__PURE__*/React.createElement("div", {
      className: "gm-up-eye"
    }, "\u05E1\u05D9\u05D9\u05DE\u05EA\u05DD \u05D0\u05EA \u05D4\u05DE\u05D9\u05DC\u05D5\u05DF"), /*#__PURE__*/React.createElement("h1", {
      className: "gm-up-h1"
    }, used.length, " \u05DE\u05D9\u05DC\u05D9\u05DD \xB7 ", score, " \u05E0\u05E7\u05D5\u05D3\u05D5\u05EA"), /*#__PURE__*/React.createElement("p", {
      className: "gm-up-sub"
    }, "\u05E2\u05D1\u05E8\u05EA \u05E2\u05DC \u05DB\u05DC \u05D4\u05DE\u05D9\u05DC\u05D9\u05DD \u05D1\u05DE\u05D9\u05DC\u05D5\u05DF \"", dictName, "\". \u05DE\u05D4 \u05D4\u05DC\u05D0\u05D4?"), /*#__PURE__*/React.createElement("button", {
      className: "gm-up-btn",
      onClick: () => {
        setUsed([]);
        setLives(3);
        setScore(0);
      }
    }, "\u05E1\u05D9\u05D1\u05D5\u05D1 \u05E0\u05D5\u05E1\u05E3 \u05E2\u05DD \u05D0\u05D5\u05EA\u05DD \u05DE\u05D9\u05DC\u05D9\u05DD"), /*#__PURE__*/React.createElement("button", {
      className: "gm-up-btn-ghost",
      onClick: resetDict
    }, "\u05D8\u05E2\u05E0\u05D5 \u05DE\u05D9\u05DC\u05D5\u05DF \u05D0\u05D7\u05E8"))));
  }
  return /*#__PURE__*/React.createElement("div", {
    className: "gm-app"
  }, /*#__PURE__*/React.createElement("div", {
    className: "gm-stage",
    ref: stageRef,
    style: {
      "--gm-scale": scale,
      "--rocket-duration": `${(isBoss ? rocketDur * 0.8 : rocketDur).toFixed(2)}s`
    }
  }, /*#__PURE__*/React.createElement(SkyZ, null), /*#__PURE__*/React.createElement(Mountains, null), /*#__PURE__*/React.createElement("div", {
    className: "gm-ground"
  }), /*#__PURE__*/React.createElement("div", {
    className: "gm-hud-brand"
  }, /*#__PURE__*/React.createElement("img", {
    src: "ez-icon.png",
    alt: ""
  }), /*#__PURE__*/React.createElement("span", {
    className: "brand-eazy"
  }, "eazy")), /*#__PURE__*/React.createElement("div", {
    className: "gm-hud"
  }, /*#__PURE__*/React.createElement("div", {
    className: "chip hearts"
  }, [0, 1, 2].map(i => /*#__PURE__*/React.createElement(Heart, {
    key: i,
    lost: i >= lives
  }))), /*#__PURE__*/React.createElement("div", {
    className: "chip score"
  }, /*#__PURE__*/React.createElement("span", {
    className: "label"
  }, "\u05E0\u05D9\u05E7\u05D5\u05D3"), /*#__PURE__*/React.createElement("span", null, score)), /*#__PURE__*/React.createElement("div", {
    className: "spacer"
  })), isBoss && /*#__PURE__*/React.createElement("div", {
    className: "gm-boss-banner",
    "aria-hidden": true
  }, /*#__PURE__*/React.createElement("svg", {
    viewBox: "0 0 24 24",
    width: "32",
    height: "32",
    fill: "currentColor"
  }, /*#__PURE__*/React.createElement("path", {
    d: "M13 2 L4 14 L11 14 L10 22 L20 9 L13 9 Z"
  })), /*#__PURE__*/React.createElement("span", null, "\u05E9\u05DC\u05D1 BOSS"), /*#__PURE__*/React.createElement("svg", {
    viewBox: "0 0 24 24",
    width: "32",
    height: "32",
    fill: "currentColor"
  }, /*#__PURE__*/React.createElement("path", {
    d: "M13 2 L4 14 L11 14 L10 22 L20 9 L13 9 Z"
  }))), /*#__PURE__*/React.createElement("div", {
    className: "gm-word" + (isBoss ? " is-boss" : "") + (used.length === 0 ? " is-first" : "")
  }, /*#__PURE__*/React.createElement("div", {
    className: "en-wrap"
  }, /*#__PURE__*/React.createElement("div", {
    className: "en"
  }, question.en))), /*#__PURE__*/React.createElement("div", {
    className: "gm-foot-actions"
  }, /*#__PURE__*/React.createElement("button", {
    className: "foot-btn",
    onClick: () => {
      try {
        window.top.location.href = "https://www.ezway.co.il";
      } catch (e) {
        window.open("https://www.ezway.co.il", "_top");
      }
    },
    title: "\u05D0\u05EA\u05E8 \u05D4\u05D1\u05D9\u05EA"
  }, /*#__PURE__*/React.createElement(I.home, null)), /*#__PURE__*/React.createElement("button", {
    className: "foot-btn",
    onClick: toggleFullscreen,
    title: "\u05DE\u05E1\u05DA \u05DE\u05DC\u05D0"
  }, /*#__PURE__*/React.createElement(I.expand, null)), /*#__PURE__*/React.createElement("button", {
    className: "foot-btn lifeline" + (fiftyAvailable ? "" : " used"),
    onClick: useFifty,
    disabled: !fiftyAvailable,
    title: fiftyAvailable ? "גלגל הצלה 50/50" : "כבר השתמשת ב-50/50"
  }, /*#__PURE__*/React.createElement("span", {
    className: "fifty-text"
  }, "50", /*#__PURE__*/React.createElement("br", null), "50")), /*#__PURE__*/React.createElement("button", {
    className: "foot-btn" + (muted ? " muted" : ""),
    onClick: toggleMute,
    title: muted ? "השמע צלילים" : "השתק צלילים"
  }, muted ? /*#__PURE__*/React.createElement(I.speakerMute, null) : /*#__PURE__*/React.createElement(I.speaker, null))), /*#__PURE__*/React.createElement("div", {
    className: "gm-rockets"
  }, question.options.map((opt, i) => {
    const state = resolved[i];
    let cls = "gm-rocket";
    if (isBoss) cls += " boss";
    if (aimed === i) cls += " aiming";
    if (state === "hit") cls += " hit";else if (state === "missed") cls += " missed";else if (state === "correct-after") cls += " correct-after";
    const paused = isRoundOver || aimed === i || resolved[i] && resolved[i] !== "correct-after"; // correct-after keeps drifting
    const hidden = hiddenIdx.has(i);
    return /*#__PURE__*/React.createElement("div", {
      key: `${question.en}-${i}`,
      className: "gm-rocket-travel" + (paused ? " paused" : "") + (hidden ? " hidden5050" : ""),
      style: {
        animationDelay: `${-i * 1.5}s`
      },
      onAnimationEnd: e => onTravelEnd(i, e)
    }, /*#__PURE__*/React.createElement("div", {
      ref: el => rocketRefs.current[i] = el,
      className: cls,
      style: {
        "--mr": STAGGER[i] + "px"
      },
      onClick: () => onTarget(i)
    }, /*#__PURE__*/React.createElement(RocketSVG, {
      isBoss: isBoss
    }), /*#__PURE__*/React.createElement("div", {
      className: "label"
    }, opt), /*#__PURE__*/React.createElement("div", {
      className: "gm-burst"
    }, /*#__PURE__*/React.createElement(BurstSVG, null))));
  })), /*#__PURE__*/React.createElement("div", {
    className: "gm-cannon" + (recoil ? " recoil" : ""),
    ref: cannonRef
  }, /*#__PURE__*/React.createElement(CannonBase, null), /*#__PURE__*/React.createElement("div", {
    className: "barrel-wrap"
  }, /*#__PURE__*/React.createElement("svg", {
    style: {
      position: "absolute",
      width: "220px",
      height: "60px",
      top: "-30px",
      left: "-30px",
      transformOrigin: "30px 30px",
      transform: `rotate(${angle}deg)`,
      transition: "transform .08s linear",
      overflow: "visible"
    },
    viewBox: "0 0 220 60"
  }, /*#__PURE__*/React.createElement("defs", null, /*#__PURE__*/React.createElement("linearGradient", {
    id: "barG2",
    x1: "0",
    y1: "0",
    x2: "0",
    y2: "1"
  }, /*#__PURE__*/React.createElement("stop", {
    offset: "0",
    stopColor: "#3a3358"
  }), /*#__PURE__*/React.createElement("stop", {
    offset: "0.5",
    stopColor: "#1A1530"
  }), /*#__PURE__*/React.createElement("stop", {
    offset: "1",
    stopColor: "#0A0820"
  })), /*#__PURE__*/React.createElement("linearGradient", {
    id: "muzzleG2",
    x1: "0",
    y1: "0",
    x2: "0",
    y2: "1"
  }, /*#__PURE__*/React.createElement("stop", {
    offset: "0",
    stopColor: "#5a5470"
  }), /*#__PURE__*/React.createElement("stop", {
    offset: "1",
    stopColor: "#2A2547"
  }))), /*#__PURE__*/React.createElement("rect", {
    x: "14",
    y: "22",
    width: "36",
    height: "20",
    rx: "4",
    fill: "#1A1530"
  }), /*#__PURE__*/React.createElement("rect", {
    x: "14",
    y: "22",
    width: "36",
    height: "3",
    fill: "rgba(255,255,255,.18)"
  }), /*#__PURE__*/React.createElement("rect", {
    x: "40",
    y: "26",
    width: "150",
    height: "12",
    rx: "4",
    fill: "url(#barG2)"
  }), /*#__PURE__*/React.createElement("rect", {
    x: "42",
    y: "27",
    width: "146",
    height: "2",
    rx: "1",
    fill: "rgba(255,255,255,.25)"
  }), /*#__PURE__*/React.createElement("rect", {
    x: "184",
    y: "22",
    width: "22",
    height: "20",
    rx: "3",
    fill: "url(#muzzleG2)"
  }), /*#__PURE__*/React.createElement("rect", {
    x: "188",
    y: "26",
    width: "2",
    height: "12",
    fill: "#0A0820"
  }), /*#__PURE__*/React.createElement("rect", {
    x: "194",
    y: "26",
    width: "2",
    height: "12",
    fill: "#0A0820"
  }), /*#__PURE__*/React.createElement("rect", {
    x: "200",
    y: "26",
    width: "2",
    height: "12",
    fill: "#0A0820"
  }), /*#__PURE__*/React.createElement("rect", {
    x: "22",
    y: "14",
    width: "6",
    height: "10",
    fill: "#1A1530"
  }), /*#__PURE__*/React.createElement("circle", {
    cx: "25",
    cy: "13",
    r: "3",
    fill: "#F33F3F"
  })))), shotEl, kitState && /*#__PURE__*/React.createElement("div", {
    className: "gm-kit-travel",
    key: kitState.id,
    onAnimationEnd: () => setKitState(null)
  }, /*#__PURE__*/React.createElement("button", {
    className: "gm-kit",
    onClick: onKitHit,
    title: "\u05D9\u05E8\u05D4 \u05D1\u05EA\u05D9\u05E7 \u05DC\u05E2\u05D5\u05D3 \u05DC\u05D1!"
  }, /*#__PURE__*/React.createElement("svg", {
    viewBox: "0 0 120 110",
    "aria-hidden": true
  }, /*#__PURE__*/React.createElement("defs", null, /*#__PURE__*/React.createElement("linearGradient", {
    id: "kitG",
    x1: "0",
    y1: "0",
    x2: "0",
    y2: "1"
  }, /*#__PURE__*/React.createElement("stop", {
    offset: "0",
    stopColor: "#FFFFFF"
  }), /*#__PURE__*/React.createElement("stop", {
    offset: "1",
    stopColor: "#E8E6F0"
  })), /*#__PURE__*/React.createElement("linearGradient", {
    id: "kitHandleG",
    x1: "0",
    y1: "0",
    x2: "0",
    y2: "1"
  }, /*#__PURE__*/React.createElement("stop", {
    offset: "0",
    stopColor: "#3a3358"
  }), /*#__PURE__*/React.createElement("stop", {
    offset: "1",
    stopColor: "#1A1530"
  }))), /*#__PURE__*/React.createElement("ellipse", {
    cx: "60",
    cy: "102",
    rx: "42",
    ry: "5",
    fill: "rgba(0,0,0,.3)"
  }), /*#__PURE__*/React.createElement("rect", {
    x: "44",
    y: "8",
    width: "32",
    height: "14",
    rx: "3",
    fill: "url(#kitHandleG)",
    stroke: "#0A0820",
    strokeWidth: "2"
  }), /*#__PURE__*/React.createElement("rect", {
    x: "48",
    y: "14",
    width: "24",
    height: "8",
    rx: "2",
    fill: "rgba(255,255,255,.15)"
  }), /*#__PURE__*/React.createElement("rect", {
    x: "14",
    y: "22",
    width: "92",
    height: "76",
    rx: "8",
    fill: "url(#kitG)",
    stroke: "#0A0820",
    strokeWidth: "2.5"
  }), /*#__PURE__*/React.createElement("rect", {
    x: "52",
    y: "34",
    width: "16",
    height: "52",
    rx: "2",
    fill: "#DC2626"
  }), /*#__PURE__*/React.createElement("rect", {
    x: "34",
    y: "52",
    width: "52",
    height: "16",
    rx: "2",
    fill: "#DC2626"
  }), /*#__PURE__*/React.createElement("rect", {
    x: "20",
    y: "28",
    width: "80",
    height: "3",
    rx: "1.5",
    fill: "rgba(255,255,255,.5)"
  }), /*#__PURE__*/React.createElement("rect", {
    x: "56",
    y: "20",
    width: "8",
    height: "6",
    fill: "#3a3358"
  })), /*#__PURE__*/React.createElement("div", {
    className: "gm-kit-label"
  }, "+1 \u05DC\u05D1"))), missFx && /*#__PURE__*/React.createElement("div", {
    className: "gm-miss-jam",
    "aria-hidden": true
  }, /*#__PURE__*/React.createElement("svg", {
    viewBox: "0 0 1600 900",
    preserveAspectRatio: "none"
  }, /*#__PURE__*/React.createElement("defs", null, /*#__PURE__*/React.createElement("linearGradient", {
    id: "jamG",
    x1: "0",
    y1: "0",
    x2: "0",
    y2: "1"
  }, /*#__PURE__*/React.createElement("stop", {
    offset: "0",
    stopColor: "#7C170F",
    stopOpacity: ".95"
  }), /*#__PURE__*/React.createElement("stop", {
    offset: ".35",
    stopColor: "#9C1E16",
    stopOpacity: ".92"
  }), /*#__PURE__*/React.createElement("stop", {
    offset: ".75",
    stopColor: "#B5251B",
    stopOpacity: ".88"
  }), /*#__PURE__*/React.createElement("stop", {
    offset: ".94",
    stopColor: "#C72A1F",
    stopOpacity: ".84"
  }), /*#__PURE__*/React.createElement("stop", {
    offset: ".95",
    stopColor: "#C72A1F",
    stopOpacity: "0"
  }), /*#__PURE__*/React.createElement("stop", {
    offset: "1",
    stopColor: "#C72A1F",
    stopOpacity: "0"
  })), /*#__PURE__*/React.createElement("linearGradient", {
    id: "curtainG",
    x1: "0",
    y1: "0",
    x2: "0",
    y2: "1"
  }, /*#__PURE__*/React.createElement("stop", {
    offset: "0",
    stopColor: "#8E1A12",
    stopOpacity: ".95"
  }), /*#__PURE__*/React.createElement("stop", {
    offset: ".5",
    stopColor: "#A8201A",
    stopOpacity: ".92"
  }), /*#__PURE__*/React.createElement("stop", {
    offset: ".9",
    stopColor: "#B5251B",
    stopOpacity: ".90"
  }), /*#__PURE__*/React.createElement("stop", {
    offset: "1",
    stopColor: "#7C170F",
    stopOpacity: ".95"
  })), /*#__PURE__*/React.createElement("filter", {
    id: "jamBlur",
    x: "-3%",
    y: "-3%",
    width: "106%",
    height: "106%"
  }, /*#__PURE__*/React.createElement("feGaussianBlur", {
    stdDeviation: ".8"
  }))), /*#__PURE__*/React.createElement("path", {
    className: "jam-splat",
    d: "M 0 0 L 1600 0 L 1600 180 C 1540 220 1490 175 1440 200 C 1380 230 1330 175 1280 215 C 1230 245 1180 185 1130 225 C 1080 255 1030 200 980 230 C 930 265 880 195 830 240 C 780 275 730 215 680 245 C 630 280 580 210 530 250 C 480 280 430 220 380 260 C 330 290 280 225 230 265 C 180 295 130 230 80 270 C 50 290 30 250 0 275 Z",
    fill: "url(#jamG)",
    filter: "url(#jamBlur)"
  }), [
  // x1, x2 define the horizontal span; depth = how far below the splat band; delay = stagger
  {
    x1: 0,
    x2: 360,
    depth: 540,
    delay: 0.05,
    dur: 2.4
  }, {
    x1: 280,
    x2: 660,
    depth: 460,
    delay: 0.45,
    dur: 2.6
  }, {
    x1: 580,
    x2: 940,
    depth: 580,
    delay: 0.20,
    dur: 2.5
  }, {
    x1: 860,
    x2: 1220,
    depth: 500,
    delay: 0.65,
    dur: 2.4
  }, {
    x1: 1140,
    x2: 1480,
    depth: 560,
    delay: 0.30,
    dur: 2.6
  }, {
    x1: 1400,
    x2: 1600,
    depth: 480,
    delay: 0.55,
    dur: 2.5
  }].map((c, i) => {
    const topY = 175;
    const bottomY = topY + c.depth;
    // wavy bottom edge — 3 peaks/valleys for irregularity
    const span = c.x2 - c.x1;
    const p1 = c.x1 + span * 0.20;
    const p2 = c.x1 + span * 0.45;
    const p3 = c.x1 + span * 0.72;
    const dip = c.depth * 0.18;
    const path = `
                  M ${c.x1} ${topY}
                  L ${c.x2} ${topY}
                  L ${c.x2} ${bottomY - dip * 0.6}
                  C ${c.x2 - 40} ${bottomY + dip * 0.4}, ${p3 + 40} ${bottomY - dip}, ${p3} ${bottomY + dip * 0.6}
                  C ${p3 - 40} ${bottomY + dip * 1.2}, ${p2 + 50} ${bottomY - dip * 0.8}, ${p2} ${bottomY + dip * 0.3}
                  C ${p2 - 50} ${bottomY + dip * 0.9}, ${p1 + 40} ${bottomY - dip * 0.5}, ${p1} ${bottomY + dip * 0.5}
                  C ${p1 - 40} ${bottomY + dip * 1.1}, ${c.x1 + 40} ${bottomY - dip * 0.3}, ${c.x1} ${bottomY - dip * 0.4}
                  Z
                `;
    return /*#__PURE__*/React.createElement("path", {
      key: i,
      className: "jam-curtain",
      d: path,
      fill: "url(#curtainG)",
      filter: "url(#jamBlur)",
      style: {
        animationDelay: `${c.delay}s`,
        animationDuration: `${c.dur}s`
      }
    });
  }))), levelUpInfo && /*#__PURE__*/React.createElement("div", {
    className: "gm-levelup" + (levelUpInfo.mode === 'audio' ? " gm-levelup-audio" : "")
  }, /*#__PURE__*/React.createElement("div", {
    className: "gm-levelup-title"
  }, "\u05E2\u05DC\u05D9\u05EA \u05E9\u05DC\u05D1", /*#__PURE__*/React.createElement("span", {
    className: "dot"
  }, "!")), /*#__PURE__*/React.createElement("div", {
    className: "gm-levelup-sub"
  }, levelUpInfo.sub), levelUpInfo.mode === 'audio' && /*#__PURE__*/React.createElement(React.Fragment, null, /*#__PURE__*/React.createElement("div", {
    className: "gm-levelup-buttons"
  }, /*#__PURE__*/React.createElement("button", {
    className: "gm-levelup-cta",
    onClick: () => {
      setAutoSpeakEnabled(true);
      // If the master sound was muted, unmute so the chosen word audio actually plays.
      if (Sound.muted) {
        Sound.setMuted(false);
        setMuted(false);
      }
      setLevelUpInfo(null);
      nextQuestion();
    }
  }, "\u05E8\u05D5\u05E6\u05D4 \u05DC\u05D4\u05DE\u05E9\u05D9\u05DA \u05E2\u05DD \u05D4\u05E9\u05DE\u05E2\u05EA \u05DE\u05D9\u05DC\u05D9\u05DD"), /*#__PURE__*/React.createElement("button", {
    className: "gm-levelup-cta secondary",
    onClick: () => {
      setAutoSpeakEnabled(false);
      setLevelUpInfo(null);
      nextQuestion();
    }
  }, "\u05E8\u05D5\u05E6\u05D4 \u05DC\u05D4\u05DE\u05E9\u05D9\u05DA \u05DC\u05DC\u05D0 \u05D4\u05E9\u05DE\u05E2\u05EA \u05DE\u05D9\u05DC\u05D9\u05DD")), /*#__PURE__*/React.createElement("div", {
    className: "gm-levelup-note"
  }, /*#__PURE__*/React.createElement("span", {
    className: "star"
  }, "*"), " \u05EA\u05DE\u05D9\u05D3 \u05E0\u05D9\u05EA\u05DF \u05DC\u05D1\u05D8\u05DC \u05D4\u05E9\u05DE\u05E2\u05EA \u05DE\u05D9\u05DC\u05D9\u05DD \u05E2\u05DD \u05DC\u05D7\u05E6\u05DF \u05D4\u05E1\u05D0\u05D5\u05E0\u05D3"))), toast && /*#__PURE__*/React.createElement("div", {
    className: "gm-toast " + toast.kind
  }, /*#__PURE__*/React.createElement("span", {
    className: "dot"
  }), toast.text), /*#__PURE__*/React.createElement("style", null, `
          @keyframes shotFly {
            from { transform: translate(-50%, -50%) translate(0, 0); opacity: 1; }
            to   { transform: translate(-50%, -50%) translate(var(--dx, 0px), var(--dy, 0px)); opacity: 1; }
          }
        `)));
}
window.Game = QuizGameServer;
})(); } catch (e) { __ds_ns.__errors.push({ path: "quiz-game-server/QuizGameServer.jsx", error: String((e && e.message) || e) }); }

// quiz-game/Game.standalone.jsx
try { (() => {
/* global React, XLSX */
const {
  useState,
  useEffect,
  useRef,
  useCallback,
  useLayoutEffect,
  useMemo
} = React;

/* ---------- built-in sample dictionary ---------- */
const SAMPLE_DICT = [{
  en: "ENHANCE",
  he: "להעצים, לשפר",
  ipa: "/ɪnˈhæns/"
}, {
  en: "MITIGATE",
  he: "להקל, למתן",
  ipa: "/ˈmɪtɪˌɡeɪt/"
}, {
  en: "AMBIGUOUS",
  he: "דו-משמעי, עמום",
  ipa: "/æmˈbɪɡjuəs/"
}, {
  en: "ADVOCATE",
  he: "לתמוך, להמליץ",
  ipa: "/ˈædvəˌkeɪt/"
}, {
  en: "SCRUTINIZE",
  he: "לבחון בקפדנות",
  ipa: "/ˈskruːtəˌnaɪz/"
}, {
  en: "INEVITABLE",
  he: "בלתי נמנע",
  ipa: "/ɪˈnɛvɪtəbəl/"
}, {
  en: "DILIGENT",
  he: "חרוץ, שקדן",
  ipa: "/ˈdɪlɪdʒənt/"
}, {
  en: "OBSOLETE",
  he: "מיושן, יצא משימוש",
  ipa: "/ˌabsəˈliːt/"
}, {
  en: "CANDID",
  he: "הֵן, ישיר, ספונטני",
  ipa: "/ˈkændɪd/"
}, {
  en: "TENACIOUS",
  he: "עיקש, דבק במטרה",
  ipa: "/təˈneɪʃəs/"
}];
const STAGGER = [0, 40, 14, 56];
const DICT_STORAGE_KEY = "ez-mcq-dict-v2";
const DICT_NAME_KEY = "ez-mcq-dict-name-v2";
const MUTED_KEY = "ez-mcq-muted-v1";
const LB_KEY = "ez-mcq-leaderboard-v1";

/* ---------- sound engine (WebAudio FX + background music) ---------- */
const Sound = {
  ctx: null,
  muted: false,
  music: null,
  // <audio> element
  musicReady: false,
  init() {
    if (!this.ctx) {
      try {
        this.ctx = new (window.AudioContext || window.webkitAudioContext)();
      } catch (e) {}
    }
    if (this.ctx && this.ctx.state === 'suspended') this.ctx.resume();
    if (!this.music) {
      this.music = document.getElementById('bg-music');
      if (this.music) {
        this.music.volume = 0.35;
        this.music.loop = true;
        this.musicReady = true;
      }
    }
  },
  startMusic() {
    this.init();
    if (this.muted || !this.music) return;
    const p = this.music.play();
    if (p && p.catch) p.catch(() => {/* autoplay blocked — will start on next user gesture */});
  },
  stopMusic() {
    if (this.music) {
      this.music.pause();
    }
  },
  setMusicVolume(v) {
    if (this.music) this.music.volume = Math.max(0, Math.min(1, v));
  },
  setMuted(m) {
    this.muted = !!m;
    if (this.muted) this.stopMusic();else this.startMusic();
    try {
      localStorage.setItem(MUTED_KEY, this.muted ? '1' : '0');
    } catch (e) {}
  },
  beep(freq, duration, type = 'sine', gain = 0.15, delay = 0) {
    if (this.muted || !this.ctx) return;
    const t = this.ctx.currentTime + delay;
    const osc = this.ctx.createOscillator();
    const g = this.ctx.createGain();
    osc.type = type;
    osc.frequency.value = freq;
    g.gain.setValueAtTime(gain, t);
    g.gain.exponentialRampToValueAtTime(0.001, t + duration);
    osc.connect(g);
    g.connect(this.ctx.destination);
    osc.start(t);
    osc.stop(t + duration);
  },
  play(name) {
    if (this.muted) return;
    this.init();
    switch (name) {
      case 'shoot':
        this.beep(540, 0.06, 'square', 0.13);
        this.beep(220, 0.07, 'sawtooth', 0.10, 0.03);
        break;
      case 'hit':
        /* punchier explosion: low thump + bright chord + bell tail */
        this.beep(80, 0.10, 'square', 0.22);
        this.beep(523, 0.10, 'square', 0.16, 0.04);
        this.beep(784, 0.12, 'square', 0.14, 0.10);
        this.beep(1047, 0.22, 'triangle', 0.16, 0.18);
        this.beep(1568, 0.30, 'sine', 0.12, 0.30);
        break;
      case 'miss':
        /* descending "wha-wha" buzzer — clearly distinct from a hit */
        this.beep(440, 0.10, 'square', 0.20);
        this.beep(330, 0.14, 'square', 0.20, 0.10);
        this.beep(220, 0.30, 'sawtooth', 0.22, 0.22);
        this.beep(150, 0.45, 'triangle', 0.20, 0.45);
        break;
      case 'lifegain':
        /* sparkle: ascending major arpeggio */
        this.beep(659, 0.10, 'triangle', 0.18);
        this.beep(880, 0.10, 'triangle', 0.18, 0.10);
        this.beep(1175, 0.10, 'triangle', 0.18, 0.20);
        this.beep(1568, 0.32, 'sine', 0.20, 0.30);
        break;
      case 'fifty':
        /* two-note chime */
        this.beep(880, 0.10, 'sine', 0.15);
        this.beep(1320, 0.18, 'sine', 0.16, 0.10);
        break;
      case 'levelup':
        this.beep(523, 0.10, 'triangle', 0.18);
        this.beep(659, 0.10, 'triangle', 0.18, 0.10);
        this.beep(784, 0.10, 'triangle', 0.18, 0.20);
        this.beep(1047, 0.32, 'sine', 0.20, 0.30);
        break;
      case 'tick':
        this.beep(720, 0.08, 'sine', 0.10);
        break;
      case 'go':
        this.beep(1200, 0.30, 'triangle', 0.22);
        break;
      case 'streak':
        this.beep(880, 0.08, 'sine', 0.13);
        this.beep(1320, 0.10, 'sine', 0.14, 0.08);
        break;
      case 'gameover':
        this.beep(440, 0.20, 'sine', 0.15);
        this.beep(330, 0.24, 'sine', 0.15, 0.20);
        this.beep(220, 0.50, 'sine', 0.18, 0.45);
        break;
    }
  }
};
try {
  Sound.muted = localStorage.getItem(MUTED_KEY) === '1';
} catch (e) {}

/* ---------- leaderboard ---------- */
function getLeaderboard() {
  try {
    return JSON.parse(localStorage.getItem(LB_KEY) || '[]');
  } catch (e) {
    return [];
  }
}
function addToLeaderboard(name, score) {
  const lb = getLeaderboard();
  lb.push({
    name: (name || "אנונימי").slice(0, 20),
    score,
    date: new Date().toISOString()
  });
  lb.sort((a, b) => b.score - a.score);
  try {
    localStorage.setItem(LB_KEY, JSON.stringify(lb.slice(0, 5)));
  } catch (e) {}
  return lb.slice(0, 5);
}
function qualifiesForLeaderboard(score) {
  if (score <= 0) return false;
  const lb = getLeaderboard();
  if (lb.length < 5) return true;
  return score > lb[lb.length - 1].score;
}

/* ---------- dictionary helpers ---------- */
function shuffleArr(a) {
  const x = [...a];
  for (let i = x.length - 1; i > 0; i--) {
    const j = Math.floor(Math.random() * (i + 1));
    [x[i], x[j]] = [x[j], x[i]];
  }
  return x;
}
function buildQuestion(dict, correctIdx) {
  const correct = dict[correctIdx];
  const correctMeaning = normalizeMeaning(correct.he);

  // Build pool excluding correct answer AND entries that share the same meaning.
  // This prevents duplicate Hebrew translations from appearing as distractors
  // (e.g. when the same meaning is split across two English words).
  const pool = dict.map((entry, i) => ({
    entry,
    i,
    key: normalizeMeaning(entry.he)
  })).filter(({
    i,
    key
  }) => i !== correctIdx && key !== correctMeaning);

  // Pick 3 distractors with distinct meanings from each other too.
  const shuffled = shuffleArr(pool);
  const picked = [];
  const seenMeanings = new Set([correctMeaning]);
  for (const {
    entry,
    key
  } of shuffled) {
    if (seenMeanings.has(key)) continue;
    seenMeanings.add(key);
    picked.push(entry);
    if (picked.length === 3) break;
  }

  // Fallback: if the dict is too small / too many duplicates, allow same-key duplicates
  // just so we always have 4 options.
  while (picked.length < 3) {
    const fillers = shuffleArr(pool).filter(p => !picked.includes(p.entry));
    if (fillers.length === 0) break;
    picked.push(fillers[0].entry);
  }
  const options = shuffleArr([correct.he, ...picked.map(d => d.he)]);
  return {
    en: String(correct.en).toUpperCase(),
    ipa: correct.ipa || "",
    correct: correct.he,
    options
  };
}

// Normalize a meaning string so "להאריך / להרחיב" and "להאריך, להרחיב" collide,
// and casing/whitespace differences don't matter.
function normalizeMeaning(s) {
  return String(s || "").toLowerCase().replace(/[\/,،]/g, " ") // treat /, comma, arabic comma as separators
  .replace(/\s+/g, " ").replace(/[״"׳'.…]/g, "").trim();
}
function parseSpreadsheet(file) {
  return new Promise((resolve, reject) => {
    const reader = new FileReader();
    reader.onerror = () => reject(new Error("לא מצליח לקרוא את הקובץ"));
    reader.onload = e => {
      try {
        if (typeof XLSX === "undefined") {
          reject(new Error("תוכנת הפיענוח לא נטענה. רענן דף ונסה שוב."));
          return;
        }
        const data = new Uint8Array(e.target.result);
        const wb = XLSX.read(data, {
          type: "array"
        });
        const sheet = wb.Sheets[wb.SheetNames[0]];
        const rows = XLSX.utils.sheet_to_json(sheet, {
          header: 1,
          blankrows: false
        });
        if (!rows.length) {
          reject(new Error("הקובץ ריק"));
          return;
        }
        const firstB = String(rows[0][1] || "").trim().toLowerCase();
        const looksLikeHeader = /english|word|מילה|אנגלית/.test(firstB) || /פירוש|תרגום|עברית/.test(String(rows[0][2] || ""));
        const start = looksLikeHeader ? 1 : 0;
        const entries = [];
        for (let i = start; i < rows.length; i++) {
          const en = String(rows[i][1] || "").trim(); // column B
          const he = String(rows[i][2] || "").trim(); // column C
          if (en && he) entries.push({
            en,
            he,
            ipa: ""
          });
        }
        if (entries.length < 4) {
          reject(new Error("צריך לפחות 4 מילים בקובץ"));
          return;
        }
        resolve(entries);
      } catch (err) {
        reject(err);
      }
    };
    reader.readAsArrayBuffer(file);
  });
}

/* ──────────────────────────────────────────────
   Polished SVG illustrations
   ────────────────────────────────────────────── */

function RocketSVG({
  isBoss
}) {
  const stroke = "#2A2155";
  const strokeW = 3.5;

  // ── Regular rockets ── use the curated reference artwork embedded as a
  // PNG. Replacing the SVG with the bitmap matches the source illustration
  // pixel-for-pixel; state-based color shifts (hit / missed / correct) come
  // from CSS filters applied to .gm-rocket via `.rocket-img`.
  if (!isBoss) {
    return /*#__PURE__*/React.createElement("svg", {
      className: "frame",
      viewBox: "0 0 620 150",
      preserveAspectRatio: "none",
      "aria-hidden": true
    }, /*#__PURE__*/React.createElement("image", {
      className: "rocket-img",
      href: "rocket-cropped.png",
      xlinkHref: "rocket-cropped.png",
      x: "0",
      y: "0",
      width: "620",
      height: "150",
      preserveAspectRatio: "none"
    }));
  }

  // ── BOSS rocket ── still drawn fully in SVG so the red gradient body,
  // shark-fins and multi-lick flame stay intact (per the user's request).
  return /*#__PURE__*/React.createElement("svg", {
    className: "frame",
    viewBox: "0 0 620 150",
    preserveAspectRatio: "none",
    "aria-hidden": true
  }, /*#__PURE__*/React.createElement("defs", null, /*#__PURE__*/React.createElement("linearGradient", {
    id: "bodyG",
    x1: "0",
    y1: "0",
    x2: "0",
    y2: "1"
  }, /*#__PURE__*/React.createElement("stop", {
    offset: "0",
    stopColor: "#FFFFFF"
  }), /*#__PURE__*/React.createElement("stop", {
    offset: ".6",
    stopColor: "#F5F3F8"
  }), /*#__PURE__*/React.createElement("stop", {
    offset: "1",
    stopColor: "#C9C7CF"
  })), /*#__PURE__*/React.createElement("linearGradient", {
    id: "bodyG-hit",
    x1: "0",
    y1: "0",
    x2: "0",
    y2: "1"
  }, /*#__PURE__*/React.createElement("stop", {
    offset: "0",
    stopColor: "#FFE6CB"
  }), /*#__PURE__*/React.createElement("stop", {
    offset: ".5",
    stopColor: "#F37327"
  }), /*#__PURE__*/React.createElement("stop", {
    offset: "1",
    stopColor: "#A93C08"
  })), /*#__PURE__*/React.createElement("linearGradient", {
    id: "bodyG-miss",
    x1: "0",
    y1: "0",
    x2: "0",
    y2: "1"
  }, /*#__PURE__*/React.createElement("stop", {
    offset: "0",
    stopColor: "#D7D5DC"
  }), /*#__PURE__*/React.createElement("stop", {
    offset: "1",
    stopColor: "#9A98A4"
  })), /*#__PURE__*/React.createElement("linearGradient", {
    id: "bodyG-correct",
    x1: "0",
    y1: "0",
    x2: "0",
    y2: "1"
  }, /*#__PURE__*/React.createElement("stop", {
    offset: "0",
    stopColor: "#BDF0D3"
  }), /*#__PURE__*/React.createElement("stop", {
    offset: "1",
    stopColor: "#3FA76C"
  })), /*#__PURE__*/React.createElement("linearGradient", {
    id: "bodyG-boss",
    x1: "0",
    y1: "0",
    x2: "0",
    y2: "1"
  }, /*#__PURE__*/React.createElement("stop", {
    offset: "0",
    stopColor: "#FCA5A5"
  }), /*#__PURE__*/React.createElement("stop", {
    offset: ".5",
    stopColor: "#DC2626"
  }), /*#__PURE__*/React.createElement("stop", {
    offset: "1",
    stopColor: "#7F1D1D"
  })), /*#__PURE__*/React.createElement("linearGradient", {
    id: "tipG-boss",
    x1: "0",
    y1: "0",
    x2: "0",
    y2: "1"
  }, /*#__PURE__*/React.createElement("stop", {
    offset: "0",
    stopColor: "#FCD34D"
  }), /*#__PURE__*/React.createElement("stop", {
    offset: ".55",
    stopColor: "#DC2626"
  }), /*#__PURE__*/React.createElement("stop", {
    offset: "1",
    stopColor: "#7F1D1D"
  })), /*#__PURE__*/React.createElement("linearGradient", {
    id: "tipG",
    x1: "0",
    y1: "0",
    x2: "0",
    y2: "1"
  }, /*#__PURE__*/React.createElement("stop", {
    offset: "0",
    stopColor: "#FFB36B"
  }), /*#__PURE__*/React.createElement("stop", {
    offset: ".55",
    stopColor: "#F37327"
  }), /*#__PURE__*/React.createElement("stop", {
    offset: "1",
    stopColor: "#B94A0C"
  })), /*#__PURE__*/React.createElement("linearGradient", {
    id: "finG",
    x1: "0",
    y1: "0",
    x2: "0",
    y2: "1"
  }, /*#__PURE__*/React.createElement("stop", {
    offset: "0",
    stopColor: "#FFB36B"
  }), /*#__PURE__*/React.createElement("stop", {
    offset: ".5",
    stopColor: "#F37327"
  }), /*#__PURE__*/React.createElement("stop", {
    offset: "1",
    stopColor: "#A0410B"
  })), /*#__PURE__*/React.createElement("radialGradient", {
    id: "flameG",
    cx: "50%",
    cy: "50%",
    r: "55%"
  }, /*#__PURE__*/React.createElement("stop", {
    offset: "0",
    stopColor: "#FFF7CE"
  }), /*#__PURE__*/React.createElement("stop", {
    offset: ".4",
    stopColor: "#FFD23F"
  }), /*#__PURE__*/React.createElement("stop", {
    offset: ".85",
    stopColor: "#F37327"
  }), /*#__PURE__*/React.createElement("stop", {
    offset: "1",
    stopColor: "#B94A0C"
  }))), /*#__PURE__*/React.createElement("g", null, /*#__PURE__*/React.createElement("path", {
    d: "M 525,40 Q 555,52 580,32 Q 568,55 595,55 Q 575,68 610,72 Q 575,80 615,90 Q 575,92 600,108 Q 570,100 588,118 Q 555,100 580,118 Q 555,98 525,110 Z",
    fill: "url(#flameG)",
    stroke: stroke,
    strokeWidth: strokeW,
    strokeLinejoin: "round"
  }), /*#__PURE__*/React.createElement("path", {
    d: "M 530,55 Q 555,55 570,42 Q 568,62 585,68 Q 565,75 582,82 Q 565,88 580,100 Q 558,92 568,110 Q 545,95 530,100 Z",
    fill: "#FFF7CE",
    opacity: ".95"
  })), /*#__PURE__*/React.createElement("path", {
    d: "M 470,42 Q 488,18 540,2 Q 540,30 520,46 Q 500,52 470,42 Z",
    fill: "url(#finG)",
    stroke: stroke,
    strokeWidth: strokeW,
    strokeLinejoin: "round"
  }), /*#__PURE__*/React.createElement("path", {
    d: "M 495,28 Q 515,18 532,12",
    stroke: "#fff",
    strokeOpacity: ".6",
    strokeWidth: "3",
    fill: "none",
    strokeLinecap: "round"
  }), /*#__PURE__*/React.createElement("path", {
    d: "M 470,108 Q 488,132 540,148 Q 540,120 520,104 Q 500,98 470,108 Z",
    fill: "url(#finG)",
    stroke: stroke,
    strokeWidth: strokeW,
    strokeLinejoin: "round"
  }), /*#__PURE__*/React.createElement("path", {
    d: "M 495,122 Q 515,132 532,138",
    stroke: "#fff",
    strokeOpacity: ".45",
    strokeWidth: "3",
    fill: "none",
    strokeLinecap: "round"
  }), /*#__PURE__*/React.createElement("path", {
    className: "body-fill",
    d: "M 40,75 Q 70,16 165,16 L 530,16 Q 560,16 560,38 L 560,112 Q 560,134 530,134 L 165,134 Q 70,134 40,75 Z",
    fill: "url(#bodyG)",
    stroke: stroke,
    strokeWidth: strokeW,
    strokeLinejoin: "round"
  }), /*#__PURE__*/React.createElement("path", {
    className: "tip-fill",
    d: "M 40,75 Q 70,16 165,16 L 175,16 Q 110,30 90,75 Q 110,120 175,134 L 165,134 Q 70,134 40,75 Z",
    fill: "url(#tipG)",
    stroke: stroke,
    strokeWidth: strokeW,
    strokeLinejoin: "round"
  }), /*#__PURE__*/React.createElement("path", {
    d: "M 70,52 Q 90,38 120,42",
    stroke: "#fff",
    strokeOpacity: ".7",
    strokeWidth: "4",
    fill: "none",
    strokeLinecap: "round"
  }), /*#__PURE__*/React.createElement("path", {
    d: "M 195,30 Q 360,24 510,32",
    stroke: "#fff",
    strokeOpacity: ".95",
    strokeWidth: "5",
    fill: "none",
    strokeLinecap: "round"
  }), /*#__PURE__*/React.createElement("path", {
    d: "M 170,124 Q 360,140 520,126",
    stroke: "#1A1530",
    strokeOpacity: ".09",
    strokeWidth: "6",
    fill: "none",
    strokeLinecap: "round"
  }), /*#__PURE__*/React.createElement("circle", {
    cx: "125",
    cy: "48",
    r: "2.5",
    fill: "#fff"
  }));
}
function BurstSVG() {
  return /*#__PURE__*/React.createElement("svg", {
    viewBox: "0 0 140 140",
    "aria-hidden": true
  }, /*#__PURE__*/React.createElement("defs", null, /*#__PURE__*/React.createElement("radialGradient", {
    id: "boom",
    cx: "50%",
    cy: "50%",
    r: "50%"
  }, /*#__PURE__*/React.createElement("stop", {
    offset: "0%",
    stopColor: "#FFF7E6"
  }), /*#__PURE__*/React.createElement("stop", {
    offset: "35%",
    stopColor: "#FFB061"
  }), /*#__PURE__*/React.createElement("stop", {
    offset: "70%",
    stopColor: "#F37327"
  }), /*#__PURE__*/React.createElement("stop", {
    offset: "100%",
    stopColor: "rgba(213,90,18,0)"
  }))), /*#__PURE__*/React.createElement("circle", {
    cx: "70",
    cy: "70",
    r: "48",
    fill: "url(#boom)"
  }), /*#__PURE__*/React.createElement("g", {
    stroke: "#FFB061",
    strokeWidth: "3",
    strokeLinecap: "round",
    fill: "none"
  }, /*#__PURE__*/React.createElement("line", {
    x1: "70",
    y1: "14",
    x2: "70",
    y2: "32"
  }), /*#__PURE__*/React.createElement("line", {
    x1: "70",
    y1: "108",
    x2: "70",
    y2: "126"
  }), /*#__PURE__*/React.createElement("line", {
    x1: "14",
    y1: "70",
    x2: "32",
    y2: "70"
  }), /*#__PURE__*/React.createElement("line", {
    x1: "108",
    y1: "70",
    x2: "126",
    y2: "70"
  }), /*#__PURE__*/React.createElement("line", {
    x1: "28",
    y1: "28",
    x2: "42",
    y2: "42"
  }), /*#__PURE__*/React.createElement("line", {
    x1: "98",
    y1: "98",
    x2: "112",
    y2: "112"
  }), /*#__PURE__*/React.createElement("line", {
    x1: "28",
    y1: "112",
    x2: "42",
    y2: "98"
  }), /*#__PURE__*/React.createElement("line", {
    x1: "98",
    y1: "42",
    x2: "112",
    y2: "28"
  })), /*#__PURE__*/React.createElement("circle", {
    cx: "70",
    cy: "70",
    r: "18",
    fill: "#FFF7E6"
  }));
}
function CannonBase() {
  return /*#__PURE__*/React.createElement("svg", {
    className: "base",
    viewBox: "0 0 280 240",
    "aria-hidden": true
  }, /*#__PURE__*/React.createElement("defs", null, /*#__PURE__*/React.createElement("linearGradient", {
    id: "domeG",
    x1: "0",
    y1: "0",
    x2: "0",
    y2: "1"
  }, /*#__PURE__*/React.createElement("stop", {
    offset: "0",
    stopColor: "#FFA362"
  }), /*#__PURE__*/React.createElement("stop", {
    offset: "0.5",
    stopColor: "#F37327"
  }), /*#__PURE__*/React.createElement("stop", {
    offset: "1",
    stopColor: "#A93C08"
  })), /*#__PURE__*/React.createElement("linearGradient", {
    id: "tracksG",
    x1: "0",
    y1: "0",
    x2: "0",
    y2: "1"
  }, /*#__PURE__*/React.createElement("stop", {
    offset: "0",
    stopColor: "#2A2547"
  }), /*#__PURE__*/React.createElement("stop", {
    offset: "1",
    stopColor: "#0A0820"
  })), /*#__PURE__*/React.createElement("linearGradient", {
    id: "metalG",
    x1: "0",
    y1: "0",
    x2: "0",
    y2: "1"
  }, /*#__PURE__*/React.createElement("stop", {
    offset: "0",
    stopColor: "#3a3358"
  }), /*#__PURE__*/React.createElement("stop", {
    offset: "1",
    stopColor: "#15102B"
  }))), /*#__PURE__*/React.createElement("ellipse", {
    cx: "140",
    cy: "226",
    rx: "120",
    ry: "10",
    fill: "rgba(0,0,0,.45)"
  }), /*#__PURE__*/React.createElement("path", {
    d: "M 20,168 L 260,168 L 250,216 L 30,216 Z",
    fill: "url(#tracksG)",
    stroke: "#000",
    strokeWidth: "1"
  }), Array.from({
    length: 12
  }).map((_, i) => /*#__PURE__*/React.createElement("rect", {
    key: i,
    x: 32 + i * 18,
    y: "174",
    width: "12",
    height: "36",
    rx: "2",
    fill: "#3a3358"
  })), [58, 98, 138, 178, 218].map((cx, i) => /*#__PURE__*/React.createElement("g", {
    key: i
  }, /*#__PURE__*/React.createElement("circle", {
    cx: cx,
    cy: "200",
    r: "13",
    fill: "#0A0820"
  }), /*#__PURE__*/React.createElement("circle", {
    cx: cx,
    cy: "200",
    r: "10",
    fill: "#3a3358",
    stroke: "#5a5470",
    strokeWidth: "2"
  }), /*#__PURE__*/React.createElement("circle", {
    cx: cx,
    cy: "200",
    r: "3",
    fill: "#5a5470"
  }))), /*#__PURE__*/React.createElement("path", {
    d: "M 30,140 L 250,140 L 260,168 L 20,168 Z",
    fill: "#1A1530"
  }), /*#__PURE__*/React.createElement("rect", {
    x: "36",
    y: "146",
    width: "208",
    height: "3",
    fill: "rgba(255,255,255,.1)",
    rx: "1"
  }), [60, 100, 140, 180, 220].map((cx, i) => /*#__PURE__*/React.createElement("circle", {
    key: i,
    cx: cx,
    cy: "156",
    r: "3",
    fill: "#5a5470"
  })), /*#__PURE__*/React.createElement("path", {
    d: "M 70,140 Q 140,40 210,140 Z",
    fill: "url(#domeG)"
  }), /*#__PURE__*/React.createElement("path", {
    d: "M 85,128 Q 110,76 138,68",
    stroke: "rgba(255,255,255,.45)",
    strokeWidth: "4",
    fill: "none",
    strokeLinecap: "round"
  }), /*#__PURE__*/React.createElement("ellipse", {
    cx: "140",
    cy: "138",
    rx: "74",
    ry: "10",
    fill: "#0A0820"
  }), /*#__PURE__*/React.createElement("ellipse", {
    cx: "140",
    cy: "135",
    rx: "74",
    ry: "10",
    fill: "#1A1530"
  }), /*#__PURE__*/React.createElement("ellipse", {
    cx: "140",
    cy: "134",
    rx: "68",
    ry: "6",
    fill: "#3a3358"
  }), /*#__PURE__*/React.createElement("path", {
    d: "M 75,138 Q 140,52 205,138",
    stroke: "rgba(0,0,0,.18)",
    strokeWidth: "1",
    fill: "none"
  }), /*#__PURE__*/React.createElement("g", {
    transform: "translate(170 96)"
  }, /*#__PURE__*/React.createElement("rect", {
    x: "-20",
    y: "-20",
    width: "40",
    height: "40",
    rx: "7",
    fill: "#fff"
  }), /*#__PURE__*/React.createElement("image", {
    href: "ez-icon.png",
    x: "-17",
    y: "-17",
    width: "34",
    height: "34"
  })), /*#__PURE__*/React.createElement("line", {
    x1: "100",
    y1: "80",
    x2: "92",
    y2: "36",
    stroke: "#1A1530",
    strokeWidth: "2"
  }), /*#__PURE__*/React.createElement("circle", {
    cx: "92",
    cy: "34",
    r: "3",
    fill: "#F33F3F"
  }), /*#__PURE__*/React.createElement("circle", {
    cx: "62",
    cy: "156",
    r: "6",
    fill: "#FFE6A8"
  }), /*#__PURE__*/React.createElement("circle", {
    cx: "62",
    cy: "156",
    r: "3",
    fill: "#FFF"
  }));
}
function CannonBarrel() {
  return /*#__PURE__*/React.createElement("svg", {
    viewBox: "0 0 220 60",
    "aria-hidden": true
  }, /*#__PURE__*/React.createElement("defs", null, /*#__PURE__*/React.createElement("linearGradient", {
    id: "barG",
    x1: "0",
    y1: "0",
    x2: "0",
    y2: "1"
  }, /*#__PURE__*/React.createElement("stop", {
    offset: "0",
    stopColor: "#3a3358"
  }), /*#__PURE__*/React.createElement("stop", {
    offset: "0.5",
    stopColor: "#1A1530"
  }), /*#__PURE__*/React.createElement("stop", {
    offset: "1",
    stopColor: "#0A0820"
  })), /*#__PURE__*/React.createElement("linearGradient", {
    id: "muzzleG",
    x1: "0",
    y1: "0",
    x2: "0",
    y2: "1"
  }, /*#__PURE__*/React.createElement("stop", {
    offset: "0",
    stopColor: "#5a5470"
  }), /*#__PURE__*/React.createElement("stop", {
    offset: "1",
    stopColor: "#2A2547"
  }))), /*#__PURE__*/React.createElement("rect", {
    x: "14",
    y: "22",
    width: "36",
    height: "20",
    rx: "4",
    fill: "#1A1530"
  }), /*#__PURE__*/React.createElement("rect", {
    x: "14",
    y: "22",
    width: "36",
    height: "3",
    fill: "rgba(255,255,255,.18)"
  }), /*#__PURE__*/React.createElement("rect", {
    x: "40",
    y: "26",
    width: "150",
    height: "12",
    rx: "4",
    fill: "url(#barG)"
  }), /*#__PURE__*/React.createElement("rect", {
    x: "42",
    y: "27",
    width: "146",
    height: "2",
    rx: "1",
    fill: "rgba(255,255,255,.25)"
  }), /*#__PURE__*/React.createElement("rect", {
    x: "184",
    y: "22",
    width: "22",
    height: "20",
    rx: "3",
    fill: "url(#muzzleG)"
  }), /*#__PURE__*/React.createElement("rect", {
    x: "188",
    y: "26",
    width: "2",
    height: "12",
    fill: "#0A0820"
  }), /*#__PURE__*/React.createElement("rect", {
    x: "194",
    y: "26",
    width: "2",
    height: "12",
    fill: "#0A0820"
  }), /*#__PURE__*/React.createElement("rect", {
    x: "200",
    y: "26",
    width: "2",
    height: "12",
    fill: "#0A0820"
  }), /*#__PURE__*/React.createElement("rect", {
    x: "22",
    y: "14",
    width: "6",
    height: "10",
    fill: "#1A1530"
  }), /*#__PURE__*/React.createElement("circle", {
    cx: "25",
    cy: "13",
    r: "3",
    fill: "#F33F3F"
  }));
}
function Mountains() {
  return /*#__PURE__*/React.createElement("div", {
    className: "gm-horizon"
  }, /*#__PURE__*/React.createElement("svg", {
    viewBox: "0 0 1600 240",
    preserveAspectRatio: "none",
    "aria-hidden": true
  }, /*#__PURE__*/React.createElement("path", {
    d: "M0,150 L120,90 L240,130 L380,70 L520,118 L660,82 L800,124 L940,86 L1080,128 L1220,94 L1360,126 L1500,90 L1600,118 L1600,240 L0,240 Z",
    fill: "#B6B1E0"
  }), /*#__PURE__*/React.createElement("path", {
    d: "M0,200 L160,140 L300,180 L440,118 L580,158 L720,128 L860,168 L1000,134 L1140,170 L1280,140 L1420,176 L1560,148 L1600,164 L1600,240 L0,240 Z",
    fill: "#8E89C8"
  })));
}
function SkyZ() {
  return /*#__PURE__*/React.createElement("div", {
    className: "gm-sky-z",
    "aria-hidden": true
  }, /*#__PURE__*/React.createElement("div", {
    className: "z",
    style: {
      top: "6%",
      left: "8%",
      width: "26%",
      background: "rgba(255,255,255,.65)"
    }
  }), /*#__PURE__*/React.createElement("div", {
    className: "z",
    style: {
      top: "10%",
      left: "46%",
      width: "20%",
      background: "rgba(255,255,255,.5)"
    }
  }), /*#__PURE__*/React.createElement("div", {
    className: "z",
    style: {
      top: "18%",
      left: "22%",
      width: "14%",
      background: "rgba(255,255,255,.35)"
    }
  }), /*#__PURE__*/React.createElement("div", {
    className: "z",
    style: {
      top: "26%",
      left: "62%",
      width: "22%",
      background: "rgba(255,255,255,.4)"
    }
  }));
}
function Heart({
  lost
}) {
  return /*#__PURE__*/React.createElement("svg", {
    viewBox: "0 0 24 24",
    className: lost ? "lost" : ""
  }, /*#__PURE__*/React.createElement("path", {
    fill: "#F33F3F",
    d: "M12 21s-7.5-4.7-9.6-9.5C.9 7.7 3.5 4 7.2 4c2 0 3.6 1 4.8 2.6C13.2 5 14.8 4 16.8 4c3.7 0 6.3 3.7 4.8 7.5C19.5 16.3 12 21 12 21z"
  }));
}
const I = {
  pause: () => /*#__PURE__*/React.createElement("svg", {
    viewBox: "0 0 24 24",
    width: "16",
    height: "16",
    fill: "currentColor"
  }, /*#__PURE__*/React.createElement("path", {
    d: "M9 5h2v14H9zM13 5h2v14h-2z"
  })),
  speaker: () => /*#__PURE__*/React.createElement("svg", {
    viewBox: "0 0 24 24",
    width: "18",
    height: "18",
    fill: "currentColor"
  }, /*#__PURE__*/React.createElement("path", {
    d: "M3 10v4a1 1 0 0 0 1 1h3l4 3.5a1 1 0 0 0 1.6-.8V6.3a1 1 0 0 0-1.6-.8L7 9H4a1 1 0 0 0-1 1Z"
  })),
  speakerMute: () => /*#__PURE__*/React.createElement("svg", {
    viewBox: "0 0 24 24",
    width: "18",
    height: "18",
    fill: "none",
    stroke: "currentColor",
    strokeWidth: "2.2",
    strokeLinecap: "round",
    strokeLinejoin: "round"
  }, /*#__PURE__*/React.createElement("path", {
    d: "M3 10v4a1 1 0 0 0 1 1h3l4 3.5a1 1 0 0 0 1.6-.8V6.3a1 1 0 0 0-1.6-.8L7 9H4a1 1 0 0 0-1 1Z",
    fill: "currentColor",
    stroke: "none"
  }), /*#__PURE__*/React.createElement("path", {
    d: "M16 8l5 5M21 8l-5 5"
  })),
  expand: () => /*#__PURE__*/React.createElement("svg", {
    viewBox: "0 0 24 24",
    width: "18",
    height: "18",
    fill: "none",
    stroke: "currentColor",
    strokeWidth: "2.2",
    strokeLinecap: "round",
    strokeLinejoin: "round"
  }, /*#__PURE__*/React.createElement("path", {
    d: "M4 9V4h5M20 9V4h-5M4 15v5h5M20 15v5h-5"
  })),
  home: () => /*#__PURE__*/React.createElement("svg", {
    viewBox: "0 0 24 24",
    width: "20",
    height: "20",
    fill: "none",
    stroke: "currentColor",
    strokeWidth: "2.2",
    strokeLinecap: "round",
    strokeLinejoin: "round"
  }, /*#__PURE__*/React.createElement("path", {
    d: "M3 11l9-8 9 8"
  }), /*#__PURE__*/React.createElement("path", {
    d: "M5 10v10h14V10"
  }), /*#__PURE__*/React.createElement("path", {
    d: "M10 20v-6h4v6"
  })),
  trophy: () => /*#__PURE__*/React.createElement("svg", {
    viewBox: "0 0 24 24",
    width: "22",
    height: "22",
    fill: "none",
    stroke: "currentColor",
    strokeWidth: "2.2",
    strokeLinecap: "round",
    strokeLinejoin: "round"
  }, /*#__PURE__*/React.createElement("path", {
    d: "M8 21h8M12 17v4M7 4h10v5a5 5 0 0 1-10 0V4z"
  }), /*#__PURE__*/React.createElement("path", {
    d: "M7 6H4v2a3 3 0 0 0 3 3M17 6h3v2a3 3 0 0 1-3 3"
  }))
};
function ScopeIcon() {
  return /*#__PURE__*/React.createElement("svg", {
    viewBox: "0 0 32 32",
    fill: "none",
    stroke: "#F37327",
    strokeWidth: "2.2"
  }, /*#__PURE__*/React.createElement("circle", {
    cx: "16",
    cy: "16",
    r: "11"
  }), /*#__PURE__*/React.createElement("path", {
    d: "M16 2v6 M16 24v6 M2 16h6 M24 16h6",
    strokeLinecap: "round"
  }), /*#__PURE__*/React.createElement("circle", {
    cx: "16",
    cy: "16",
    r: "2",
    fill: "#F37327",
    stroke: "none"
  }));
}

/* ──────────────────────────────────────────────
   Stage scaler: fits 1600×900 into viewport, letterboxing.
   ────────────────────────────────────────────── */
function useStageScale(designW, designH) {
  const [scale, setScale] = useState(1);
  useLayoutEffect(() => {
    const recalc = () => {
      const w = window.innerWidth;
      const h = window.innerHeight;
      setScale(Math.min(w / designW, h / designH));
    };
    recalc();
    window.addEventListener("resize", recalc);
    return () => window.removeEventListener("resize", recalc);
  }, [designW, designH]);
  return scale;
}

/* ──────────────────────────────────────────────
   Upload screen — load Excel/CSV
   ────────────────────────────────────────────── */
function UploadScreen({
  onLoad
}) {
  const [drag, setDrag] = useState(false);
  const [err, setErr] = useState(null);
  const [busy, setBusy] = useState(false);
  const inputRef = useRef(null);
  const handle = useCallback(async file => {
    if (!file) return;
    setErr(null);
    setBusy(true);
    try {
      const entries = await parseSpreadsheet(file);
      onLoad(entries, file.name);
    } catch (e) {
      setErr(e.message || "שגיאה בקריאת הקובץ");
    } finally {
      setBusy(false);
    }
  }, [onLoad]);
  const onDrop = e => {
    e.preventDefault();
    setDrag(false);
    const f = e.dataTransfer?.files?.[0];
    if (f) handle(f);
  };
  return /*#__PURE__*/React.createElement("div", {
    className: "gm-app gm-up-app"
  }, /*#__PURE__*/React.createElement("div", {
    className: "gm-up-wrap"
  }, /*#__PURE__*/React.createElement("div", {
    className: "gm-up-card"
  }, /*#__PURE__*/React.createElement("div", {
    className: "gm-up-eye"
  }, /*#__PURE__*/React.createElement("span", {
    className: "brand-eazy"
  }, "eazy"), " \xB7 \u05DE\u05E9\u05D7\u05E7 \u05DE\u05D9\u05DC\u05D9\u05DD"), /*#__PURE__*/React.createElement("h1", {
    className: "gm-up-h1"
  }, "\u05D8\u05E2\u05E0\u05D5 \u05DE\u05D9\u05DC\u05D5\u05DF \u05DC\u05DE\u05E9\u05D7\u05E7."), /*#__PURE__*/React.createElement("p", {
    className: "gm-up-sub"
  }, "\u05E7\u05D5\u05D1\u05E5 Excel \u05D0\u05D5 CSV. \u05E2\u05DE\u05D5\u05D3\u05D4 B = \u05DE\u05D9\u05DC\u05D4 \u05D1\u05D0\u05E0\u05D2\u05DC\u05D9\u05EA, \u05E2\u05DE\u05D5\u05D3\u05D4 C = \u05E4\u05D9\u05E8\u05D5\u05E9 \u05D1\u05E2\u05D1\u05E8\u05D9\u05EA. \u05E0\u05D1\u05D7\u05E8 \u05D1\u05DB\u05DC \u05E1\u05D9\u05D1\u05D5\u05D1 4 \u05DE\u05D9\u05DC\u05D9\u05DD: \u05D0\u05D7\u05EA \u05D4\u05E0\u05DB\u05D5\u05E0\u05D4, \u05E9\u05DC\u05D5\u05E9 \u05D0\u05D7\u05E8\u05D5\u05EA \u05DE\u05D4\u05DE\u05D9\u05DC\u05D5\u05DF \u05DB\u05DE\u05E1\u05D9\u05D7\u05D9\u05DD."), /*#__PURE__*/React.createElement("div", {
    className: "gm-dropzone " + (drag ? "drag" : ""),
    onClick: () => inputRef.current?.click(),
    onDragOver: e => {
      e.preventDefault();
      setDrag(true);
    },
    onDragLeave: () => setDrag(false),
    onDrop: onDrop
  }, /*#__PURE__*/React.createElement("div", {
    className: "gm-dz-icon"
  }, /*#__PURE__*/React.createElement("svg", {
    viewBox: "0 0 32 32",
    width: "42",
    height: "42",
    fill: "none",
    stroke: "#F37327",
    strokeWidth: "2",
    strokeLinecap: "round",
    strokeLinejoin: "round"
  }, /*#__PURE__*/React.createElement("path", {
    d: "M16 4v18"
  }), /*#__PURE__*/React.createElement("path", {
    d: "M9 11l7-7 7 7"
  }), /*#__PURE__*/React.createElement("path", {
    d: "M4 26h24"
  }))), /*#__PURE__*/React.createElement("div", {
    className: "gm-dz-title"
  }, "\u05D2\u05E8\u05E8\u05D5 \u05DC\u05DB\u05D0\u05DF \u05D0\u05D5 \u05DC\u05D7\u05E6\u05D5"), /*#__PURE__*/React.createElement("div", {
    className: "gm-dz-sub"
  }, ".xlsx / .xls / .csv"), /*#__PURE__*/React.createElement("input", {
    ref: inputRef,
    type: "file",
    accept: ".xlsx,.xls,.csv,application/vnd.ms-excel,application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",
    style: {
      display: "none"
    },
    onChange: e => handle(e.target.files[0])
  })), busy && /*#__PURE__*/React.createElement("div", {
    className: "gm-up-info"
  }, "\u05E7\u05D5\u05E8\u05D0\u05D9 \u05D0\u05EA \u05D4\u05E7\u05D5\u05D1\u05E5\u2026"), err && /*#__PURE__*/React.createElement("div", {
    className: "gm-up-err"
  }, err), /*#__PURE__*/React.createElement("div", {
    className: "gm-up-or"
  }, "\u2014 \u05D0\u05D5 \u2014"), /*#__PURE__*/React.createElement("button", {
    className: "gm-up-btn-ghost",
    onClick: () => onLoad(SAMPLE_DICT, "מילון לדוגמה")
  }, "\u05D4\u05EA\u05D7\u05D9\u05DC\u05D5 \u05E2\u05DD \u05DE\u05D9\u05DC\u05D5\u05DF \u05D3\u05D5\u05D2\u05DE\u05D4 (", SAMPLE_DICT.length, " \u05DE\u05D9\u05DC\u05D9\u05DD)"), /*#__PURE__*/React.createElement("div", {
    className: "gm-up-format"
  }, /*#__PURE__*/React.createElement("div", {
    className: "gm-fmt-title"
  }, "\u05E4\u05D5\u05E8\u05DE\u05D8 \u05D4\u05E7\u05D5\u05D1\u05E5:"), /*#__PURE__*/React.createElement("table", null, /*#__PURE__*/React.createElement("thead", null, /*#__PURE__*/React.createElement("tr", null, /*#__PURE__*/React.createElement("th", null, "A"), /*#__PURE__*/React.createElement("th", null, "B \u2014 English"), /*#__PURE__*/React.createElement("th", null, "C \u2014 \u05E2\u05D1\u05E8\u05D9\u05EA"))), /*#__PURE__*/React.createElement("tbody", null, /*#__PURE__*/React.createElement("tr", null, /*#__PURE__*/React.createElement("td", null, "1"), /*#__PURE__*/React.createElement("td", {
    dir: "ltr"
  }, "enhance"), /*#__PURE__*/React.createElement("td", null, "\u05DC\u05D4\u05E2\u05E6\u05D9\u05DD, \u05DC\u05E9\u05E4\u05E8")), /*#__PURE__*/React.createElement("tr", null, /*#__PURE__*/React.createElement("td", null, "2"), /*#__PURE__*/React.createElement("td", {
    dir: "ltr"
  }, "mitigate"), /*#__PURE__*/React.createElement("td", null, "\u05DC\u05D4\u05E7\u05DC, \u05DC\u05DE\u05EA\u05DF")), /*#__PURE__*/React.createElement("tr", null, /*#__PURE__*/React.createElement("td", null, "3"), /*#__PURE__*/React.createElement("td", {
    dir: "ltr"
  }, "ambiguous"), /*#__PURE__*/React.createElement("td", null, "\u05D3\u05D5-\u05DE\u05E9\u05DE\u05E2\u05D9")))), /*#__PURE__*/React.createElement("div", {
    className: "gm-fmt-note"
  }, "\u05E9\u05D5\u05E8\u05EA \u05DB\u05D5\u05EA\u05E8\u05EA \u05EA\u05D6\u05D5\u05D4\u05D4 \u05D0\u05D5\u05D8\u05D5\u05DE\u05D8\u05D9\u05EA. \u05E2\u05DE\u05D5\u05D3\u05D4 A \u05DE\u05EA\u05E2\u05DC\u05DE\u05D9\u05DD \u05DE\u05DE\u05E0\u05D4 (\u05DE\u05E1\u05E4\u05D5\u05E8 / \u05DE\u05D6\u05D4\u05D4).")))));
}

/* ──────────────────────────────────────────────
   Intro screen — first thing the user sees
   ───────────────────────────────────────────── */
function IntroScreen({
  onStart,
  toggleFullscreen,
  muted,
  toggleMute
}) {
  const scale = useStageScale(1600, 900);
  // Combined handler: enter fullscreen on the user's tap (must come from a
  // gesture) and then start the round. Failures are non-fatal — we still
  // start the game even if the browser blocks fullscreen.
  const startAndFullscreen = () => {
    try {
      const el = document.documentElement;
      const req = el.requestFullscreen || el.webkitRequestFullscreen || el.msRequestFullscreen;
      if (req && !document.fullscreenElement && !document.webkitFullscreenElement) {
        const p = req.call(el);
        if (p && typeof p.catch === 'function') p.catch(() => {});
      }
    } catch (e) {}
    onStart();
  };
  return /*#__PURE__*/React.createElement("div", {
    className: "gm-app"
  }, /*#__PURE__*/React.createElement("div", {
    className: "gm-stage gm-intro-stage",
    style: {
      "--gm-scale": scale
    }
  }, /*#__PURE__*/React.createElement(SkyZ, null), /*#__PURE__*/React.createElement(Mountains, null), /*#__PURE__*/React.createElement("div", {
    className: "gm-ground"
  }), /*#__PURE__*/React.createElement("div", {
    className: "gm-hud-brand"
  }, /*#__PURE__*/React.createElement("img", {
    src: window.__resources.ezIcon,
    alt: ""
  }), /*#__PURE__*/React.createElement("span", {
    className: "brand-eazy"
  }, "eazy")), /*#__PURE__*/React.createElement("div", {
    className: "gm-cannon gm-intro-cannon"
  }, /*#__PURE__*/React.createElement(CannonBase, null), /*#__PURE__*/React.createElement("div", {
    className: "barrel-wrap"
  }, /*#__PURE__*/React.createElement("svg", {
    style: {
      position: "absolute",
      width: "220px",
      height: "60px",
      top: "-30px",
      left: "-30px",
      transformOrigin: "30px 30px",
      transform: `rotate(-22deg)`,
      overflow: "visible"
    },
    viewBox: "0 0 220 60"
  }, /*#__PURE__*/React.createElement("defs", null, /*#__PURE__*/React.createElement("linearGradient", {
    id: "barG3",
    x1: "0",
    y1: "0",
    x2: "0",
    y2: "1"
  }, /*#__PURE__*/React.createElement("stop", {
    offset: "0",
    stopColor: "#3a3358"
  }), /*#__PURE__*/React.createElement("stop", {
    offset: "0.5",
    stopColor: "#1A1530"
  }), /*#__PURE__*/React.createElement("stop", {
    offset: "1",
    stopColor: "#0A0820"
  })), /*#__PURE__*/React.createElement("linearGradient", {
    id: "muzzleG3",
    x1: "0",
    y1: "0",
    x2: "0",
    y2: "1"
  }, /*#__PURE__*/React.createElement("stop", {
    offset: "0",
    stopColor: "#5a5470"
  }), /*#__PURE__*/React.createElement("stop", {
    offset: "1",
    stopColor: "#2A2547"
  }))), /*#__PURE__*/React.createElement("rect", {
    x: "14",
    y: "22",
    width: "36",
    height: "20",
    rx: "4",
    fill: "#1A1530"
  }), /*#__PURE__*/React.createElement("rect", {
    x: "14",
    y: "22",
    width: "36",
    height: "3",
    fill: "rgba(255,255,255,.18)"
  }), /*#__PURE__*/React.createElement("rect", {
    x: "40",
    y: "26",
    width: "150",
    height: "12",
    rx: "4",
    fill: "url(#barG3)"
  }), /*#__PURE__*/React.createElement("rect", {
    x: "42",
    y: "27",
    width: "146",
    height: "2",
    rx: "1",
    fill: "rgba(255,255,255,.25)"
  }), /*#__PURE__*/React.createElement("rect", {
    x: "184",
    y: "22",
    width: "22",
    height: "20",
    rx: "3",
    fill: "url(#muzzleG3)"
  }), /*#__PURE__*/React.createElement("rect", {
    x: "188",
    y: "26",
    width: "2",
    height: "12",
    fill: "#0A0820"
  }), /*#__PURE__*/React.createElement("rect", {
    x: "194",
    y: "26",
    width: "2",
    height: "12",
    fill: "#0A0820"
  }), /*#__PURE__*/React.createElement("rect", {
    x: "200",
    y: "26",
    width: "2",
    height: "12",
    fill: "#0A0820"
  }), /*#__PURE__*/React.createElement("rect", {
    x: "22",
    y: "14",
    width: "6",
    height: "10",
    fill: "#1A1530"
  }), /*#__PURE__*/React.createElement("circle", {
    cx: "25",
    cy: "13",
    r: "3",
    fill: "#F33F3F"
  })))), /*#__PURE__*/React.createElement("div", {
    className: "gm-intro-text"
  }, /*#__PURE__*/React.createElement("div", {
    className: "gm-intro-eye"
  }, "\u05DE\u05E9\u05D7\u05E7 \u05D0\u05E0\u05D2\u05DC\u05D9\u05EA \u05DE\u05D1\u05D9\u05EA ", /*#__PURE__*/React.createElement("span", {
    className: "en brand-eazy"
  }, "eazy")), /*#__PURE__*/React.createElement("h1", {
    className: "gm-intro-title"
  }, "\u05EA\u05D5\u05EA\u05D7 \u05DE\u05D9\u05DC\u05D9\u05DD", /*#__PURE__*/React.createElement("span", {
    className: "dot"
  }, ".")), /*#__PURE__*/React.createElement("p", {
    className: "gm-intro-lead"
  }, "\u05E2\u05D5\u05DE\u05D3\u05D9\u05DD \u05DC\u05E8\u05E9\u05D5\u05EA\u05DB\u05DD \u05EA\u05D5\u05EA\u05D7 \u05DE\u05D9\u05DC\u05D9\u05DD \u05D5\u05D4\u05D9\u05D3\u05E2 \u05E9\u05DC\u05DB\u05DD \u05D1\u05D0\u05E0\u05D2\u05DC\u05D9\u05EA."), /*#__PURE__*/React.createElement("p", {
    className: "gm-intro-body"
  }, "\u05D1\u05EA\u05D7\u05EA\u05D9\u05EA \u05D4\u05DE\u05E1\u05DA \u05DE\u05D5\u05E4\u05D9\u05E2\u05D4 \u05DE\u05D9\u05DC\u05D4 \u05D1\u05D0\u05E0\u05D2\u05DC\u05D9\u05EA. \u05D6\u05D4\u05D5 \u05D0\u05EA \u05D4\u05D8\u05D9\u05DC \u05E2\u05DD \u05D4\u05E4\u05D9\u05E8\u05D5\u05E9 \u05D4\u05DE\u05EA\u05D0\u05D9\u05DD \u05D5\u05EA\u05DC\u05D7\u05E6\u05D5 \u05E2\u05DC\u05D9\u05D5.", /*#__PURE__*/React.createElement("br", null), "\u05DB\u05DB\u05DC \u05E9\u05E2\u05D5\u05E0\u05D9\u05DD \u05DE\u05D4\u05E8 \u05D9\u05D5\u05EA\u05E8, \u05E6\u05D5\u05D1\u05E8\u05D9\u05DD \u05D9\u05D5\u05EA\u05E8 \u05E0\u05E7\u05D5\u05D3\u05D5\u05EA. \u05D1\u05D4\u05E6\u05DC\u05D7\u05D4!")), /*#__PURE__*/React.createElement("button", {
    className: "gm-intro-cta",
    onClick: startAndFullscreen
  }, /*#__PURE__*/React.createElement("span", null, "\u05DC\u05D4\u05EA\u05D7\u05D9\u05DC \u05DC\u05E9\u05D7\u05E7"), /*#__PURE__*/React.createElement("svg", {
    viewBox: "0 0 24 24",
    width: "28",
    height: "28",
    fill: "none",
    stroke: "currentColor",
    strokeWidth: "2.6",
    strokeLinecap: "round",
    strokeLinejoin: "round"
  }, /*#__PURE__*/React.createElement("path", {
    d: "M19 12H5"
  }), /*#__PURE__*/React.createElement("path", {
    d: "M12 19l-7-7 7-7"
  }))), /*#__PURE__*/React.createElement("div", {
    className: "gm-foot-actions"
  }, /*#__PURE__*/React.createElement("button", {
    className: "foot-btn",
    onClick: () => {
      try {
        window.top.location.href = "https://www.ezway.co.il";
      } catch (e) {
        window.open("https://www.ezway.co.il", "_top");
      }
    },
    title: "\u05D0\u05EA\u05E8 \u05D4\u05D1\u05D9\u05EA"
  }, /*#__PURE__*/React.createElement(I.home, null)), /*#__PURE__*/React.createElement("button", {
    className: "foot-btn",
    onClick: toggleFullscreen,
    title: "\u05DE\u05E1\u05DA \u05DE\u05DC\u05D0"
  }, /*#__PURE__*/React.createElement(I.expand, null)), /*#__PURE__*/React.createElement("button", {
    className: "foot-btn" + (muted ? " muted" : ""),
    onClick: toggleMute,
    title: muted ? "השמע צלילים" : "השתק צלילים"
  }, muted ? /*#__PURE__*/React.createElement(I.speakerMute, null) : /*#__PURE__*/React.createElement(I.speaker, null)))));
}
function EndScreen({
  score,
  missedWords,
  onRestart
}) {
  const [submitted, setSubmitted] = useState(false);
  const [name, setName] = useState("");
  const [board, setBoard] = useState(() => getLeaderboard());
  const [showLb, setShowLb] = useState(false);
  const qualifies = qualifiesForLeaderboard(score) && !submitted;
  const submitName = () => {
    const newBoard = addToLeaderboard(name.trim() || "אנונימי", score);
    setBoard(newBoard);
    setSubmitted(true);
    setShowLb(true); // auto-open to show new ranking
  };
  return /*#__PURE__*/React.createElement("div", {
    className: "gm-app gm-end-app"
  }, /*#__PURE__*/React.createElement("div", {
    className: "gm-end-hud"
  }, /*#__PURE__*/React.createElement("button", {
    className: "gm-end-home",
    onClick: () => {
      try {
        window.top.location.href = "https://www.ezway.co.il";
      } catch (e) {
        window.open("https://www.ezway.co.il", "_top");
      }
    },
    title: "\u05D0\u05EA\u05E8 \u05D4\u05D1\u05D9\u05EA",
    "aria-label": "\u05DC\u05D0\u05EA\u05E8 eazy"
  }, /*#__PURE__*/React.createElement(I.home, null)), /*#__PURE__*/React.createElement("div", {
    className: "gm-end-brand"
  }, /*#__PURE__*/React.createElement("img", {
    src: window.__resources.ezIcon,
    alt: ""
  }), /*#__PURE__*/React.createElement("span", {
    className: "brand-eazy"
  }, "eazy"))), /*#__PURE__*/React.createElement("div", {
    className: "gm-end-score"
  }, /*#__PURE__*/React.createElement("div", {
    className: "gm-end-score-text"
  }, /*#__PURE__*/React.createElement("div", {
    className: "gm-end-eye"
  }, "\u05E1\u05D5\u05E3 \u05E1\u05D9\u05D1\u05D5\u05D1", /*#__PURE__*/React.createElement("span", {
    className: "dot"
  }, ".")), /*#__PURE__*/React.createElement("div", {
    className: "gm-end-line"
  }, /*#__PURE__*/React.createElement("span", null, "\u05D4\u05E9\u05D2\u05EA"), /*#__PURE__*/React.createElement("span", {
    className: "num"
  }, score), /*#__PURE__*/React.createElement("span", null, "\u05E0\u05E7\u05D5\u05D3\u05D5\u05EA."))), qualifies ? /*#__PURE__*/React.createElement("div", {
    className: "gm-lb-prompt"
  }, /*#__PURE__*/React.createElement("div", {
    className: "gm-lb-prompt-eye"
  }, /*#__PURE__*/React.createElement(I.trophy, null), " \u05E0\u05DB\u05E0\u05E1\u05EA \u05DC\u05D8\u05D1\u05DC\u05EA \u05D4\u05E9\u05D9\u05D0\u05D9\u05DD!"), /*#__PURE__*/React.createElement("div", {
    className: "gm-lb-prompt-row"
  }, /*#__PURE__*/React.createElement("input", {
    className: "gm-lb-input",
    type: "text",
    placeholder: "\u05D4\u05E9\u05DD \u05E9\u05DC\u05DA",
    value: name,
    onChange: e => setName(e.target.value),
    onKeyDown: e => e.key === 'Enter' && submitName(),
    maxLength: 20,
    autoFocus: true
  }), /*#__PURE__*/React.createElement("button", {
    className: "gm-lb-save",
    onClick: submitName
  }, "\u05E9\u05DE\u05D5\u05E8"))) : /*#__PURE__*/React.createElement("button", {
    className: "gm-end-cta secondary gm-end-lb-btn",
    onClick: () => setShowLb(true)
  }, /*#__PURE__*/React.createElement(I.trophy, null), /*#__PURE__*/React.createElement("span", null, "\u05D8\u05D1\u05DC\u05EA \u05D4\u05E9\u05D9\u05D0\u05D9\u05DD"))), /*#__PURE__*/React.createElement("div", {
    className: "gm-end-vrule"
  }), /*#__PURE__*/React.createElement("div", {
    className: "gm-end-list-wrap"
  }, missedWords.length > 0 ? /*#__PURE__*/React.createElement(React.Fragment, null, /*#__PURE__*/React.createElement("div", {
    className: "gm-end-list-eye"
  }, "\u05D0\u05DC\u05D5 \u05D4\u05DE\u05D9\u05DC\u05D9\u05DD \u05E9\u05E4\u05E1\u05E4\u05E1\u05EA"), /*#__PURE__*/React.createElement("div", {
    className: "gm-end-list"
  }, missedWords.map((w, i) => /*#__PURE__*/React.createElement("div", {
    key: i,
    className: "gm-end-row"
  }, /*#__PURE__*/React.createElement("span", {
    className: "gm-end-en"
  }, String(w.en).toUpperCase()), /*#__PURE__*/React.createElement("span", {
    className: "gm-end-he"
  }, w.he))))) : /*#__PURE__*/React.createElement("div", {
    className: "gm-end-no-miss"
  }, /*#__PURE__*/React.createElement("span", {
    className: "hi"
  }, "\u05DB\u05DC \u05D4\u05DB\u05D1\u05D5\u05D3", /*#__PURE__*/React.createElement("span", {
    className: "dot"
  }, "!")), /*#__PURE__*/React.createElement("span", {
    className: "lo"
  }, "\u05DC\u05D0 \u05E4\u05E1\u05E4\u05E1\u05EA \u05D0\u05E3 \u05DE\u05D9\u05DC\u05D4.")), /*#__PURE__*/React.createElement("button", {
    className: "gm-end-cta gm-end-restart",
    onClick: onRestart
  }, /*#__PURE__*/React.createElement("span", null, "\u05D9\u05D5\u05E6\u05D0\u05D9\u05DD \u05DC\u05E1\u05D9\u05D1\u05D5\u05D1 \u05E0\u05D5\u05E1\u05E3 \u05E2\u05DD \u05D4\u05EA\u05D5\u05EA\u05D7?"), /*#__PURE__*/React.createElement("span", {
    className: "cta-arrow",
    "aria-hidden": true
  }, "\u203A"))), showLb && /*#__PURE__*/React.createElement("div", {
    className: "gm-lb-modal",
    onClick: () => setShowLb(false)
  }, /*#__PURE__*/React.createElement("div", {
    className: "gm-lb-modal-card",
    onClick: e => e.stopPropagation()
  }, /*#__PURE__*/React.createElement("button", {
    className: "gm-lb-close",
    onClick: () => setShowLb(false),
    "aria-label": "\u05E1\u05D2\u05D5\u05E8"
  }, "\xD7"), /*#__PURE__*/React.createElement("div", {
    className: "gm-lb-title"
  }, /*#__PURE__*/React.createElement(I.trophy, null), /*#__PURE__*/React.createElement("span", null, "\u05D8\u05D1\u05DC\u05EA \u05D4\u05E9\u05D9\u05D0\u05D9\u05DD")), board.length === 0 ? /*#__PURE__*/React.createElement("div", {
    className: "gm-lb-empty"
  }, "\u05E2\u05D3\u05D9\u05D9\u05DF \u05D0\u05D9\u05DF \u05E9\u05D9\u05D0\u05D9\u05DD. \u05D0\u05EA\u05D4 \u05D9\u05DB\u05D5\u05DC \u05DC\u05D4\u05D9\u05D5\u05EA \u05D4\u05E8\u05D0\u05E9\u05D5\u05DF.") : /*#__PURE__*/React.createElement("ol", {
    className: "gm-lb-list"
  }, board.map((entry, i) => /*#__PURE__*/React.createElement("li", {
    key: i,
    className: "gm-lb-row " + (submitted && entry.score === score && entry.name === (name.trim() || "אנונימי") ? "you" : "")
  }, /*#__PURE__*/React.createElement("span", {
    className: "rank"
  }, i + 1), /*#__PURE__*/React.createElement("span", {
    className: "name"
  }, entry.name), /*#__PURE__*/React.createElement("span", {
    className: "pts"
  }, entry.score)))))));
}

/* ──────────────────────────────────────────────
   Game
   ────────────────────────────────────────────── */
function Game() {
  const [started, setStarted] = useState(false);
  const [dict, setDict] = useState(null);
  const [dictName, setDictName] = useState("");
  const [used, setUsed] = useState([]);
  const [missed, setMissed] = useState([]);
  const [question, setQuestion] = useState(null);
  const [lives, setLives] = useState(3);
  const [score, setScore] = useState(0);
  const [aimed, setAimed] = useState(null);
  const [resolved, setResolved] = useState({});
  const [angle, setAngle] = useState(-18);
  const [shot, setShot] = useState(null);
  const [toast, setToast] = useState(null);
  const [missFx, setMissFx] = useState(false);
  const [recoil, setRecoil] = useState(false);
  const [levelUpInfo, setLevelUpInfo] = useState(null);
  const [audioUnlocked, setAudioUnlocked] = useState(false);
  const [autoSpeakEnabled, setAutoSpeakEnabled] = useState(true);
  // streak (consecutive correct answers), and the last time a streak bonus
  // fired — combo bonuses are gated to once per 5 minutes so they stay rare.
  const [streak, setStreak] = useState(0);
  const lastBonusTimeRef = useRef(0);
  const questionStartRef = useRef(Date.now());
  const [muted, setMuted] = useState(Sound.muted);
  // lifelines & bonuses
  const [fiftyAvailable, setFiftyAvailable] = useState(true);
  const [hiddenIdx, setHiddenIdx] = useState(() => new Set());
  const [kitState, setKitState] = useState(null);
  const prevQuestionEnRef = useRef(null);
  const prevLevelRef = useRef(0);
  const stageRef = useRef(null);
  const cannonRef = useRef(null);
  const rocketRefs = useRef([]);
  const scale = useStageScale(1600, 900);

  // ── level system: every 15 questions speeds up + raises points ──
  const level = Math.floor(used.length / 15);
  const rocketDur = Math.max(8, 22 - level * 3); // seconds, min 8s
  const pointsPerHit = 200 + level * 100;
  useEffect(() => {
    if (level > prevLevelRef.current && used.length > 0) {
      setLevelUpInfo({
        sub: `הטילים מהירים יותר · +${pointsPerHit} לכל תשובה נכונה`
      });
      const t = setTimeout(() => setLevelUpInfo(null), 2600);
      prevLevelRef.current = level;
      return () => clearTimeout(t);
    }
    prevLevelRef.current = level;
  }, [level, used.length, pointsPerHit]);

  // ── BOSS question + audio unlock ──
  // The 6th question (after 5 normal answers) is a one-time BOSS round. Hitting
  // it unlocks the per-word speaker icon for the rest of the run.
  const isBoss = used.length === 5 && !audioUnlocked;

  // Speak the current English word via the browser's SpeechSynthesis. Works
  // regardless of the game's mute toggle (those are SFX/music; this is content).
  const speakWord = useCallback(text => {
    if (!text) return;
    try {
      const synth = window.speechSynthesis;
      if (!synth) return;
      synth.cancel();
      const u = new SpeechSynthesisUtterance(String(text));
      u.lang = 'en-US';
      u.rate = 0.85;
      u.pitch = 1.0;
      u.volume = 1.0;
      // Prefer a real English voice if the browser has finished loading them.
      try {
        const voices = synth.getVoices ? synth.getVoices() : [];
        const en = voices.find(v => /^en[-_]/i.test(v.lang)) || voices.find(v => /english/i.test(v.name));
        if (en) u.voice = en;
      } catch (e) {}
      synth.speak(u);
    } catch (e) {/* ignore — TTS just won't fire */}
  }, []);

  // After the BOSS is beaten and audio is unlocked, auto-speak every new word.
  // Three independent guards: the audio must be unlocked (boss beaten), the
  // user must have opted in at the level-up screen, and the master sound
  // toggle must be unmuted.
  useEffect(() => {
    if (!audioUnlocked) return;
    if (!autoSpeakEnabled) return;
    if (muted) return;
    if (!question?.en) return;
    // Small delay so the new word has time to render and any in-flight SFX
    // (hit/levelup) doesn't compete with the TTS.
    const t = setTimeout(() => speakWord(question.en), 350);
    return () => clearTimeout(t);
  }, [audioUnlocked, autoSpeakEnabled, muted, question?.en, speakWord]);

  // mouse-tracking aim when idle
  useEffect(() => {
    const stage = stageRef.current;
    const cannon = cannonRef.current;
    if (!stage || !cannon) return;
    const onMove = ev => {
      if (aimed !== null) return; // a shot is in flight
      if (isRoundOver) return;
      const sR = stage.getBoundingClientRect();
      const cR = cannon.getBoundingClientRect();
      const mx = (ev.clientX - sR.left) / scale;
      const my = (ev.clientY - sR.top) / scale;
      const fromX = (cR.left - sR.left + cR.width * 0.5) / scale;
      const fromY = (cR.top - sR.top + cR.height * 0.42) / scale;
      let ang = Math.atan2(my - fromY, mx - fromX) * (180 / Math.PI);
      // clamp barrel rotation
      if (ang < -55) ang = -55;
      if (ang > 20) ang = 20;
      setAngle(ang);
    };
    stage.addEventListener("mousemove", onMove);
    return () => stage.removeEventListener("mousemove", onMove);
  }, [aimed, isRoundOver, scale]);

  // fullscreen toggle — also locks orientation to landscape on mobile
  const toggleFullscreen = useCallback(() => {
    try {
      const target = window.frameElement ? window.frameElement : document.documentElement;
      const doc = window.frameElement ? window.parent.document : document;
      const isFs = doc.fullscreenElement || doc.webkitFullscreenElement;
      if (!isFs) {
        const req = target.requestFullscreen || target.webkitRequestFullscreen || target.mozRequestFullScreen || target.msRequestFullscreen;
        if (req) {
          const p = req.call(target);
          // attempt to lock landscape on mobile devices
          if (p && p.then) {
            p.then(() => {
              try {
                if (screen.orientation && screen.orientation.lock) {
                  screen.orientation.lock('landscape').catch(() => {});
                }
              } catch (e) {}
            }).catch(() => {});
          } else {
            try {
              if (screen.orientation && screen.orientation.lock) {
                screen.orientation.lock('landscape').catch(() => {});
              }
            } catch (e) {}
          }
        }
      } else {
        try {
          if (screen.orientation && screen.orientation.unlock) screen.orientation.unlock();
        } catch (e) {}
        const exit = doc.exitFullscreen || doc.webkitExitFullscreen || doc.mozCancelFullScreen || doc.msExitFullscreen;
        if (exit) exit.call(doc);
      }
    } catch (e) {/* permission blocked in iframe — silent */}
  }, []);

  // mute toggle — controls background music, sound FX, AND (after the BOSS
  // unlock) the per-word audio. This is the single source of truth for any
  // sound coming out of the game.
  const toggleMute = useCallback(() => {
    const next = !Sound.muted;
    Sound.setMuted(next);
    setMuted(next);
    if (next) {
      // muting → stop any in-flight TTS immediately
      try {
        window.speechSynthesis?.cancel();
      } catch (e) {}
    }
  }, []);

  // hydrate dictionary — bundled words.js takes precedence over localStorage
  useEffect(() => {
    if (window.GAME_DICTIONARY && Array.isArray(window.GAME_DICTIONARY) && window.GAME_DICTIONARY.length >= 4) {
      setDict(window.GAME_DICTIONARY);
      setDictName("מילון המשחק");
      return;
    }
    try {
      const raw = localStorage.getItem(DICT_STORAGE_KEY);
      if (raw) {
        const arr = JSON.parse(raw);
        if (Array.isArray(arr) && arr.length >= 4) {
          setDict(arr);
          setDictName(localStorage.getItem(DICT_NAME_KEY) || "");
        }
      }
    } catch (e) {}
  }, []);

  // draw a question whenever dict changes or used grows
  useEffect(() => {
    if (!dict) return;
    const available = dict.map((_, i) => i).filter(i => !used.includes(i));
    if (available.length === 0) {
      setQuestion(null);
      return;
    }
    const correctIdx = available[Math.floor(Math.random() * available.length)];
    setQuestion({
      ...buildQuestion(dict, correctIdx),
      correctDictIdx: correctIdx
    });
  }, [dict, used]);
  const loadDict = useCallback((entries, name) => {
    setDict(entries);
    setDictName(name);
    setUsed([]);
    setMissed([]);
    setLives(3);
    setScore(0);
    setResolved({});
    setAimed(null);
    try {
      localStorage.setItem(DICT_STORAGE_KEY, JSON.stringify(entries));
      localStorage.setItem(DICT_NAME_KEY, name);
    } catch (e) {}
  }, []);
  const resetDict = useCallback(() => {
    setDict(null);
    setDictName("");
    setUsed([]);
    setMissed([]);
    setLives(3);
    setScore(0);
    setResolved({});
    setAimed(null);
    setQuestion(null);
    try {
      localStorage.removeItem(DICT_STORAGE_KEY);
      localStorage.removeItem(DICT_NAME_KEY);
    } catch (e) {}
  }, []);
  const restartGame = useCallback(() => {
    setUsed([]);
    setMissed([]);
    setLives(3);
    setScore(0);
    setResolved({});
    setAimed(null);
    setFiftyAvailable(true);
    setHiddenIdx(new Set());
    setKitState(null);
    setAudioUnlocked(false);
    setAutoSpeakEnabled(true);
    setLevelUpInfo(null);
    setStreak(0);
    lastBonusTimeRef.current = 0;
    questionStartRef.current = Date.now();
    prevLevelRef.current = 0;
    Sound.startMusic();
  }, []);
  const correctIdx = question ? question.options.indexOf(question.correct) : -1;
  const isRoundOver = resolved[correctIdx] === "hit" || lives <= 0;

  // Reset 50/50 hidden distractors whenever a new question appears;
  // every 8th question, drop a first-aid kit (if not full lives + not already showing).
  useEffect(() => {
    if (!question) return;
    if (prevQuestionEnRef.current !== question.en) {
      setHiddenIdx(new Set());
      prevQuestionEnRef.current = question.en;
      // Stamp the new question's start time so the speed bonus can be computed
      // when the user finally shoots.
      questionStartRef.current = Date.now();
      if (used.length > 0 && used.length % 8 === 0 && !kitState && lives < 3) {
        setKitState({
          id: Date.now()
        });
      }
    }
  }, [question, used.length, lives, kitState]);

  // 50/50 lifeline: hide 2 of the 3 wrong distractors
  const useFifty = useCallback(() => {
    if (!fiftyAvailable || !question || isRoundOver) return;
    const wrongs = question.options.map((_, i) => i).filter(i => i !== correctIdx);
    const toHide = shuffleArr(wrongs).slice(0, 2);
    setHiddenIdx(new Set(toHide));
    setFiftyAvailable(false);
    Sound.play('fifty');
  }, [fiftyAvailable, question, correctIdx, isRoundOver]);

  // Shooting the first-aid kit grants a life back
  const onKitHit = useCallback(() => {
    if (!kitState) return;
    setLives(l => Math.min(3, l + 1));
    setKitState(null);
    Sound.play('lifegain');
    setToast({
      kind: "win",
      text: "+1 לב · תיק עזרה ראשונה!"
    });
    setTimeout(() => setToast(null), 1800);
  }, [kitState]);

  // Kit auto-vanishes if not shot in time
  useEffect(() => {
    if (!kitState) return;
    const t = setTimeout(() => setKitState(null), 9000);
    return () => clearTimeout(t);
  }, [kitState]);
  const nextQuestion = useCallback(() => {
    if (!question) return;
    setUsed(u => [...u, question.correctDictIdx]);
    setResolved({});
    setAimed(null);
    setAngle(-18);
  }, [question]);
  const onTarget = useCallback(i => {
    if (!question) return;
    if (hiddenIdx.has(i)) return;
    if (resolved[i] || isRoundOver || aimed !== null) return;
    setAimed(i);
    Sound.play('shoot');
    const stage = stageRef.current;
    const cannon = cannonRef.current;
    const target = rocketRefs.current[i];
    if (!stage || !cannon || !target) return;
    const sR = stage.getBoundingClientRect();
    const cR = cannon.getBoundingClientRect();
    const tR = target.getBoundingClientRect();
    const fromX = (cR.left - sR.left + cR.width * 0.5) / scale;
    const fromY = (cR.top - sR.top + cR.height * 0.42) / scale;
    const toX = (tR.left - sR.left + 70) / scale;
    const toY = (tR.top - sR.top + tR.height * 0.5) / scale;
    const ang = Math.atan2(toY - fromY, toX - fromX) * (180 / Math.PI);
    setAngle(ang);
    setTimeout(() => {
      setShot({
        fromX,
        fromY,
        toX,
        toY
      });
      setTimeout(() => {
        const correct = i === correctIdx;
        const isBossHit = isBoss && correct;
        setResolved(r => ({
          ...r,
          [i]: correct ? "hit" : "missed"
        }));
        if (correct) {
          // ── speed bonus: faster hits earn more points (linear 2× → 1×) ──
          const effectiveDur = isBoss ? rocketDur * 0.8 : rocketDur;
          const elapsed = (Date.now() - questionStartRef.current) / 1000;
          const speedMult = Math.max(1, Math.min(2, 2 - elapsed / Math.max(1, effectiveDur)));

          // ── streak bonus: every 5 in a row unlocks a special — but a special
          // bonus fires at most once per 5 minutes so it stays meaningful. ──
          const newStreak = streak + 1;
          const now = Date.now();
          const cooldownPassed = now - lastBonusTimeRef.current >= 5 * 60 * 1000;
          let comboMult = 1,
            comboBonus = 0,
            comboLabel = null;
          if (newStreak >= 5 && newStreak % 5 === 0 && cooldownPassed) {
            if (newStreak >= 20) {
              comboMult = 3;
              comboLabel = `סטריק ${newStreak} ✦ ×3 ניקוד`;
            } else if (newStreak >= 10) {
              comboMult = 2;
              comboLabel = `סטריק ${newStreak} ✦ ×2 ניקוד`;
            } else {
              comboBonus = 500;
              comboLabel = `סטריק ${newStreak} ✦ +500 בונוס`;
            }
            lastBonusTimeRef.current = now;
          }
          const basePoints = isBossHit ? 500 : pointsPerHit;
          const points = Math.round(basePoints * speedMult * comboMult) + comboBonus;
          setScore(s => s + points);
          setStreak(newStreak);
          Sound.play(comboLabel ? 'levelup' : 'hit');
          if (comboLabel) {
            setToast({
              kind: "win",
              text: `${comboLabel} · +${points}`
            });
          } else {
            const speedTag = speedMult >= 1.7 ? "מהיר! " : speedMult >= 1.35 ? "יפה! " : "";
            setToast({
              kind: "win",
              text: `${speedTag}פגיעה ישירה +${points}`
            });
          }
          // BOSS pass → unlock the per-word audio, show a custom level-up overlay.
          // The overlay has its own continue buttons so we DON'T auto-advance here.
          if (isBossHit) {
            setAudioUnlocked(true);
            Sound.play('levelup');
            setTimeout(() => {
              setLevelUpInfo({
                mode: 'audio',
                sub: 'מעכשיו אפשר גם לשמוע כל מילה באנגלית.'
              });
            }, 500);
          }
        } else {
          setStreak(0);
          setLives(l => Math.max(0, l - 1));
          setMissed(m => m.includes(question.correctDictIdx) ? m : [...m, question.correctDictIdx]);
          setMissFx(true);
          setTimeout(() => setMissFx(false), 5400);
          setRecoil(true);
          setTimeout(() => setRecoil(false), 500);
          Sound.play('miss');
          setToast({
            kind: "lose",
            text: "פספסת — לב אחד נפל"
          });
          setTimeout(() => {
            setResolved(r => ({
              ...r,
              [correctIdx]: r[correctIdx] || "correct-after"
            }));
          }, 700);
        }
        setShot(null);
        setAimed(null);
        setTimeout(() => setToast(null), 1800);
        // auto-advance to next question — skipped for the BOSS hit (the
        // unlock overlay's "Continue" button handles that)
        if (!isBossHit) {
          setTimeout(() => {
            setUsed(u => [...u, question.correctDictIdx]);
            setResolved({});
            setAimed(null);
            setAngle(-18);
          }, correct ? 1400 : 5600);
        }
      }, 380);
    }, 340);
  }, [resolved, isRoundOver, aimed, correctIdx, scale, question, pointsPerHit, hiddenIdx, isBoss, rocketDur, streak]);

  // Rocket reaches the cannon zone = wrong answer
  const onTravelEnd = useCallback((i, e) => {
    if (e.animationName !== "rocketTravel") return;
    // Hard guard: once the correct rocket is resolved (hit, missed, or
    // revealed-after), no other rocket of the same round can deduct another
    // life. Without this, multiple rockets reaching the line in a row burned
    // through every heart in one round.
    if (!question || resolved[i] || isRoundOver || resolved[correctIdx]) return;
    setStreak(0);
    setLives(l => Math.max(0, l - 1));
    setMissed(m => m.includes(question.correctDictIdx) ? m : [...m, question.correctDictIdx]);
    setResolved(r => ({
      ...r,
      [i]: "missed",
      [correctIdx]: r[correctIdx] || "correct-after"
    }));
    setMissFx(true);
    setTimeout(() => setMissFx(false), 5400);
    Sound.play('miss');
    setToast({
      kind: "lose",
      text: "הטיל הגיע — לב אחד נפל"
    });
    setTimeout(() => setToast(null), 1800);
    setTimeout(() => {
      setUsed(u => [...u, question.correctDictIdx]);
      setResolved({});
      setAimed(null);
      setAngle(-18);
    }, 5600);
  }, [question, resolved, isRoundOver, correctIdx]);
  let shotEl = null;
  if (shot) {
    const dx = shot.toX - shot.fromX;
    const dy = shot.toY - shot.fromY;
    shotEl = /*#__PURE__*/React.createElement("div", {
      className: "gm-shot active",
      style: {
        left: shot.fromX,
        top: shot.fromY,
        animation: "shotFly .4s linear forwards",
        "--dx": `${dx}px`,
        "--dy": `${dy}px`
      }
    });
  }

  // ── intro first ──
  if (!started) return /*#__PURE__*/React.createElement(IntroScreen, {
    onStart: () => {
      setStarted(true);
      Sound.startMusic();
      // Prime SpeechSynthesis on user gesture so iOS will let later auto-speaks fire.
      // Also kicks the browser to start loading its voice list.
      try {
        const s = window.speechSynthesis;
        if (s) {
          const primer = new SpeechSynthesisUtterance(' ');
          primer.volume = 0;
          primer.rate = 1;
          s.speak(primer);
          s.getVoices?.();
        }
      } catch (e) {}
    },
    toggleFullscreen: toggleFullscreen,
    muted: muted,
    toggleMute: toggleMute
  });

  // ── no dict yet — only shown if bundled words.js missing AND no localStorage ──
  if (!dict) return /*#__PURE__*/React.createElement(UploadScreen, {
    onLoad: loadDict
  });

  // ── game over (lives exhausted) ──
  if (lives <= 0) {
    const missedWords = missed.map(idx => dict[idx]).filter(Boolean);
    return /*#__PURE__*/React.createElement(EndScreen, {
      score: score,
      missedWords: missedWords,
      onRestart: restartGame
    });
  }

  // ── dict exhausted ──
  if (!question) {
    return /*#__PURE__*/React.createElement("div", {
      className: "gm-app gm-up-app"
    }, /*#__PURE__*/React.createElement("div", {
      className: "gm-up-wrap"
    }, /*#__PURE__*/React.createElement("div", {
      className: "gm-up-card"
    }, /*#__PURE__*/React.createElement("div", {
      className: "gm-up-eye"
    }, "\u05E1\u05D9\u05D9\u05DE\u05EA\u05DD \u05D0\u05EA \u05D4\u05DE\u05D9\u05DC\u05D5\u05DF"), /*#__PURE__*/React.createElement("h1", {
      className: "gm-up-h1"
    }, used.length, " \u05DE\u05D9\u05DC\u05D9\u05DD \xB7 ", score, " \u05E0\u05E7\u05D5\u05D3\u05D5\u05EA"), /*#__PURE__*/React.createElement("p", {
      className: "gm-up-sub"
    }, "\u05E2\u05D1\u05E8\u05EA \u05E2\u05DC \u05DB\u05DC \u05D4\u05DE\u05D9\u05DC\u05D9\u05DD \u05D1\u05DE\u05D9\u05DC\u05D5\u05DF \"", dictName, "\". \u05DE\u05D4 \u05D4\u05DC\u05D0\u05D4?"), /*#__PURE__*/React.createElement("button", {
      className: "gm-up-btn",
      onClick: () => {
        setUsed([]);
        setLives(3);
        setScore(0);
      }
    }, "\u05E1\u05D9\u05D1\u05D5\u05D1 \u05E0\u05D5\u05E1\u05E3 \u05E2\u05DD \u05D0\u05D5\u05EA\u05DD \u05DE\u05D9\u05DC\u05D9\u05DD"), /*#__PURE__*/React.createElement("button", {
      className: "gm-up-btn-ghost",
      onClick: resetDict
    }, "\u05D8\u05E2\u05E0\u05D5 \u05DE\u05D9\u05DC\u05D5\u05DF \u05D0\u05D7\u05E8"))));
  }
  return /*#__PURE__*/React.createElement("div", {
    className: "gm-app"
  }, /*#__PURE__*/React.createElement("div", {
    className: "gm-stage",
    ref: stageRef,
    style: {
      "--gm-scale": scale,
      "--rocket-duration": `${(isBoss ? rocketDur * 0.8 : rocketDur).toFixed(2)}s`
    }
  }, /*#__PURE__*/React.createElement(SkyZ, null), /*#__PURE__*/React.createElement(Mountains, null), /*#__PURE__*/React.createElement("div", {
    className: "gm-ground"
  }), /*#__PURE__*/React.createElement("div", {
    className: "gm-hud-brand"
  }, /*#__PURE__*/React.createElement("img", {
    src: window.__resources.ezIcon,
    alt: ""
  }), /*#__PURE__*/React.createElement("span", {
    className: "brand-eazy"
  }, "eazy")), /*#__PURE__*/React.createElement("div", {
    className: "gm-hud"
  }, /*#__PURE__*/React.createElement("div", {
    className: "chip hearts"
  }, [0, 1, 2].map(i => /*#__PURE__*/React.createElement(Heart, {
    key: i,
    lost: i >= lives
  }))), /*#__PURE__*/React.createElement("div", {
    className: "chip score"
  }, /*#__PURE__*/React.createElement("span", {
    className: "label"
  }, "\u05E0\u05D9\u05E7\u05D5\u05D3"), /*#__PURE__*/React.createElement("span", null, score)), /*#__PURE__*/React.createElement("div", {
    className: "spacer"
  })), isBoss && /*#__PURE__*/React.createElement("div", {
    className: "gm-boss-banner",
    "aria-hidden": true
  }, /*#__PURE__*/React.createElement("svg", {
    viewBox: "0 0 24 24",
    width: "32",
    height: "32",
    fill: "currentColor"
  }, /*#__PURE__*/React.createElement("path", {
    d: "M13 2 L4 14 L11 14 L10 22 L20 9 L13 9 Z"
  })), /*#__PURE__*/React.createElement("span", null, "\u05E9\u05DC\u05D1 BOSS"), /*#__PURE__*/React.createElement("svg", {
    viewBox: "0 0 24 24",
    width: "32",
    height: "32",
    fill: "currentColor"
  }, /*#__PURE__*/React.createElement("path", {
    d: "M13 2 L4 14 L11 14 L10 22 L20 9 L13 9 Z"
  }))), /*#__PURE__*/React.createElement("div", {
    className: "gm-word" + (isBoss ? " is-boss" : "") + (used.length === 0 ? " is-first" : "")
  }, /*#__PURE__*/React.createElement("div", {
    className: "en-wrap"
  }, /*#__PURE__*/React.createElement("div", {
    className: "en"
  }, question.en))), /*#__PURE__*/React.createElement("div", {
    className: "gm-foot-actions"
  }, /*#__PURE__*/React.createElement("button", {
    className: "foot-btn",
    onClick: () => {
      try {
        window.top.location.href = "https://www.ezway.co.il";
      } catch (e) {
        window.open("https://www.ezway.co.il", "_top");
      }
    },
    title: "\u05D0\u05EA\u05E8 \u05D4\u05D1\u05D9\u05EA"
  }, /*#__PURE__*/React.createElement(I.home, null)), /*#__PURE__*/React.createElement("button", {
    className: "foot-btn",
    onClick: toggleFullscreen,
    title: "\u05DE\u05E1\u05DA \u05DE\u05DC\u05D0"
  }, /*#__PURE__*/React.createElement(I.expand, null)), /*#__PURE__*/React.createElement("button", {
    className: "foot-btn lifeline" + (fiftyAvailable ? "" : " used"),
    onClick: useFifty,
    disabled: !fiftyAvailable,
    title: fiftyAvailable ? "גלגל הצלה 50/50" : "כבר השתמשת ב-50/50"
  }, /*#__PURE__*/React.createElement("span", {
    className: "fifty-text"
  }, "50", /*#__PURE__*/React.createElement("br", null), "50")), /*#__PURE__*/React.createElement("button", {
    className: "foot-btn" + (muted ? " muted" : ""),
    onClick: toggleMute,
    title: muted ? "השמע צלילים" : "השתק צלילים"
  }, muted ? /*#__PURE__*/React.createElement(I.speakerMute, null) : /*#__PURE__*/React.createElement(I.speaker, null))), /*#__PURE__*/React.createElement("div", {
    className: "gm-rockets"
  }, question.options.map((opt, i) => {
    const state = resolved[i];
    let cls = "gm-rocket";
    if (isBoss) cls += " boss";
    if (aimed === i) cls += " aiming";
    if (state === "hit") cls += " hit";else if (state === "missed") cls += " missed";else if (state === "correct-after") cls += " correct-after";
    const paused = isRoundOver || aimed === i || resolved[i] && resolved[i] !== "correct-after"; // correct-after keeps drifting
    const hidden = hiddenIdx.has(i);
    return /*#__PURE__*/React.createElement("div", {
      key: `${question.en}-${i}`,
      className: "gm-rocket-travel" + (paused ? " paused" : "") + (hidden ? " hidden5050" : ""),
      style: {
        animationDelay: `${-i * 1.5}s`
      },
      onAnimationEnd: e => onTravelEnd(i, e)
    }, /*#__PURE__*/React.createElement("div", {
      ref: el => rocketRefs.current[i] = el,
      className: cls,
      style: {
        "--mr": STAGGER[i] + "px"
      },
      onClick: () => onTarget(i)
    }, /*#__PURE__*/React.createElement(RocketSVG, {
      isBoss: isBoss
    }), /*#__PURE__*/React.createElement("div", {
      className: "label"
    }, opt), /*#__PURE__*/React.createElement("div", {
      className: "gm-burst"
    }, /*#__PURE__*/React.createElement(BurstSVG, null))));
  })), /*#__PURE__*/React.createElement("div", {
    className: "gm-cannon" + (recoil ? " recoil" : ""),
    ref: cannonRef
  }, /*#__PURE__*/React.createElement(CannonBase, null), /*#__PURE__*/React.createElement("div", {
    className: "barrel-wrap"
  }, /*#__PURE__*/React.createElement("svg", {
    style: {
      position: "absolute",
      width: "220px",
      height: "60px",
      top: "-30px",
      left: "-30px",
      transformOrigin: "30px 30px",
      transform: `rotate(${angle}deg)`,
      transition: "transform .08s linear",
      overflow: "visible"
    },
    viewBox: "0 0 220 60"
  }, /*#__PURE__*/React.createElement("defs", null, /*#__PURE__*/React.createElement("linearGradient", {
    id: "barG2",
    x1: "0",
    y1: "0",
    x2: "0",
    y2: "1"
  }, /*#__PURE__*/React.createElement("stop", {
    offset: "0",
    stopColor: "#3a3358"
  }), /*#__PURE__*/React.createElement("stop", {
    offset: "0.5",
    stopColor: "#1A1530"
  }), /*#__PURE__*/React.createElement("stop", {
    offset: "1",
    stopColor: "#0A0820"
  })), /*#__PURE__*/React.createElement("linearGradient", {
    id: "muzzleG2",
    x1: "0",
    y1: "0",
    x2: "0",
    y2: "1"
  }, /*#__PURE__*/React.createElement("stop", {
    offset: "0",
    stopColor: "#5a5470"
  }), /*#__PURE__*/React.createElement("stop", {
    offset: "1",
    stopColor: "#2A2547"
  }))), /*#__PURE__*/React.createElement("rect", {
    x: "14",
    y: "22",
    width: "36",
    height: "20",
    rx: "4",
    fill: "#1A1530"
  }), /*#__PURE__*/React.createElement("rect", {
    x: "14",
    y: "22",
    width: "36",
    height: "3",
    fill: "rgba(255,255,255,.18)"
  }), /*#__PURE__*/React.createElement("rect", {
    x: "40",
    y: "26",
    width: "150",
    height: "12",
    rx: "4",
    fill: "url(#barG2)"
  }), /*#__PURE__*/React.createElement("rect", {
    x: "42",
    y: "27",
    width: "146",
    height: "2",
    rx: "1",
    fill: "rgba(255,255,255,.25)"
  }), /*#__PURE__*/React.createElement("rect", {
    x: "184",
    y: "22",
    width: "22",
    height: "20",
    rx: "3",
    fill: "url(#muzzleG2)"
  }), /*#__PURE__*/React.createElement("rect", {
    x: "188",
    y: "26",
    width: "2",
    height: "12",
    fill: "#0A0820"
  }), /*#__PURE__*/React.createElement("rect", {
    x: "194",
    y: "26",
    width: "2",
    height: "12",
    fill: "#0A0820"
  }), /*#__PURE__*/React.createElement("rect", {
    x: "200",
    y: "26",
    width: "2",
    height: "12",
    fill: "#0A0820"
  }), /*#__PURE__*/React.createElement("rect", {
    x: "22",
    y: "14",
    width: "6",
    height: "10",
    fill: "#1A1530"
  }), /*#__PURE__*/React.createElement("circle", {
    cx: "25",
    cy: "13",
    r: "3",
    fill: "#F33F3F"
  })))), shotEl, kitState && /*#__PURE__*/React.createElement("div", {
    className: "gm-kit-travel",
    key: kitState.id,
    onAnimationEnd: () => setKitState(null)
  }, /*#__PURE__*/React.createElement("button", {
    className: "gm-kit",
    onClick: onKitHit,
    title: "\u05D9\u05E8\u05D4 \u05D1\u05EA\u05D9\u05E7 \u05DC\u05E2\u05D5\u05D3 \u05DC\u05D1!"
  }, /*#__PURE__*/React.createElement("svg", {
    viewBox: "0 0 120 110",
    "aria-hidden": true
  }, /*#__PURE__*/React.createElement("defs", null, /*#__PURE__*/React.createElement("linearGradient", {
    id: "kitG",
    x1: "0",
    y1: "0",
    x2: "0",
    y2: "1"
  }, /*#__PURE__*/React.createElement("stop", {
    offset: "0",
    stopColor: "#FFFFFF"
  }), /*#__PURE__*/React.createElement("stop", {
    offset: "1",
    stopColor: "#E8E6F0"
  })), /*#__PURE__*/React.createElement("linearGradient", {
    id: "kitHandleG",
    x1: "0",
    y1: "0",
    x2: "0",
    y2: "1"
  }, /*#__PURE__*/React.createElement("stop", {
    offset: "0",
    stopColor: "#3a3358"
  }), /*#__PURE__*/React.createElement("stop", {
    offset: "1",
    stopColor: "#1A1530"
  }))), /*#__PURE__*/React.createElement("ellipse", {
    cx: "60",
    cy: "102",
    rx: "42",
    ry: "5",
    fill: "rgba(0,0,0,.3)"
  }), /*#__PURE__*/React.createElement("rect", {
    x: "44",
    y: "8",
    width: "32",
    height: "14",
    rx: "3",
    fill: "url(#kitHandleG)",
    stroke: "#0A0820",
    strokeWidth: "2"
  }), /*#__PURE__*/React.createElement("rect", {
    x: "48",
    y: "14",
    width: "24",
    height: "8",
    rx: "2",
    fill: "rgba(255,255,255,.15)"
  }), /*#__PURE__*/React.createElement("rect", {
    x: "14",
    y: "22",
    width: "92",
    height: "76",
    rx: "8",
    fill: "url(#kitG)",
    stroke: "#0A0820",
    strokeWidth: "2.5"
  }), /*#__PURE__*/React.createElement("rect", {
    x: "52",
    y: "34",
    width: "16",
    height: "52",
    rx: "2",
    fill: "#DC2626"
  }), /*#__PURE__*/React.createElement("rect", {
    x: "34",
    y: "52",
    width: "52",
    height: "16",
    rx: "2",
    fill: "#DC2626"
  }), /*#__PURE__*/React.createElement("rect", {
    x: "20",
    y: "28",
    width: "80",
    height: "3",
    rx: "1.5",
    fill: "rgba(255,255,255,.5)"
  }), /*#__PURE__*/React.createElement("rect", {
    x: "56",
    y: "20",
    width: "8",
    height: "6",
    fill: "#3a3358"
  })), /*#__PURE__*/React.createElement("div", {
    className: "gm-kit-label"
  }, "+1 \u05DC\u05D1"))), missFx && /*#__PURE__*/React.createElement("div", {
    className: "gm-miss-jam",
    "aria-hidden": true
  }, /*#__PURE__*/React.createElement("svg", {
    viewBox: "0 0 1600 900",
    preserveAspectRatio: "none"
  }, /*#__PURE__*/React.createElement("defs", null, /*#__PURE__*/React.createElement("linearGradient", {
    id: "jamG",
    x1: "0",
    y1: "0",
    x2: "0",
    y2: "1"
  }, /*#__PURE__*/React.createElement("stop", {
    offset: "0",
    stopColor: "#7C170F",
    stopOpacity: ".95"
  }), /*#__PURE__*/React.createElement("stop", {
    offset: ".35",
    stopColor: "#9C1E16",
    stopOpacity: ".92"
  }), /*#__PURE__*/React.createElement("stop", {
    offset: ".75",
    stopColor: "#B5251B",
    stopOpacity: ".88"
  }), /*#__PURE__*/React.createElement("stop", {
    offset: ".94",
    stopColor: "#C72A1F",
    stopOpacity: ".84"
  }), /*#__PURE__*/React.createElement("stop", {
    offset: ".95",
    stopColor: "#C72A1F",
    stopOpacity: "0"
  }), /*#__PURE__*/React.createElement("stop", {
    offset: "1",
    stopColor: "#C72A1F",
    stopOpacity: "0"
  })), /*#__PURE__*/React.createElement("linearGradient", {
    id: "curtainG",
    x1: "0",
    y1: "0",
    x2: "0",
    y2: "1"
  }, /*#__PURE__*/React.createElement("stop", {
    offset: "0",
    stopColor: "#8E1A12",
    stopOpacity: ".95"
  }), /*#__PURE__*/React.createElement("stop", {
    offset: ".5",
    stopColor: "#A8201A",
    stopOpacity: ".92"
  }), /*#__PURE__*/React.createElement("stop", {
    offset: ".9",
    stopColor: "#B5251B",
    stopOpacity: ".90"
  }), /*#__PURE__*/React.createElement("stop", {
    offset: "1",
    stopColor: "#7C170F",
    stopOpacity: ".95"
  })), /*#__PURE__*/React.createElement("filter", {
    id: "jamBlur",
    x: "-3%",
    y: "-3%",
    width: "106%",
    height: "106%"
  }, /*#__PURE__*/React.createElement("feGaussianBlur", {
    stdDeviation: ".8"
  }))), /*#__PURE__*/React.createElement("path", {
    className: "jam-splat",
    d: "M 0 0 L 1600 0 L 1600 180 C 1540 220 1490 175 1440 200 C 1380 230 1330 175 1280 215 C 1230 245 1180 185 1130 225 C 1080 255 1030 200 980 230 C 930 265 880 195 830 240 C 780 275 730 215 680 245 C 630 280 580 210 530 250 C 480 280 430 220 380 260 C 330 290 280 225 230 265 C 180 295 130 230 80 270 C 50 290 30 250 0 275 Z",
    fill: "url(#jamG)",
    filter: "url(#jamBlur)"
  }), [
  // x1, x2 define the horizontal span; depth = how far below the splat band; delay = stagger
  {
    x1: 0,
    x2: 360,
    depth: 540,
    delay: 0.05,
    dur: 2.4
  }, {
    x1: 280,
    x2: 660,
    depth: 460,
    delay: 0.45,
    dur: 2.6
  }, {
    x1: 580,
    x2: 940,
    depth: 580,
    delay: 0.20,
    dur: 2.5
  }, {
    x1: 860,
    x2: 1220,
    depth: 500,
    delay: 0.65,
    dur: 2.4
  }, {
    x1: 1140,
    x2: 1480,
    depth: 560,
    delay: 0.30,
    dur: 2.6
  }, {
    x1: 1400,
    x2: 1600,
    depth: 480,
    delay: 0.55,
    dur: 2.5
  }].map((c, i) => {
    const topY = 175;
    const bottomY = topY + c.depth;
    // wavy bottom edge — 3 peaks/valleys for irregularity
    const span = c.x2 - c.x1;
    const p1 = c.x1 + span * 0.20;
    const p2 = c.x1 + span * 0.45;
    const p3 = c.x1 + span * 0.72;
    const dip = c.depth * 0.18;
    const path = `
                  M ${c.x1} ${topY}
                  L ${c.x2} ${topY}
                  L ${c.x2} ${bottomY - dip * 0.6}
                  C ${c.x2 - 40} ${bottomY + dip * 0.4}, ${p3 + 40} ${bottomY - dip}, ${p3} ${bottomY + dip * 0.6}
                  C ${p3 - 40} ${bottomY + dip * 1.2}, ${p2 + 50} ${bottomY - dip * 0.8}, ${p2} ${bottomY + dip * 0.3}
                  C ${p2 - 50} ${bottomY + dip * 0.9}, ${p1 + 40} ${bottomY - dip * 0.5}, ${p1} ${bottomY + dip * 0.5}
                  C ${p1 - 40} ${bottomY + dip * 1.1}, ${c.x1 + 40} ${bottomY - dip * 0.3}, ${c.x1} ${bottomY - dip * 0.4}
                  Z
                `;
    return /*#__PURE__*/React.createElement("path", {
      key: i,
      className: "jam-curtain",
      d: path,
      fill: "url(#curtainG)",
      filter: "url(#jamBlur)",
      style: {
        animationDelay: `${c.delay}s`,
        animationDuration: `${c.dur}s`
      }
    });
  }))), levelUpInfo && /*#__PURE__*/React.createElement("div", {
    className: "gm-levelup" + (levelUpInfo.mode === 'audio' ? " gm-levelup-audio" : "")
  }, /*#__PURE__*/React.createElement("div", {
    className: "gm-levelup-title"
  }, "\u05E2\u05DC\u05D9\u05EA \u05E9\u05DC\u05D1", /*#__PURE__*/React.createElement("span", {
    className: "dot"
  }, "!")), /*#__PURE__*/React.createElement("div", {
    className: "gm-levelup-sub"
  }, levelUpInfo.sub), levelUpInfo.mode === 'audio' && /*#__PURE__*/React.createElement(React.Fragment, null, /*#__PURE__*/React.createElement("div", {
    className: "gm-levelup-buttons"
  }, /*#__PURE__*/React.createElement("button", {
    className: "gm-levelup-cta",
    onClick: () => {
      setAutoSpeakEnabled(true);
      // If the master sound was muted, unmute so the chosen word audio actually plays.
      if (Sound.muted) {
        Sound.setMuted(false);
        setMuted(false);
      }
      setLevelUpInfo(null);
      nextQuestion();
    }
  }, "\u05E8\u05D5\u05E6\u05D4 \u05DC\u05D4\u05DE\u05E9\u05D9\u05DA \u05E2\u05DD \u05D4\u05E9\u05DE\u05E2\u05EA \u05DE\u05D9\u05DC\u05D9\u05DD"), /*#__PURE__*/React.createElement("button", {
    className: "gm-levelup-cta secondary",
    onClick: () => {
      setAutoSpeakEnabled(false);
      setLevelUpInfo(null);
      nextQuestion();
    }
  }, "\u05E8\u05D5\u05E6\u05D4 \u05DC\u05D4\u05DE\u05E9\u05D9\u05DA \u05DC\u05DC\u05D0 \u05D4\u05E9\u05DE\u05E2\u05EA \u05DE\u05D9\u05DC\u05D9\u05DD")), /*#__PURE__*/React.createElement("div", {
    className: "gm-levelup-note"
  }, /*#__PURE__*/React.createElement("span", {
    className: "star"
  }, "*"), " \u05EA\u05DE\u05D9\u05D3 \u05E0\u05D9\u05EA\u05DF \u05DC\u05D1\u05D8\u05DC \u05D4\u05E9\u05DE\u05E2\u05EA \u05DE\u05D9\u05DC\u05D9\u05DD \u05E2\u05DD \u05DC\u05D7\u05E6\u05DF \u05D4\u05E1\u05D0\u05D5\u05E0\u05D3"))), toast && /*#__PURE__*/React.createElement("div", {
    className: "gm-toast " + toast.kind
  }, /*#__PURE__*/React.createElement("span", {
    className: "dot"
  }), toast.text), /*#__PURE__*/React.createElement("style", null, `
          @keyframes shotFly {
            from { transform: translate(-50%, -50%) translate(0, 0); opacity: 1; }
            to   { transform: translate(-50%, -50%) translate(var(--dx, 0px), var(--dy, 0px)); opacity: 1; }
          }
        `)));
}
window.Game = Game;
})(); } catch (e) { __ds_ns.__errors.push({ path: "quiz-game/Game.standalone.jsx", error: String((e && e.message) || e) }); }

// quiz-game/QuizGame.jsx
try { (() => {
/* global React, XLSX */
const {
  useState,
  useEffect,
  useRef,
  useCallback,
  useLayoutEffect,
  useMemo
} = React;

/* ---------- built-in sample dictionary ---------- */
const SAMPLE_DICT = [{
  en: "ENHANCE",
  he: "להעצים, לשפר",
  ipa: "/ɪnˈhæns/"
}, {
  en: "MITIGATE",
  he: "להקל, למתן",
  ipa: "/ˈmɪtɪˌɡeɪt/"
}, {
  en: "AMBIGUOUS",
  he: "דו-משמעי, עמום",
  ipa: "/æmˈbɪɡjuəs/"
}, {
  en: "ADVOCATE",
  he: "לתמוך, להמליץ",
  ipa: "/ˈædvəˌkeɪt/"
}, {
  en: "SCRUTINIZE",
  he: "לבחון בקפדנות",
  ipa: "/ˈskruːtəˌnaɪz/"
}, {
  en: "INEVITABLE",
  he: "בלתי נמנע",
  ipa: "/ɪˈnɛvɪtəbəl/"
}, {
  en: "DILIGENT",
  he: "חרוץ, שקדן",
  ipa: "/ˈdɪlɪdʒənt/"
}, {
  en: "OBSOLETE",
  he: "מיושן, יצא משימוש",
  ipa: "/ˌabsəˈliːt/"
}, {
  en: "CANDID",
  he: "הֵן, ישיר, ספונטני",
  ipa: "/ˈkændɪd/"
}, {
  en: "TENACIOUS",
  he: "עיקש, דבק במטרה",
  ipa: "/təˈneɪʃəs/"
}];
const STAGGER = [0, 40, 14, 56];
const DICT_STORAGE_KEY = "ez-mcq-dict-v2";
const DICT_NAME_KEY = "ez-mcq-dict-name-v2";
const MUTED_KEY = "ez-mcq-muted-v1";
const LB_KEY = "ez-mcq-leaderboard-v1";

/* ---------- sound engine (WebAudio FX + background music) ---------- */
const Sound = {
  ctx: null,
  muted: false,
  music: null,
  // <audio> element
  musicReady: false,
  init() {
    if (!this.ctx) {
      try {
        this.ctx = new (window.AudioContext || window.webkitAudioContext)();
      } catch (e) {}
    }
    if (this.ctx && this.ctx.state === 'suspended') this.ctx.resume();
    if (!this.music) {
      this.music = document.getElementById('bg-music');
      if (this.music) {
        this.music.volume = 0.35;
        this.music.loop = true;
        this.musicReady = true;
      }
    }
  },
  startMusic() {
    this.init();
    if (this.muted || !this.music) return;
    const p = this.music.play();
    if (p && p.catch) p.catch(() => {/* autoplay blocked — will start on next user gesture */});
  },
  stopMusic() {
    if (this.music) {
      this.music.pause();
    }
  },
  setMusicVolume(v) {
    if (this.music) this.music.volume = Math.max(0, Math.min(1, v));
  },
  setMuted(m) {
    this.muted = !!m;
    if (this.muted) this.stopMusic();else this.startMusic();
    try {
      localStorage.setItem(MUTED_KEY, this.muted ? '1' : '0');
    } catch (e) {}
  },
  beep(freq, duration, type = 'sine', gain = 0.15, delay = 0) {
    if (this.muted || !this.ctx) return;
    const t = this.ctx.currentTime + delay;
    const osc = this.ctx.createOscillator();
    const g = this.ctx.createGain();
    osc.type = type;
    osc.frequency.value = freq;
    g.gain.setValueAtTime(gain, t);
    g.gain.exponentialRampToValueAtTime(0.001, t + duration);
    osc.connect(g);
    g.connect(this.ctx.destination);
    osc.start(t);
    osc.stop(t + duration);
  },
  play(name) {
    if (this.muted) return;
    this.init();
    switch (name) {
      case 'shoot':
        this.beep(540, 0.06, 'square', 0.13);
        this.beep(220, 0.07, 'sawtooth', 0.10, 0.03);
        break;
      case 'hit':
        /* punchier explosion: low thump + bright chord + bell tail */
        this.beep(80, 0.10, 'square', 0.22);
        this.beep(523, 0.10, 'square', 0.16, 0.04);
        this.beep(784, 0.12, 'square', 0.14, 0.10);
        this.beep(1047, 0.22, 'triangle', 0.16, 0.18);
        this.beep(1568, 0.30, 'sine', 0.12, 0.30);
        break;
      case 'miss':
        /* descending "wha-wha" buzzer — clearly distinct from a hit */
        this.beep(440, 0.10, 'square', 0.20);
        this.beep(330, 0.14, 'square', 0.20, 0.10);
        this.beep(220, 0.30, 'sawtooth', 0.22, 0.22);
        this.beep(150, 0.45, 'triangle', 0.20, 0.45);
        break;
      case 'lifegain':
        /* sparkle: ascending major arpeggio */
        this.beep(659, 0.10, 'triangle', 0.18);
        this.beep(880, 0.10, 'triangle', 0.18, 0.10);
        this.beep(1175, 0.10, 'triangle', 0.18, 0.20);
        this.beep(1568, 0.32, 'sine', 0.20, 0.30);
        break;
      case 'fifty':
        /* two-note chime */
        this.beep(880, 0.10, 'sine', 0.15);
        this.beep(1320, 0.18, 'sine', 0.16, 0.10);
        break;
      case 'levelup':
        this.beep(523, 0.10, 'triangle', 0.18);
        this.beep(659, 0.10, 'triangle', 0.18, 0.10);
        this.beep(784, 0.10, 'triangle', 0.18, 0.20);
        this.beep(1047, 0.32, 'sine', 0.20, 0.30);
        break;
      case 'tick':
        this.beep(720, 0.08, 'sine', 0.10);
        break;
      case 'go':
        this.beep(1200, 0.30, 'triangle', 0.22);
        break;
      case 'streak':
        this.beep(880, 0.08, 'sine', 0.13);
        this.beep(1320, 0.10, 'sine', 0.14, 0.08);
        break;
      case 'gameover':
        this.beep(440, 0.20, 'sine', 0.15);
        this.beep(330, 0.24, 'sine', 0.15, 0.20);
        this.beep(220, 0.50, 'sine', 0.18, 0.45);
        break;
    }
  }
};
try {
  Sound.muted = localStorage.getItem(MUTED_KEY) === '1';
} catch (e) {}

/* ---------- leaderboard ---------- */
function getLeaderboard() {
  try {
    return JSON.parse(localStorage.getItem(LB_KEY) || '[]');
  } catch (e) {
    return [];
  }
}
function addToLeaderboard(name, score) {
  const lb = getLeaderboard();
  lb.push({
    name: (name || "אנונימי").slice(0, 20),
    score,
    date: new Date().toISOString()
  });
  lb.sort((a, b) => b.score - a.score);
  try {
    localStorage.setItem(LB_KEY, JSON.stringify(lb.slice(0, 5)));
  } catch (e) {}
  return lb.slice(0, 5);
}
function qualifiesForLeaderboard(score) {
  if (score <= 0) return false;
  const lb = getLeaderboard();
  if (lb.length < 5) return true;
  return score > lb[lb.length - 1].score;
}

/* ---------- dictionary helpers ---------- */
function shuffleArr(a) {
  const x = [...a];
  for (let i = x.length - 1; i > 0; i--) {
    const j = Math.floor(Math.random() * (i + 1));
    [x[i], x[j]] = [x[j], x[i]];
  }
  return x;
}
function buildQuestion(dict, correctIdx) {
  const correct = dict[correctIdx];
  const correctMeaning = normalizeMeaning(correct.he);

  // Build pool excluding correct answer AND entries that share the same meaning.
  // This prevents duplicate Hebrew translations from appearing as distractors
  // (e.g. when the same meaning is split across two English words).
  const pool = dict.map((entry, i) => ({
    entry,
    i,
    key: normalizeMeaning(entry.he)
  })).filter(({
    i,
    key
  }) => i !== correctIdx && key !== correctMeaning);

  // Pick 3 distractors with distinct meanings from each other too.
  const shuffled = shuffleArr(pool);
  const picked = [];
  const seenMeanings = new Set([correctMeaning]);
  for (const {
    entry,
    key
  } of shuffled) {
    if (seenMeanings.has(key)) continue;
    seenMeanings.add(key);
    picked.push(entry);
    if (picked.length === 3) break;
  }

  // Fallback: if the dict is too small / too many duplicates, allow same-key duplicates
  // just so we always have 4 options.
  while (picked.length < 3) {
    const fillers = shuffleArr(pool).filter(p => !picked.includes(p.entry));
    if (fillers.length === 0) break;
    picked.push(fillers[0].entry);
  }
  const options = shuffleArr([correct.he, ...picked.map(d => d.he)]);
  return {
    en: String(correct.en).toUpperCase(),
    ipa: correct.ipa || "",
    correct: correct.he,
    options
  };
}

// Normalize a meaning string so "להאריך / להרחיב" and "להאריך, להרחיב" collide,
// and casing/whitespace differences don't matter.
function normalizeMeaning(s) {
  return String(s || "").toLowerCase().replace(/[\/,،]/g, " ") // treat /, comma, arabic comma as separators
  .replace(/\s+/g, " ").replace(/[״"׳'.…]/g, "").trim();
}
function parseSpreadsheet(file) {
  return new Promise((resolve, reject) => {
    const reader = new FileReader();
    reader.onerror = () => reject(new Error("לא מצליח לקרוא את הקובץ"));
    reader.onload = e => {
      try {
        if (typeof XLSX === "undefined") {
          reject(new Error("תוכנת הפיענוח לא נטענה. רענן דף ונסה שוב."));
          return;
        }
        const data = new Uint8Array(e.target.result);
        const wb = XLSX.read(data, {
          type: "array"
        });
        const sheet = wb.Sheets[wb.SheetNames[0]];
        const rows = XLSX.utils.sheet_to_json(sheet, {
          header: 1,
          blankrows: false
        });
        if (!rows.length) {
          reject(new Error("הקובץ ריק"));
          return;
        }
        const firstB = String(rows[0][1] || "").trim().toLowerCase();
        const looksLikeHeader = /english|word|מילה|אנגלית/.test(firstB) || /פירוש|תרגום|עברית/.test(String(rows[0][2] || ""));
        const start = looksLikeHeader ? 1 : 0;
        const entries = [];
        for (let i = start; i < rows.length; i++) {
          const en = String(rows[i][1] || "").trim(); // column B
          const he = String(rows[i][2] || "").trim(); // column C
          if (en && he) entries.push({
            en,
            he,
            ipa: ""
          });
        }
        if (entries.length < 4) {
          reject(new Error("צריך לפחות 4 מילים בקובץ"));
          return;
        }
        resolve(entries);
      } catch (err) {
        reject(err);
      }
    };
    reader.readAsArrayBuffer(file);
  });
}

/* ──────────────────────────────────────────────
   Polished SVG illustrations
   ────────────────────────────────────────────── */

function RocketSVG({
  isBoss
}) {
  const stroke = "#2A2155";
  const strokeW = 3.5;

  // ── Regular rockets ── use the curated reference artwork embedded as a
  // PNG. Replacing the SVG with the bitmap matches the source illustration
  // pixel-for-pixel; state-based color shifts (hit / missed / correct) come
  // from CSS filters applied to .gm-rocket via `.rocket-img`.
  if (!isBoss) {
    return /*#__PURE__*/React.createElement("svg", {
      className: "frame",
      viewBox: "0 0 620 150",
      preserveAspectRatio: "none",
      "aria-hidden": true
    }, /*#__PURE__*/React.createElement("image", {
      className: "rocket-img",
      href: "rocket-cropped.png",
      xlinkHref: "rocket-cropped.png",
      x: "0",
      y: "0",
      width: "620",
      height: "150",
      preserveAspectRatio: "none"
    }));
  }

  // ── BOSS rocket ── still drawn fully in SVG so the red gradient body,
  // shark-fins and multi-lick flame stay intact (per the user's request).
  return /*#__PURE__*/React.createElement("svg", {
    className: "frame",
    viewBox: "0 0 620 150",
    preserveAspectRatio: "none",
    "aria-hidden": true
  }, /*#__PURE__*/React.createElement("defs", null, /*#__PURE__*/React.createElement("linearGradient", {
    id: "bodyG",
    x1: "0",
    y1: "0",
    x2: "0",
    y2: "1"
  }, /*#__PURE__*/React.createElement("stop", {
    offset: "0",
    stopColor: "#FFFFFF"
  }), /*#__PURE__*/React.createElement("stop", {
    offset: ".6",
    stopColor: "#F5F3F8"
  }), /*#__PURE__*/React.createElement("stop", {
    offset: "1",
    stopColor: "#C9C7CF"
  })), /*#__PURE__*/React.createElement("linearGradient", {
    id: "bodyG-hit",
    x1: "0",
    y1: "0",
    x2: "0",
    y2: "1"
  }, /*#__PURE__*/React.createElement("stop", {
    offset: "0",
    stopColor: "#FFE6CB"
  }), /*#__PURE__*/React.createElement("stop", {
    offset: ".5",
    stopColor: "#F37327"
  }), /*#__PURE__*/React.createElement("stop", {
    offset: "1",
    stopColor: "#A93C08"
  })), /*#__PURE__*/React.createElement("linearGradient", {
    id: "bodyG-miss",
    x1: "0",
    y1: "0",
    x2: "0",
    y2: "1"
  }, /*#__PURE__*/React.createElement("stop", {
    offset: "0",
    stopColor: "#D7D5DC"
  }), /*#__PURE__*/React.createElement("stop", {
    offset: "1",
    stopColor: "#9A98A4"
  })), /*#__PURE__*/React.createElement("linearGradient", {
    id: "bodyG-correct",
    x1: "0",
    y1: "0",
    x2: "0",
    y2: "1"
  }, /*#__PURE__*/React.createElement("stop", {
    offset: "0",
    stopColor: "#BDF0D3"
  }), /*#__PURE__*/React.createElement("stop", {
    offset: "1",
    stopColor: "#3FA76C"
  })), /*#__PURE__*/React.createElement("linearGradient", {
    id: "bodyG-boss",
    x1: "0",
    y1: "0",
    x2: "0",
    y2: "1"
  }, /*#__PURE__*/React.createElement("stop", {
    offset: "0",
    stopColor: "#FCA5A5"
  }), /*#__PURE__*/React.createElement("stop", {
    offset: ".5",
    stopColor: "#DC2626"
  }), /*#__PURE__*/React.createElement("stop", {
    offset: "1",
    stopColor: "#7F1D1D"
  })), /*#__PURE__*/React.createElement("linearGradient", {
    id: "tipG-boss",
    x1: "0",
    y1: "0",
    x2: "0",
    y2: "1"
  }, /*#__PURE__*/React.createElement("stop", {
    offset: "0",
    stopColor: "#FCD34D"
  }), /*#__PURE__*/React.createElement("stop", {
    offset: ".55",
    stopColor: "#DC2626"
  }), /*#__PURE__*/React.createElement("stop", {
    offset: "1",
    stopColor: "#7F1D1D"
  })), /*#__PURE__*/React.createElement("linearGradient", {
    id: "tipG",
    x1: "0",
    y1: "0",
    x2: "0",
    y2: "1"
  }, /*#__PURE__*/React.createElement("stop", {
    offset: "0",
    stopColor: "#FFB36B"
  }), /*#__PURE__*/React.createElement("stop", {
    offset: ".55",
    stopColor: "#F37327"
  }), /*#__PURE__*/React.createElement("stop", {
    offset: "1",
    stopColor: "#B94A0C"
  })), /*#__PURE__*/React.createElement("linearGradient", {
    id: "finG",
    x1: "0",
    y1: "0",
    x2: "0",
    y2: "1"
  }, /*#__PURE__*/React.createElement("stop", {
    offset: "0",
    stopColor: "#FFB36B"
  }), /*#__PURE__*/React.createElement("stop", {
    offset: ".5",
    stopColor: "#F37327"
  }), /*#__PURE__*/React.createElement("stop", {
    offset: "1",
    stopColor: "#A0410B"
  })), /*#__PURE__*/React.createElement("radialGradient", {
    id: "flameG",
    cx: "50%",
    cy: "50%",
    r: "55%"
  }, /*#__PURE__*/React.createElement("stop", {
    offset: "0",
    stopColor: "#FFF7CE"
  }), /*#__PURE__*/React.createElement("stop", {
    offset: ".4",
    stopColor: "#FFD23F"
  }), /*#__PURE__*/React.createElement("stop", {
    offset: ".85",
    stopColor: "#F37327"
  }), /*#__PURE__*/React.createElement("stop", {
    offset: "1",
    stopColor: "#B94A0C"
  }))), /*#__PURE__*/React.createElement("g", null, /*#__PURE__*/React.createElement("path", {
    d: "M 525,40 Q 555,52 580,32 Q 568,55 595,55 Q 575,68 610,72 Q 575,80 615,90 Q 575,92 600,108 Q 570,100 588,118 Q 555,100 580,118 Q 555,98 525,110 Z",
    fill: "url(#flameG)",
    stroke: stroke,
    strokeWidth: strokeW,
    strokeLinejoin: "round"
  }), /*#__PURE__*/React.createElement("path", {
    d: "M 530,55 Q 555,55 570,42 Q 568,62 585,68 Q 565,75 582,82 Q 565,88 580,100 Q 558,92 568,110 Q 545,95 530,100 Z",
    fill: "#FFF7CE",
    opacity: ".95"
  })), /*#__PURE__*/React.createElement("path", {
    d: "M 470,42 Q 488,18 540,2 Q 540,30 520,46 Q 500,52 470,42 Z",
    fill: "url(#finG)",
    stroke: stroke,
    strokeWidth: strokeW,
    strokeLinejoin: "round"
  }), /*#__PURE__*/React.createElement("path", {
    d: "M 495,28 Q 515,18 532,12",
    stroke: "#fff",
    strokeOpacity: ".6",
    strokeWidth: "3",
    fill: "none",
    strokeLinecap: "round"
  }), /*#__PURE__*/React.createElement("path", {
    d: "M 470,108 Q 488,132 540,148 Q 540,120 520,104 Q 500,98 470,108 Z",
    fill: "url(#finG)",
    stroke: stroke,
    strokeWidth: strokeW,
    strokeLinejoin: "round"
  }), /*#__PURE__*/React.createElement("path", {
    d: "M 495,122 Q 515,132 532,138",
    stroke: "#fff",
    strokeOpacity: ".45",
    strokeWidth: "3",
    fill: "none",
    strokeLinecap: "round"
  }), /*#__PURE__*/React.createElement("path", {
    className: "body-fill",
    d: "M 40,75 Q 70,16 165,16 L 530,16 Q 560,16 560,38 L 560,112 Q 560,134 530,134 L 165,134 Q 70,134 40,75 Z",
    fill: "url(#bodyG)",
    stroke: stroke,
    strokeWidth: strokeW,
    strokeLinejoin: "round"
  }), /*#__PURE__*/React.createElement("path", {
    className: "tip-fill",
    d: "M 40,75 Q 70,16 165,16 L 175,16 Q 110,30 90,75 Q 110,120 175,134 L 165,134 Q 70,134 40,75 Z",
    fill: "url(#tipG)",
    stroke: stroke,
    strokeWidth: strokeW,
    strokeLinejoin: "round"
  }), /*#__PURE__*/React.createElement("path", {
    d: "M 70,52 Q 90,38 120,42",
    stroke: "#fff",
    strokeOpacity: ".7",
    strokeWidth: "4",
    fill: "none",
    strokeLinecap: "round"
  }), /*#__PURE__*/React.createElement("path", {
    d: "M 195,30 Q 360,24 510,32",
    stroke: "#fff",
    strokeOpacity: ".95",
    strokeWidth: "5",
    fill: "none",
    strokeLinecap: "round"
  }), /*#__PURE__*/React.createElement("path", {
    d: "M 170,124 Q 360,140 520,126",
    stroke: "#1A1530",
    strokeOpacity: ".09",
    strokeWidth: "6",
    fill: "none",
    strokeLinecap: "round"
  }), /*#__PURE__*/React.createElement("circle", {
    cx: "125",
    cy: "48",
    r: "2.5",
    fill: "#fff"
  }));
}
function BurstSVG() {
  return /*#__PURE__*/React.createElement("svg", {
    viewBox: "0 0 140 140",
    "aria-hidden": true
  }, /*#__PURE__*/React.createElement("defs", null, /*#__PURE__*/React.createElement("radialGradient", {
    id: "boom",
    cx: "50%",
    cy: "50%",
    r: "50%"
  }, /*#__PURE__*/React.createElement("stop", {
    offset: "0%",
    stopColor: "#FFF7E6"
  }), /*#__PURE__*/React.createElement("stop", {
    offset: "35%",
    stopColor: "#FFB061"
  }), /*#__PURE__*/React.createElement("stop", {
    offset: "70%",
    stopColor: "#F37327"
  }), /*#__PURE__*/React.createElement("stop", {
    offset: "100%",
    stopColor: "rgba(213,90,18,0)"
  }))), /*#__PURE__*/React.createElement("circle", {
    cx: "70",
    cy: "70",
    r: "48",
    fill: "url(#boom)"
  }), /*#__PURE__*/React.createElement("g", {
    stroke: "#FFB061",
    strokeWidth: "3",
    strokeLinecap: "round",
    fill: "none"
  }, /*#__PURE__*/React.createElement("line", {
    x1: "70",
    y1: "14",
    x2: "70",
    y2: "32"
  }), /*#__PURE__*/React.createElement("line", {
    x1: "70",
    y1: "108",
    x2: "70",
    y2: "126"
  }), /*#__PURE__*/React.createElement("line", {
    x1: "14",
    y1: "70",
    x2: "32",
    y2: "70"
  }), /*#__PURE__*/React.createElement("line", {
    x1: "108",
    y1: "70",
    x2: "126",
    y2: "70"
  }), /*#__PURE__*/React.createElement("line", {
    x1: "28",
    y1: "28",
    x2: "42",
    y2: "42"
  }), /*#__PURE__*/React.createElement("line", {
    x1: "98",
    y1: "98",
    x2: "112",
    y2: "112"
  }), /*#__PURE__*/React.createElement("line", {
    x1: "28",
    y1: "112",
    x2: "42",
    y2: "98"
  }), /*#__PURE__*/React.createElement("line", {
    x1: "98",
    y1: "42",
    x2: "112",
    y2: "28"
  })), /*#__PURE__*/React.createElement("circle", {
    cx: "70",
    cy: "70",
    r: "18",
    fill: "#FFF7E6"
  }));
}
function CannonBase() {
  return /*#__PURE__*/React.createElement("svg", {
    className: "base",
    viewBox: "0 0 280 240",
    "aria-hidden": true
  }, /*#__PURE__*/React.createElement("defs", null, /*#__PURE__*/React.createElement("linearGradient", {
    id: "domeG",
    x1: "0",
    y1: "0",
    x2: "0",
    y2: "1"
  }, /*#__PURE__*/React.createElement("stop", {
    offset: "0",
    stopColor: "#FFA362"
  }), /*#__PURE__*/React.createElement("stop", {
    offset: "0.5",
    stopColor: "#F37327"
  }), /*#__PURE__*/React.createElement("stop", {
    offset: "1",
    stopColor: "#A93C08"
  })), /*#__PURE__*/React.createElement("linearGradient", {
    id: "tracksG",
    x1: "0",
    y1: "0",
    x2: "0",
    y2: "1"
  }, /*#__PURE__*/React.createElement("stop", {
    offset: "0",
    stopColor: "#2A2547"
  }), /*#__PURE__*/React.createElement("stop", {
    offset: "1",
    stopColor: "#0A0820"
  })), /*#__PURE__*/React.createElement("linearGradient", {
    id: "metalG",
    x1: "0",
    y1: "0",
    x2: "0",
    y2: "1"
  }, /*#__PURE__*/React.createElement("stop", {
    offset: "0",
    stopColor: "#3a3358"
  }), /*#__PURE__*/React.createElement("stop", {
    offset: "1",
    stopColor: "#15102B"
  }))), /*#__PURE__*/React.createElement("ellipse", {
    cx: "140",
    cy: "226",
    rx: "120",
    ry: "10",
    fill: "rgba(0,0,0,.45)"
  }), /*#__PURE__*/React.createElement("path", {
    d: "M 20,168 L 260,168 L 250,216 L 30,216 Z",
    fill: "url(#tracksG)",
    stroke: "#000",
    strokeWidth: "1"
  }), Array.from({
    length: 12
  }).map((_, i) => /*#__PURE__*/React.createElement("rect", {
    key: i,
    x: 32 + i * 18,
    y: "174",
    width: "12",
    height: "36",
    rx: "2",
    fill: "#3a3358"
  })), [58, 98, 138, 178, 218].map((cx, i) => /*#__PURE__*/React.createElement("g", {
    key: i
  }, /*#__PURE__*/React.createElement("circle", {
    cx: cx,
    cy: "200",
    r: "13",
    fill: "#0A0820"
  }), /*#__PURE__*/React.createElement("circle", {
    cx: cx,
    cy: "200",
    r: "10",
    fill: "#3a3358",
    stroke: "#5a5470",
    strokeWidth: "2"
  }), /*#__PURE__*/React.createElement("circle", {
    cx: cx,
    cy: "200",
    r: "3",
    fill: "#5a5470"
  }))), /*#__PURE__*/React.createElement("path", {
    d: "M 30,140 L 250,140 L 260,168 L 20,168 Z",
    fill: "#1A1530"
  }), /*#__PURE__*/React.createElement("rect", {
    x: "36",
    y: "146",
    width: "208",
    height: "3",
    fill: "rgba(255,255,255,.1)",
    rx: "1"
  }), [60, 100, 140, 180, 220].map((cx, i) => /*#__PURE__*/React.createElement("circle", {
    key: i,
    cx: cx,
    cy: "156",
    r: "3",
    fill: "#5a5470"
  })), /*#__PURE__*/React.createElement("path", {
    d: "M 70,140 Q 140,40 210,140 Z",
    fill: "url(#domeG)"
  }), /*#__PURE__*/React.createElement("path", {
    d: "M 85,128 Q 110,76 138,68",
    stroke: "rgba(255,255,255,.45)",
    strokeWidth: "4",
    fill: "none",
    strokeLinecap: "round"
  }), /*#__PURE__*/React.createElement("ellipse", {
    cx: "140",
    cy: "138",
    rx: "74",
    ry: "10",
    fill: "#0A0820"
  }), /*#__PURE__*/React.createElement("ellipse", {
    cx: "140",
    cy: "135",
    rx: "74",
    ry: "10",
    fill: "#1A1530"
  }), /*#__PURE__*/React.createElement("ellipse", {
    cx: "140",
    cy: "134",
    rx: "68",
    ry: "6",
    fill: "#3a3358"
  }), /*#__PURE__*/React.createElement("path", {
    d: "M 75,138 Q 140,52 205,138",
    stroke: "rgba(0,0,0,.18)",
    strokeWidth: "1",
    fill: "none"
  }), /*#__PURE__*/React.createElement("g", {
    transform: "translate(170 96)"
  }, /*#__PURE__*/React.createElement("rect", {
    x: "-20",
    y: "-20",
    width: "40",
    height: "40",
    rx: "7",
    fill: "#fff"
  }), /*#__PURE__*/React.createElement("image", {
    href: "ez-icon.png",
    x: "-17",
    y: "-17",
    width: "34",
    height: "34"
  })), /*#__PURE__*/React.createElement("line", {
    x1: "100",
    y1: "80",
    x2: "92",
    y2: "36",
    stroke: "#1A1530",
    strokeWidth: "2"
  }), /*#__PURE__*/React.createElement("circle", {
    cx: "92",
    cy: "34",
    r: "3",
    fill: "#F33F3F"
  }), /*#__PURE__*/React.createElement("circle", {
    cx: "62",
    cy: "156",
    r: "6",
    fill: "#FFE6A8"
  }), /*#__PURE__*/React.createElement("circle", {
    cx: "62",
    cy: "156",
    r: "3",
    fill: "#FFF"
  }));
}
function CannonBarrel() {
  return /*#__PURE__*/React.createElement("svg", {
    viewBox: "0 0 220 60",
    "aria-hidden": true
  }, /*#__PURE__*/React.createElement("defs", null, /*#__PURE__*/React.createElement("linearGradient", {
    id: "barG",
    x1: "0",
    y1: "0",
    x2: "0",
    y2: "1"
  }, /*#__PURE__*/React.createElement("stop", {
    offset: "0",
    stopColor: "#3a3358"
  }), /*#__PURE__*/React.createElement("stop", {
    offset: "0.5",
    stopColor: "#1A1530"
  }), /*#__PURE__*/React.createElement("stop", {
    offset: "1",
    stopColor: "#0A0820"
  })), /*#__PURE__*/React.createElement("linearGradient", {
    id: "muzzleG",
    x1: "0",
    y1: "0",
    x2: "0",
    y2: "1"
  }, /*#__PURE__*/React.createElement("stop", {
    offset: "0",
    stopColor: "#5a5470"
  }), /*#__PURE__*/React.createElement("stop", {
    offset: "1",
    stopColor: "#2A2547"
  }))), /*#__PURE__*/React.createElement("rect", {
    x: "14",
    y: "22",
    width: "36",
    height: "20",
    rx: "4",
    fill: "#1A1530"
  }), /*#__PURE__*/React.createElement("rect", {
    x: "14",
    y: "22",
    width: "36",
    height: "3",
    fill: "rgba(255,255,255,.18)"
  }), /*#__PURE__*/React.createElement("rect", {
    x: "40",
    y: "26",
    width: "150",
    height: "12",
    rx: "4",
    fill: "url(#barG)"
  }), /*#__PURE__*/React.createElement("rect", {
    x: "42",
    y: "27",
    width: "146",
    height: "2",
    rx: "1",
    fill: "rgba(255,255,255,.25)"
  }), /*#__PURE__*/React.createElement("rect", {
    x: "184",
    y: "22",
    width: "22",
    height: "20",
    rx: "3",
    fill: "url(#muzzleG)"
  }), /*#__PURE__*/React.createElement("rect", {
    x: "188",
    y: "26",
    width: "2",
    height: "12",
    fill: "#0A0820"
  }), /*#__PURE__*/React.createElement("rect", {
    x: "194",
    y: "26",
    width: "2",
    height: "12",
    fill: "#0A0820"
  }), /*#__PURE__*/React.createElement("rect", {
    x: "200",
    y: "26",
    width: "2",
    height: "12",
    fill: "#0A0820"
  }), /*#__PURE__*/React.createElement("rect", {
    x: "22",
    y: "14",
    width: "6",
    height: "10",
    fill: "#1A1530"
  }), /*#__PURE__*/React.createElement("circle", {
    cx: "25",
    cy: "13",
    r: "3",
    fill: "#F33F3F"
  }));
}
function Mountains() {
  return /*#__PURE__*/React.createElement("div", {
    className: "gm-horizon"
  }, /*#__PURE__*/React.createElement("svg", {
    viewBox: "0 0 1600 240",
    preserveAspectRatio: "none",
    "aria-hidden": true
  }, /*#__PURE__*/React.createElement("path", {
    d: "M0,150 L120,90 L240,130 L380,70 L520,118 L660,82 L800,124 L940,86 L1080,128 L1220,94 L1360,126 L1500,90 L1600,118 L1600,240 L0,240 Z",
    fill: "#B6B1E0"
  }), /*#__PURE__*/React.createElement("path", {
    d: "M0,200 L160,140 L300,180 L440,118 L580,158 L720,128 L860,168 L1000,134 L1140,170 L1280,140 L1420,176 L1560,148 L1600,164 L1600,240 L0,240 Z",
    fill: "#8E89C8"
  })));
}
function SkyZ() {
  return /*#__PURE__*/React.createElement("div", {
    className: "gm-sky-z",
    "aria-hidden": true
  }, /*#__PURE__*/React.createElement("div", {
    className: "z",
    style: {
      top: "6%",
      left: "8%",
      width: "26%",
      background: "rgba(255,255,255,.65)"
    }
  }), /*#__PURE__*/React.createElement("div", {
    className: "z",
    style: {
      top: "10%",
      left: "46%",
      width: "20%",
      background: "rgba(255,255,255,.5)"
    }
  }), /*#__PURE__*/React.createElement("div", {
    className: "z",
    style: {
      top: "18%",
      left: "22%",
      width: "14%",
      background: "rgba(255,255,255,.35)"
    }
  }), /*#__PURE__*/React.createElement("div", {
    className: "z",
    style: {
      top: "26%",
      left: "62%",
      width: "22%",
      background: "rgba(255,255,255,.4)"
    }
  }));
}
function Heart({
  lost
}) {
  return /*#__PURE__*/React.createElement("svg", {
    viewBox: "0 0 24 24",
    className: lost ? "lost" : ""
  }, /*#__PURE__*/React.createElement("path", {
    fill: "#F33F3F",
    d: "M12 21s-7.5-4.7-9.6-9.5C.9 7.7 3.5 4 7.2 4c2 0 3.6 1 4.8 2.6C13.2 5 14.8 4 16.8 4c3.7 0 6.3 3.7 4.8 7.5C19.5 16.3 12 21 12 21z"
  }));
}
const I = {
  pause: () => /*#__PURE__*/React.createElement("svg", {
    viewBox: "0 0 24 24",
    width: "16",
    height: "16",
    fill: "currentColor"
  }, /*#__PURE__*/React.createElement("path", {
    d: "M9 5h2v14H9zM13 5h2v14h-2z"
  })),
  speaker: () => /*#__PURE__*/React.createElement("svg", {
    viewBox: "0 0 24 24",
    width: "18",
    height: "18",
    fill: "currentColor"
  }, /*#__PURE__*/React.createElement("path", {
    d: "M3 10v4a1 1 0 0 0 1 1h3l4 3.5a1 1 0 0 0 1.6-.8V6.3a1 1 0 0 0-1.6-.8L7 9H4a1 1 0 0 0-1 1Z"
  })),
  speakerMute: () => /*#__PURE__*/React.createElement("svg", {
    viewBox: "0 0 24 24",
    width: "18",
    height: "18",
    fill: "none",
    stroke: "currentColor",
    strokeWidth: "2.2",
    strokeLinecap: "round",
    strokeLinejoin: "round"
  }, /*#__PURE__*/React.createElement("path", {
    d: "M3 10v4a1 1 0 0 0 1 1h3l4 3.5a1 1 0 0 0 1.6-.8V6.3a1 1 0 0 0-1.6-.8L7 9H4a1 1 0 0 0-1 1Z",
    fill: "currentColor",
    stroke: "none"
  }), /*#__PURE__*/React.createElement("path", {
    d: "M16 8l5 5M21 8l-5 5"
  })),
  expand: () => /*#__PURE__*/React.createElement("svg", {
    viewBox: "0 0 24 24",
    width: "18",
    height: "18",
    fill: "none",
    stroke: "currentColor",
    strokeWidth: "2.2",
    strokeLinecap: "round",
    strokeLinejoin: "round"
  }, /*#__PURE__*/React.createElement("path", {
    d: "M4 9V4h5M20 9V4h-5M4 15v5h5M20 15v5h-5"
  })),
  home: () => /*#__PURE__*/React.createElement("svg", {
    viewBox: "0 0 24 24",
    width: "20",
    height: "20",
    fill: "none",
    stroke: "currentColor",
    strokeWidth: "2.2",
    strokeLinecap: "round",
    strokeLinejoin: "round"
  }, /*#__PURE__*/React.createElement("path", {
    d: "M3 11l9-8 9 8"
  }), /*#__PURE__*/React.createElement("path", {
    d: "M5 10v10h14V10"
  }), /*#__PURE__*/React.createElement("path", {
    d: "M10 20v-6h4v6"
  })),
  trophy: () => /*#__PURE__*/React.createElement("svg", {
    viewBox: "0 0 24 24",
    width: "22",
    height: "22",
    fill: "none",
    stroke: "currentColor",
    strokeWidth: "2.2",
    strokeLinecap: "round",
    strokeLinejoin: "round"
  }, /*#__PURE__*/React.createElement("path", {
    d: "M8 21h8M12 17v4M7 4h10v5a5 5 0 0 1-10 0V4z"
  }), /*#__PURE__*/React.createElement("path", {
    d: "M7 6H4v2a3 3 0 0 0 3 3M17 6h3v2a3 3 0 0 1-3 3"
  }))
};
function ScopeIcon() {
  return /*#__PURE__*/React.createElement("svg", {
    viewBox: "0 0 32 32",
    fill: "none",
    stroke: "#F37327",
    strokeWidth: "2.2"
  }, /*#__PURE__*/React.createElement("circle", {
    cx: "16",
    cy: "16",
    r: "11"
  }), /*#__PURE__*/React.createElement("path", {
    d: "M16 2v6 M16 24v6 M2 16h6 M24 16h6",
    strokeLinecap: "round"
  }), /*#__PURE__*/React.createElement("circle", {
    cx: "16",
    cy: "16",
    r: "2",
    fill: "#F37327",
    stroke: "none"
  }));
}

/* ──────────────────────────────────────────────
   Stage scaler: fits 1600×900 into viewport, letterboxing.
   ────────────────────────────────────────────── */
function useStageScale(designW, designH) {
  const [scale, setScale] = useState(1);
  useLayoutEffect(() => {
    const recalc = () => {
      const w = window.innerWidth;
      const h = window.innerHeight;
      setScale(Math.min(w / designW, h / designH));
    };
    recalc();
    window.addEventListener("resize", recalc);
    return () => window.removeEventListener("resize", recalc);
  }, [designW, designH]);
  return scale;
}

/* ──────────────────────────────────────────────
   Upload screen — load Excel/CSV
   ────────────────────────────────────────────── */
function UploadScreen({
  onLoad
}) {
  const [drag, setDrag] = useState(false);
  const [err, setErr] = useState(null);
  const [busy, setBusy] = useState(false);
  const inputRef = useRef(null);
  const handle = useCallback(async file => {
    if (!file) return;
    setErr(null);
    setBusy(true);
    try {
      const entries = await parseSpreadsheet(file);
      onLoad(entries, file.name);
    } catch (e) {
      setErr(e.message || "שגיאה בקריאת הקובץ");
    } finally {
      setBusy(false);
    }
  }, [onLoad]);
  const onDrop = e => {
    e.preventDefault();
    setDrag(false);
    const f = e.dataTransfer?.files?.[0];
    if (f) handle(f);
  };
  return /*#__PURE__*/React.createElement("div", {
    className: "gm-app gm-up-app"
  }, /*#__PURE__*/React.createElement("div", {
    className: "gm-up-wrap"
  }, /*#__PURE__*/React.createElement("div", {
    className: "gm-up-card"
  }, /*#__PURE__*/React.createElement("div", {
    className: "gm-up-eye"
  }, /*#__PURE__*/React.createElement("span", {
    className: "brand-eazy"
  }, "eazy"), " \xB7 \u05DE\u05E9\u05D7\u05E7 \u05DE\u05D9\u05DC\u05D9\u05DD"), /*#__PURE__*/React.createElement("h1", {
    className: "gm-up-h1"
  }, "\u05D8\u05E2\u05E0\u05D5 \u05DE\u05D9\u05DC\u05D5\u05DF \u05DC\u05DE\u05E9\u05D7\u05E7."), /*#__PURE__*/React.createElement("p", {
    className: "gm-up-sub"
  }, "\u05E7\u05D5\u05D1\u05E5 Excel \u05D0\u05D5 CSV. \u05E2\u05DE\u05D5\u05D3\u05D4 B = \u05DE\u05D9\u05DC\u05D4 \u05D1\u05D0\u05E0\u05D2\u05DC\u05D9\u05EA, \u05E2\u05DE\u05D5\u05D3\u05D4 C = \u05E4\u05D9\u05E8\u05D5\u05E9 \u05D1\u05E2\u05D1\u05E8\u05D9\u05EA. \u05E0\u05D1\u05D7\u05E8 \u05D1\u05DB\u05DC \u05E1\u05D9\u05D1\u05D5\u05D1 4 \u05DE\u05D9\u05DC\u05D9\u05DD: \u05D0\u05D7\u05EA \u05D4\u05E0\u05DB\u05D5\u05E0\u05D4, \u05E9\u05DC\u05D5\u05E9 \u05D0\u05D7\u05E8\u05D5\u05EA \u05DE\u05D4\u05DE\u05D9\u05DC\u05D5\u05DF \u05DB\u05DE\u05E1\u05D9\u05D7\u05D9\u05DD."), /*#__PURE__*/React.createElement("div", {
    className: "gm-dropzone " + (drag ? "drag" : ""),
    onClick: () => inputRef.current?.click(),
    onDragOver: e => {
      e.preventDefault();
      setDrag(true);
    },
    onDragLeave: () => setDrag(false),
    onDrop: onDrop
  }, /*#__PURE__*/React.createElement("div", {
    className: "gm-dz-icon"
  }, /*#__PURE__*/React.createElement("svg", {
    viewBox: "0 0 32 32",
    width: "42",
    height: "42",
    fill: "none",
    stroke: "#F37327",
    strokeWidth: "2",
    strokeLinecap: "round",
    strokeLinejoin: "round"
  }, /*#__PURE__*/React.createElement("path", {
    d: "M16 4v18"
  }), /*#__PURE__*/React.createElement("path", {
    d: "M9 11l7-7 7 7"
  }), /*#__PURE__*/React.createElement("path", {
    d: "M4 26h24"
  }))), /*#__PURE__*/React.createElement("div", {
    className: "gm-dz-title"
  }, "\u05D2\u05E8\u05E8\u05D5 \u05DC\u05DB\u05D0\u05DF \u05D0\u05D5 \u05DC\u05D7\u05E6\u05D5"), /*#__PURE__*/React.createElement("div", {
    className: "gm-dz-sub"
  }, ".xlsx / .xls / .csv"), /*#__PURE__*/React.createElement("input", {
    ref: inputRef,
    type: "file",
    accept: ".xlsx,.xls,.csv,application/vnd.ms-excel,application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",
    style: {
      display: "none"
    },
    onChange: e => handle(e.target.files[0])
  })), busy && /*#__PURE__*/React.createElement("div", {
    className: "gm-up-info"
  }, "\u05E7\u05D5\u05E8\u05D0\u05D9 \u05D0\u05EA \u05D4\u05E7\u05D5\u05D1\u05E5\u2026"), err && /*#__PURE__*/React.createElement("div", {
    className: "gm-up-err"
  }, err), /*#__PURE__*/React.createElement("div", {
    className: "gm-up-or"
  }, "\u2014 \u05D0\u05D5 \u2014"), /*#__PURE__*/React.createElement("button", {
    className: "gm-up-btn-ghost",
    onClick: () => onLoad(SAMPLE_DICT, "מילון לדוגמה")
  }, "\u05D4\u05EA\u05D7\u05D9\u05DC\u05D5 \u05E2\u05DD \u05DE\u05D9\u05DC\u05D5\u05DF \u05D3\u05D5\u05D2\u05DE\u05D4 (", SAMPLE_DICT.length, " \u05DE\u05D9\u05DC\u05D9\u05DD)"), /*#__PURE__*/React.createElement("div", {
    className: "gm-up-format"
  }, /*#__PURE__*/React.createElement("div", {
    className: "gm-fmt-title"
  }, "\u05E4\u05D5\u05E8\u05DE\u05D8 \u05D4\u05E7\u05D5\u05D1\u05E5:"), /*#__PURE__*/React.createElement("table", null, /*#__PURE__*/React.createElement("thead", null, /*#__PURE__*/React.createElement("tr", null, /*#__PURE__*/React.createElement("th", null, "A"), /*#__PURE__*/React.createElement("th", null, "B \u2014 English"), /*#__PURE__*/React.createElement("th", null, "C \u2014 \u05E2\u05D1\u05E8\u05D9\u05EA"))), /*#__PURE__*/React.createElement("tbody", null, /*#__PURE__*/React.createElement("tr", null, /*#__PURE__*/React.createElement("td", null, "1"), /*#__PURE__*/React.createElement("td", {
    dir: "ltr"
  }, "enhance"), /*#__PURE__*/React.createElement("td", null, "\u05DC\u05D4\u05E2\u05E6\u05D9\u05DD, \u05DC\u05E9\u05E4\u05E8")), /*#__PURE__*/React.createElement("tr", null, /*#__PURE__*/React.createElement("td", null, "2"), /*#__PURE__*/React.createElement("td", {
    dir: "ltr"
  }, "mitigate"), /*#__PURE__*/React.createElement("td", null, "\u05DC\u05D4\u05E7\u05DC, \u05DC\u05DE\u05EA\u05DF")), /*#__PURE__*/React.createElement("tr", null, /*#__PURE__*/React.createElement("td", null, "3"), /*#__PURE__*/React.createElement("td", {
    dir: "ltr"
  }, "ambiguous"), /*#__PURE__*/React.createElement("td", null, "\u05D3\u05D5-\u05DE\u05E9\u05DE\u05E2\u05D9")))), /*#__PURE__*/React.createElement("div", {
    className: "gm-fmt-note"
  }, "\u05E9\u05D5\u05E8\u05EA \u05DB\u05D5\u05EA\u05E8\u05EA \u05EA\u05D6\u05D5\u05D4\u05D4 \u05D0\u05D5\u05D8\u05D5\u05DE\u05D8\u05D9\u05EA. \u05E2\u05DE\u05D5\u05D3\u05D4 A \u05DE\u05EA\u05E2\u05DC\u05DE\u05D9\u05DD \u05DE\u05DE\u05E0\u05D4 (\u05DE\u05E1\u05E4\u05D5\u05E8 / \u05DE\u05D6\u05D4\u05D4).")))));
}

/* ──────────────────────────────────────────────
   Intro screen — first thing the user sees
   ───────────────────────────────────────────── */
function IntroScreen({
  onStart,
  toggleFullscreen,
  muted,
  toggleMute
}) {
  const scale = useStageScale(1600, 900);
  // Combined handler: enter fullscreen on the user's tap (must come from a
  // gesture) and then start the round. Failures are non-fatal — we still
  // start the game even if the browser blocks fullscreen.
  const startAndFullscreen = () => {
    try {
      const el = document.documentElement;
      const req = el.requestFullscreen || el.webkitRequestFullscreen || el.msRequestFullscreen;
      if (req && !document.fullscreenElement && !document.webkitFullscreenElement) {
        const p = req.call(el);
        if (p && typeof p.catch === 'function') p.catch(() => {});
      }
    } catch (e) {}
    onStart();
  };
  return /*#__PURE__*/React.createElement("div", {
    className: "gm-app"
  }, /*#__PURE__*/React.createElement("div", {
    className: "gm-stage gm-intro-stage",
    style: {
      "--gm-scale": scale
    }
  }, /*#__PURE__*/React.createElement(SkyZ, null), /*#__PURE__*/React.createElement(Mountains, null), /*#__PURE__*/React.createElement("div", {
    className: "gm-ground"
  }), /*#__PURE__*/React.createElement("div", {
    className: "gm-hud-brand"
  }, /*#__PURE__*/React.createElement("img", {
    src: "../assets/ez-icon.png",
    alt: ""
  }), /*#__PURE__*/React.createElement("span", {
    className: "brand-eazy"
  }, "eazy")), /*#__PURE__*/React.createElement("div", {
    className: "gm-cannon gm-intro-cannon"
  }, /*#__PURE__*/React.createElement(CannonBase, null), /*#__PURE__*/React.createElement("div", {
    className: "barrel-wrap"
  }, /*#__PURE__*/React.createElement("svg", {
    style: {
      position: "absolute",
      width: "220px",
      height: "60px",
      top: "-30px",
      left: "-30px",
      transformOrigin: "30px 30px",
      transform: `rotate(-22deg)`,
      overflow: "visible"
    },
    viewBox: "0 0 220 60"
  }, /*#__PURE__*/React.createElement("defs", null, /*#__PURE__*/React.createElement("linearGradient", {
    id: "barG3",
    x1: "0",
    y1: "0",
    x2: "0",
    y2: "1"
  }, /*#__PURE__*/React.createElement("stop", {
    offset: "0",
    stopColor: "#3a3358"
  }), /*#__PURE__*/React.createElement("stop", {
    offset: "0.5",
    stopColor: "#1A1530"
  }), /*#__PURE__*/React.createElement("stop", {
    offset: "1",
    stopColor: "#0A0820"
  })), /*#__PURE__*/React.createElement("linearGradient", {
    id: "muzzleG3",
    x1: "0",
    y1: "0",
    x2: "0",
    y2: "1"
  }, /*#__PURE__*/React.createElement("stop", {
    offset: "0",
    stopColor: "#5a5470"
  }), /*#__PURE__*/React.createElement("stop", {
    offset: "1",
    stopColor: "#2A2547"
  }))), /*#__PURE__*/React.createElement("rect", {
    x: "14",
    y: "22",
    width: "36",
    height: "20",
    rx: "4",
    fill: "#1A1530"
  }), /*#__PURE__*/React.createElement("rect", {
    x: "14",
    y: "22",
    width: "36",
    height: "3",
    fill: "rgba(255,255,255,.18)"
  }), /*#__PURE__*/React.createElement("rect", {
    x: "40",
    y: "26",
    width: "150",
    height: "12",
    rx: "4",
    fill: "url(#barG3)"
  }), /*#__PURE__*/React.createElement("rect", {
    x: "42",
    y: "27",
    width: "146",
    height: "2",
    rx: "1",
    fill: "rgba(255,255,255,.25)"
  }), /*#__PURE__*/React.createElement("rect", {
    x: "184",
    y: "22",
    width: "22",
    height: "20",
    rx: "3",
    fill: "url(#muzzleG3)"
  }), /*#__PURE__*/React.createElement("rect", {
    x: "188",
    y: "26",
    width: "2",
    height: "12",
    fill: "#0A0820"
  }), /*#__PURE__*/React.createElement("rect", {
    x: "194",
    y: "26",
    width: "2",
    height: "12",
    fill: "#0A0820"
  }), /*#__PURE__*/React.createElement("rect", {
    x: "200",
    y: "26",
    width: "2",
    height: "12",
    fill: "#0A0820"
  }), /*#__PURE__*/React.createElement("rect", {
    x: "22",
    y: "14",
    width: "6",
    height: "10",
    fill: "#1A1530"
  }), /*#__PURE__*/React.createElement("circle", {
    cx: "25",
    cy: "13",
    r: "3",
    fill: "#F33F3F"
  })))), /*#__PURE__*/React.createElement("div", {
    className: "gm-intro-text"
  }, /*#__PURE__*/React.createElement("div", {
    className: "gm-intro-eye"
  }, "\u05DE\u05E9\u05D7\u05E7 \u05D0\u05E0\u05D2\u05DC\u05D9\u05EA \u05DE\u05D1\u05D9\u05EA ", /*#__PURE__*/React.createElement("span", {
    className: "en brand-eazy"
  }, "eazy")), /*#__PURE__*/React.createElement("h1", {
    className: "gm-intro-title"
  }, "\u05EA\u05D5\u05EA\u05D7 \u05DE\u05D9\u05DC\u05D9\u05DD", /*#__PURE__*/React.createElement("span", {
    className: "dot"
  }, ".")), /*#__PURE__*/React.createElement("p", {
    className: "gm-intro-lead"
  }, "\u05E2\u05D5\u05DE\u05D3\u05D9\u05DD \u05DC\u05E8\u05E9\u05D5\u05EA\u05DB\u05DD \u05EA\u05D5\u05EA\u05D7 \u05DE\u05D9\u05DC\u05D9\u05DD \u05D5\u05D4\u05D9\u05D3\u05E2 \u05E9\u05DC\u05DB\u05DD \u05D1\u05D0\u05E0\u05D2\u05DC\u05D9\u05EA."), /*#__PURE__*/React.createElement("p", {
    className: "gm-intro-body"
  }, "\u05D1\u05EA\u05D7\u05EA\u05D9\u05EA \u05D4\u05DE\u05E1\u05DA \u05DE\u05D5\u05E4\u05D9\u05E2\u05D4 \u05DE\u05D9\u05DC\u05D4 \u05D1\u05D0\u05E0\u05D2\u05DC\u05D9\u05EA. \u05D6\u05D4\u05D5 \u05D0\u05EA \u05D4\u05D8\u05D9\u05DC \u05E2\u05DD \u05D4\u05E4\u05D9\u05E8\u05D5\u05E9 \u05D4\u05DE\u05EA\u05D0\u05D9\u05DD \u05D5\u05EA\u05DC\u05D7\u05E6\u05D5 \u05E2\u05DC\u05D9\u05D5.", /*#__PURE__*/React.createElement("br", null), "\u05DB\u05DB\u05DC \u05E9\u05E2\u05D5\u05E0\u05D9\u05DD \u05DE\u05D4\u05E8 \u05D9\u05D5\u05EA\u05E8, \u05E6\u05D5\u05D1\u05E8\u05D9\u05DD \u05D9\u05D5\u05EA\u05E8 \u05E0\u05E7\u05D5\u05D3\u05D5\u05EA. \u05D1\u05D4\u05E6\u05DC\u05D7\u05D4!")), /*#__PURE__*/React.createElement("button", {
    className: "gm-intro-cta",
    onClick: startAndFullscreen
  }, /*#__PURE__*/React.createElement("span", null, "\u05DC\u05D4\u05EA\u05D7\u05D9\u05DC \u05DC\u05E9\u05D7\u05E7"), /*#__PURE__*/React.createElement("svg", {
    viewBox: "0 0 24 24",
    width: "28",
    height: "28",
    fill: "none",
    stroke: "currentColor",
    strokeWidth: "2.6",
    strokeLinecap: "round",
    strokeLinejoin: "round"
  }, /*#__PURE__*/React.createElement("path", {
    d: "M19 12H5"
  }), /*#__PURE__*/React.createElement("path", {
    d: "M12 19l-7-7 7-7"
  }))), /*#__PURE__*/React.createElement("div", {
    className: "gm-foot-actions"
  }, /*#__PURE__*/React.createElement("button", {
    className: "foot-btn",
    onClick: () => {
      try {
        window.top.location.href = "https://www.ezway.co.il";
      } catch (e) {
        window.open("https://www.ezway.co.il", "_top");
      }
    },
    title: "\u05D0\u05EA\u05E8 \u05D4\u05D1\u05D9\u05EA"
  }, /*#__PURE__*/React.createElement(I.home, null)), /*#__PURE__*/React.createElement("button", {
    className: "foot-btn",
    onClick: toggleFullscreen,
    title: "\u05DE\u05E1\u05DA \u05DE\u05DC\u05D0"
  }, /*#__PURE__*/React.createElement(I.expand, null)), /*#__PURE__*/React.createElement("button", {
    className: "foot-btn" + (muted ? " muted" : ""),
    onClick: toggleMute,
    title: muted ? "השמע צלילים" : "השתק צלילים"
  }, muted ? /*#__PURE__*/React.createElement(I.speakerMute, null) : /*#__PURE__*/React.createElement(I.speaker, null)))));
}
function EndScreen({
  score,
  missedWords,
  onRestart
}) {
  const [submitted, setSubmitted] = useState(false);
  const [name, setName] = useState("");
  const [board, setBoard] = useState(() => getLeaderboard());
  const [showLb, setShowLb] = useState(false);
  const qualifies = qualifiesForLeaderboard(score) && !submitted;
  const submitName = () => {
    const newBoard = addToLeaderboard(name.trim() || "אנונימי", score);
    setBoard(newBoard);
    setSubmitted(true);
    setShowLb(true); // auto-open to show new ranking
  };
  return /*#__PURE__*/React.createElement("div", {
    className: "gm-app gm-end-app"
  }, /*#__PURE__*/React.createElement("div", {
    className: "gm-end-hud"
  }, /*#__PURE__*/React.createElement("button", {
    className: "gm-end-home",
    onClick: () => {
      try {
        window.top.location.href = "https://www.ezway.co.il";
      } catch (e) {
        window.open("https://www.ezway.co.il", "_top");
      }
    },
    title: "\u05D0\u05EA\u05E8 \u05D4\u05D1\u05D9\u05EA",
    "aria-label": "\u05DC\u05D0\u05EA\u05E8 eazy"
  }, /*#__PURE__*/React.createElement(I.home, null)), /*#__PURE__*/React.createElement("div", {
    className: "gm-end-brand"
  }, /*#__PURE__*/React.createElement("img", {
    src: "../assets/ez-icon.png",
    alt: ""
  }), /*#__PURE__*/React.createElement("span", {
    className: "brand-eazy"
  }, "eazy"))), /*#__PURE__*/React.createElement("div", {
    className: "gm-end-score"
  }, /*#__PURE__*/React.createElement("div", {
    className: "gm-end-score-text"
  }, /*#__PURE__*/React.createElement("div", {
    className: "gm-end-eye"
  }, "\u05E1\u05D5\u05E3 \u05E1\u05D9\u05D1\u05D5\u05D1", /*#__PURE__*/React.createElement("span", {
    className: "dot"
  }, ".")), /*#__PURE__*/React.createElement("div", {
    className: "gm-end-line"
  }, /*#__PURE__*/React.createElement("span", null, "\u05D4\u05E9\u05D2\u05EA"), /*#__PURE__*/React.createElement("span", {
    className: "num"
  }, score), /*#__PURE__*/React.createElement("span", null, "\u05E0\u05E7\u05D5\u05D3\u05D5\u05EA."))), qualifies ? /*#__PURE__*/React.createElement("div", {
    className: "gm-lb-prompt"
  }, /*#__PURE__*/React.createElement("div", {
    className: "gm-lb-prompt-eye"
  }, /*#__PURE__*/React.createElement(I.trophy, null), " \u05E0\u05DB\u05E0\u05E1\u05EA \u05DC\u05D8\u05D1\u05DC\u05EA \u05D4\u05E9\u05D9\u05D0\u05D9\u05DD!"), /*#__PURE__*/React.createElement("div", {
    className: "gm-lb-prompt-row"
  }, /*#__PURE__*/React.createElement("input", {
    className: "gm-lb-input",
    type: "text",
    placeholder: "\u05D4\u05E9\u05DD \u05E9\u05DC\u05DA",
    value: name,
    onChange: e => setName(e.target.value),
    onKeyDown: e => e.key === 'Enter' && submitName(),
    maxLength: 20,
    autoFocus: true
  }), /*#__PURE__*/React.createElement("button", {
    className: "gm-lb-save",
    onClick: submitName
  }, "\u05E9\u05DE\u05D5\u05E8"))) : /*#__PURE__*/React.createElement("button", {
    className: "gm-end-cta secondary gm-end-lb-btn",
    onClick: () => setShowLb(true)
  }, /*#__PURE__*/React.createElement(I.trophy, null), /*#__PURE__*/React.createElement("span", null, "\u05D8\u05D1\u05DC\u05EA \u05D4\u05E9\u05D9\u05D0\u05D9\u05DD"))), /*#__PURE__*/React.createElement("div", {
    className: "gm-end-vrule"
  }), /*#__PURE__*/React.createElement("div", {
    className: "gm-end-list-wrap"
  }, missedWords.length > 0 ? /*#__PURE__*/React.createElement(React.Fragment, null, /*#__PURE__*/React.createElement("div", {
    className: "gm-end-list-eye"
  }, "\u05D0\u05DC\u05D5 \u05D4\u05DE\u05D9\u05DC\u05D9\u05DD \u05E9\u05E4\u05E1\u05E4\u05E1\u05EA"), /*#__PURE__*/React.createElement("div", {
    className: "gm-end-list"
  }, missedWords.map((w, i) => /*#__PURE__*/React.createElement("div", {
    key: i,
    className: "gm-end-row"
  }, /*#__PURE__*/React.createElement("span", {
    className: "gm-end-en"
  }, String(w.en).toUpperCase()), /*#__PURE__*/React.createElement("span", {
    className: "gm-end-he"
  }, w.he))))) : /*#__PURE__*/React.createElement("div", {
    className: "gm-end-no-miss"
  }, /*#__PURE__*/React.createElement("span", {
    className: "hi"
  }, "\u05DB\u05DC \u05D4\u05DB\u05D1\u05D5\u05D3", /*#__PURE__*/React.createElement("span", {
    className: "dot"
  }, "!")), /*#__PURE__*/React.createElement("span", {
    className: "lo"
  }, "\u05DC\u05D0 \u05E4\u05E1\u05E4\u05E1\u05EA \u05D0\u05E3 \u05DE\u05D9\u05DC\u05D4.")), /*#__PURE__*/React.createElement("button", {
    className: "gm-end-cta gm-end-restart",
    onClick: onRestart
  }, /*#__PURE__*/React.createElement("span", null, "\u05D9\u05D5\u05E6\u05D0\u05D9\u05DD \u05DC\u05E1\u05D9\u05D1\u05D5\u05D1 \u05E0\u05D5\u05E1\u05E3 \u05E2\u05DD \u05D4\u05EA\u05D5\u05EA\u05D7?"), /*#__PURE__*/React.createElement("span", {
    className: "cta-arrow",
    "aria-hidden": true
  }, "\u203A"))), showLb && /*#__PURE__*/React.createElement("div", {
    className: "gm-lb-modal",
    onClick: () => setShowLb(false)
  }, /*#__PURE__*/React.createElement("div", {
    className: "gm-lb-modal-card",
    onClick: e => e.stopPropagation()
  }, /*#__PURE__*/React.createElement("button", {
    className: "gm-lb-close",
    onClick: () => setShowLb(false),
    "aria-label": "\u05E1\u05D2\u05D5\u05E8"
  }, "\xD7"), /*#__PURE__*/React.createElement("div", {
    className: "gm-lb-title"
  }, /*#__PURE__*/React.createElement(I.trophy, null), /*#__PURE__*/React.createElement("span", null, "\u05D8\u05D1\u05DC\u05EA \u05D4\u05E9\u05D9\u05D0\u05D9\u05DD")), board.length === 0 ? /*#__PURE__*/React.createElement("div", {
    className: "gm-lb-empty"
  }, "\u05E2\u05D3\u05D9\u05D9\u05DF \u05D0\u05D9\u05DF \u05E9\u05D9\u05D0\u05D9\u05DD. \u05D0\u05EA\u05D4 \u05D9\u05DB\u05D5\u05DC \u05DC\u05D4\u05D9\u05D5\u05EA \u05D4\u05E8\u05D0\u05E9\u05D5\u05DF.") : /*#__PURE__*/React.createElement("ol", {
    className: "gm-lb-list"
  }, board.map((entry, i) => /*#__PURE__*/React.createElement("li", {
    key: i,
    className: "gm-lb-row " + (submitted && entry.score === score && entry.name === (name.trim() || "אנונימי") ? "you" : "")
  }, /*#__PURE__*/React.createElement("span", {
    className: "rank"
  }, i + 1), /*#__PURE__*/React.createElement("span", {
    className: "name"
  }, entry.name), /*#__PURE__*/React.createElement("span", {
    className: "pts"
  }, entry.score)))))));
}

/* ──────────────────────────────────────────────
   Game
   ────────────────────────────────────────────── */
function QuizGame() {
  const [started, setStarted] = useState(false);
  const [dict, setDict] = useState(null);
  const [dictName, setDictName] = useState("");
  const [used, setUsed] = useState([]);
  const [missed, setMissed] = useState([]);
  const [question, setQuestion] = useState(null);
  const [lives, setLives] = useState(3);
  const [score, setScore] = useState(0);
  const [aimed, setAimed] = useState(null);
  const [resolved, setResolved] = useState({});
  const [angle, setAngle] = useState(-18);
  const [shot, setShot] = useState(null);
  const [toast, setToast] = useState(null);
  const [missFx, setMissFx] = useState(false);
  const [recoil, setRecoil] = useState(false);
  const [levelUpInfo, setLevelUpInfo] = useState(null);
  const [audioUnlocked, setAudioUnlocked] = useState(false);
  const [autoSpeakEnabled, setAutoSpeakEnabled] = useState(true);
  // streak (consecutive correct answers), and the last time a streak bonus
  // fired — combo bonuses are gated to once per 5 minutes so they stay rare.
  const [streak, setStreak] = useState(0);
  const lastBonusTimeRef = useRef(0);
  const questionStartRef = useRef(Date.now());
  const [muted, setMuted] = useState(Sound.muted);
  // lifelines & bonuses
  const [fiftyAvailable, setFiftyAvailable] = useState(true);
  const [hiddenIdx, setHiddenIdx] = useState(() => new Set());
  const [kitState, setKitState] = useState(null);
  const prevQuestionEnRef = useRef(null);
  const prevLevelRef = useRef(0);
  const stageRef = useRef(null);
  const cannonRef = useRef(null);
  const rocketRefs = useRef([]);
  const scale = useStageScale(1600, 900);

  // ── level system: every 15 questions speeds up + raises points ──
  const level = Math.floor(used.length / 15);
  const rocketDur = Math.max(8, 22 - level * 3); // seconds, min 8s
  const pointsPerHit = 200 + level * 100;
  useEffect(() => {
    if (level > prevLevelRef.current && used.length > 0) {
      setLevelUpInfo({
        sub: `הטילים מהירים יותר · +${pointsPerHit} לכל תשובה נכונה`
      });
      const t = setTimeout(() => setLevelUpInfo(null), 2600);
      prevLevelRef.current = level;
      return () => clearTimeout(t);
    }
    prevLevelRef.current = level;
  }, [level, used.length, pointsPerHit]);

  // ── BOSS question + audio unlock ──
  // The 6th question (after 5 normal answers) is a one-time BOSS round. Hitting
  // it unlocks the per-word speaker icon for the rest of the run.
  const isBoss = used.length === 5 && !audioUnlocked;

  // Speak the current English word via the browser's SpeechSynthesis. Works
  // regardless of the game's mute toggle (those are SFX/music; this is content).
  const speakWord = useCallback(text => {
    if (!text) return;
    try {
      const synth = window.speechSynthesis;
      if (!synth) return;
      synth.cancel();
      const u = new SpeechSynthesisUtterance(String(text));
      u.lang = 'en-US';
      u.rate = 0.85;
      u.pitch = 1.0;
      u.volume = 1.0;
      // Prefer a real English voice if the browser has finished loading them.
      try {
        const voices = synth.getVoices ? synth.getVoices() : [];
        const en = voices.find(v => /^en[-_]/i.test(v.lang)) || voices.find(v => /english/i.test(v.name));
        if (en) u.voice = en;
      } catch (e) {}
      synth.speak(u);
    } catch (e) {/* ignore — TTS just won't fire */}
  }, []);

  // After the BOSS is beaten and audio is unlocked, auto-speak every new word.
  // Three independent guards: the audio must be unlocked (boss beaten), the
  // user must have opted in at the level-up screen, and the master sound
  // toggle must be unmuted.
  useEffect(() => {
    if (!audioUnlocked) return;
    if (!autoSpeakEnabled) return;
    if (muted) return;
    if (!question?.en) return;
    // Small delay so the new word has time to render and any in-flight SFX
    // (hit/levelup) doesn't compete with the TTS.
    const t = setTimeout(() => speakWord(question.en), 350);
    return () => clearTimeout(t);
  }, [audioUnlocked, autoSpeakEnabled, muted, question?.en, speakWord]);

  // mouse-tracking aim when idle
  useEffect(() => {
    const stage = stageRef.current;
    const cannon = cannonRef.current;
    if (!stage || !cannon) return;
    const onMove = ev => {
      if (aimed !== null) return; // a shot is in flight
      if (isRoundOver) return;
      const sR = stage.getBoundingClientRect();
      const cR = cannon.getBoundingClientRect();
      const mx = (ev.clientX - sR.left) / scale;
      const my = (ev.clientY - sR.top) / scale;
      const fromX = (cR.left - sR.left + cR.width * 0.5) / scale;
      const fromY = (cR.top - sR.top + cR.height * 0.42) / scale;
      let ang = Math.atan2(my - fromY, mx - fromX) * (180 / Math.PI);
      // clamp barrel rotation
      if (ang < -55) ang = -55;
      if (ang > 20) ang = 20;
      setAngle(ang);
    };
    stage.addEventListener("mousemove", onMove);
    return () => stage.removeEventListener("mousemove", onMove);
  }, [aimed, isRoundOver, scale]);

  // fullscreen toggle — also locks orientation to landscape on mobile
  const toggleFullscreen = useCallback(() => {
    try {
      const target = window.frameElement ? window.frameElement : document.documentElement;
      const doc = window.frameElement ? window.parent.document : document;
      const isFs = doc.fullscreenElement || doc.webkitFullscreenElement;
      if (!isFs) {
        const req = target.requestFullscreen || target.webkitRequestFullscreen || target.mozRequestFullScreen || target.msRequestFullscreen;
        if (req) {
          const p = req.call(target);
          // attempt to lock landscape on mobile devices
          if (p && p.then) {
            p.then(() => {
              try {
                if (screen.orientation && screen.orientation.lock) {
                  screen.orientation.lock('landscape').catch(() => {});
                }
              } catch (e) {}
            }).catch(() => {});
          } else {
            try {
              if (screen.orientation && screen.orientation.lock) {
                screen.orientation.lock('landscape').catch(() => {});
              }
            } catch (e) {}
          }
        }
      } else {
        try {
          if (screen.orientation && screen.orientation.unlock) screen.orientation.unlock();
        } catch (e) {}
        const exit = doc.exitFullscreen || doc.webkitExitFullscreen || doc.mozCancelFullScreen || doc.msExitFullscreen;
        if (exit) exit.call(doc);
      }
    } catch (e) {/* permission blocked in iframe — silent */}
  }, []);

  // mute toggle — controls background music, sound FX, AND (after the BOSS
  // unlock) the per-word audio. This is the single source of truth for any
  // sound coming out of the game.
  const toggleMute = useCallback(() => {
    const next = !Sound.muted;
    Sound.setMuted(next);
    setMuted(next);
    if (next) {
      // muting → stop any in-flight TTS immediately
      try {
        window.speechSynthesis?.cancel();
      } catch (e) {}
    }
  }, []);

  // hydrate dictionary — bundled words.js takes precedence over localStorage
  useEffect(() => {
    if (window.GAME_DICTIONARY && Array.isArray(window.GAME_DICTIONARY) && window.GAME_DICTIONARY.length >= 4) {
      setDict(window.GAME_DICTIONARY);
      setDictName("מילון המשחק");
      return;
    }
    try {
      const raw = localStorage.getItem(DICT_STORAGE_KEY);
      if (raw) {
        const arr = JSON.parse(raw);
        if (Array.isArray(arr) && arr.length >= 4) {
          setDict(arr);
          setDictName(localStorage.getItem(DICT_NAME_KEY) || "");
        }
      }
    } catch (e) {}
  }, []);

  // draw a question whenever dict changes or used grows
  useEffect(() => {
    if (!dict) return;
    const available = dict.map((_, i) => i).filter(i => !used.includes(i));
    if (available.length === 0) {
      setQuestion(null);
      return;
    }
    const correctIdx = available[Math.floor(Math.random() * available.length)];
    setQuestion({
      ...buildQuestion(dict, correctIdx),
      correctDictIdx: correctIdx
    });
  }, [dict, used]);
  const loadDict = useCallback((entries, name) => {
    setDict(entries);
    setDictName(name);
    setUsed([]);
    setMissed([]);
    setLives(3);
    setScore(0);
    setResolved({});
    setAimed(null);
    try {
      localStorage.setItem(DICT_STORAGE_KEY, JSON.stringify(entries));
      localStorage.setItem(DICT_NAME_KEY, name);
    } catch (e) {}
  }, []);
  const resetDict = useCallback(() => {
    setDict(null);
    setDictName("");
    setUsed([]);
    setMissed([]);
    setLives(3);
    setScore(0);
    setResolved({});
    setAimed(null);
    setQuestion(null);
    try {
      localStorage.removeItem(DICT_STORAGE_KEY);
      localStorage.removeItem(DICT_NAME_KEY);
    } catch (e) {}
  }, []);
  const restartGame = useCallback(() => {
    setUsed([]);
    setMissed([]);
    setLives(3);
    setScore(0);
    setResolved({});
    setAimed(null);
    setFiftyAvailable(true);
    setHiddenIdx(new Set());
    setKitState(null);
    setAudioUnlocked(false);
    setAutoSpeakEnabled(true);
    setLevelUpInfo(null);
    setStreak(0);
    lastBonusTimeRef.current = 0;
    questionStartRef.current = Date.now();
    prevLevelRef.current = 0;
    Sound.startMusic();
  }, []);
  const correctIdx = question ? question.options.indexOf(question.correct) : -1;
  const isRoundOver = resolved[correctIdx] === "hit" || lives <= 0;

  // Reset 50/50 hidden distractors whenever a new question appears;
  // every 8th question, drop a first-aid kit (if not full lives + not already showing).
  useEffect(() => {
    if (!question) return;
    if (prevQuestionEnRef.current !== question.en) {
      setHiddenIdx(new Set());
      prevQuestionEnRef.current = question.en;
      // Stamp the new question's start time so the speed bonus can be computed
      // when the user finally shoots.
      questionStartRef.current = Date.now();
      if (used.length > 0 && used.length % 8 === 0 && !kitState && lives < 3) {
        setKitState({
          id: Date.now()
        });
      }
    }
  }, [question, used.length, lives, kitState]);

  // 50/50 lifeline: hide 2 of the 3 wrong distractors
  const useFifty = useCallback(() => {
    if (!fiftyAvailable || !question || isRoundOver) return;
    const wrongs = question.options.map((_, i) => i).filter(i => i !== correctIdx);
    const toHide = shuffleArr(wrongs).slice(0, 2);
    setHiddenIdx(new Set(toHide));
    setFiftyAvailable(false);
    Sound.play('fifty');
  }, [fiftyAvailable, question, correctIdx, isRoundOver]);

  // Shooting the first-aid kit grants a life back
  const onKitHit = useCallback(() => {
    if (!kitState) return;
    setLives(l => Math.min(3, l + 1));
    setKitState(null);
    Sound.play('lifegain');
    setToast({
      kind: "win",
      text: "+1 לב · תיק עזרה ראשונה!"
    });
    setTimeout(() => setToast(null), 1800);
  }, [kitState]);

  // Kit auto-vanishes if not shot in time
  useEffect(() => {
    if (!kitState) return;
    const t = setTimeout(() => setKitState(null), 9000);
    return () => clearTimeout(t);
  }, [kitState]);
  const nextQuestion = useCallback(() => {
    if (!question) return;
    setUsed(u => [...u, question.correctDictIdx]);
    setResolved({});
    setAimed(null);
    setAngle(-18);
  }, [question]);
  const onTarget = useCallback(i => {
    if (!question) return;
    if (hiddenIdx.has(i)) return;
    if (resolved[i] || isRoundOver || aimed !== null) return;
    setAimed(i);
    Sound.play('shoot');
    const stage = stageRef.current;
    const cannon = cannonRef.current;
    const target = rocketRefs.current[i];
    if (!stage || !cannon || !target) return;
    const sR = stage.getBoundingClientRect();
    const cR = cannon.getBoundingClientRect();
    const tR = target.getBoundingClientRect();
    const fromX = (cR.left - sR.left + cR.width * 0.5) / scale;
    const fromY = (cR.top - sR.top + cR.height * 0.42) / scale;
    const toX = (tR.left - sR.left + 70) / scale;
    const toY = (tR.top - sR.top + tR.height * 0.5) / scale;
    const ang = Math.atan2(toY - fromY, toX - fromX) * (180 / Math.PI);
    setAngle(ang);
    setTimeout(() => {
      setShot({
        fromX,
        fromY,
        toX,
        toY
      });
      setTimeout(() => {
        const correct = i === correctIdx;
        const isBossHit = isBoss && correct;
        setResolved(r => ({
          ...r,
          [i]: correct ? "hit" : "missed"
        }));
        if (correct) {
          // ── speed bonus: faster hits earn more points (linear 2× → 1×) ──
          const effectiveDur = isBoss ? rocketDur * 0.8 : rocketDur;
          const elapsed = (Date.now() - questionStartRef.current) / 1000;
          const speedMult = Math.max(1, Math.min(2, 2 - elapsed / Math.max(1, effectiveDur)));

          // ── streak bonus: every 5 in a row unlocks a special — but a special
          // bonus fires at most once per 5 minutes so it stays meaningful. ──
          const newStreak = streak + 1;
          const now = Date.now();
          const cooldownPassed = now - lastBonusTimeRef.current >= 5 * 60 * 1000;
          let comboMult = 1,
            comboBonus = 0,
            comboLabel = null;
          if (newStreak >= 5 && newStreak % 5 === 0 && cooldownPassed) {
            if (newStreak >= 20) {
              comboMult = 3;
              comboLabel = `סטריק ${newStreak} ✦ ×3 ניקוד`;
            } else if (newStreak >= 10) {
              comboMult = 2;
              comboLabel = `סטריק ${newStreak} ✦ ×2 ניקוד`;
            } else {
              comboBonus = 500;
              comboLabel = `סטריק ${newStreak} ✦ +500 בונוס`;
            }
            lastBonusTimeRef.current = now;
          }
          const basePoints = isBossHit ? 500 : pointsPerHit;
          const points = Math.round(basePoints * speedMult * comboMult) + comboBonus;
          setScore(s => s + points);
          setStreak(newStreak);
          Sound.play(comboLabel ? 'levelup' : 'hit');
          if (comboLabel) {
            setToast({
              kind: "win",
              text: `${comboLabel} · +${points}`
            });
          } else {
            const speedTag = speedMult >= 1.7 ? "מהיר! " : speedMult >= 1.35 ? "יפה! " : "";
            setToast({
              kind: "win",
              text: `${speedTag}פגיעה ישירה +${points}`
            });
          }
          // BOSS pass → unlock the per-word audio, show a custom level-up overlay.
          // The overlay has its own continue buttons so we DON'T auto-advance here.
          if (isBossHit) {
            setAudioUnlocked(true);
            Sound.play('levelup');
            setTimeout(() => {
              setLevelUpInfo({
                mode: 'audio',
                sub: 'מעכשיו אפשר גם לשמוע כל מילה באנגלית.'
              });
            }, 500);
          }
        } else {
          setStreak(0);
          setLives(l => Math.max(0, l - 1));
          setMissed(m => m.includes(question.correctDictIdx) ? m : [...m, question.correctDictIdx]);
          setMissFx(true);
          setTimeout(() => setMissFx(false), 5400);
          setRecoil(true);
          setTimeout(() => setRecoil(false), 500);
          Sound.play('miss');
          setToast({
            kind: "lose",
            text: "פספסת — לב אחד נפל"
          });
          setTimeout(() => {
            setResolved(r => ({
              ...r,
              [correctIdx]: r[correctIdx] || "correct-after"
            }));
          }, 700);
        }
        setShot(null);
        setAimed(null);
        setTimeout(() => setToast(null), 1800);
        // auto-advance to next question — skipped for the BOSS hit (the
        // unlock overlay's "Continue" button handles that)
        if (!isBossHit) {
          setTimeout(() => {
            setUsed(u => [...u, question.correctDictIdx]);
            setResolved({});
            setAimed(null);
            setAngle(-18);
          }, correct ? 1400 : 5600);
        }
      }, 380);
    }, 340);
  }, [resolved, isRoundOver, aimed, correctIdx, scale, question, pointsPerHit, hiddenIdx, isBoss, rocketDur, streak]);

  // Rocket reaches the cannon zone = wrong answer
  const onTravelEnd = useCallback((i, e) => {
    if (e.animationName !== "rocketTravel") return;
    // Hard guard: once the correct rocket is resolved (hit, missed, or
    // revealed-after), no other rocket of the same round can deduct another
    // life. Without this, multiple rockets reaching the line in a row burned
    // through every heart in one round.
    if (!question || resolved[i] || isRoundOver || resolved[correctIdx]) return;
    setStreak(0);
    setLives(l => Math.max(0, l - 1));
    setMissed(m => m.includes(question.correctDictIdx) ? m : [...m, question.correctDictIdx]);
    setResolved(r => ({
      ...r,
      [i]: "missed",
      [correctIdx]: r[correctIdx] || "correct-after"
    }));
    setMissFx(true);
    setTimeout(() => setMissFx(false), 5400);
    Sound.play('miss');
    setToast({
      kind: "lose",
      text: "הטיל הגיע — לב אחד נפל"
    });
    setTimeout(() => setToast(null), 1800);
    setTimeout(() => {
      setUsed(u => [...u, question.correctDictIdx]);
      setResolved({});
      setAimed(null);
      setAngle(-18);
    }, 5600);
  }, [question, resolved, isRoundOver, correctIdx]);
  let shotEl = null;
  if (shot) {
    const dx = shot.toX - shot.fromX;
    const dy = shot.toY - shot.fromY;
    shotEl = /*#__PURE__*/React.createElement("div", {
      className: "gm-shot active",
      style: {
        left: shot.fromX,
        top: shot.fromY,
        animation: "shotFly .4s linear forwards",
        "--dx": `${dx}px`,
        "--dy": `${dy}px`
      }
    });
  }

  // ── intro first ──
  if (!started) return /*#__PURE__*/React.createElement(IntroScreen, {
    onStart: () => {
      setStarted(true);
      Sound.startMusic();
      // Prime SpeechSynthesis on user gesture so iOS will let later auto-speaks fire.
      // Also kicks the browser to start loading its voice list.
      try {
        const s = window.speechSynthesis;
        if (s) {
          const primer = new SpeechSynthesisUtterance(' ');
          primer.volume = 0;
          primer.rate = 1;
          s.speak(primer);
          s.getVoices?.();
        }
      } catch (e) {}
    },
    toggleFullscreen: toggleFullscreen,
    muted: muted,
    toggleMute: toggleMute
  });

  // ── no dict yet — only shown if bundled words.js missing AND no localStorage ──
  if (!dict) return /*#__PURE__*/React.createElement(UploadScreen, {
    onLoad: loadDict
  });

  // ── game over (lives exhausted) ──
  if (lives <= 0) {
    const missedWords = missed.map(idx => dict[idx]).filter(Boolean);
    return /*#__PURE__*/React.createElement(EndScreen, {
      score: score,
      missedWords: missedWords,
      onRestart: restartGame
    });
  }

  // ── dict exhausted ──
  if (!question) {
    return /*#__PURE__*/React.createElement("div", {
      className: "gm-app gm-up-app"
    }, /*#__PURE__*/React.createElement("div", {
      className: "gm-up-wrap"
    }, /*#__PURE__*/React.createElement("div", {
      className: "gm-up-card"
    }, /*#__PURE__*/React.createElement("div", {
      className: "gm-up-eye"
    }, "\u05E1\u05D9\u05D9\u05DE\u05EA\u05DD \u05D0\u05EA \u05D4\u05DE\u05D9\u05DC\u05D5\u05DF"), /*#__PURE__*/React.createElement("h1", {
      className: "gm-up-h1"
    }, used.length, " \u05DE\u05D9\u05DC\u05D9\u05DD \xB7 ", score, " \u05E0\u05E7\u05D5\u05D3\u05D5\u05EA"), /*#__PURE__*/React.createElement("p", {
      className: "gm-up-sub"
    }, "\u05E2\u05D1\u05E8\u05EA \u05E2\u05DC \u05DB\u05DC \u05D4\u05DE\u05D9\u05DC\u05D9\u05DD \u05D1\u05DE\u05D9\u05DC\u05D5\u05DF \"", dictName, "\". \u05DE\u05D4 \u05D4\u05DC\u05D0\u05D4?"), /*#__PURE__*/React.createElement("button", {
      className: "gm-up-btn",
      onClick: () => {
        setUsed([]);
        setLives(3);
        setScore(0);
      }
    }, "\u05E1\u05D9\u05D1\u05D5\u05D1 \u05E0\u05D5\u05E1\u05E3 \u05E2\u05DD \u05D0\u05D5\u05EA\u05DD \u05DE\u05D9\u05DC\u05D9\u05DD"), /*#__PURE__*/React.createElement("button", {
      className: "gm-up-btn-ghost",
      onClick: resetDict
    }, "\u05D8\u05E2\u05E0\u05D5 \u05DE\u05D9\u05DC\u05D5\u05DF \u05D0\u05D7\u05E8"))));
  }
  return /*#__PURE__*/React.createElement("div", {
    className: "gm-app"
  }, /*#__PURE__*/React.createElement("div", {
    className: "gm-stage",
    ref: stageRef,
    style: {
      "--gm-scale": scale,
      "--rocket-duration": `${(isBoss ? rocketDur * 0.8 : rocketDur).toFixed(2)}s`
    }
  }, /*#__PURE__*/React.createElement(SkyZ, null), /*#__PURE__*/React.createElement(Mountains, null), /*#__PURE__*/React.createElement("div", {
    className: "gm-ground"
  }), /*#__PURE__*/React.createElement("div", {
    className: "gm-hud-brand"
  }, /*#__PURE__*/React.createElement("img", {
    src: "../assets/ez-icon.png",
    alt: ""
  }), /*#__PURE__*/React.createElement("span", {
    className: "brand-eazy"
  }, "eazy")), /*#__PURE__*/React.createElement("div", {
    className: "gm-hud"
  }, /*#__PURE__*/React.createElement("div", {
    className: "chip hearts"
  }, [0, 1, 2].map(i => /*#__PURE__*/React.createElement(Heart, {
    key: i,
    lost: i >= lives
  }))), /*#__PURE__*/React.createElement("div", {
    className: "chip score"
  }, /*#__PURE__*/React.createElement("span", {
    className: "label"
  }, "\u05E0\u05D9\u05E7\u05D5\u05D3"), /*#__PURE__*/React.createElement("span", null, score)), /*#__PURE__*/React.createElement("div", {
    className: "spacer"
  })), isBoss && /*#__PURE__*/React.createElement("div", {
    className: "gm-boss-banner",
    "aria-hidden": true
  }, /*#__PURE__*/React.createElement("svg", {
    viewBox: "0 0 24 24",
    width: "32",
    height: "32",
    fill: "currentColor"
  }, /*#__PURE__*/React.createElement("path", {
    d: "M13 2 L4 14 L11 14 L10 22 L20 9 L13 9 Z"
  })), /*#__PURE__*/React.createElement("span", null, "\u05E9\u05DC\u05D1 BOSS"), /*#__PURE__*/React.createElement("svg", {
    viewBox: "0 0 24 24",
    width: "32",
    height: "32",
    fill: "currentColor"
  }, /*#__PURE__*/React.createElement("path", {
    d: "M13 2 L4 14 L11 14 L10 22 L20 9 L13 9 Z"
  }))), /*#__PURE__*/React.createElement("div", {
    className: "gm-word" + (isBoss ? " is-boss" : "") + (used.length === 0 ? " is-first" : "")
  }, /*#__PURE__*/React.createElement("div", {
    className: "en-wrap"
  }, /*#__PURE__*/React.createElement("div", {
    className: "en"
  }, question.en))), /*#__PURE__*/React.createElement("div", {
    className: "gm-foot-actions"
  }, /*#__PURE__*/React.createElement("button", {
    className: "foot-btn",
    onClick: () => {
      try {
        window.top.location.href = "https://www.ezway.co.il";
      } catch (e) {
        window.open("https://www.ezway.co.il", "_top");
      }
    },
    title: "\u05D0\u05EA\u05E8 \u05D4\u05D1\u05D9\u05EA"
  }, /*#__PURE__*/React.createElement(I.home, null)), /*#__PURE__*/React.createElement("button", {
    className: "foot-btn",
    onClick: toggleFullscreen,
    title: "\u05DE\u05E1\u05DA \u05DE\u05DC\u05D0"
  }, /*#__PURE__*/React.createElement(I.expand, null)), /*#__PURE__*/React.createElement("button", {
    className: "foot-btn lifeline" + (fiftyAvailable ? "" : " used"),
    onClick: useFifty,
    disabled: !fiftyAvailable,
    title: fiftyAvailable ? "גלגל הצלה 50/50" : "כבר השתמשת ב-50/50"
  }, /*#__PURE__*/React.createElement("span", {
    className: "fifty-text"
  }, "50", /*#__PURE__*/React.createElement("br", null), "50")), /*#__PURE__*/React.createElement("button", {
    className: "foot-btn" + (muted ? " muted" : ""),
    onClick: toggleMute,
    title: muted ? "השמע צלילים" : "השתק צלילים"
  }, muted ? /*#__PURE__*/React.createElement(I.speakerMute, null) : /*#__PURE__*/React.createElement(I.speaker, null))), /*#__PURE__*/React.createElement("div", {
    className: "gm-rockets"
  }, question.options.map((opt, i) => {
    const state = resolved[i];
    let cls = "gm-rocket";
    if (isBoss) cls += " boss";
    if (aimed === i) cls += " aiming";
    if (state === "hit") cls += " hit";else if (state === "missed") cls += " missed";else if (state === "correct-after") cls += " correct-after";
    const paused = isRoundOver || aimed === i || resolved[i] && resolved[i] !== "correct-after"; // correct-after keeps drifting
    const hidden = hiddenIdx.has(i);
    return /*#__PURE__*/React.createElement("div", {
      key: `${question.en}-${i}`,
      className: "gm-rocket-travel" + (paused ? " paused" : "") + (hidden ? " hidden5050" : ""),
      style: {
        animationDelay: `${-i * 1.5}s`
      },
      onAnimationEnd: e => onTravelEnd(i, e)
    }, /*#__PURE__*/React.createElement("div", {
      ref: el => rocketRefs.current[i] = el,
      className: cls,
      style: {
        "--mr": STAGGER[i] + "px"
      },
      onClick: () => onTarget(i)
    }, /*#__PURE__*/React.createElement(RocketSVG, {
      isBoss: isBoss
    }), /*#__PURE__*/React.createElement("div", {
      className: "label"
    }, opt), /*#__PURE__*/React.createElement("div", {
      className: "gm-burst"
    }, /*#__PURE__*/React.createElement(BurstSVG, null))));
  })), /*#__PURE__*/React.createElement("div", {
    className: "gm-cannon" + (recoil ? " recoil" : ""),
    ref: cannonRef
  }, /*#__PURE__*/React.createElement(CannonBase, null), /*#__PURE__*/React.createElement("div", {
    className: "barrel-wrap"
  }, /*#__PURE__*/React.createElement("svg", {
    style: {
      position: "absolute",
      width: "220px",
      height: "60px",
      top: "-30px",
      left: "-30px",
      transformOrigin: "30px 30px",
      transform: `rotate(${angle}deg)`,
      transition: "transform .08s linear",
      overflow: "visible"
    },
    viewBox: "0 0 220 60"
  }, /*#__PURE__*/React.createElement("defs", null, /*#__PURE__*/React.createElement("linearGradient", {
    id: "barG2",
    x1: "0",
    y1: "0",
    x2: "0",
    y2: "1"
  }, /*#__PURE__*/React.createElement("stop", {
    offset: "0",
    stopColor: "#3a3358"
  }), /*#__PURE__*/React.createElement("stop", {
    offset: "0.5",
    stopColor: "#1A1530"
  }), /*#__PURE__*/React.createElement("stop", {
    offset: "1",
    stopColor: "#0A0820"
  })), /*#__PURE__*/React.createElement("linearGradient", {
    id: "muzzleG2",
    x1: "0",
    y1: "0",
    x2: "0",
    y2: "1"
  }, /*#__PURE__*/React.createElement("stop", {
    offset: "0",
    stopColor: "#5a5470"
  }), /*#__PURE__*/React.createElement("stop", {
    offset: "1",
    stopColor: "#2A2547"
  }))), /*#__PURE__*/React.createElement("rect", {
    x: "14",
    y: "22",
    width: "36",
    height: "20",
    rx: "4",
    fill: "#1A1530"
  }), /*#__PURE__*/React.createElement("rect", {
    x: "14",
    y: "22",
    width: "36",
    height: "3",
    fill: "rgba(255,255,255,.18)"
  }), /*#__PURE__*/React.createElement("rect", {
    x: "40",
    y: "26",
    width: "150",
    height: "12",
    rx: "4",
    fill: "url(#barG2)"
  }), /*#__PURE__*/React.createElement("rect", {
    x: "42",
    y: "27",
    width: "146",
    height: "2",
    rx: "1",
    fill: "rgba(255,255,255,.25)"
  }), /*#__PURE__*/React.createElement("rect", {
    x: "184",
    y: "22",
    width: "22",
    height: "20",
    rx: "3",
    fill: "url(#muzzleG2)"
  }), /*#__PURE__*/React.createElement("rect", {
    x: "188",
    y: "26",
    width: "2",
    height: "12",
    fill: "#0A0820"
  }), /*#__PURE__*/React.createElement("rect", {
    x: "194",
    y: "26",
    width: "2",
    height: "12",
    fill: "#0A0820"
  }), /*#__PURE__*/React.createElement("rect", {
    x: "200",
    y: "26",
    width: "2",
    height: "12",
    fill: "#0A0820"
  }), /*#__PURE__*/React.createElement("rect", {
    x: "22",
    y: "14",
    width: "6",
    height: "10",
    fill: "#1A1530"
  }), /*#__PURE__*/React.createElement("circle", {
    cx: "25",
    cy: "13",
    r: "3",
    fill: "#F33F3F"
  })))), shotEl, kitState && /*#__PURE__*/React.createElement("div", {
    className: "gm-kit-travel",
    key: kitState.id,
    onAnimationEnd: () => setKitState(null)
  }, /*#__PURE__*/React.createElement("button", {
    className: "gm-kit",
    onClick: onKitHit,
    title: "\u05D9\u05E8\u05D4 \u05D1\u05EA\u05D9\u05E7 \u05DC\u05E2\u05D5\u05D3 \u05DC\u05D1!"
  }, /*#__PURE__*/React.createElement("svg", {
    viewBox: "0 0 120 110",
    "aria-hidden": true
  }, /*#__PURE__*/React.createElement("defs", null, /*#__PURE__*/React.createElement("linearGradient", {
    id: "kitG",
    x1: "0",
    y1: "0",
    x2: "0",
    y2: "1"
  }, /*#__PURE__*/React.createElement("stop", {
    offset: "0",
    stopColor: "#FFFFFF"
  }), /*#__PURE__*/React.createElement("stop", {
    offset: "1",
    stopColor: "#E8E6F0"
  })), /*#__PURE__*/React.createElement("linearGradient", {
    id: "kitHandleG",
    x1: "0",
    y1: "0",
    x2: "0",
    y2: "1"
  }, /*#__PURE__*/React.createElement("stop", {
    offset: "0",
    stopColor: "#3a3358"
  }), /*#__PURE__*/React.createElement("stop", {
    offset: "1",
    stopColor: "#1A1530"
  }))), /*#__PURE__*/React.createElement("ellipse", {
    cx: "60",
    cy: "102",
    rx: "42",
    ry: "5",
    fill: "rgba(0,0,0,.3)"
  }), /*#__PURE__*/React.createElement("rect", {
    x: "44",
    y: "8",
    width: "32",
    height: "14",
    rx: "3",
    fill: "url(#kitHandleG)",
    stroke: "#0A0820",
    strokeWidth: "2"
  }), /*#__PURE__*/React.createElement("rect", {
    x: "48",
    y: "14",
    width: "24",
    height: "8",
    rx: "2",
    fill: "rgba(255,255,255,.15)"
  }), /*#__PURE__*/React.createElement("rect", {
    x: "14",
    y: "22",
    width: "92",
    height: "76",
    rx: "8",
    fill: "url(#kitG)",
    stroke: "#0A0820",
    strokeWidth: "2.5"
  }), /*#__PURE__*/React.createElement("rect", {
    x: "52",
    y: "34",
    width: "16",
    height: "52",
    rx: "2",
    fill: "#DC2626"
  }), /*#__PURE__*/React.createElement("rect", {
    x: "34",
    y: "52",
    width: "52",
    height: "16",
    rx: "2",
    fill: "#DC2626"
  }), /*#__PURE__*/React.createElement("rect", {
    x: "20",
    y: "28",
    width: "80",
    height: "3",
    rx: "1.5",
    fill: "rgba(255,255,255,.5)"
  }), /*#__PURE__*/React.createElement("rect", {
    x: "56",
    y: "20",
    width: "8",
    height: "6",
    fill: "#3a3358"
  })), /*#__PURE__*/React.createElement("div", {
    className: "gm-kit-label"
  }, "+1 \u05DC\u05D1"))), missFx && /*#__PURE__*/React.createElement("div", {
    className: "gm-miss-jam",
    "aria-hidden": true
  }, /*#__PURE__*/React.createElement("svg", {
    viewBox: "0 0 1600 900",
    preserveAspectRatio: "none"
  }, /*#__PURE__*/React.createElement("defs", null, /*#__PURE__*/React.createElement("linearGradient", {
    id: "jamG",
    x1: "0",
    y1: "0",
    x2: "0",
    y2: "1"
  }, /*#__PURE__*/React.createElement("stop", {
    offset: "0",
    stopColor: "#7C170F",
    stopOpacity: ".95"
  }), /*#__PURE__*/React.createElement("stop", {
    offset: ".35",
    stopColor: "#9C1E16",
    stopOpacity: ".92"
  }), /*#__PURE__*/React.createElement("stop", {
    offset: ".75",
    stopColor: "#B5251B",
    stopOpacity: ".88"
  }), /*#__PURE__*/React.createElement("stop", {
    offset: ".94",
    stopColor: "#C72A1F",
    stopOpacity: ".84"
  }), /*#__PURE__*/React.createElement("stop", {
    offset: ".95",
    stopColor: "#C72A1F",
    stopOpacity: "0"
  }), /*#__PURE__*/React.createElement("stop", {
    offset: "1",
    stopColor: "#C72A1F",
    stopOpacity: "0"
  })), /*#__PURE__*/React.createElement("linearGradient", {
    id: "curtainG",
    x1: "0",
    y1: "0",
    x2: "0",
    y2: "1"
  }, /*#__PURE__*/React.createElement("stop", {
    offset: "0",
    stopColor: "#8E1A12",
    stopOpacity: ".95"
  }), /*#__PURE__*/React.createElement("stop", {
    offset: ".5",
    stopColor: "#A8201A",
    stopOpacity: ".92"
  }), /*#__PURE__*/React.createElement("stop", {
    offset: ".9",
    stopColor: "#B5251B",
    stopOpacity: ".90"
  }), /*#__PURE__*/React.createElement("stop", {
    offset: "1",
    stopColor: "#7C170F",
    stopOpacity: ".95"
  })), /*#__PURE__*/React.createElement("filter", {
    id: "jamBlur",
    x: "-3%",
    y: "-3%",
    width: "106%",
    height: "106%"
  }, /*#__PURE__*/React.createElement("feGaussianBlur", {
    stdDeviation: ".8"
  }))), /*#__PURE__*/React.createElement("path", {
    className: "jam-splat",
    d: "M 0 0 L 1600 0 L 1600 180 C 1540 220 1490 175 1440 200 C 1380 230 1330 175 1280 215 C 1230 245 1180 185 1130 225 C 1080 255 1030 200 980 230 C 930 265 880 195 830 240 C 780 275 730 215 680 245 C 630 280 580 210 530 250 C 480 280 430 220 380 260 C 330 290 280 225 230 265 C 180 295 130 230 80 270 C 50 290 30 250 0 275 Z",
    fill: "url(#jamG)",
    filter: "url(#jamBlur)"
  }), [
  // x1, x2 define the horizontal span; depth = how far below the splat band; delay = stagger
  {
    x1: 0,
    x2: 360,
    depth: 540,
    delay: 0.05,
    dur: 2.4
  }, {
    x1: 280,
    x2: 660,
    depth: 460,
    delay: 0.45,
    dur: 2.6
  }, {
    x1: 580,
    x2: 940,
    depth: 580,
    delay: 0.20,
    dur: 2.5
  }, {
    x1: 860,
    x2: 1220,
    depth: 500,
    delay: 0.65,
    dur: 2.4
  }, {
    x1: 1140,
    x2: 1480,
    depth: 560,
    delay: 0.30,
    dur: 2.6
  }, {
    x1: 1400,
    x2: 1600,
    depth: 480,
    delay: 0.55,
    dur: 2.5
  }].map((c, i) => {
    const topY = 175;
    const bottomY = topY + c.depth;
    // wavy bottom edge — 3 peaks/valleys for irregularity
    const span = c.x2 - c.x1;
    const p1 = c.x1 + span * 0.20;
    const p2 = c.x1 + span * 0.45;
    const p3 = c.x1 + span * 0.72;
    const dip = c.depth * 0.18;
    const path = `
                  M ${c.x1} ${topY}
                  L ${c.x2} ${topY}
                  L ${c.x2} ${bottomY - dip * 0.6}
                  C ${c.x2 - 40} ${bottomY + dip * 0.4}, ${p3 + 40} ${bottomY - dip}, ${p3} ${bottomY + dip * 0.6}
                  C ${p3 - 40} ${bottomY + dip * 1.2}, ${p2 + 50} ${bottomY - dip * 0.8}, ${p2} ${bottomY + dip * 0.3}
                  C ${p2 - 50} ${bottomY + dip * 0.9}, ${p1 + 40} ${bottomY - dip * 0.5}, ${p1} ${bottomY + dip * 0.5}
                  C ${p1 - 40} ${bottomY + dip * 1.1}, ${c.x1 + 40} ${bottomY - dip * 0.3}, ${c.x1} ${bottomY - dip * 0.4}
                  Z
                `;
    return /*#__PURE__*/React.createElement("path", {
      key: i,
      className: "jam-curtain",
      d: path,
      fill: "url(#curtainG)",
      filter: "url(#jamBlur)",
      style: {
        animationDelay: `${c.delay}s`,
        animationDuration: `${c.dur}s`
      }
    });
  }))), levelUpInfo && /*#__PURE__*/React.createElement("div", {
    className: "gm-levelup" + (levelUpInfo.mode === 'audio' ? " gm-levelup-audio" : "")
  }, /*#__PURE__*/React.createElement("div", {
    className: "gm-levelup-title"
  }, "\u05E2\u05DC\u05D9\u05EA \u05E9\u05DC\u05D1", /*#__PURE__*/React.createElement("span", {
    className: "dot"
  }, "!")), /*#__PURE__*/React.createElement("div", {
    className: "gm-levelup-sub"
  }, levelUpInfo.sub), levelUpInfo.mode === 'audio' && /*#__PURE__*/React.createElement(React.Fragment, null, /*#__PURE__*/React.createElement("div", {
    className: "gm-levelup-buttons"
  }, /*#__PURE__*/React.createElement("button", {
    className: "gm-levelup-cta",
    onClick: () => {
      setAutoSpeakEnabled(true);
      // If the master sound was muted, unmute so the chosen word audio actually plays.
      if (Sound.muted) {
        Sound.setMuted(false);
        setMuted(false);
      }
      setLevelUpInfo(null);
      nextQuestion();
    }
  }, "\u05E8\u05D5\u05E6\u05D4 \u05DC\u05D4\u05DE\u05E9\u05D9\u05DA \u05E2\u05DD \u05D4\u05E9\u05DE\u05E2\u05EA \u05DE\u05D9\u05DC\u05D9\u05DD"), /*#__PURE__*/React.createElement("button", {
    className: "gm-levelup-cta secondary",
    onClick: () => {
      setAutoSpeakEnabled(false);
      setLevelUpInfo(null);
      nextQuestion();
    }
  }, "\u05E8\u05D5\u05E6\u05D4 \u05DC\u05D4\u05DE\u05E9\u05D9\u05DA \u05DC\u05DC\u05D0 \u05D4\u05E9\u05DE\u05E2\u05EA \u05DE\u05D9\u05DC\u05D9\u05DD")), /*#__PURE__*/React.createElement("div", {
    className: "gm-levelup-note"
  }, /*#__PURE__*/React.createElement("span", {
    className: "star"
  }, "*"), " \u05EA\u05DE\u05D9\u05D3 \u05E0\u05D9\u05EA\u05DF \u05DC\u05D1\u05D8\u05DC \u05D4\u05E9\u05DE\u05E2\u05EA \u05DE\u05D9\u05DC\u05D9\u05DD \u05E2\u05DD \u05DC\u05D7\u05E6\u05DF \u05D4\u05E1\u05D0\u05D5\u05E0\u05D3"))), toast && /*#__PURE__*/React.createElement("div", {
    className: "gm-toast " + toast.kind
  }, /*#__PURE__*/React.createElement("span", {
    className: "dot"
  }), toast.text), /*#__PURE__*/React.createElement("style", null, `
          @keyframes shotFly {
            from { transform: translate(-50%, -50%) translate(0, 0); opacity: 1; }
            to   { transform: translate(-50%, -50%) translate(var(--dx, 0px), var(--dy, 0px)); opacity: 1; }
          }
        `)));
}
window.Game = QuizGame;
})(); } catch (e) { __ds_ns.__errors.push({ path: "quiz-game/QuizGame.jsx", error: String((e && e.message) || e) }); }

// quiz-game/design-canvas.jsx
try { (() => {
// DesignCanvas.jsx — Figma-ish design canvas wrapper
// Warm gray grid bg + Sections + Artboards + PostIt notes.
// Artboards are reorderable (grip-drag), deletable, labels/titles are
// inline-editable, and any artboard can be opened in a fullscreen focus
// overlay (←/→/Esc). State persists to a .design-canvas.state.json sidecar
// via the host bridge. No assets, no deps.
//
// Usage:
//   <DesignCanvas>
//     <DCSection id="onboarding" title="Onboarding" subtitle="First-run variants">
//       <DCArtboard id="a" label="A · Dusk" width={260} height={480}>…</DCArtboard>
//       <DCArtboard id="b" label="B · Minimal" width={260} height={480}>…</DCArtboard>
//     </DCSection>
//   </DesignCanvas>

const DC = {
  bg: '#f0eee9',
  grid: 'rgba(0,0,0,0.06)',
  label: 'rgba(60,50,40,0.7)',
  title: 'rgba(40,30,20,0.85)',
  subtitle: 'rgba(60,50,40,0.6)',
  postitBg: '#fef4a8',
  postitText: '#5a4a2a',
  font: '-apple-system, BlinkMacSystemFont, "Segoe UI", system-ui, sans-serif'
};

// One-time CSS injection (classes are dc-prefixed so they don't collide with
// the hosted design's own styles).
if (typeof document !== 'undefined' && !document.getElementById('dc-styles')) {
  const s = document.createElement('style');
  s.id = 'dc-styles';
  s.textContent = ['.dc-editable{cursor:text;outline:none;white-space:nowrap;border-radius:3px;padding:0 2px;margin:0 -2px}', '.dc-editable:focus{background:#fff;box-shadow:0 0 0 1.5px #c96442}', '[data-dc-slot]{transition:transform .18s cubic-bezier(.2,.7,.3,1)}', '[data-dc-slot].dc-dragging{transition:none;z-index:10;pointer-events:none}', '[data-dc-slot].dc-dragging .dc-card{box-shadow:0 12px 40px rgba(0,0,0,.25),0 0 0 2px #c96442;transform:scale(1.02)}',
  // isolation:isolate contains artboard content's z-indexes so a
  // z-indexed child (sticky navbar etc.) can't paint over .dc-header or
  // the .dc-menu popover that drops into the top of the card.
  '.dc-card{isolation:isolate;transition:box-shadow .15s,transform .15s}', '.dc-card *{scrollbar-width:none}', '.dc-card *::-webkit-scrollbar{display:none}',
  // Per-artboard header: grip + label on the left, delete/expand on the
  // right. Single flex row; when the artboard's on-screen width is too
  // narrow for both the label yields (ellipsis, then hidden entirely below
  // ~4ch via the container query) and the buttons stay on the row.
  '.dc-header{position:absolute;bottom:100%;left:-4px;margin-bottom:calc(4px * var(--dc-inv-zoom,1));z-index:2;', '  display:flex;align-items:center;container-type:inline-size}', '.dc-labelrow{display:flex;align-items:center;gap:4px;height:24px;flex:1 1 auto;min-width:0}', '.dc-grip{flex:0 0 auto;cursor:grab;display:flex;align-items:center;padding:5px 4px;border-radius:4px;transition:background .12s,opacity .12s}', '.dc-grip:hover{background:rgba(0,0,0,.08)}', '.dc-grip:active{cursor:grabbing}', '.dc-labeltext{flex:1 1 auto;min-width:0;cursor:pointer;border-radius:4px;padding:3px 6px;', '  display:flex;align-items:center;transition:background .12s;overflow:hidden}',
  // Below ~4ch of label room: hide the label entirely, and drop the grip to
  // hover-only (same reveal rule as .dc-btns) so a narrow header is clean
  // until the card is moused.
  '@container (max-width: 110px){', '  .dc-labeltext{display:none}', '  .dc-grip{opacity:0}', '  [data-dc-slot]:hover .dc-grip{opacity:1}', '}', '.dc-labeltext:hover{background:rgba(0,0,0,.05)}', '.dc-labeltext .dc-editable{overflow:hidden;text-overflow:ellipsis;max-width:100%}', '.dc-labeltext .dc-editable:focus{overflow:visible;text-overflow:clip}', '.dc-btns{flex:0 0 auto;margin-left:auto;display:flex;gap:2px;opacity:0;transition:opacity .12s}', '[data-dc-slot]:hover .dc-btns,.dc-btns:has(.dc-menu){opacity:1}', '.dc-expand,.dc-kebab{width:22px;height:22px;border-radius:5px;border:none;cursor:pointer;padding:0;', '  background:transparent;color:rgba(60,50,40,.7);display:flex;align-items:center;justify-content:center;', '  font:inherit;transition:background .12s,color .12s}', '.dc-expand:hover,.dc-kebab:hover{background:rgba(0,0,0,.06);color:#2a251f}',
  // Slot hosting an open menu floats above later siblings (which otherwise
  // paint on top — same z-index:auto, later DOM order) so the popup isn't
  // clipped by the next card.
  '[data-dc-slot]:has(.dc-menu){z-index:10}', '.dc-menu{position:absolute;top:100%;right:0;margin-top:4px;background:#fff;border-radius:8px;', '  box-shadow:0 8px 28px rgba(0,0,0,.18),0 0 0 1px rgba(0,0,0,.05);padding:4px;min-width:160px;z-index:10}', '.dc-menu button{display:block;width:100%;padding:7px 10px;border:0;background:transparent;', '  border-radius:5px;font-family:inherit;font-size:13px;font-weight:500;line-height:1.2;', '  color:#29261b;cursor:pointer;text-align:left;transition:background .12s;white-space:nowrap}', '.dc-menu button:hover{background:rgba(0,0,0,.05)}', '.dc-menu hr{border:0;border-top:1px solid rgba(0,0,0,.08);margin:4px 2px}', '.dc-menu .dc-danger{color:#c96442}', '.dc-menu .dc-danger:hover{background:rgba(201,100,66,.1)}',
  // Chrome (titles / labels / buttons) counter-scales against the viewport
  // zoom so it stays a constant on-screen size. --dc-inv-zoom is set by
  // DCViewport on every transform update and inherits to all descendants —
  // any overlay inside the world (e.g. a TweaksPanel on an artboard) can use
  // it the same way.
  //
  // The header uses transform:scale (out-of-flow, so layout impact doesn't
  // matter) with its world-space width set to card-width / inv-zoom so that
  // after counter-scaling its on-screen width exactly matches the card's —
  // that's what lets the container query + text-overflow behave against the
  // card's visible edge at every zoom level.
  //
  // The section head uses CSS zoom instead of transform so its layout box
  // grows with the counter-scale, pushing the card row down — otherwise the
  // constant-screen-size title would overflow into the (shrinking) world-
  // space gap and overlap the artboard headers at low zoom.
  '.dc-header{width:calc((100% + 4px) / var(--dc-inv-zoom,1));', '  transform:scale(var(--dc-inv-zoom,1));transform-origin:bottom left}', '.dc-sectionhead{zoom:var(--dc-inv-zoom,1)}'].join('\n');
  document.head.appendChild(s);
}
const DCCtx = React.createContext(null);

// Recursively unwrap React.Fragment so <>…</> grouping doesn't hide
// DCSection/DCArtboard children from the type-based walks below.
function dcFlatten(children) {
  const out = [];
  React.Children.forEach(children, c => {
    if (c && c.type === React.Fragment) out.push(...dcFlatten(c.props.children));else out.push(c);
  });
  return out;
}

// ─────────────────────────────────────────────────────────────
// DesignCanvas — stateful wrapper around the pan/zoom viewport.
// Owns runtime state (per-section order, renamed titles/labels, hidden
// artboards, focused artboard). Order/titles/labels/hidden persist to a
// .design-canvas.state.json
// sidecar next to the HTML. Reads go via plain fetch() so the saved
// arrangement is visible anywhere the HTML + sidecar are served together
// (omelette preview, direct link, downloaded zip). Writes go through the
// host's window.omelette bridge — editing requires the omelette runtime.
// Focus is ephemeral.
// ─────────────────────────────────────────────────────────────
const DC_STATE_FILE = '.design-canvas.state.json';
function DesignCanvas({
  children,
  minScale,
  maxScale,
  style
}) {
  const [state, setState] = React.useState({
    sections: {},
    focus: null
  });
  // Hold rendering until the sidecar read settles so the saved order/titles
  // appear on first paint (no source-order flash). didRead gates writes until
  // the read settles so the empty initial state can't clobber a slow read;
  // skipNextWrite suppresses the one echo-write that would otherwise follow
  // hydration.
  const [ready, setReady] = React.useState(false);
  const didRead = React.useRef(false);
  const skipNextWrite = React.useRef(false);
  React.useEffect(() => {
    let off = false;
    fetch('./' + DC_STATE_FILE).then(r => r.ok ? r.json() : null).then(saved => {
      if (off || !saved || !saved.sections) return;
      skipNextWrite.current = true;
      setState(s => ({
        ...s,
        sections: saved.sections
      }));
    }).catch(() => {}).finally(() => {
      didRead.current = true;
      if (!off) setReady(true);
    });
    const t = setTimeout(() => {
      if (!off) setReady(true);
    }, 150);
    return () => {
      off = true;
      clearTimeout(t);
    };
  }, []);
  React.useEffect(() => {
    if (!didRead.current) return;
    if (skipNextWrite.current) {
      skipNextWrite.current = false;
      return;
    }
    const t = setTimeout(() => {
      window.omelette?.writeFile(DC_STATE_FILE, JSON.stringify({
        sections: state.sections
      })).catch(() => {});
    }, 250);
    return () => clearTimeout(t);
  }, [state.sections]);

  // Build registries synchronously from children so FocusOverlay can read
  // them in the same render. Fragments are flattened; wrapping in other
  // elements still opts out of focus/reorder.
  const registry = {}; // slotId -> { sectionId, artboard }
  const sectionMeta = {}; // sectionId -> { title, subtitle, slotIds[] }
  const sectionOrder = [];
  dcFlatten(children).forEach(sec => {
    if (!sec || sec.type !== DCSection) return;
    const sid = sec.props.id ?? sec.props.title;
    if (!sid) return;
    sectionOrder.push(sid);
    const persisted = state.sections[sid] || {};
    const abs = [];
    dcFlatten(sec.props.children).forEach(ab => {
      if (!ab || ab.type !== DCArtboard) return;
      const aid = ab.props.id ?? ab.props.label;
      if (aid) abs.push([aid, ab]);
    });
    // hidden is scoped to one source revision — when the agent regenerates
    // (artboard-ID set changes), prior deletes don't apply to new content.
    const srcKey = abs.map(([k]) => k).join('\x1f');
    const hidden = persisted.srcKey === srcKey ? persisted.hidden || [] : [];
    const srcIds = [];
    abs.forEach(([aid, ab]) => {
      if (hidden.includes(aid)) return;
      registry[`${sid}/${aid}`] = {
        sectionId: sid,
        artboard: ab
      };
      srcIds.push(aid);
    });
    const kept = (persisted.order || []).filter(k => srcIds.includes(k));
    sectionMeta[sid] = {
      title: persisted.title ?? sec.props.title,
      subtitle: sec.props.subtitle,
      slotIds: [...kept, ...srcIds.filter(k => !kept.includes(k))]
    };
  });
  const api = React.useMemo(() => ({
    state,
    section: id => state.sections[id] || {},
    patchSection: (id, p) => setState(s => ({
      ...s,
      sections: {
        ...s.sections,
        [id]: {
          ...s.sections[id],
          ...(typeof p === 'function' ? p(s.sections[id] || {}) : p)
        }
      }
    })),
    setFocus: slotId => setState(s => ({
      ...s,
      focus: slotId
    }))
  }), [state]);

  // Esc exits focus; any outside pointerdown commits an in-progress rename.
  React.useEffect(() => {
    const onKey = e => {
      if (e.key === 'Escape') api.setFocus(null);
    };
    const onPd = e => {
      const ae = document.activeElement;
      if (ae && ae.isContentEditable && !ae.contains(e.target)) ae.blur();
    };
    document.addEventListener('keydown', onKey);
    document.addEventListener('pointerdown', onPd, true);
    return () => {
      document.removeEventListener('keydown', onKey);
      document.removeEventListener('pointerdown', onPd, true);
    };
  }, [api]);
  return /*#__PURE__*/React.createElement(DCCtx.Provider, {
    value: api
  }, /*#__PURE__*/React.createElement(DCViewport, {
    minScale: minScale,
    maxScale: maxScale,
    style: style
  }, ready && children), state.focus && registry[state.focus] && /*#__PURE__*/React.createElement(DCFocusOverlay, {
    entry: registry[state.focus],
    sectionMeta: sectionMeta,
    sectionOrder: sectionOrder
  }));
}

// ─────────────────────────────────────────────────────────────
// DCViewport — transform-based pan/zoom (internal)
//
// Input mapping (Figma-style):
//   • trackpad pinch  → zoom   (ctrlKey wheel; Safari gesture* events)
//   • trackpad scroll → pan    (two-finger)
//   • mouse wheel     → zoom   (notched; distinguished from trackpad scroll)
//   • middle-drag / primary-drag-on-bg → pan
//
// Transform state lives in a ref and is written straight to the DOM
// (translate3d + will-change) so wheel ticks don't go through React —
// keeps pans at 60fps on dense canvases.
// ─────────────────────────────────────────────────────────────
function DCViewport({
  children,
  minScale = 0.1,
  maxScale = 8,
  style = {}
}) {
  const vpRef = React.useRef(null);
  const worldRef = React.useRef(null);
  const tf = React.useRef({
    x: 0,
    y: 0,
    scale: 1
  });
  // Persist viewport across reloads so the user lands back where they were
  // after an agent edit or browser refresh. The sandbox origin is already
  // per-project; pathname keeps multiple canvas files in one project apart.
  const tfKey = 'dc-viewport:' + location.pathname;
  const saveT = React.useRef(0);
  const lastPostedScale = React.useRef();
  const apply = React.useCallback(() => {
    const {
      x,
      y,
      scale
    } = tf.current;
    const el = worldRef.current;
    if (!el) return;
    el.style.transform = `translate3d(${x}px, ${y}px, 0) scale(${scale})`;
    // Exposed for zoom-invariant chrome (labels, buttons, TweaksPanel).
    el.style.setProperty('--dc-inv-zoom', String(1 / scale));
    // Keep the host toolbar's % readout in sync with the canvas scale. Pan
    // ticks leave scale unchanged — skip the cross-frame post for those.
    if (lastPostedScale.current !== scale) {
      lastPostedScale.current = scale;
      window.parent.postMessage({
        type: '__dc_zoom',
        scale
      }, '*');
    }
    clearTimeout(saveT.current);
    saveT.current = setTimeout(() => {
      try {
        localStorage.setItem(tfKey, JSON.stringify(tf.current));
      } catch {}
    }, 200);
  }, [tfKey]);
  React.useLayoutEffect(() => {
    const flush = () => {
      clearTimeout(saveT.current);
      try {
        localStorage.setItem(tfKey, JSON.stringify(tf.current));
      } catch {}
    };
    try {
      const s = JSON.parse(localStorage.getItem(tfKey) || 'null');
      if (s && Number.isFinite(s.x) && Number.isFinite(s.y) && Number.isFinite(s.scale)) {
        tf.current = {
          x: s.x,
          y: s.y,
          scale: Math.min(maxScale, Math.max(minScale, s.scale))
        };
        apply();
      }
    } catch {}
    // Flush on pagehide and unmount so a reload within the 200ms debounce
    // window doesn't drop the last pan/zoom.
    window.addEventListener('pagehide', flush);
    return () => {
      window.removeEventListener('pagehide', flush);
      flush();
    };
  }, []);
  React.useEffect(() => {
    const vp = vpRef.current;
    if (!vp) return;
    const zoomAt = (cx, cy, factor) => {
      const r = vp.getBoundingClientRect();
      const px = cx - r.left,
        py = cy - r.top;
      const t = tf.current;
      const next = Math.min(maxScale, Math.max(minScale, t.scale * factor));
      const k = next / t.scale;
      // --dc-inv-zoom consumers (.dc-sectionhead's CSS zoom, each section's
      // marginBottom) reflow on every scale change, vertically shifting the
      // world layout — so a world point mathematically pinned under the cursor
      // drifts as you zoom (content creeps up on zoom-in, down on zoom-out).
      // Anchor the DOM element under the cursor instead: record its screen Y,
      // apply the transform + --dc-inv-zoom, then cancel whatever vertical
      // drift the reflow introduced so it stays put on screen.
      let marker = null,
        markerY0 = 0;
      if (k !== 1) {
        const hit = document.elementFromPoint(cx, cy);
        marker = hit && hit.closest ? hit.closest('[data-dc-slot],[data-dc-section]') : null;
        if (marker) markerY0 = marker.getBoundingClientRect().top;
      }
      // keep the world point under the cursor fixed
      t.x = px - (px - t.x) * k;
      t.y = py - (py - t.y) * k;
      t.scale = next;
      apply();
      if (marker) {
        // A pure zoom around (cx, cy) maps screen Y → cy + (Y - cy) * k. Any
        // departure after the --dc-inv-zoom reflow is the layout drift.
        const drift = marker.getBoundingClientRect().top - (cy + (markerY0 - cy) * k);
        if (Math.abs(drift) > 0.1) {
          t.y -= drift;
          apply();
        }
      }
    };

    // Mouse-wheel vs trackpad-scroll heuristic. A physical wheel sends
    // line-mode deltas (Firefox) or large integer pixel deltas with no X
    // component (Chrome/Safari, typically multiples of 100/120). Trackpad
    // two-finger scroll sends small/fractional pixel deltas, often with
    // non-zero deltaX. ctrlKey is set by the browser for trackpad pinch.
    const isMouseWheel = e => e.deltaMode !== 0 || e.deltaX === 0 && Number.isInteger(e.deltaY) && Math.abs(e.deltaY) >= 40;
    const onWheel = e => {
      e.preventDefault();
      if (isGesturing) return; // Safari: gesture* owns the pinch — discard concurrent wheels
      if ((e.ctrlKey || e.metaKey) && !isMouseWheel(e)) {
        // trackpad pinch, or ctrl/cmd + smooth-scroll mouse. Notched
        // wheels fall through to the fixed-step branch below.
        zoomAt(e.clientX, e.clientY, Math.exp(-e.deltaY * 0.01));
      } else if (isMouseWheel(e)) {
        // notched mouse wheel — fixed-ratio step per click
        zoomAt(e.clientX, e.clientY, Math.exp(-Math.sign(e.deltaY) * 0.18));
      } else {
        // trackpad two-finger scroll — pan
        tf.current.x -= e.deltaX;
        tf.current.y -= e.deltaY;
        apply();
      }
    };

    // Safari sends native gesture* events for trackpad pinch with a smooth
    // e.scale; preferring these over the ctrl+wheel fallback gives a much
    // better feel there. No-ops on other browsers. Safari also fires
    // ctrlKey wheel events during the same pinch — isGesturing makes
    // onWheel drop those entirely so they neither zoom nor pan.
    let gsBase = 1;
    let isGesturing = false;
    const onGestureStart = e => {
      e.preventDefault();
      isGesturing = true;
      gsBase = tf.current.scale;
    };
    const onGestureChange = e => {
      e.preventDefault();
      zoomAt(e.clientX, e.clientY, gsBase * e.scale / tf.current.scale);
    };
    const onGestureEnd = e => {
      e.preventDefault();
      isGesturing = false;
    };

    // Drag-pan: middle button anywhere, or primary button on canvas
    // background (anything that isn't an artboard or an inline editor).
    let drag = null;
    const onPointerDown = e => {
      const onBg = !e.target.closest('[data-dc-slot], .dc-editable');
      if (!(e.button === 1 || e.button === 0 && onBg)) return;
      e.preventDefault();
      vp.setPointerCapture(e.pointerId);
      drag = {
        id: e.pointerId,
        lx: e.clientX,
        ly: e.clientY
      };
      vp.style.cursor = 'grabbing';
    };
    const onPointerMove = e => {
      if (!drag || e.pointerId !== drag.id) return;
      tf.current.x += e.clientX - drag.lx;
      tf.current.y += e.clientY - drag.ly;
      drag.lx = e.clientX;
      drag.ly = e.clientY;
      apply();
    };
    const onPointerUp = e => {
      if (!drag || e.pointerId !== drag.id) return;
      vp.releasePointerCapture(e.pointerId);
      drag = null;
      vp.style.cursor = '';
    };

    // Host-driven zoom (toolbar % menu). Zooms around viewport centre so the
    // visible midpoint stays fixed — matching the host's iframe-zoom feel.
    const onHostMsg = e => {
      const d = e.data;
      if (d && d.type === '__dc_set_zoom' && typeof d.scale === 'number') {
        const r = vp.getBoundingClientRect();
        zoomAt(r.left + r.width / 2, r.top + r.height / 2, d.scale / tf.current.scale);
      } else if (d && d.type === '__dc_probe') {
        // Host's [readyGen] reset asks whether a canvas is present; it
        // fires on the iframe's native 'load', which for canvases with
        // images/fonts is after our mount-time announce, so re-announce.
        // Clear the pan-tick guard so apply() re-posts the current scale
        // even if it's unchanged — the host just reset dcScale to 1.
        window.parent.postMessage({
          type: '__dc_present'
        }, '*');
        lastPostedScale.current = undefined;
        apply();
      }
    };
    window.addEventListener('message', onHostMsg);
    // Announce canvas mode so the host toolbar proxies its % control here
    // instead of scaling the iframe element (which would just shrink the
    // viewport window of an infinite canvas). The apply() that follows emits
    // the initial __dc_zoom so the toolbar % is correct before first pinch.
    // lastPostedScale reset mirrors the __dc_probe handler: the layout
    // effect's restore-path apply() may already have posted the restored
    // scale (before __dc_present), so clear the guard to re-post it in order.
    window.parent.postMessage({
      type: '__dc_present'
    }, '*');
    lastPostedScale.current = undefined;
    apply();
    vp.addEventListener('wheel', onWheel, {
      passive: false
    });
    vp.addEventListener('gesturestart', onGestureStart, {
      passive: false
    });
    vp.addEventListener('gesturechange', onGestureChange, {
      passive: false
    });
    vp.addEventListener('gestureend', onGestureEnd, {
      passive: false
    });
    vp.addEventListener('pointerdown', onPointerDown);
    vp.addEventListener('pointermove', onPointerMove);
    vp.addEventListener('pointerup', onPointerUp);
    vp.addEventListener('pointercancel', onPointerUp);
    return () => {
      window.removeEventListener('message', onHostMsg);
      vp.removeEventListener('wheel', onWheel);
      vp.removeEventListener('gesturestart', onGestureStart);
      vp.removeEventListener('gesturechange', onGestureChange);
      vp.removeEventListener('gestureend', onGestureEnd);
      vp.removeEventListener('pointerdown', onPointerDown);
      vp.removeEventListener('pointermove', onPointerMove);
      vp.removeEventListener('pointerup', onPointerUp);
      vp.removeEventListener('pointercancel', onPointerUp);
    };
  }, [apply, minScale, maxScale]);
  const gridSvg = `url("data:image/svg+xml,%3Csvg width='120' height='120' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath d='M120 0H0v120' fill='none' stroke='${encodeURIComponent(DC.grid)}' stroke-width='1'/%3E%3C/svg%3E")`;
  return /*#__PURE__*/React.createElement("div", {
    ref: vpRef,
    className: "design-canvas",
    style: {
      height: '100vh',
      width: '100vw',
      background: DC.bg,
      overflow: 'hidden',
      overscrollBehavior: 'none',
      touchAction: 'none',
      position: 'relative',
      fontFamily: DC.font,
      boxSizing: 'border-box',
      ...style
    }
  }, /*#__PURE__*/React.createElement("div", {
    ref: worldRef,
    style: {
      position: 'absolute',
      top: 0,
      left: 0,
      transformOrigin: '0 0',
      willChange: 'transform',
      width: 'max-content',
      minWidth: '100%',
      minHeight: '100%',
      padding: '60px 0 80px'
    }
  }, /*#__PURE__*/React.createElement("div", {
    style: {
      position: 'absolute',
      inset: -6000,
      backgroundImage: gridSvg,
      backgroundSize: '120px 120px',
      pointerEvents: 'none',
      zIndex: -1
    }
  }), children));
}

// ─────────────────────────────────────────────────────────────
// DCSection — editable title + h-row of artboards in persisted order
// ─────────────────────────────────────────────────────────────
function DCSection({
  id,
  title,
  subtitle,
  children,
  gap = 48
}) {
  const ctx = React.useContext(DCCtx);
  const sid = id ?? title;
  const all = React.Children.toArray(dcFlatten(children));
  const artboards = all.filter(c => c && c.type === DCArtboard);
  const rest = all.filter(c => !(c && c.type === DCArtboard));
  const sec = ctx && sid && ctx.section(sid) || {};
  // Must match DesignCanvas's srcKey computation exactly (it filters falsy
  // IDs), or onDelete persists a srcKey that DesignCanvas never recognizes.
  const allIds = artboards.map(a => a.props.id ?? a.props.label).filter(Boolean);
  const srcKey = allIds.join('\x1f');
  const hidden = sec.srcKey === srcKey ? sec.hidden || [] : [];
  const srcOrder = allIds.filter(k => !hidden.includes(k));
  const order = React.useMemo(() => {
    const kept = (sec.order || []).filter(k => srcOrder.includes(k));
    return [...kept, ...srcOrder.filter(k => !kept.includes(k))];
  }, [sec.order, srcOrder.join('|')]);
  const byId = Object.fromEntries(artboards.map(a => [a.props.id ?? a.props.label, a]));

  // marginBottom counter-scales so the on-screen gap between sections stays
  // constant — otherwise at low zoom the (world-space) gap collapses while
  // the screen-constant sectionhead below it doesn't, and the title reads as
  // belonging to the section above. paddingBottom below is just enough for
  // the 24px artboard-header (abs-positioned above each card) plus ~8px, so
  // the title sits tight against its own row at every zoom.
  return /*#__PURE__*/React.createElement("div", {
    "data-dc-section": sid,
    style: {
      marginBottom: 'calc(80px * var(--dc-inv-zoom, 1))',
      position: 'relative'
    }
  }, /*#__PURE__*/React.createElement("div", {
    style: {
      padding: '0 60px'
    }
  }, /*#__PURE__*/React.createElement("div", {
    className: "dc-sectionhead",
    style: {
      paddingBottom: 36
    }
  }, /*#__PURE__*/React.createElement(DCEditable, {
    tag: "div",
    value: sec.title ?? title,
    onChange: v => ctx && sid && ctx.patchSection(sid, {
      title: v
    }),
    style: {
      fontSize: 28,
      fontWeight: 600,
      color: DC.title,
      letterSpacing: -0.4,
      marginBottom: 6,
      display: 'inline-block'
    }
  }), subtitle && /*#__PURE__*/React.createElement("div", {
    style: {
      fontSize: 16,
      color: DC.subtitle
    }
  }, subtitle))), /*#__PURE__*/React.createElement("div", {
    style: {
      display: 'flex',
      gap,
      padding: '0 60px',
      alignItems: 'flex-start',
      width: 'max-content'
    }
  }, order.map(k => /*#__PURE__*/React.createElement(DCArtboardFrame, {
    key: k,
    sectionId: sid,
    artboard: byId[k],
    order: order,
    label: (sec.labels || {})[k] ?? byId[k].props.label,
    onRename: v => ctx && ctx.patchSection(sid, x => ({
      labels: {
        ...x.labels,
        [k]: v
      }
    })),
    onReorder: next => ctx && ctx.patchSection(sid, {
      order: next
    }),
    onDelete: () => ctx && ctx.patchSection(sid, x => ({
      hidden: [...(x.srcKey === srcKey ? x.hidden || [] : []), k],
      srcKey
    })),
    onFocus: () => ctx && ctx.setFocus(`${sid}/${k}`)
  }))), rest);
}

// DCArtboard — marker; rendered by DCArtboardFrame via DCSection.
function DCArtboard() {
  return null;
}

// Per-artboard export (kind: 'png' | 'html'). Both paths share the same
// self-contained clone: computed styles baked in, @font-face / <img> /
// inline-style background-image urls inlined as data URIs. PNG wraps the
// clone in foreignObject→canvas at 3× the artboard's natural width×height
// (same pipeline the host uses for page captures); HTML wraps it in a
// minimal standalone document. Both are independent of viewport zoom.
async function dcExport(node, w, h, name, kind) {
  try {
    await document.fonts.ready;
  } catch {}
  const toDataURL = url => fetch(url).then(r => r.blob()).then(b => new Promise(res => {
    const fr = new FileReader();
    fr.onload = () => res(fr.result);
    fr.onerror = () => res(url);
    fr.readAsDataURL(b);
  })).catch(() => url);

  // Collect @font-face rules. ss.cssRules throws SecurityError on
  // cross-origin sheets (e.g. fonts.googleapis.com) — in that case fetch
  // the CSS text directly (those endpoints send ACAO:*) and regex-extract
  // the blocks. @import and @media/@supports are walked so nested
  // @font-face rules aren't missed.
  const fontRules = [],
    pending = [],
    seen = new Set();
  const scrapeCss = href => {
    if (seen.has(href)) return;
    seen.add(href);
    pending.push(fetch(href).then(r => r.text()).then(css => {
      for (const m of css.match(/@font-face\s*{[^}]*}/g) || []) fontRules.push({
        css: m,
        base: href
      });
      for (const m of css.matchAll(/@import\s+(?:url\()?['"]?([^'")\s;]+)/g)) scrapeCss(new URL(m[1], href).href);
    }).catch(() => {}));
  };
  const walk = (rules, base) => {
    for (const r of rules) {
      if (r.type === CSSRule.FONT_FACE_RULE) fontRules.push({
        css: r.cssText,
        base
      });else if (r.type === CSSRule.IMPORT_RULE && r.styleSheet) {
        const ibase = r.styleSheet.href || base;
        try {
          walk(r.styleSheet.cssRules, ibase);
        } catch {
          scrapeCss(ibase);
        }
      } else if (r.cssRules) walk(r.cssRules, base);
    }
  };
  for (const ss of document.styleSheets) {
    const base = ss.href || location.href;
    try {
      walk(ss.cssRules, base);
    } catch {
      if (ss.href) scrapeCss(ss.href);
    }
  }
  while (pending.length) await pending.shift();
  const fontCss = (await Promise.all(fontRules.map(async rule => {
    let out = rule.css,
      m;
    const re = /url\((['"]?)([^'")]+)\1\)/g;
    while (m = re.exec(rule.css)) {
      if (m[2].indexOf('data:') === 0) continue;
      let abs;
      try {
        abs = new URL(m[2], rule.base).href;
      } catch {
        continue;
      }
      out = out.split(m[0]).join('url("' + (await toDataURL(abs)) + '")');
    }
    return out;
  }))).join('\n');
  const cloneStyled = src => {
    if (src.nodeType === 8 || src.nodeType === 1 && src.tagName === 'SCRIPT') return document.createTextNode('');
    const dst = src.cloneNode(false);
    if (src.nodeType === 1) {
      const cs = getComputedStyle(src);
      let txt = '';
      for (let i = 0; i < cs.length; i++) txt += cs[i] + ':' + cs.getPropertyValue(cs[i]) + ';';
      dst.setAttribute('style', txt + 'animation:none;transition:none;');
      if (src.tagName === 'CANVAS') try {
        const im = document.createElement('img');
        im.src = src.toDataURL();
        im.setAttribute('style', txt);
        return im;
      } catch {}
    }
    for (let c = src.firstChild; c; c = c.nextSibling) dst.appendChild(cloneStyled(c));
    return dst;
  };
  const clone = cloneStyled(node);
  clone.setAttribute('xmlns', 'http://www.w3.org/1999/xhtml');
  // Drop the card's own shadow/radius so the export is a flush w×h rect;
  // the artboard's own background (if any) is already in the computed style.
  clone.style.boxShadow = 'none';
  clone.style.borderRadius = '0';
  const jobs = [];
  clone.querySelectorAll('img').forEach(el => {
    const s = el.getAttribute('src');
    if (s && s.indexOf('data:') !== 0) jobs.push(toDataURL(el.src).then(d => el.setAttribute('src', d)));
  });
  [clone, ...clone.querySelectorAll('*')].forEach(el => {
    const bg = el.style.backgroundImage;
    if (!bg) return;
    let m;
    const re = /url\(["']?([^"')]+)["']?\)/g;
    while (m = re.exec(bg)) {
      const tok = m[0],
        url = m[1];
      if (url.indexOf('data:') === 0) continue;
      jobs.push(toDataURL(url).then(d => {
        el.style.backgroundImage = el.style.backgroundImage.split(tok).join('url("' + d + '")');
      }));
    }
  });
  await Promise.all(jobs);
  const xml = new XMLSerializer().serializeToString(clone);
  const save = (blob, ext) => {
    if (!blob) return;
    const a = document.createElement('a');
    a.href = URL.createObjectURL(blob);
    a.download = name + '.' + ext;
    a.click();
    setTimeout(() => URL.revokeObjectURL(a.href), 1000);
  };
  if (kind === 'html') {
    const html = '<!doctype html><html><head><meta charset="utf-8"><title>' + name + '</title>' + (fontCss ? '<style>' + fontCss + '</style>' : '') + '</head><body style="margin:0">' + xml + '</body></html>';
    return save(new Blob([html], {
      type: 'text/html'
    }), 'html');
  }

  // PNG: the SVG's own width/height must be the output resolution — an
  // <img>-loaded SVG rasterizes at its intrinsic size, so sizing it at 1×
  // and ctx.scale()-ing up would just upscale a 1× bitmap. viewBox maps the
  // w×h foreignObject onto the px·w × px·h SVG canvas so the browser renders
  // the HTML at full resolution.
  const px = 3;
  const svg = '<svg xmlns="http://www.w3.org/2000/svg" width="' + w * px + '" height="' + h * px + '" viewBox="0 0 ' + w + ' ' + h + '"><foreignObject width="' + w + '" height="' + h + '">' + (fontCss ? '<style><![CDATA[' + fontCss + ']]></style>' : '') + xml + '</foreignObject></svg>';
  const img = new Image();
  await new Promise((res, rej) => {
    img.onload = res;
    img.onerror = () => rej(new Error('svg load failed'));
    img.src = 'data:image/svg+xml;charset=utf-8,' + encodeURIComponent(svg);
  });
  const cv = document.createElement('canvas');
  cv.width = w * px;
  cv.height = h * px;
  cv.getContext('2d').drawImage(img, 0, 0);
  cv.toBlob(blob => save(blob, 'png'), 'image/png');
}
function DCArtboardFrame({
  sectionId,
  artboard,
  label,
  order,
  onRename,
  onReorder,
  onFocus,
  onDelete
}) {
  const {
    id: rawId,
    label: rawLabel,
    width = 260,
    height = 480,
    children,
    style = {}
  } = artboard.props;
  const id = rawId ?? rawLabel;
  const ref = React.useRef(null);
  const cardRef = React.useRef(null);
  const menuRef = React.useRef(null);
  const [menuOpen, setMenuOpen] = React.useState(false);
  const [confirming, setConfirming] = React.useState(false);

  // ⋯ menu: close on any outside pointerdown. Two-click delete lives inside
  // the menu — first click arms the row, second commits; closing disarms.
  React.useEffect(() => {
    if (!menuOpen) {
      setConfirming(false);
      return;
    }
    const off = e => {
      if (!menuRef.current || !menuRef.current.contains(e.target)) setMenuOpen(false);
    };
    document.addEventListener('pointerdown', off, true);
    return () => document.removeEventListener('pointerdown', off, true);
  }, [menuOpen]);
  const doExport = kind => {
    setMenuOpen(false);
    if (!cardRef.current) return;
    const name = String(label || id || 'artboard').replace(/[^\w\s.-]+/g, '_');
    dcExport(cardRef.current, width, height, name, kind).catch(e => console.error('[design-canvas] export failed:', e));
  };

  // Live drag-reorder: dragged card sticks to cursor; siblings slide into
  // their would-be slots in real time via transforms. DOM order only
  // changes on drop.
  const onGripDown = e => {
    e.preventDefault();
    e.stopPropagation();
    const me = ref.current;
    // translateX is applied in local (pre-scale) space but pointer deltas and
    // getBoundingClientRect().left are screen-space — divide by the viewport's
    // current scale so the dragged card tracks the cursor at any zoom level.
    const scale = me.getBoundingClientRect().width / me.offsetWidth || 1;
    const peers = Array.from(document.querySelectorAll(`[data-dc-section="${sectionId}"] [data-dc-slot]`));
    const homes = peers.map(el => ({
      el,
      id: el.dataset.dcSlot,
      x: el.getBoundingClientRect().left
    }));
    const slotXs = homes.map(h => h.x);
    const startIdx = order.indexOf(id);
    const startX = e.clientX;
    let liveOrder = order.slice();
    me.classList.add('dc-dragging');
    const layout = () => {
      for (const h of homes) {
        if (h.id === id) continue;
        const slot = liveOrder.indexOf(h.id);
        h.el.style.transform = `translateX(${(slotXs[slot] - h.x) / scale}px)`;
      }
    };
    const move = ev => {
      const dx = ev.clientX - startX;
      me.style.transform = `translateX(${dx / scale}px)`;
      const cur = homes[startIdx].x + dx;
      let nearest = 0,
        best = Infinity;
      for (let i = 0; i < slotXs.length; i++) {
        const d = Math.abs(slotXs[i] - cur);
        if (d < best) {
          best = d;
          nearest = i;
        }
      }
      if (liveOrder.indexOf(id) !== nearest) {
        liveOrder = order.filter(k => k !== id);
        liveOrder.splice(nearest, 0, id);
        layout();
      }
    };
    const up = () => {
      document.removeEventListener('pointermove', move);
      document.removeEventListener('pointerup', up);
      const finalSlot = liveOrder.indexOf(id);
      me.classList.remove('dc-dragging');
      me.style.transform = `translateX(${(slotXs[finalSlot] - homes[startIdx].x) / scale}px)`;
      // After the settle transition, kill transitions + clear transforms +
      // commit the reorder in the same frame so there's no visual snap-back.
      setTimeout(() => {
        for (const h of homes) {
          h.el.style.transition = 'none';
          h.el.style.transform = '';
        }
        if (liveOrder.join('|') !== order.join('|')) onReorder(liveOrder);
        requestAnimationFrame(() => requestAnimationFrame(() => {
          for (const h of homes) h.el.style.transition = '';
        }));
      }, 180);
    };
    document.addEventListener('pointermove', move);
    document.addEventListener('pointerup', up);
  };
  return /*#__PURE__*/React.createElement("div", {
    ref: ref,
    "data-dc-slot": id,
    style: {
      position: 'relative',
      flexShrink: 0
    }
  }, /*#__PURE__*/React.createElement("div", {
    className: "dc-header",
    "data-noncommentable": "",
    style: {
      color: DC.label
    },
    onPointerDown: e => e.stopPropagation()
  }, /*#__PURE__*/React.createElement("div", {
    className: "dc-labelrow"
  }, /*#__PURE__*/React.createElement("div", {
    className: "dc-grip",
    onPointerDown: onGripDown,
    title: "Drag to reorder"
  }, /*#__PURE__*/React.createElement("svg", {
    width: "9",
    height: "13",
    viewBox: "0 0 9 13",
    fill: "currentColor"
  }, /*#__PURE__*/React.createElement("circle", {
    cx: "2",
    cy: "2",
    r: "1.1"
  }), /*#__PURE__*/React.createElement("circle", {
    cx: "7",
    cy: "2",
    r: "1.1"
  }), /*#__PURE__*/React.createElement("circle", {
    cx: "2",
    cy: "6.5",
    r: "1.1"
  }), /*#__PURE__*/React.createElement("circle", {
    cx: "7",
    cy: "6.5",
    r: "1.1"
  }), /*#__PURE__*/React.createElement("circle", {
    cx: "2",
    cy: "11",
    r: "1.1"
  }), /*#__PURE__*/React.createElement("circle", {
    cx: "7",
    cy: "11",
    r: "1.1"
  }))), /*#__PURE__*/React.createElement("div", {
    className: "dc-labeltext",
    onClick: onFocus,
    title: "Click to focus"
  }, /*#__PURE__*/React.createElement(DCEditable, {
    value: label,
    onChange: onRename,
    onClick: e => e.stopPropagation(),
    style: {
      fontSize: 15,
      fontWeight: 500,
      color: DC.label,
      lineHeight: 1
    }
  }))), /*#__PURE__*/React.createElement("div", {
    className: "dc-btns"
  }, /*#__PURE__*/React.createElement("div", {
    ref: menuRef,
    style: {
      position: 'relative'
    }
  }, /*#__PURE__*/React.createElement("button", {
    className: "dc-kebab",
    title: "More",
    onClick: () => setMenuOpen(o => !o)
  }, /*#__PURE__*/React.createElement("svg", {
    width: "12",
    height: "12",
    viewBox: "0 0 12 12",
    fill: "currentColor"
  }, /*#__PURE__*/React.createElement("circle", {
    cx: "2.5",
    cy: "6",
    r: "1.1"
  }), /*#__PURE__*/React.createElement("circle", {
    cx: "6",
    cy: "6",
    r: "1.1"
  }), /*#__PURE__*/React.createElement("circle", {
    cx: "9.5",
    cy: "6",
    r: "1.1"
  }))), menuOpen && /*#__PURE__*/React.createElement("div", {
    className: "dc-menu",
    onPointerDown: e => e.stopPropagation()
  }, /*#__PURE__*/React.createElement("button", {
    onClick: () => doExport('png')
  }, "Download PNG"), /*#__PURE__*/React.createElement("button", {
    onClick: () => doExport('html')
  }, "Download HTML"), /*#__PURE__*/React.createElement("hr", null), /*#__PURE__*/React.createElement("button", {
    className: "dc-danger",
    onClick: () => {
      if (confirming) {
        setMenuOpen(false);
        onDelete();
      } else setConfirming(true);
    }
  }, confirming ? 'Click again to delete' : 'Delete'))), /*#__PURE__*/React.createElement("button", {
    className: "dc-expand",
    onClick: onFocus,
    title: "Focus"
  }, /*#__PURE__*/React.createElement("svg", {
    width: "12",
    height: "12",
    viewBox: "0 0 12 12",
    fill: "none",
    stroke: "currentColor",
    strokeWidth: "1.6",
    strokeLinecap: "round"
  }, /*#__PURE__*/React.createElement("path", {
    d: "M7 1h4v4M5 11H1V7M11 1L7.5 4.5M1 11l3.5-3.5"
  }))))), /*#__PURE__*/React.createElement("div", {
    ref: cardRef,
    className: "dc-card",
    style: {
      borderRadius: 2,
      boxShadow: '0 1px 3px rgba(0,0,0,.08),0 4px 16px rgba(0,0,0,.06)',
      overflow: 'hidden',
      width,
      height,
      background: '#fff',
      ...style
    }
  }, children || /*#__PURE__*/React.createElement("div", {
    style: {
      height: '100%',
      display: 'flex',
      alignItems: 'center',
      justifyContent: 'center',
      color: '#bbb',
      fontSize: 13,
      fontFamily: DC.font
    }
  }, id)));
}

// Inline rename — commits on blur or Enter.
function DCEditable({
  value,
  onChange,
  style,
  tag = 'span',
  onClick
}) {
  const T = tag;
  return /*#__PURE__*/React.createElement(T, {
    className: "dc-editable",
    contentEditable: true,
    suppressContentEditableWarning: true,
    onClick: onClick,
    onPointerDown: e => e.stopPropagation(),
    onBlur: e => onChange && onChange(e.currentTarget.textContent),
    onKeyDown: e => {
      if (e.key === 'Enter') {
        e.preventDefault();
        e.currentTarget.blur();
      }
    },
    style: style
  }, value);
}

// ─────────────────────────────────────────────────────────────
// Focus mode — overlay one artboard; ←/→ within section, ↑/↓ across
// sections, Esc or backdrop click to exit.
// ─────────────────────────────────────────────────────────────
function DCFocusOverlay({
  entry,
  sectionMeta,
  sectionOrder
}) {
  const ctx = React.useContext(DCCtx);
  const {
    sectionId,
    artboard
  } = entry;
  const sec = ctx.section(sectionId);
  const meta = sectionMeta[sectionId];
  const peers = meta.slotIds;
  const aid = artboard.props.id ?? artboard.props.label;
  const idx = peers.indexOf(aid);
  const secIdx = sectionOrder.indexOf(sectionId);
  const go = d => {
    const n = peers[(idx + d + peers.length) % peers.length];
    if (n) ctx.setFocus(`${sectionId}/${n}`);
  };
  const goSection = d => {
    // Sections whose artboards are all deleted have slotIds:[] — step past
    // them to the next non-empty section so ↑/↓ doesn't dead-end.
    const n = sectionOrder.length;
    for (let i = 1; i < n; i++) {
      const ns = sectionOrder[((secIdx + d * i) % n + n) % n];
      const first = sectionMeta[ns] && sectionMeta[ns].slotIds[0];
      if (first) {
        ctx.setFocus(`${ns}/${first}`);
        return;
      }
    }
  };
  React.useEffect(() => {
    const k = e => {
      if (e.key === 'ArrowLeft') {
        e.preventDefault();
        go(-1);
      }
      if (e.key === 'ArrowRight') {
        e.preventDefault();
        go(1);
      }
      if (e.key === 'ArrowUp') {
        e.preventDefault();
        goSection(-1);
      }
      if (e.key === 'ArrowDown') {
        e.preventDefault();
        goSection(1);
      }
    };
    document.addEventListener('keydown', k);
    return () => document.removeEventListener('keydown', k);
  });
  const {
    width = 260,
    height = 480,
    children
  } = artboard.props;
  const [vp, setVp] = React.useState({
    w: window.innerWidth,
    h: window.innerHeight
  });
  React.useEffect(() => {
    const r = () => setVp({
      w: window.innerWidth,
      h: window.innerHeight
    });
    window.addEventListener('resize', r);
    return () => window.removeEventListener('resize', r);
  }, []);
  const scale = Math.max(0.1, Math.min((vp.w - 200) / width, (vp.h - 260) / height, 2));
  const [ddOpen, setDd] = React.useState(false);
  const Arrow = ({
    dir,
    onClick
  }) => /*#__PURE__*/React.createElement("button", {
    onClick: e => {
      e.stopPropagation();
      onClick();
    },
    style: {
      position: 'absolute',
      top: '50%',
      [dir]: 28,
      transform: 'translateY(-50%)',
      border: 'none',
      background: 'rgba(255,255,255,.08)',
      color: 'rgba(255,255,255,.9)',
      width: 44,
      height: 44,
      borderRadius: 22,
      fontSize: 18,
      cursor: 'pointer',
      display: 'flex',
      alignItems: 'center',
      justifyContent: 'center',
      transition: 'background .15s'
    },
    onMouseEnter: e => e.currentTarget.style.background = 'rgba(255,255,255,.18)',
    onMouseLeave: e => e.currentTarget.style.background = 'rgba(255,255,255,.08)'
  }, /*#__PURE__*/React.createElement("svg", {
    width: "18",
    height: "18",
    viewBox: "0 0 18 18",
    fill: "none",
    stroke: "currentColor",
    strokeWidth: "2",
    strokeLinecap: "round"
  }, /*#__PURE__*/React.createElement("path", {
    d: dir === 'left' ? 'M11 3L5 9l6 6' : 'M7 3l6 6-6 6'
  })));

  // Portal to body so position:fixed is the real viewport regardless of any
  // transform on DesignCanvas's ancestors (including the canvas zoom itself).
  return ReactDOM.createPortal(/*#__PURE__*/React.createElement("div", {
    onClick: () => ctx.setFocus(null),
    onWheel: e => e.preventDefault(),
    style: {
      position: 'fixed',
      inset: 0,
      zIndex: 100,
      background: 'rgba(24,20,16,.6)',
      backdropFilter: 'blur(14px)',
      fontFamily: DC.font,
      color: '#fff'
    }
  }, /*#__PURE__*/React.createElement("div", {
    onClick: e => e.stopPropagation(),
    style: {
      position: 'absolute',
      top: 0,
      left: 0,
      right: 0,
      height: 72,
      display: 'flex',
      alignItems: 'flex-start',
      padding: '16px 20px 0',
      gap: 16
    }
  }, /*#__PURE__*/React.createElement("div", {
    style: {
      position: 'relative'
    }
  }, /*#__PURE__*/React.createElement("button", {
    onClick: () => setDd(o => !o),
    style: {
      border: 'none',
      background: 'transparent',
      color: '#fff',
      cursor: 'pointer',
      padding: '6px 8px',
      borderRadius: 6,
      textAlign: 'left',
      fontFamily: 'inherit'
    }
  }, /*#__PURE__*/React.createElement("span", {
    style: {
      display: 'flex',
      alignItems: 'center',
      gap: 8
    }
  }, /*#__PURE__*/React.createElement("span", {
    style: {
      fontSize: 18,
      fontWeight: 600,
      letterSpacing: -0.3
    }
  }, meta.title), /*#__PURE__*/React.createElement("svg", {
    width: "11",
    height: "11",
    viewBox: "0 0 11 11",
    fill: "none",
    stroke: "currentColor",
    strokeWidth: "1.8",
    strokeLinecap: "round",
    style: {
      opacity: .7
    }
  }, /*#__PURE__*/React.createElement("path", {
    d: "M2 4l3.5 3.5L9 4"
  }))), meta.subtitle && /*#__PURE__*/React.createElement("span", {
    style: {
      display: 'block',
      fontSize: 13,
      opacity: .6,
      fontWeight: 400,
      marginTop: 2
    }
  }, meta.subtitle)), ddOpen && /*#__PURE__*/React.createElement("div", {
    style: {
      position: 'absolute',
      top: '100%',
      left: 0,
      marginTop: 4,
      background: '#2a251f',
      borderRadius: 8,
      boxShadow: '0 8px 32px rgba(0,0,0,.4)',
      padding: 4,
      minWidth: 200,
      zIndex: 10
    }
  }, sectionOrder.filter(sid => sectionMeta[sid].slotIds.length).map(sid => /*#__PURE__*/React.createElement("button", {
    key: sid,
    onClick: () => {
      setDd(false);
      const f = sectionMeta[sid].slotIds[0];
      if (f) ctx.setFocus(`${sid}/${f}`);
    },
    style: {
      display: 'block',
      width: '100%',
      textAlign: 'left',
      border: 'none',
      cursor: 'pointer',
      background: sid === sectionId ? 'rgba(255,255,255,.1)' : 'transparent',
      color: '#fff',
      padding: '8px 12px',
      borderRadius: 5,
      fontSize: 14,
      fontWeight: sid === sectionId ? 600 : 400,
      fontFamily: 'inherit'
    }
  }, sectionMeta[sid].title)))), /*#__PURE__*/React.createElement("div", {
    style: {
      flex: 1
    }
  }), /*#__PURE__*/React.createElement("button", {
    onClick: () => ctx.setFocus(null),
    onMouseEnter: e => e.currentTarget.style.background = 'rgba(255,255,255,.12)',
    onMouseLeave: e => e.currentTarget.style.background = 'transparent',
    style: {
      border: 'none',
      background: 'transparent',
      color: 'rgba(255,255,255,.7)',
      width: 32,
      height: 32,
      borderRadius: 16,
      fontSize: 20,
      cursor: 'pointer',
      lineHeight: 1,
      transition: 'background .12s'
    }
  }, "\xD7")), /*#__PURE__*/React.createElement("div", {
    style: {
      position: 'absolute',
      top: 64,
      bottom: 56,
      left: 100,
      right: 100,
      display: 'flex',
      flexDirection: 'column',
      alignItems: 'center',
      justifyContent: 'center',
      gap: 16
    }
  }, /*#__PURE__*/React.createElement("div", {
    onClick: e => e.stopPropagation(),
    style: {
      width: width * scale,
      height: height * scale,
      position: 'relative'
    }
  }, /*#__PURE__*/React.createElement("div", {
    style: {
      width,
      height,
      transform: `scale(${scale})`,
      transformOrigin: 'top left',
      background: '#fff',
      borderRadius: 2,
      overflow: 'hidden',
      boxShadow: '0 20px 80px rgba(0,0,0,.4)'
    }
  }, children || /*#__PURE__*/React.createElement("div", {
    style: {
      height: '100%',
      display: 'flex',
      alignItems: 'center',
      justifyContent: 'center',
      color: '#bbb'
    }
  }, aid))), /*#__PURE__*/React.createElement("div", {
    onClick: e => e.stopPropagation(),
    style: {
      fontSize: 14,
      fontWeight: 500,
      opacity: .85,
      textAlign: 'center'
    }
  }, (sec.labels || {})[aid] ?? artboard.props.label, /*#__PURE__*/React.createElement("span", {
    style: {
      opacity: .5,
      marginLeft: 10,
      fontVariantNumeric: 'tabular-nums'
    }
  }, idx + 1, " / ", peers.length))), /*#__PURE__*/React.createElement(Arrow, {
    dir: "left",
    onClick: () => go(-1)
  }), /*#__PURE__*/React.createElement(Arrow, {
    dir: "right",
    onClick: () => go(1)
  }), /*#__PURE__*/React.createElement("div", {
    onClick: e => e.stopPropagation(),
    style: {
      position: 'absolute',
      bottom: 20,
      left: '50%',
      transform: 'translateX(-50%)',
      display: 'flex',
      gap: 8
    }
  }, peers.map((p, i) => /*#__PURE__*/React.createElement("button", {
    key: p,
    onClick: () => ctx.setFocus(`${sectionId}/${p}`),
    style: {
      border: 'none',
      padding: 0,
      cursor: 'pointer',
      width: 6,
      height: 6,
      borderRadius: 3,
      background: i === idx ? '#fff' : 'rgba(255,255,255,.3)'
    }
  })))), document.body);
}

// ─────────────────────────────────────────────────────────────
// Post-it — absolute-positioned sticky note
// ─────────────────────────────────────────────────────────────
function DCPostIt({
  children,
  top,
  left,
  right,
  bottom,
  rotate = -2,
  width = 180
}) {
  return /*#__PURE__*/React.createElement("div", {
    style: {
      position: 'absolute',
      top,
      left,
      right,
      bottom,
      width,
      background: DC.postitBg,
      padding: '14px 16px',
      fontFamily: '"Comic Sans MS", "Marker Felt", "Segoe Print", cursive',
      fontSize: 14,
      lineHeight: 1.4,
      color: DC.postitText,
      boxShadow: '0 2px 8px rgba(0,0,0,0.12), 0 1px 2px rgba(0,0,0,0.08)',
      transform: `rotate(${rotate}deg)`,
      zIndex: 5
    }
  }, children);
}
Object.assign(window, {
  DesignCanvas,
  DCSection,
  DCArtboard,
  DCPostIt
});
})(); } catch (e) { __ds_ns.__errors.push({ path: "quiz-game/design-canvas.jsx", error: String((e && e.message) || e) }); }

// quiz-game/dist/game.js
try { (() => {
"use strict";

function _typeof(o) {
  "@babel/helpers - typeof";

  return _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function (o) {
    return typeof o;
  } : function (o) {
    return o && "function" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? "symbol" : typeof o;
  }, _typeof(o);
}
function ownKeys(e, r) {
  var t = Object.keys(e);
  if (Object.getOwnPropertySymbols) {
    var o = Object.getOwnPropertySymbols(e);
    r && (o = o.filter(function (r) {
      return Object.getOwnPropertyDescriptor(e, r).enumerable;
    })), t.push.apply(t, o);
  }
  return t;
}
function _objectSpread(e) {
  for (var r = 1; r < arguments.length; r++) {
    var t = null != arguments[r] ? arguments[r] : {};
    r % 2 ? ownKeys(Object(t), !0).forEach(function (r) {
      _defineProperty(e, r, t[r]);
    }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) {
      Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r));
    });
  }
  return e;
}
function _defineProperty(e, r, t) {
  return (r = _toPropertyKey(r)) in e ? Object.defineProperty(e, r, {
    value: t,
    enumerable: !0,
    configurable: !0,
    writable: !0
  }) : e[r] = t, e;
}
function _toPropertyKey(t) {
  var i = _toPrimitive(t, "string");
  return "symbol" == _typeof(i) ? i : i + "";
}
function _toPrimitive(t, r) {
  if ("object" != _typeof(t) || !t) return t;
  var e = t[Symbol.toPrimitive];
  if (void 0 !== e) {
    var i = e.call(t, r || "default");
    if ("object" != _typeof(i)) return i;
    throw new TypeError("@@toPrimitive must return a primitive value.");
  }
  return ("string" === r ? String : Number)(t);
}
function _regenerator() {
  /*! regenerator-runtime -- Copyright (c) 2014-present, Facebook, Inc. -- license (MIT): https://github.com/babel/babel/blob/main/packages/babel-helpers/LICENSE */var e,
    t,
    r = "function" == typeof Symbol ? Symbol : {},
    n = r.iterator || "@@iterator",
    o = r.toStringTag || "@@toStringTag";
  function i(r, n, o, i) {
    var c = n && n.prototype instanceof Generator ? n : Generator,
      u = Object.create(c.prototype);
    return _regeneratorDefine2(u, "_invoke", function (r, n, o) {
      var i,
        c,
        u,
        f = 0,
        p = o || [],
        y = !1,
        G = {
          p: 0,
          n: 0,
          v: e,
          a: d,
          f: d.bind(e, 4),
          d: function d(t, r) {
            return i = t, c = 0, u = e, G.n = r, a;
          }
        };
      function d(r, n) {
        for (c = r, u = n, t = 0; !y && f && !o && t < p.length; t++) {
          var o,
            i = p[t],
            d = G.p,
            l = i[2];
          r > 3 ? (o = l === n) && (u = i[(c = i[4]) ? 5 : (c = 3, 3)], i[4] = i[5] = e) : i[0] <= d && ((o = r < 2 && d < i[1]) ? (c = 0, G.v = n, G.n = i[1]) : d < l && (o = r < 3 || i[0] > n || n > l) && (i[4] = r, i[5] = n, G.n = l, c = 0));
        }
        if (o || r > 1) return a;
        throw y = !0, n;
      }
      return function (o, p, l) {
        if (f > 1) throw TypeError("Generator is already running");
        for (y && 1 === p && d(p, l), c = p, u = l; (t = c < 2 ? e : u) || !y;) {
          i || (c ? c < 3 ? (c > 1 && (G.n = -1), d(c, u)) : G.n = u : G.v = u);
          try {
            if (f = 2, i) {
              if (c || (o = "next"), t = i[o]) {
                if (!(t = t.call(i, u))) throw TypeError("iterator result is not an object");
                if (!t.done) return t;
                u = t.value, c < 2 && (c = 0);
              } else 1 === c && (t = i.return) && t.call(i), c < 2 && (u = TypeError("The iterator does not provide a '" + o + "' method"), c = 1);
              i = e;
            } else if ((t = (y = G.n < 0) ? u : r.call(n, G)) !== a) break;
          } catch (t) {
            i = e, c = 1, u = t;
          } finally {
            f = 1;
          }
        }
        return {
          value: t,
          done: y
        };
      };
    }(r, o, i), !0), u;
  }
  var a = {};
  function Generator() {}
  function GeneratorFunction() {}
  function GeneratorFunctionPrototype() {}
  t = Object.getPrototypeOf;
  var c = [][n] ? t(t([][n]())) : (_regeneratorDefine2(t = {}, n, function () {
      return this;
    }), t),
    u = GeneratorFunctionPrototype.prototype = Generator.prototype = Object.create(c);
  function f(e) {
    return Object.setPrototypeOf ? Object.setPrototypeOf(e, GeneratorFunctionPrototype) : (e.__proto__ = GeneratorFunctionPrototype, _regeneratorDefine2(e, o, "GeneratorFunction")), e.prototype = Object.create(u), e;
  }
  return GeneratorFunction.prototype = GeneratorFunctionPrototype, _regeneratorDefine2(u, "constructor", GeneratorFunctionPrototype), _regeneratorDefine2(GeneratorFunctionPrototype, "constructor", GeneratorFunction), GeneratorFunction.displayName = "GeneratorFunction", _regeneratorDefine2(GeneratorFunctionPrototype, o, "GeneratorFunction"), _regeneratorDefine2(u), _regeneratorDefine2(u, o, "Generator"), _regeneratorDefine2(u, n, function () {
    return this;
  }), _regeneratorDefine2(u, "toString", function () {
    return "[object Generator]";
  }), (_regenerator = function _regenerator() {
    return {
      w: i,
      m: f
    };
  })();
}
function _regeneratorDefine2(e, r, n, t) {
  var i = Object.defineProperty;
  try {
    i({}, "", {});
  } catch (e) {
    i = 0;
  }
  _regeneratorDefine2 = function _regeneratorDefine(e, r, n, t) {
    function o(r, n) {
      _regeneratorDefine2(e, r, function (e) {
        return this._invoke(r, n, e);
      });
    }
    r ? i ? i(e, r, {
      value: n,
      enumerable: !t,
      configurable: !t,
      writable: !t
    }) : e[r] = n : (o("next", 0), o("throw", 1), o("return", 2));
  }, _regeneratorDefine2(e, r, n, t);
}
function asyncGeneratorStep(n, t, e, r, o, a, c) {
  try {
    var i = n[a](c),
      u = i.value;
  } catch (n) {
    return void e(n);
  }
  i.done ? t(u) : Promise.resolve(u).then(r, o);
}
function _asyncToGenerator(n) {
  return function () {
    var t = this,
      e = arguments;
    return new Promise(function (r, o) {
      var a = n.apply(t, e);
      function _next(n) {
        asyncGeneratorStep(a, r, o, _next, _throw, "next", n);
      }
      function _throw(n) {
        asyncGeneratorStep(a, r, o, _next, _throw, "throw", n);
      }
      _next(void 0);
    });
  };
}
function _slicedToArray(r, e) {
  return _arrayWithHoles(r) || _iterableToArrayLimit(r, e) || _unsupportedIterableToArray(r, e) || _nonIterableRest();
}
function _nonIterableRest() {
  throw new TypeError("Invalid attempt to destructure non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.");
}
function _iterableToArrayLimit(r, l) {
  var t = null == r ? null : "undefined" != typeof Symbol && r[Symbol.iterator] || r["@@iterator"];
  if (null != t) {
    var e,
      n,
      i,
      u,
      a = [],
      f = !0,
      o = !1;
    try {
      if (i = (t = t.call(r)).next, 0 === l) {
        if (Object(t) !== t) return;
        f = !1;
      } else for (; !(f = (e = i.call(t)).done) && (a.push(e.value), a.length !== l); f = !0);
    } catch (r) {
      o = !0, n = r;
    } finally {
      try {
        if (!f && null != t.return && (u = t.return(), Object(u) !== u)) return;
      } finally {
        if (o) throw n;
      }
    }
    return a;
  }
}
function _arrayWithHoles(r) {
  if (Array.isArray(r)) return r;
}
function _createForOfIteratorHelper(r, e) {
  var t = "undefined" != typeof Symbol && r[Symbol.iterator] || r["@@iterator"];
  if (!t) {
    if (Array.isArray(r) || (t = _unsupportedIterableToArray(r)) || e && r && "number" == typeof r.length) {
      t && (r = t);
      var _n = 0,
        F = function F() {};
      return {
        s: F,
        n: function n() {
          return _n >= r.length ? {
            done: !0
          } : {
            done: !1,
            value: r[_n++]
          };
        },
        e: function e(r) {
          throw r;
        },
        f: F
      };
    }
    throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.");
  }
  var o,
    a = !0,
    u = !1;
  return {
    s: function s() {
      t = t.call(r);
    },
    n: function n() {
      var r = t.next();
      return a = r.done, r;
    },
    e: function e(r) {
      u = !0, o = r;
    },
    f: function f() {
      try {
        a || null == t.return || t.return();
      } finally {
        if (u) throw o;
      }
    }
  };
}
function _toConsumableArray(r) {
  return _arrayWithoutHoles(r) || _iterableToArray(r) || _unsupportedIterableToArray(r) || _nonIterableSpread();
}
function _nonIterableSpread() {
  throw new TypeError("Invalid attempt to spread non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.");
}
function _unsupportedIterableToArray(r, a) {
  if (r) {
    if ("string" == typeof r) return _arrayLikeToArray(r, a);
    var t = {}.toString.call(r).slice(8, -1);
    return "Object" === t && r.constructor && (t = r.constructor.name), "Map" === t || "Set" === t ? Array.from(r) : "Arguments" === t || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(t) ? _arrayLikeToArray(r, a) : void 0;
  }
}
function _iterableToArray(r) {
  if ("undefined" != typeof Symbol && null != r[Symbol.iterator] || null != r["@@iterator"]) return Array.from(r);
}
function _arrayWithoutHoles(r) {
  if (Array.isArray(r)) return _arrayLikeToArray(r);
}
function _arrayLikeToArray(r, a) {
  (null == a || a > r.length) && (a = r.length);
  for (var e = 0, n = Array(a); e < a; e++) n[e] = r[e];
  return n;
}
/* global React, XLSX */
var _React = React,
  useState = _React.useState,
  useEffect = _React.useEffect,
  useRef = _React.useRef,
  useCallback = _React.useCallback,
  useLayoutEffect = _React.useLayoutEffect,
  useMemo = _React.useMemo;

/* ---------- built-in sample dictionary ---------- */
var SAMPLE_DICT = [{
  en: "ENHANCE",
  he: "להעצים, לשפר",
  ipa: "/ɪnˈhæns/"
}, {
  en: "MITIGATE",
  he: "להקל, למתן",
  ipa: "/ˈmɪtɪˌɡeɪt/"
}, {
  en: "AMBIGUOUS",
  he: "דו-משמעי, עמום",
  ipa: "/æmˈbɪɡjuəs/"
}, {
  en: "ADVOCATE",
  he: "לתמוך, להמליץ",
  ipa: "/ˈædvəˌkeɪt/"
}, {
  en: "SCRUTINIZE",
  he: "לבחון בקפדנות",
  ipa: "/ˈskruːtəˌnaɪz/"
}, {
  en: "INEVITABLE",
  he: "בלתי נמנע",
  ipa: "/ɪˈnɛvɪtəbəl/"
}, {
  en: "DILIGENT",
  he: "חרוץ, שקדן",
  ipa: "/ˈdɪlɪdʒənt/"
}, {
  en: "OBSOLETE",
  he: "מיושן, יצא משימוש",
  ipa: "/ˌabsəˈliːt/"
}, {
  en: "CANDID",
  he: "הֵן, ישיר, ספונטני",
  ipa: "/ˈkændɪd/"
}, {
  en: "TENACIOUS",
  he: "עיקש, דבק במטרה",
  ipa: "/təˈneɪʃəs/"
}];
var STAGGER = [0, 40, 14, 56];
var DICT_STORAGE_KEY = "ez-mcq-dict-v2";
var DICT_NAME_KEY = "ez-mcq-dict-name-v2";
var MUTED_KEY = "ez-mcq-muted-v1";
var LB_KEY = "ez-mcq-leaderboard-v1";

/* ---------- sound engine (WebAudio FX + background music) ---------- */
var Sound = {
  ctx: null,
  muted: false,
  music: null,
  // <audio> element
  musicReady: false,
  init: function init() {
    if (!this.ctx) {
      try {
        this.ctx = new (window.AudioContext || window.webkitAudioContext)();
      } catch (e) {}
    }
    if (this.ctx && this.ctx.state === 'suspended') this.ctx.resume();
    if (!this.music) {
      this.music = document.getElementById('bg-music');
      if (this.music) {
        this.music.volume = 0.35;
        this.music.loop = true;
        this.musicReady = true;
      }
    }
  },
  startMusic: function startMusic() {
    this.init();
    if (this.muted || !this.music) return;
    var p = this.music.play();
    if (p && p.catch) p.catch(function () {/* autoplay blocked — will start on next user gesture */});
  },
  stopMusic: function stopMusic() {
    if (this.music) {
      this.music.pause();
    }
  },
  setMusicVolume: function setMusicVolume(v) {
    if (this.music) this.music.volume = Math.max(0, Math.min(1, v));
  },
  setMuted: function setMuted(m) {
    this.muted = !!m;
    if (this.muted) this.stopMusic();else this.startMusic();
    try {
      localStorage.setItem(MUTED_KEY, this.muted ? '1' : '0');
    } catch (e) {}
  },
  beep: function beep(freq, duration) {
    var type = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : 'sine';
    var gain = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : 0.15;
    var delay = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : 0;
    if (this.muted || !this.ctx) return;
    var t = this.ctx.currentTime + delay;
    var osc = this.ctx.createOscillator();
    var g = this.ctx.createGain();
    osc.type = type;
    osc.frequency.value = freq;
    g.gain.setValueAtTime(gain, t);
    g.gain.exponentialRampToValueAtTime(0.001, t + duration);
    osc.connect(g);
    g.connect(this.ctx.destination);
    osc.start(t);
    osc.stop(t + duration);
  },
  play: function play(name) {
    if (this.muted) return;
    this.init();
    switch (name) {
      case 'shoot':
        this.beep(540, 0.06, 'square', 0.13);
        this.beep(220, 0.07, 'sawtooth', 0.10, 0.03);
        break;
      case 'hit':
        /* punchier explosion: low thump + bright chord + bell tail */
        this.beep(80, 0.10, 'square', 0.22);
        this.beep(523, 0.10, 'square', 0.16, 0.04);
        this.beep(784, 0.12, 'square', 0.14, 0.10);
        this.beep(1047, 0.22, 'triangle', 0.16, 0.18);
        this.beep(1568, 0.30, 'sine', 0.12, 0.30);
        break;
      case 'miss':
        /* descending "wha-wha" buzzer — clearly distinct from a hit */
        this.beep(440, 0.10, 'square', 0.20);
        this.beep(330, 0.14, 'square', 0.20, 0.10);
        this.beep(220, 0.30, 'sawtooth', 0.22, 0.22);
        this.beep(150, 0.45, 'triangle', 0.20, 0.45);
        break;
      case 'lifegain':
        /* sparkle: ascending major arpeggio */
        this.beep(659, 0.10, 'triangle', 0.18);
        this.beep(880, 0.10, 'triangle', 0.18, 0.10);
        this.beep(1175, 0.10, 'triangle', 0.18, 0.20);
        this.beep(1568, 0.32, 'sine', 0.20, 0.30);
        break;
      case 'fifty':
        /* two-note chime */
        this.beep(880, 0.10, 'sine', 0.15);
        this.beep(1320, 0.18, 'sine', 0.16, 0.10);
        break;
      case 'levelup':
        this.beep(523, 0.10, 'triangle', 0.18);
        this.beep(659, 0.10, 'triangle', 0.18, 0.10);
        this.beep(784, 0.10, 'triangle', 0.18, 0.20);
        this.beep(1047, 0.32, 'sine', 0.20, 0.30);
        break;
      case 'tick':
        this.beep(720, 0.08, 'sine', 0.10);
        break;
      case 'go':
        this.beep(1200, 0.30, 'triangle', 0.22);
        break;
      case 'streak':
        this.beep(880, 0.08, 'sine', 0.13);
        this.beep(1320, 0.10, 'sine', 0.14, 0.08);
        break;
      case 'gameover':
        this.beep(440, 0.20, 'sine', 0.15);
        this.beep(330, 0.24, 'sine', 0.15, 0.20);
        this.beep(220, 0.50, 'sine', 0.18, 0.45);
        break;
    }
  }
};
try {
  Sound.muted = localStorage.getItem(MUTED_KEY) === '1';
} catch (e) {}

/* ---------- leaderboard ---------- */
function getLeaderboard() {
  try {
    return JSON.parse(localStorage.getItem(LB_KEY) || '[]');
  } catch (e) {
    return [];
  }
}
function addToLeaderboard(name, score) {
  var lb = getLeaderboard();
  lb.push({
    name: (name || "אנונימי").slice(0, 20),
    score: score,
    date: new Date().toISOString()
  });
  lb.sort(function (a, b) {
    return b.score - a.score;
  });
  try {
    localStorage.setItem(LB_KEY, JSON.stringify(lb.slice(0, 5)));
  } catch (e) {}
  return lb.slice(0, 5);
}
function qualifiesForLeaderboard(score) {
  if (score <= 0) return false;
  var lb = getLeaderboard();
  if (lb.length < 5) return true;
  return score > lb[lb.length - 1].score;
}

/* ---------- dictionary helpers ---------- */
function shuffleArr(a) {
  var x = _toConsumableArray(a);
  for (var i = x.length - 1; i > 0; i--) {
    var j = Math.floor(Math.random() * (i + 1));
    var _ref = [x[j], x[i]];
    x[i] = _ref[0];
    x[j] = _ref[1];
  }
  return x;
}
function buildQuestion(dict, correctIdx) {
  var correct = dict[correctIdx];
  var correctMeaning = normalizeMeaning(correct.he);

  // Build pool excluding correct answer AND entries that share the same meaning.
  // This prevents duplicate Hebrew translations from appearing as distractors
  // (e.g. when the same meaning is split across two English words).
  var pool = dict.map(function (entry, i) {
    return {
      entry: entry,
      i: i,
      key: normalizeMeaning(entry.he)
    };
  }).filter(function (_ref2) {
    var i = _ref2.i,
      key = _ref2.key;
    return i !== correctIdx && key !== correctMeaning;
  });

  // Pick 3 distractors with distinct meanings from each other too.
  var shuffled = shuffleArr(pool);
  var picked = [];
  var seenMeanings = new Set([correctMeaning]);
  var _iterator = _createForOfIteratorHelper(shuffled),
    _step;
  try {
    for (_iterator.s(); !(_step = _iterator.n()).done;) {
      var _step$value = _step.value,
        entry = _step$value.entry,
        key = _step$value.key;
      if (seenMeanings.has(key)) continue;
      seenMeanings.add(key);
      picked.push(entry);
      if (picked.length === 3) break;
    }

    // Fallback: if the dict is too small / too many duplicates, allow same-key duplicates
    // just so we always have 4 options.
  } catch (err) {
    _iterator.e(err);
  } finally {
    _iterator.f();
  }
  while (picked.length < 3) {
    var fillers = shuffleArr(pool).filter(function (p) {
      return !picked.includes(p.entry);
    });
    if (fillers.length === 0) break;
    picked.push(fillers[0].entry);
  }
  var options = shuffleArr([correct.he].concat(_toConsumableArray(picked.map(function (d) {
    return d.he;
  }))));
  return {
    en: String(correct.en).toUpperCase(),
    ipa: correct.ipa || "",
    correct: correct.he,
    options: options
  };
}

// Normalize a meaning string so "להאריך / להרחיב" and "להאריך, להרחיב" collide,
// and casing/whitespace differences don't matter.
function normalizeMeaning(s) {
  return String(s || "").toLowerCase().replace(/[\/,،]/g, " ") // treat /, comma, arabic comma as separators
  .replace(/\s+/g, " ").replace(/[״"׳'.…]/g, "").trim();
}
function parseSpreadsheet(file) {
  return new Promise(function (resolve, reject) {
    var reader = new FileReader();
    reader.onerror = function () {
      return reject(new Error("לא מצליח לקרוא את הקובץ"));
    };
    reader.onload = function (e) {
      try {
        if (typeof XLSX === "undefined") {
          reject(new Error("תוכנת הפיענוח לא נטענה. רענן דף ונסה שוב."));
          return;
        }
        var data = new Uint8Array(e.target.result);
        var wb = XLSX.read(data, {
          type: "array"
        });
        var sheet = wb.Sheets[wb.SheetNames[0]];
        var rows = XLSX.utils.sheet_to_json(sheet, {
          header: 1,
          blankrows: false
        });
        if (!rows.length) {
          reject(new Error("הקובץ ריק"));
          return;
        }
        var firstB = String(rows[0][1] || "").trim().toLowerCase();
        var looksLikeHeader = /english|word|מילה|אנגלית/.test(firstB) || /פירוש|תרגום|עברית/.test(String(rows[0][2] || ""));
        var start = looksLikeHeader ? 1 : 0;
        var entries = [];
        for (var i = start; i < rows.length; i++) {
          var en = String(rows[i][1] || "").trim(); // column B
          var he = String(rows[i][2] || "").trim(); // column C
          if (en && he) entries.push({
            en: en,
            he: he,
            ipa: ""
          });
        }
        if (entries.length < 4) {
          reject(new Error("צריך לפחות 4 מילים בקובץ"));
          return;
        }
        resolve(entries);
      } catch (err) {
        reject(err);
      }
    };
    reader.readAsArrayBuffer(file);
  });
}

/* ──────────────────────────────────────────────
   Polished SVG illustrations
   ────────────────────────────────────────────── */

function RocketSVG(_ref3) {
  var isBoss = _ref3.isBoss;
  var stroke = "#2A2155";
  var strokeW = 3.5;

  // ── Regular rockets ── use the curated reference artwork embedded as a
  // PNG. Replacing the SVG with the bitmap matches the source illustration
  // pixel-for-pixel; state-based color shifts (hit / missed / correct) come
  // from CSS filters applied to .gm-rocket via `.rocket-img`.
  if (!isBoss) {
    return /*#__PURE__*/React.createElement("svg", {
      className: "frame",
      viewBox: "0 0 620 150",
      preserveAspectRatio: "none",
      "aria-hidden": true
    }, /*#__PURE__*/React.createElement("image", {
      className: "rocket-img",
      href: "rocket-cropped.png",
      xlinkHref: "rocket-cropped.png",
      x: "0",
      y: "0",
      width: "620",
      height: "150",
      preserveAspectRatio: "none"
    }));
  }

  // ── BOSS rocket ── still drawn fully in SVG so the red gradient body,
  // shark-fins and multi-lick flame stay intact (per the user's request).
  return /*#__PURE__*/React.createElement("svg", {
    className: "frame",
    viewBox: "0 0 620 150",
    preserveAspectRatio: "none",
    "aria-hidden": true
  }, /*#__PURE__*/React.createElement("defs", null, /*#__PURE__*/React.createElement("linearGradient", {
    id: "bodyG",
    x1: "0",
    y1: "0",
    x2: "0",
    y2: "1"
  }, /*#__PURE__*/React.createElement("stop", {
    offset: "0",
    stopColor: "#FFFFFF"
  }), /*#__PURE__*/React.createElement("stop", {
    offset: ".6",
    stopColor: "#F5F3F8"
  }), /*#__PURE__*/React.createElement("stop", {
    offset: "1",
    stopColor: "#C9C7CF"
  })), /*#__PURE__*/React.createElement("linearGradient", {
    id: "bodyG-hit",
    x1: "0",
    y1: "0",
    x2: "0",
    y2: "1"
  }, /*#__PURE__*/React.createElement("stop", {
    offset: "0",
    stopColor: "#FFE6CB"
  }), /*#__PURE__*/React.createElement("stop", {
    offset: ".5",
    stopColor: "#F37327"
  }), /*#__PURE__*/React.createElement("stop", {
    offset: "1",
    stopColor: "#A93C08"
  })), /*#__PURE__*/React.createElement("linearGradient", {
    id: "bodyG-miss",
    x1: "0",
    y1: "0",
    x2: "0",
    y2: "1"
  }, /*#__PURE__*/React.createElement("stop", {
    offset: "0",
    stopColor: "#D7D5DC"
  }), /*#__PURE__*/React.createElement("stop", {
    offset: "1",
    stopColor: "#9A98A4"
  })), /*#__PURE__*/React.createElement("linearGradient", {
    id: "bodyG-correct",
    x1: "0",
    y1: "0",
    x2: "0",
    y2: "1"
  }, /*#__PURE__*/React.createElement("stop", {
    offset: "0",
    stopColor: "#BDF0D3"
  }), /*#__PURE__*/React.createElement("stop", {
    offset: "1",
    stopColor: "#3FA76C"
  })), /*#__PURE__*/React.createElement("linearGradient", {
    id: "bodyG-boss",
    x1: "0",
    y1: "0",
    x2: "0",
    y2: "1"
  }, /*#__PURE__*/React.createElement("stop", {
    offset: "0",
    stopColor: "#FCA5A5"
  }), /*#__PURE__*/React.createElement("stop", {
    offset: ".5",
    stopColor: "#DC2626"
  }), /*#__PURE__*/React.createElement("stop", {
    offset: "1",
    stopColor: "#7F1D1D"
  })), /*#__PURE__*/React.createElement("linearGradient", {
    id: "tipG-boss",
    x1: "0",
    y1: "0",
    x2: "0",
    y2: "1"
  }, /*#__PURE__*/React.createElement("stop", {
    offset: "0",
    stopColor: "#FCD34D"
  }), /*#__PURE__*/React.createElement("stop", {
    offset: ".55",
    stopColor: "#DC2626"
  }), /*#__PURE__*/React.createElement("stop", {
    offset: "1",
    stopColor: "#7F1D1D"
  })), /*#__PURE__*/React.createElement("linearGradient", {
    id: "tipG",
    x1: "0",
    y1: "0",
    x2: "0",
    y2: "1"
  }, /*#__PURE__*/React.createElement("stop", {
    offset: "0",
    stopColor: "#FFB36B"
  }), /*#__PURE__*/React.createElement("stop", {
    offset: ".55",
    stopColor: "#F37327"
  }), /*#__PURE__*/React.createElement("stop", {
    offset: "1",
    stopColor: "#B94A0C"
  })), /*#__PURE__*/React.createElement("linearGradient", {
    id: "finG",
    x1: "0",
    y1: "0",
    x2: "0",
    y2: "1"
  }, /*#__PURE__*/React.createElement("stop", {
    offset: "0",
    stopColor: "#FFB36B"
  }), /*#__PURE__*/React.createElement("stop", {
    offset: ".5",
    stopColor: "#F37327"
  }), /*#__PURE__*/React.createElement("stop", {
    offset: "1",
    stopColor: "#A0410B"
  })), /*#__PURE__*/React.createElement("radialGradient", {
    id: "flameG",
    cx: "50%",
    cy: "50%",
    r: "55%"
  }, /*#__PURE__*/React.createElement("stop", {
    offset: "0",
    stopColor: "#FFF7CE"
  }), /*#__PURE__*/React.createElement("stop", {
    offset: ".4",
    stopColor: "#FFD23F"
  }), /*#__PURE__*/React.createElement("stop", {
    offset: ".85",
    stopColor: "#F37327"
  }), /*#__PURE__*/React.createElement("stop", {
    offset: "1",
    stopColor: "#B94A0C"
  }))), /*#__PURE__*/React.createElement("g", null, /*#__PURE__*/React.createElement("path", {
    d: "M 525,40 Q 555,52 580,32 Q 568,55 595,55 Q 575,68 610,72 Q 575,80 615,90 Q 575,92 600,108 Q 570,100 588,118 Q 555,100 580,118 Q 555,98 525,110 Z",
    fill: "url(#flameG)",
    stroke: stroke,
    strokeWidth: strokeW,
    strokeLinejoin: "round"
  }), /*#__PURE__*/React.createElement("path", {
    d: "M 530,55 Q 555,55 570,42 Q 568,62 585,68 Q 565,75 582,82 Q 565,88 580,100 Q 558,92 568,110 Q 545,95 530,100 Z",
    fill: "#FFF7CE",
    opacity: ".95"
  })), /*#__PURE__*/React.createElement("path", {
    d: "M 470,42 Q 488,18 540,2 Q 540,30 520,46 Q 500,52 470,42 Z",
    fill: "url(#finG)",
    stroke: stroke,
    strokeWidth: strokeW,
    strokeLinejoin: "round"
  }), /*#__PURE__*/React.createElement("path", {
    d: "M 495,28 Q 515,18 532,12",
    stroke: "#fff",
    strokeOpacity: ".6",
    strokeWidth: "3",
    fill: "none",
    strokeLinecap: "round"
  }), /*#__PURE__*/React.createElement("path", {
    d: "M 470,108 Q 488,132 540,148 Q 540,120 520,104 Q 500,98 470,108 Z",
    fill: "url(#finG)",
    stroke: stroke,
    strokeWidth: strokeW,
    strokeLinejoin: "round"
  }), /*#__PURE__*/React.createElement("path", {
    d: "M 495,122 Q 515,132 532,138",
    stroke: "#fff",
    strokeOpacity: ".45",
    strokeWidth: "3",
    fill: "none",
    strokeLinecap: "round"
  }), /*#__PURE__*/React.createElement("path", {
    className: "body-fill",
    d: "M 40,75 Q 70,16 165,16 L 530,16 Q 560,16 560,38 L 560,112 Q 560,134 530,134 L 165,134 Q 70,134 40,75 Z",
    fill: "url(#bodyG)",
    stroke: stroke,
    strokeWidth: strokeW,
    strokeLinejoin: "round"
  }), /*#__PURE__*/React.createElement("path", {
    className: "tip-fill",
    d: "M 40,75 Q 70,16 165,16 L 175,16 Q 110,30 90,75 Q 110,120 175,134 L 165,134 Q 70,134 40,75 Z",
    fill: "url(#tipG)",
    stroke: stroke,
    strokeWidth: strokeW,
    strokeLinejoin: "round"
  }), /*#__PURE__*/React.createElement("path", {
    d: "M 70,52 Q 90,38 120,42",
    stroke: "#fff",
    strokeOpacity: ".7",
    strokeWidth: "4",
    fill: "none",
    strokeLinecap: "round"
  }), /*#__PURE__*/React.createElement("path", {
    d: "M 195,30 Q 360,24 510,32",
    stroke: "#fff",
    strokeOpacity: ".95",
    strokeWidth: "5",
    fill: "none",
    strokeLinecap: "round"
  }), /*#__PURE__*/React.createElement("path", {
    d: "M 170,124 Q 360,140 520,126",
    stroke: "#1A1530",
    strokeOpacity: ".09",
    strokeWidth: "6",
    fill: "none",
    strokeLinecap: "round"
  }), /*#__PURE__*/React.createElement("circle", {
    cx: "125",
    cy: "48",
    r: "2.5",
    fill: "#fff"
  }));
}
function BurstSVG() {
  return /*#__PURE__*/React.createElement("svg", {
    viewBox: "0 0 140 140",
    "aria-hidden": true
  }, /*#__PURE__*/React.createElement("defs", null, /*#__PURE__*/React.createElement("radialGradient", {
    id: "boom",
    cx: "50%",
    cy: "50%",
    r: "50%"
  }, /*#__PURE__*/React.createElement("stop", {
    offset: "0%",
    stopColor: "#FFF7E6"
  }), /*#__PURE__*/React.createElement("stop", {
    offset: "35%",
    stopColor: "#FFB061"
  }), /*#__PURE__*/React.createElement("stop", {
    offset: "70%",
    stopColor: "#F37327"
  }), /*#__PURE__*/React.createElement("stop", {
    offset: "100%",
    stopColor: "rgba(213,90,18,0)"
  }))), /*#__PURE__*/React.createElement("circle", {
    cx: "70",
    cy: "70",
    r: "48",
    fill: "url(#boom)"
  }), /*#__PURE__*/React.createElement("g", {
    stroke: "#FFB061",
    strokeWidth: "3",
    strokeLinecap: "round",
    fill: "none"
  }, /*#__PURE__*/React.createElement("line", {
    x1: "70",
    y1: "14",
    x2: "70",
    y2: "32"
  }), /*#__PURE__*/React.createElement("line", {
    x1: "70",
    y1: "108",
    x2: "70",
    y2: "126"
  }), /*#__PURE__*/React.createElement("line", {
    x1: "14",
    y1: "70",
    x2: "32",
    y2: "70"
  }), /*#__PURE__*/React.createElement("line", {
    x1: "108",
    y1: "70",
    x2: "126",
    y2: "70"
  }), /*#__PURE__*/React.createElement("line", {
    x1: "28",
    y1: "28",
    x2: "42",
    y2: "42"
  }), /*#__PURE__*/React.createElement("line", {
    x1: "98",
    y1: "98",
    x2: "112",
    y2: "112"
  }), /*#__PURE__*/React.createElement("line", {
    x1: "28",
    y1: "112",
    x2: "42",
    y2: "98"
  }), /*#__PURE__*/React.createElement("line", {
    x1: "98",
    y1: "42",
    x2: "112",
    y2: "28"
  })), /*#__PURE__*/React.createElement("circle", {
    cx: "70",
    cy: "70",
    r: "18",
    fill: "#FFF7E6"
  }));
}
function CannonBase() {
  return /*#__PURE__*/React.createElement("svg", {
    className: "base",
    viewBox: "0 0 280 240",
    "aria-hidden": true
  }, /*#__PURE__*/React.createElement("defs", null, /*#__PURE__*/React.createElement("linearGradient", {
    id: "domeG",
    x1: "0",
    y1: "0",
    x2: "0",
    y2: "1"
  }, /*#__PURE__*/React.createElement("stop", {
    offset: "0",
    stopColor: "#FFA362"
  }), /*#__PURE__*/React.createElement("stop", {
    offset: "0.5",
    stopColor: "#F37327"
  }), /*#__PURE__*/React.createElement("stop", {
    offset: "1",
    stopColor: "#A93C08"
  })), /*#__PURE__*/React.createElement("linearGradient", {
    id: "tracksG",
    x1: "0",
    y1: "0",
    x2: "0",
    y2: "1"
  }, /*#__PURE__*/React.createElement("stop", {
    offset: "0",
    stopColor: "#2A2547"
  }), /*#__PURE__*/React.createElement("stop", {
    offset: "1",
    stopColor: "#0A0820"
  })), /*#__PURE__*/React.createElement("linearGradient", {
    id: "metalG",
    x1: "0",
    y1: "0",
    x2: "0",
    y2: "1"
  }, /*#__PURE__*/React.createElement("stop", {
    offset: "0",
    stopColor: "#3a3358"
  }), /*#__PURE__*/React.createElement("stop", {
    offset: "1",
    stopColor: "#15102B"
  }))), /*#__PURE__*/React.createElement("ellipse", {
    cx: "140",
    cy: "226",
    rx: "120",
    ry: "10",
    fill: "rgba(0,0,0,.45)"
  }), /*#__PURE__*/React.createElement("path", {
    d: "M 20,168 L 260,168 L 250,216 L 30,216 Z",
    fill: "url(#tracksG)",
    stroke: "#000",
    strokeWidth: "1"
  }), Array.from({
    length: 12
  }).map(function (_, i) {
    return /*#__PURE__*/React.createElement("rect", {
      key: i,
      x: 32 + i * 18,
      y: "174",
      width: "12",
      height: "36",
      rx: "2",
      fill: "#3a3358"
    });
  }), [58, 98, 138, 178, 218].map(function (cx, i) {
    return /*#__PURE__*/React.createElement("g", {
      key: i
    }, /*#__PURE__*/React.createElement("circle", {
      cx: cx,
      cy: "200",
      r: "13",
      fill: "#0A0820"
    }), /*#__PURE__*/React.createElement("circle", {
      cx: cx,
      cy: "200",
      r: "10",
      fill: "#3a3358",
      stroke: "#5a5470",
      strokeWidth: "2"
    }), /*#__PURE__*/React.createElement("circle", {
      cx: cx,
      cy: "200",
      r: "3",
      fill: "#5a5470"
    }));
  }), /*#__PURE__*/React.createElement("path", {
    d: "M 30,140 L 250,140 L 260,168 L 20,168 Z",
    fill: "#1A1530"
  }), /*#__PURE__*/React.createElement("rect", {
    x: "36",
    y: "146",
    width: "208",
    height: "3",
    fill: "rgba(255,255,255,.1)",
    rx: "1"
  }), [60, 100, 140, 180, 220].map(function (cx, i) {
    return /*#__PURE__*/React.createElement("circle", {
      key: i,
      cx: cx,
      cy: "156",
      r: "3",
      fill: "#5a5470"
    });
  }), /*#__PURE__*/React.createElement("path", {
    d: "M 70,140 Q 140,40 210,140 Z",
    fill: "url(#domeG)"
  }), /*#__PURE__*/React.createElement("path", {
    d: "M 85,128 Q 110,76 138,68",
    stroke: "rgba(255,255,255,.45)",
    strokeWidth: "4",
    fill: "none",
    strokeLinecap: "round"
  }), /*#__PURE__*/React.createElement("ellipse", {
    cx: "140",
    cy: "138",
    rx: "74",
    ry: "10",
    fill: "#0A0820"
  }), /*#__PURE__*/React.createElement("ellipse", {
    cx: "140",
    cy: "135",
    rx: "74",
    ry: "10",
    fill: "#1A1530"
  }), /*#__PURE__*/React.createElement("ellipse", {
    cx: "140",
    cy: "134",
    rx: "68",
    ry: "6",
    fill: "#3a3358"
  }), /*#__PURE__*/React.createElement("path", {
    d: "M 75,138 Q 140,52 205,138",
    stroke: "rgba(0,0,0,.18)",
    strokeWidth: "1",
    fill: "none"
  }), /*#__PURE__*/React.createElement("g", {
    transform: "translate(170 96)"
  }, /*#__PURE__*/React.createElement("rect", {
    x: "-20",
    y: "-20",
    width: "40",
    height: "40",
    rx: "7",
    fill: "#fff"
  }), /*#__PURE__*/React.createElement("image", {
    href: "ez-icon.png",
    x: "-17",
    y: "-17",
    width: "34",
    height: "34"
  })), /*#__PURE__*/React.createElement("line", {
    x1: "100",
    y1: "80",
    x2: "92",
    y2: "36",
    stroke: "#1A1530",
    strokeWidth: "2"
  }), /*#__PURE__*/React.createElement("circle", {
    cx: "92",
    cy: "34",
    r: "3",
    fill: "#F33F3F"
  }), /*#__PURE__*/React.createElement("circle", {
    cx: "62",
    cy: "156",
    r: "6",
    fill: "#FFE6A8"
  }), /*#__PURE__*/React.createElement("circle", {
    cx: "62",
    cy: "156",
    r: "3",
    fill: "#FFF"
  }));
}
function CannonBarrel() {
  return /*#__PURE__*/React.createElement("svg", {
    viewBox: "0 0 220 60",
    "aria-hidden": true
  }, /*#__PURE__*/React.createElement("defs", null, /*#__PURE__*/React.createElement("linearGradient", {
    id: "barG",
    x1: "0",
    y1: "0",
    x2: "0",
    y2: "1"
  }, /*#__PURE__*/React.createElement("stop", {
    offset: "0",
    stopColor: "#3a3358"
  }), /*#__PURE__*/React.createElement("stop", {
    offset: "0.5",
    stopColor: "#1A1530"
  }), /*#__PURE__*/React.createElement("stop", {
    offset: "1",
    stopColor: "#0A0820"
  })), /*#__PURE__*/React.createElement("linearGradient", {
    id: "muzzleG",
    x1: "0",
    y1: "0",
    x2: "0",
    y2: "1"
  }, /*#__PURE__*/React.createElement("stop", {
    offset: "0",
    stopColor: "#5a5470"
  }), /*#__PURE__*/React.createElement("stop", {
    offset: "1",
    stopColor: "#2A2547"
  }))), /*#__PURE__*/React.createElement("rect", {
    x: "14",
    y: "22",
    width: "36",
    height: "20",
    rx: "4",
    fill: "#1A1530"
  }), /*#__PURE__*/React.createElement("rect", {
    x: "14",
    y: "22",
    width: "36",
    height: "3",
    fill: "rgba(255,255,255,.18)"
  }), /*#__PURE__*/React.createElement("rect", {
    x: "40",
    y: "26",
    width: "150",
    height: "12",
    rx: "4",
    fill: "url(#barG)"
  }), /*#__PURE__*/React.createElement("rect", {
    x: "42",
    y: "27",
    width: "146",
    height: "2",
    rx: "1",
    fill: "rgba(255,255,255,.25)"
  }), /*#__PURE__*/React.createElement("rect", {
    x: "184",
    y: "22",
    width: "22",
    height: "20",
    rx: "3",
    fill: "url(#muzzleG)"
  }), /*#__PURE__*/React.createElement("rect", {
    x: "188",
    y: "26",
    width: "2",
    height: "12",
    fill: "#0A0820"
  }), /*#__PURE__*/React.createElement("rect", {
    x: "194",
    y: "26",
    width: "2",
    height: "12",
    fill: "#0A0820"
  }), /*#__PURE__*/React.createElement("rect", {
    x: "200",
    y: "26",
    width: "2",
    height: "12",
    fill: "#0A0820"
  }), /*#__PURE__*/React.createElement("rect", {
    x: "22",
    y: "14",
    width: "6",
    height: "10",
    fill: "#1A1530"
  }), /*#__PURE__*/React.createElement("circle", {
    cx: "25",
    cy: "13",
    r: "3",
    fill: "#F33F3F"
  }));
}
function Mountains() {
  return /*#__PURE__*/React.createElement("div", {
    className: "gm-horizon"
  }, /*#__PURE__*/React.createElement("svg", {
    viewBox: "0 0 1600 240",
    preserveAspectRatio: "none",
    "aria-hidden": true
  }, /*#__PURE__*/React.createElement("path", {
    d: "M0,150 L120,90 L240,130 L380,70 L520,118 L660,82 L800,124 L940,86 L1080,128 L1220,94 L1360,126 L1500,90 L1600,118 L1600,240 L0,240 Z",
    fill: "#B6B1E0"
  }), /*#__PURE__*/React.createElement("path", {
    d: "M0,200 L160,140 L300,180 L440,118 L580,158 L720,128 L860,168 L1000,134 L1140,170 L1280,140 L1420,176 L1560,148 L1600,164 L1600,240 L0,240 Z",
    fill: "#8E89C8"
  })));
}
function SkyZ() {
  return /*#__PURE__*/React.createElement("div", {
    className: "gm-sky-z",
    "aria-hidden": true
  }, /*#__PURE__*/React.createElement("div", {
    className: "z",
    style: {
      top: "6%",
      left: "8%",
      width: "26%",
      background: "rgba(255,255,255,.65)"
    }
  }), /*#__PURE__*/React.createElement("div", {
    className: "z",
    style: {
      top: "10%",
      left: "46%",
      width: "20%",
      background: "rgba(255,255,255,.5)"
    }
  }), /*#__PURE__*/React.createElement("div", {
    className: "z",
    style: {
      top: "18%",
      left: "22%",
      width: "14%",
      background: "rgba(255,255,255,.35)"
    }
  }), /*#__PURE__*/React.createElement("div", {
    className: "z",
    style: {
      top: "26%",
      left: "62%",
      width: "22%",
      background: "rgba(255,255,255,.4)"
    }
  }));
}
function Heart(_ref4) {
  var lost = _ref4.lost;
  return /*#__PURE__*/React.createElement("svg", {
    viewBox: "0 0 24 24",
    className: lost ? "lost" : ""
  }, /*#__PURE__*/React.createElement("path", {
    fill: "#F33F3F",
    d: "M12 21s-7.5-4.7-9.6-9.5C.9 7.7 3.5 4 7.2 4c2 0 3.6 1 4.8 2.6C13.2 5 14.8 4 16.8 4c3.7 0 6.3 3.7 4.8 7.5C19.5 16.3 12 21 12 21z"
  }));
}
var I = {
  pause: function pause() {
    return /*#__PURE__*/React.createElement("svg", {
      viewBox: "0 0 24 24",
      width: "16",
      height: "16",
      fill: "currentColor"
    }, /*#__PURE__*/React.createElement("path", {
      d: "M9 5h2v14H9zM13 5h2v14h-2z"
    }));
  },
  speaker: function speaker() {
    return /*#__PURE__*/React.createElement("svg", {
      viewBox: "0 0 24 24",
      width: "18",
      height: "18",
      fill: "currentColor"
    }, /*#__PURE__*/React.createElement("path", {
      d: "M3 10v4a1 1 0 0 0 1 1h3l4 3.5a1 1 0 0 0 1.6-.8V6.3a1 1 0 0 0-1.6-.8L7 9H4a1 1 0 0 0-1 1Z"
    }));
  },
  speakerMute: function speakerMute() {
    return /*#__PURE__*/React.createElement("svg", {
      viewBox: "0 0 24 24",
      width: "18",
      height: "18",
      fill: "none",
      stroke: "currentColor",
      strokeWidth: "2.2",
      strokeLinecap: "round",
      strokeLinejoin: "round"
    }, /*#__PURE__*/React.createElement("path", {
      d: "M3 10v4a1 1 0 0 0 1 1h3l4 3.5a1 1 0 0 0 1.6-.8V6.3a1 1 0 0 0-1.6-.8L7 9H4a1 1 0 0 0-1 1Z",
      fill: "currentColor",
      stroke: "none"
    }), /*#__PURE__*/React.createElement("path", {
      d: "M16 8l5 5M21 8l-5 5"
    }));
  },
  expand: function expand() {
    return /*#__PURE__*/React.createElement("svg", {
      viewBox: "0 0 24 24",
      width: "18",
      height: "18",
      fill: "none",
      stroke: "currentColor",
      strokeWidth: "2.2",
      strokeLinecap: "round",
      strokeLinejoin: "round"
    }, /*#__PURE__*/React.createElement("path", {
      d: "M4 9V4h5M20 9V4h-5M4 15v5h5M20 15v5h-5"
    }));
  },
  home: function home() {
    return /*#__PURE__*/React.createElement("svg", {
      viewBox: "0 0 24 24",
      width: "20",
      height: "20",
      fill: "none",
      stroke: "currentColor",
      strokeWidth: "2.2",
      strokeLinecap: "round",
      strokeLinejoin: "round"
    }, /*#__PURE__*/React.createElement("path", {
      d: "M3 11l9-8 9 8"
    }), /*#__PURE__*/React.createElement("path", {
      d: "M5 10v10h14V10"
    }), /*#__PURE__*/React.createElement("path", {
      d: "M10 20v-6h4v6"
    }));
  },
  trophy: function trophy() {
    return /*#__PURE__*/React.createElement("svg", {
      viewBox: "0 0 24 24",
      width: "22",
      height: "22",
      fill: "none",
      stroke: "currentColor",
      strokeWidth: "2.2",
      strokeLinecap: "round",
      strokeLinejoin: "round"
    }, /*#__PURE__*/React.createElement("path", {
      d: "M8 21h8M12 17v4M7 4h10v5a5 5 0 0 1-10 0V4z"
    }), /*#__PURE__*/React.createElement("path", {
      d: "M7 6H4v2a3 3 0 0 0 3 3M17 6h3v2a3 3 0 0 1-3 3"
    }));
  }
};
function ScopeIcon() {
  return /*#__PURE__*/React.createElement("svg", {
    viewBox: "0 0 32 32",
    fill: "none",
    stroke: "#F37327",
    strokeWidth: "2.2"
  }, /*#__PURE__*/React.createElement("circle", {
    cx: "16",
    cy: "16",
    r: "11"
  }), /*#__PURE__*/React.createElement("path", {
    d: "M16 2v6 M16 24v6 M2 16h6 M24 16h6",
    strokeLinecap: "round"
  }), /*#__PURE__*/React.createElement("circle", {
    cx: "16",
    cy: "16",
    r: "2",
    fill: "#F37327",
    stroke: "none"
  }));
}

/* ──────────────────────────────────────────────
   Stage scaler: fits 1600×900 into viewport, letterboxing.
   ────────────────────────────────────────────── */
function useStageScale(designW, designH) {
  var _useState = useState(1),
    _useState2 = _slicedToArray(_useState, 2),
    scale = _useState2[0],
    setScale = _useState2[1];
  useLayoutEffect(function () {
    var recalc = function recalc() {
      var w = window.innerWidth;
      var h = window.innerHeight;
      setScale(Math.min(w / designW, h / designH));
    };
    recalc();
    window.addEventListener("resize", recalc);
    return function () {
      return window.removeEventListener("resize", recalc);
    };
  }, [designW, designH]);
  return scale;
}

/* ──────────────────────────────────────────────
   Upload screen — load Excel/CSV
   ────────────────────────────────────────────── */
function UploadScreen(_ref5) {
  var onLoad = _ref5.onLoad;
  var _useState3 = useState(false),
    _useState4 = _slicedToArray(_useState3, 2),
    drag = _useState4[0],
    setDrag = _useState4[1];
  var _useState5 = useState(null),
    _useState6 = _slicedToArray(_useState5, 2),
    err = _useState6[0],
    setErr = _useState6[1];
  var _useState7 = useState(false),
    _useState8 = _slicedToArray(_useState7, 2),
    busy = _useState8[0],
    setBusy = _useState8[1];
  var inputRef = useRef(null);
  var handle = useCallback(/*#__PURE__*/function () {
    var _ref6 = _asyncToGenerator(/*#__PURE__*/_regenerator().m(function _callee(file) {
      var entries, _t;
      return _regenerator().w(function (_context) {
        while (1) switch (_context.p = _context.n) {
          case 0:
            if (file) {
              _context.n = 1;
              break;
            }
            return _context.a(2);
          case 1:
            setErr(null);
            setBusy(true);
            _context.p = 2;
            _context.n = 3;
            return parseSpreadsheet(file);
          case 3:
            entries = _context.v;
            onLoad(entries, file.name);
            _context.n = 5;
            break;
          case 4:
            _context.p = 4;
            _t = _context.v;
            setErr(_t.message || "שגיאה בקריאת הקובץ");
          case 5:
            _context.p = 5;
            setBusy(false);
            return _context.f(5);
          case 6:
            return _context.a(2);
        }
      }, _callee, null, [[2, 4, 5, 6]]);
    }));
    return function (_x) {
      return _ref6.apply(this, arguments);
    };
  }(), [onLoad]);
  var onDrop = function onDrop(e) {
    var _e$dataTransfer;
    e.preventDefault();
    setDrag(false);
    var f = (_e$dataTransfer = e.dataTransfer) === null || _e$dataTransfer === void 0 || (_e$dataTransfer = _e$dataTransfer.files) === null || _e$dataTransfer === void 0 ? void 0 : _e$dataTransfer[0];
    if (f) handle(f);
  };
  return /*#__PURE__*/React.createElement("div", {
    className: "gm-app gm-up-app"
  }, /*#__PURE__*/React.createElement("div", {
    className: "gm-up-wrap"
  }, /*#__PURE__*/React.createElement("div", {
    className: "gm-up-card"
  }, /*#__PURE__*/React.createElement("div", {
    className: "gm-up-eye"
  }, /*#__PURE__*/React.createElement("span", {
    className: "brand-eazy"
  }, "eazy"), " \xB7 \u05DE\u05E9\u05D7\u05E7 \u05DE\u05D9\u05DC\u05D9\u05DD"), /*#__PURE__*/React.createElement("h1", {
    className: "gm-up-h1"
  }, "\u05D8\u05E2\u05E0\u05D5 \u05DE\u05D9\u05DC\u05D5\u05DF \u05DC\u05DE\u05E9\u05D7\u05E7."), /*#__PURE__*/React.createElement("p", {
    className: "gm-up-sub"
  }, "\u05E7\u05D5\u05D1\u05E5 Excel \u05D0\u05D5 CSV. \u05E2\u05DE\u05D5\u05D3\u05D4 B = \u05DE\u05D9\u05DC\u05D4 \u05D1\u05D0\u05E0\u05D2\u05DC\u05D9\u05EA, \u05E2\u05DE\u05D5\u05D3\u05D4 C = \u05E4\u05D9\u05E8\u05D5\u05E9 \u05D1\u05E2\u05D1\u05E8\u05D9\u05EA. \u05E0\u05D1\u05D7\u05E8 \u05D1\u05DB\u05DC \u05E1\u05D9\u05D1\u05D5\u05D1 4 \u05DE\u05D9\u05DC\u05D9\u05DD: \u05D0\u05D7\u05EA \u05D4\u05E0\u05DB\u05D5\u05E0\u05D4, \u05E9\u05DC\u05D5\u05E9 \u05D0\u05D7\u05E8\u05D5\u05EA \u05DE\u05D4\u05DE\u05D9\u05DC\u05D5\u05DF \u05DB\u05DE\u05E1\u05D9\u05D7\u05D9\u05DD."), /*#__PURE__*/React.createElement("div", {
    className: "gm-dropzone " + (drag ? "drag" : ""),
    onClick: function onClick() {
      var _inputRef$current;
      return (_inputRef$current = inputRef.current) === null || _inputRef$current === void 0 ? void 0 : _inputRef$current.click();
    },
    onDragOver: function onDragOver(e) {
      e.preventDefault();
      setDrag(true);
    },
    onDragLeave: function onDragLeave() {
      return setDrag(false);
    },
    onDrop: onDrop
  }, /*#__PURE__*/React.createElement("div", {
    className: "gm-dz-icon"
  }, /*#__PURE__*/React.createElement("svg", {
    viewBox: "0 0 32 32",
    width: "42",
    height: "42",
    fill: "none",
    stroke: "#F37327",
    strokeWidth: "2",
    strokeLinecap: "round",
    strokeLinejoin: "round"
  }, /*#__PURE__*/React.createElement("path", {
    d: "M16 4v18"
  }), /*#__PURE__*/React.createElement("path", {
    d: "M9 11l7-7 7 7"
  }), /*#__PURE__*/React.createElement("path", {
    d: "M4 26h24"
  }))), /*#__PURE__*/React.createElement("div", {
    className: "gm-dz-title"
  }, "\u05D2\u05E8\u05E8\u05D5 \u05DC\u05DB\u05D0\u05DF \u05D0\u05D5 \u05DC\u05D7\u05E6\u05D5"), /*#__PURE__*/React.createElement("div", {
    className: "gm-dz-sub"
  }, ".xlsx / .xls / .csv"), /*#__PURE__*/React.createElement("input", {
    ref: inputRef,
    type: "file",
    accept: ".xlsx,.xls,.csv,application/vnd.ms-excel,application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",
    style: {
      display: "none"
    },
    onChange: function onChange(e) {
      return handle(e.target.files[0]);
    }
  })), busy && /*#__PURE__*/React.createElement("div", {
    className: "gm-up-info"
  }, "\u05E7\u05D5\u05E8\u05D0\u05D9 \u05D0\u05EA \u05D4\u05E7\u05D5\u05D1\u05E5\u2026"), err && /*#__PURE__*/React.createElement("div", {
    className: "gm-up-err"
  }, err), /*#__PURE__*/React.createElement("div", {
    className: "gm-up-or"
  }, "\u2014 \u05D0\u05D5 \u2014"), /*#__PURE__*/React.createElement("button", {
    className: "gm-up-btn-ghost",
    onClick: function onClick() {
      return onLoad(SAMPLE_DICT, "מילון לדוגמה");
    }
  }, "\u05D4\u05EA\u05D7\u05D9\u05DC\u05D5 \u05E2\u05DD \u05DE\u05D9\u05DC\u05D5\u05DF \u05D3\u05D5\u05D2\u05DE\u05D4 (", SAMPLE_DICT.length, " \u05DE\u05D9\u05DC\u05D9\u05DD)"), /*#__PURE__*/React.createElement("div", {
    className: "gm-up-format"
  }, /*#__PURE__*/React.createElement("div", {
    className: "gm-fmt-title"
  }, "\u05E4\u05D5\u05E8\u05DE\u05D8 \u05D4\u05E7\u05D5\u05D1\u05E5:"), /*#__PURE__*/React.createElement("table", null, /*#__PURE__*/React.createElement("thead", null, /*#__PURE__*/React.createElement("tr", null, /*#__PURE__*/React.createElement("th", null, "A"), /*#__PURE__*/React.createElement("th", null, "B \u2014 English"), /*#__PURE__*/React.createElement("th", null, "C \u2014 \u05E2\u05D1\u05E8\u05D9\u05EA"))), /*#__PURE__*/React.createElement("tbody", null, /*#__PURE__*/React.createElement("tr", null, /*#__PURE__*/React.createElement("td", null, "1"), /*#__PURE__*/React.createElement("td", {
    dir: "ltr"
  }, "enhance"), /*#__PURE__*/React.createElement("td", null, "\u05DC\u05D4\u05E2\u05E6\u05D9\u05DD, \u05DC\u05E9\u05E4\u05E8")), /*#__PURE__*/React.createElement("tr", null, /*#__PURE__*/React.createElement("td", null, "2"), /*#__PURE__*/React.createElement("td", {
    dir: "ltr"
  }, "mitigate"), /*#__PURE__*/React.createElement("td", null, "\u05DC\u05D4\u05E7\u05DC, \u05DC\u05DE\u05EA\u05DF")), /*#__PURE__*/React.createElement("tr", null, /*#__PURE__*/React.createElement("td", null, "3"), /*#__PURE__*/React.createElement("td", {
    dir: "ltr"
  }, "ambiguous"), /*#__PURE__*/React.createElement("td", null, "\u05D3\u05D5-\u05DE\u05E9\u05DE\u05E2\u05D9")))), /*#__PURE__*/React.createElement("div", {
    className: "gm-fmt-note"
  }, "\u05E9\u05D5\u05E8\u05EA \u05DB\u05D5\u05EA\u05E8\u05EA \u05EA\u05D6\u05D5\u05D4\u05D4 \u05D0\u05D5\u05D8\u05D5\u05DE\u05D8\u05D9\u05EA. \u05E2\u05DE\u05D5\u05D3\u05D4 A \u05DE\u05EA\u05E2\u05DC\u05DE\u05D9\u05DD \u05DE\u05DE\u05E0\u05D4 (\u05DE\u05E1\u05E4\u05D5\u05E8 / \u05DE\u05D6\u05D4\u05D4).")))));
}

/* ──────────────────────────────────────────────
   Intro screen — first thing the user sees
   ───────────────────────────────────────────── */
function IntroScreen(_ref7) {
  var onStart = _ref7.onStart,
    toggleFullscreen = _ref7.toggleFullscreen,
    muted = _ref7.muted,
    toggleMute = _ref7.toggleMute;
  var scale = useStageScale(1600, 900);
  // Combined handler: enter fullscreen on the user's tap (must come from a
  // gesture) and then start the round. Failures are non-fatal — we still
  // start the game even if the browser blocks fullscreen.
  var startAndFullscreen = function startAndFullscreen() {
    try {
      var el = document.documentElement;
      var req = el.requestFullscreen || el.webkitRequestFullscreen || el.msRequestFullscreen;
      if (req && !document.fullscreenElement && !document.webkitFullscreenElement) {
        var p = req.call(el);
        if (p && typeof p.catch === 'function') p.catch(function () {});
      }
    } catch (e) {}
    onStart();
  };
  return /*#__PURE__*/React.createElement("div", {
    className: "gm-app"
  }, /*#__PURE__*/React.createElement("div", {
    className: "gm-stage gm-intro-stage",
    style: {
      "--gm-scale": scale
    }
  }, /*#__PURE__*/React.createElement(SkyZ, null), /*#__PURE__*/React.createElement(Mountains, null), /*#__PURE__*/React.createElement("div", {
    className: "gm-ground"
  }), /*#__PURE__*/React.createElement("div", {
    className: "gm-hud-brand"
  }, /*#__PURE__*/React.createElement("img", {
    src: window.__resources.ezIcon,
    alt: ""
  }), /*#__PURE__*/React.createElement("span", {
    className: "brand-eazy"
  }, "eazy")), /*#__PURE__*/React.createElement("div", {
    className: "gm-cannon gm-intro-cannon"
  }, /*#__PURE__*/React.createElement(CannonBase, null), /*#__PURE__*/React.createElement("div", {
    className: "barrel-wrap"
  }, /*#__PURE__*/React.createElement("svg", {
    style: {
      position: "absolute",
      width: "220px",
      height: "60px",
      top: "-30px",
      left: "-30px",
      transformOrigin: "30px 30px",
      transform: "rotate(-22deg)",
      overflow: "visible"
    },
    viewBox: "0 0 220 60"
  }, /*#__PURE__*/React.createElement("defs", null, /*#__PURE__*/React.createElement("linearGradient", {
    id: "barG3",
    x1: "0",
    y1: "0",
    x2: "0",
    y2: "1"
  }, /*#__PURE__*/React.createElement("stop", {
    offset: "0",
    stopColor: "#3a3358"
  }), /*#__PURE__*/React.createElement("stop", {
    offset: "0.5",
    stopColor: "#1A1530"
  }), /*#__PURE__*/React.createElement("stop", {
    offset: "1",
    stopColor: "#0A0820"
  })), /*#__PURE__*/React.createElement("linearGradient", {
    id: "muzzleG3",
    x1: "0",
    y1: "0",
    x2: "0",
    y2: "1"
  }, /*#__PURE__*/React.createElement("stop", {
    offset: "0",
    stopColor: "#5a5470"
  }), /*#__PURE__*/React.createElement("stop", {
    offset: "1",
    stopColor: "#2A2547"
  }))), /*#__PURE__*/React.createElement("rect", {
    x: "14",
    y: "22",
    width: "36",
    height: "20",
    rx: "4",
    fill: "#1A1530"
  }), /*#__PURE__*/React.createElement("rect", {
    x: "14",
    y: "22",
    width: "36",
    height: "3",
    fill: "rgba(255,255,255,.18)"
  }), /*#__PURE__*/React.createElement("rect", {
    x: "40",
    y: "26",
    width: "150",
    height: "12",
    rx: "4",
    fill: "url(#barG3)"
  }), /*#__PURE__*/React.createElement("rect", {
    x: "42",
    y: "27",
    width: "146",
    height: "2",
    rx: "1",
    fill: "rgba(255,255,255,.25)"
  }), /*#__PURE__*/React.createElement("rect", {
    x: "184",
    y: "22",
    width: "22",
    height: "20",
    rx: "3",
    fill: "url(#muzzleG3)"
  }), /*#__PURE__*/React.createElement("rect", {
    x: "188",
    y: "26",
    width: "2",
    height: "12",
    fill: "#0A0820"
  }), /*#__PURE__*/React.createElement("rect", {
    x: "194",
    y: "26",
    width: "2",
    height: "12",
    fill: "#0A0820"
  }), /*#__PURE__*/React.createElement("rect", {
    x: "200",
    y: "26",
    width: "2",
    height: "12",
    fill: "#0A0820"
  }), /*#__PURE__*/React.createElement("rect", {
    x: "22",
    y: "14",
    width: "6",
    height: "10",
    fill: "#1A1530"
  }), /*#__PURE__*/React.createElement("circle", {
    cx: "25",
    cy: "13",
    r: "3",
    fill: "#F33F3F"
  })))), /*#__PURE__*/React.createElement("div", {
    className: "gm-intro-text"
  }, /*#__PURE__*/React.createElement("div", {
    className: "gm-intro-eye"
  }, "\u05DE\u05E9\u05D7\u05E7 \u05D0\u05E0\u05D2\u05DC\u05D9\u05EA \u05DE\u05D1\u05D9\u05EA ", /*#__PURE__*/React.createElement("span", {
    className: "en brand-eazy"
  }, "eazy")), /*#__PURE__*/React.createElement("h1", {
    className: "gm-intro-title"
  }, "\u05EA\u05D5\u05EA\u05D7 \u05DE\u05D9\u05DC\u05D9\u05DD", /*#__PURE__*/React.createElement("span", {
    className: "dot"
  }, ".")), /*#__PURE__*/React.createElement("p", {
    className: "gm-intro-lead"
  }, "\u05E2\u05D5\u05DE\u05D3\u05D9\u05DD \u05DC\u05E8\u05E9\u05D5\u05EA\u05DB\u05DD \u05EA\u05D5\u05EA\u05D7 \u05DE\u05D9\u05DC\u05D9\u05DD \u05D5\u05D4\u05D9\u05D3\u05E2 \u05E9\u05DC\u05DB\u05DD \u05D1\u05D0\u05E0\u05D2\u05DC\u05D9\u05EA."), /*#__PURE__*/React.createElement("p", {
    className: "gm-intro-body"
  }, "\u05D1\u05EA\u05D7\u05EA\u05D9\u05EA \u05D4\u05DE\u05E1\u05DA \u05DE\u05D5\u05E4\u05D9\u05E2\u05D4 \u05DE\u05D9\u05DC\u05D4 \u05D1\u05D0\u05E0\u05D2\u05DC\u05D9\u05EA. \u05D6\u05D4\u05D5 \u05D0\u05EA \u05D4\u05D8\u05D9\u05DC \u05E2\u05DD \u05D4\u05E4\u05D9\u05E8\u05D5\u05E9 \u05D4\u05DE\u05EA\u05D0\u05D9\u05DD \u05D5\u05EA\u05DC\u05D7\u05E6\u05D5 \u05E2\u05DC\u05D9\u05D5.", /*#__PURE__*/React.createElement("br", null), "\u05DB\u05DB\u05DC \u05E9\u05E2\u05D5\u05E0\u05D9\u05DD \u05DE\u05D4\u05E8 \u05D9\u05D5\u05EA\u05E8, \u05E6\u05D5\u05D1\u05E8\u05D9\u05DD \u05D9\u05D5\u05EA\u05E8 \u05E0\u05E7\u05D5\u05D3\u05D5\u05EA. \u05D1\u05D4\u05E6\u05DC\u05D7\u05D4!")), /*#__PURE__*/React.createElement("button", {
    className: "gm-intro-cta",
    onClick: startAndFullscreen
  }, /*#__PURE__*/React.createElement("span", null, "\u05DC\u05D4\u05EA\u05D7\u05D9\u05DC \u05DC\u05E9\u05D7\u05E7"), /*#__PURE__*/React.createElement("svg", {
    viewBox: "0 0 24 24",
    width: "28",
    height: "28",
    fill: "none",
    stroke: "currentColor",
    strokeWidth: "2.6",
    strokeLinecap: "round",
    strokeLinejoin: "round"
  }, /*#__PURE__*/React.createElement("path", {
    d: "M19 12H5"
  }), /*#__PURE__*/React.createElement("path", {
    d: "M12 19l-7-7 7-7"
  }))), /*#__PURE__*/React.createElement("div", {
    className: "gm-foot-actions"
  }, /*#__PURE__*/React.createElement("button", {
    className: "foot-btn",
    onClick: function onClick() {
      try {
        window.top.location.href = "https://www.ezway.co.il";
      } catch (e) {
        window.open("https://www.ezway.co.il", "_top");
      }
    },
    title: "\u05D0\u05EA\u05E8 \u05D4\u05D1\u05D9\u05EA"
  }, /*#__PURE__*/React.createElement(I.home, null)), /*#__PURE__*/React.createElement("button", {
    className: "foot-btn",
    onClick: toggleFullscreen,
    title: "\u05DE\u05E1\u05DA \u05DE\u05DC\u05D0"
  }, /*#__PURE__*/React.createElement(I.expand, null)), /*#__PURE__*/React.createElement("button", {
    className: "foot-btn" + (muted ? " muted" : ""),
    onClick: toggleMute,
    title: muted ? "השמע צלילים" : "השתק צלילים"
  }, muted ? /*#__PURE__*/React.createElement(I.speakerMute, null) : /*#__PURE__*/React.createElement(I.speaker, null)))));
}
function EndScreen(_ref8) {
  var score = _ref8.score,
    missedWords = _ref8.missedWords,
    onRestart = _ref8.onRestart;
  var _useState9 = useState(false),
    _useState0 = _slicedToArray(_useState9, 2),
    submitted = _useState0[0],
    setSubmitted = _useState0[1];
  var _useState1 = useState(""),
    _useState10 = _slicedToArray(_useState1, 2),
    name = _useState10[0],
    setName = _useState10[1];
  var _useState11 = useState(function () {
      return getLeaderboard();
    }),
    _useState12 = _slicedToArray(_useState11, 2),
    board = _useState12[0],
    setBoard = _useState12[1];
  var _useState13 = useState(false),
    _useState14 = _slicedToArray(_useState13, 2),
    showLb = _useState14[0],
    setShowLb = _useState14[1];
  var qualifies = qualifiesForLeaderboard(score) && !submitted;
  var submitName = function submitName() {
    var newBoard = addToLeaderboard(name.trim() || "אנונימי", score);
    setBoard(newBoard);
    setSubmitted(true);
    setShowLb(true); // auto-open to show new ranking
  };
  return /*#__PURE__*/React.createElement("div", {
    className: "gm-app gm-end-app"
  }, /*#__PURE__*/React.createElement("div", {
    className: "gm-end-hud"
  }, /*#__PURE__*/React.createElement("button", {
    className: "gm-end-home",
    onClick: function onClick() {
      try {
        window.top.location.href = "https://www.ezway.co.il";
      } catch (e) {
        window.open("https://www.ezway.co.il", "_top");
      }
    },
    title: "\u05D0\u05EA\u05E8 \u05D4\u05D1\u05D9\u05EA",
    "aria-label": "\u05DC\u05D0\u05EA\u05E8 eazy"
  }, /*#__PURE__*/React.createElement(I.home, null)), /*#__PURE__*/React.createElement("div", {
    className: "gm-end-brand"
  }, /*#__PURE__*/React.createElement("img", {
    src: window.__resources.ezIcon,
    alt: ""
  }), /*#__PURE__*/React.createElement("span", {
    className: "brand-eazy"
  }, "eazy"))), /*#__PURE__*/React.createElement("div", {
    className: "gm-end-score"
  }, /*#__PURE__*/React.createElement("div", {
    className: "gm-end-score-text"
  }, /*#__PURE__*/React.createElement("div", {
    className: "gm-end-eye"
  }, "\u05E1\u05D5\u05E3 \u05E1\u05D9\u05D1\u05D5\u05D1", /*#__PURE__*/React.createElement("span", {
    className: "dot"
  }, ".")), /*#__PURE__*/React.createElement("div", {
    className: "gm-end-line"
  }, /*#__PURE__*/React.createElement("span", null, "\u05D4\u05E9\u05D2\u05EA"), /*#__PURE__*/React.createElement("span", {
    className: "num"
  }, score), /*#__PURE__*/React.createElement("span", null, "\u05E0\u05E7\u05D5\u05D3\u05D5\u05EA."))), qualifies ? /*#__PURE__*/React.createElement("div", {
    className: "gm-lb-prompt"
  }, /*#__PURE__*/React.createElement("div", {
    className: "gm-lb-prompt-eye"
  }, /*#__PURE__*/React.createElement(I.trophy, null), " \u05E0\u05DB\u05E0\u05E1\u05EA \u05DC\u05D8\u05D1\u05DC\u05EA \u05D4\u05E9\u05D9\u05D0\u05D9\u05DD!"), /*#__PURE__*/React.createElement("div", {
    className: "gm-lb-prompt-row"
  }, /*#__PURE__*/React.createElement("input", {
    className: "gm-lb-input",
    type: "text",
    placeholder: "\u05D4\u05E9\u05DD \u05E9\u05DC\u05DA",
    value: name,
    onChange: function onChange(e) {
      return setName(e.target.value);
    },
    onKeyDown: function onKeyDown(e) {
      return e.key === 'Enter' && submitName();
    },
    maxLength: 20,
    autoFocus: true
  }), /*#__PURE__*/React.createElement("button", {
    className: "gm-lb-save",
    onClick: submitName
  }, "\u05E9\u05DE\u05D5\u05E8"))) : /*#__PURE__*/React.createElement("button", {
    className: "gm-end-cta secondary gm-end-lb-btn",
    onClick: function onClick() {
      return setShowLb(true);
    }
  }, /*#__PURE__*/React.createElement(I.trophy, null), /*#__PURE__*/React.createElement("span", null, "\u05D8\u05D1\u05DC\u05EA \u05D4\u05E9\u05D9\u05D0\u05D9\u05DD"))), /*#__PURE__*/React.createElement("div", {
    className: "gm-end-vrule"
  }), /*#__PURE__*/React.createElement("div", {
    className: "gm-end-list-wrap"
  }, missedWords.length > 0 ? /*#__PURE__*/React.createElement(React.Fragment, null, /*#__PURE__*/React.createElement("div", {
    className: "gm-end-list-eye"
  }, "\u05D0\u05DC\u05D5 \u05D4\u05DE\u05D9\u05DC\u05D9\u05DD \u05E9\u05E4\u05E1\u05E4\u05E1\u05EA"), /*#__PURE__*/React.createElement("div", {
    className: "gm-end-list"
  }, missedWords.map(function (w, i) {
    return /*#__PURE__*/React.createElement("div", {
      key: i,
      className: "gm-end-row"
    }, /*#__PURE__*/React.createElement("span", {
      className: "gm-end-en"
    }, String(w.en).toUpperCase()), /*#__PURE__*/React.createElement("span", {
      className: "gm-end-he"
    }, w.he));
  }))) : /*#__PURE__*/React.createElement("div", {
    className: "gm-end-no-miss"
  }, /*#__PURE__*/React.createElement("span", {
    className: "hi"
  }, "\u05DB\u05DC \u05D4\u05DB\u05D1\u05D5\u05D3", /*#__PURE__*/React.createElement("span", {
    className: "dot"
  }, "!")), /*#__PURE__*/React.createElement("span", {
    className: "lo"
  }, "\u05DC\u05D0 \u05E4\u05E1\u05E4\u05E1\u05EA \u05D0\u05E3 \u05DE\u05D9\u05DC\u05D4.")), /*#__PURE__*/React.createElement("button", {
    className: "gm-end-cta gm-end-restart",
    onClick: onRestart
  }, /*#__PURE__*/React.createElement("span", null, "\u05D9\u05D5\u05E6\u05D0\u05D9\u05DD \u05DC\u05E1\u05D9\u05D1\u05D5\u05D1 \u05E0\u05D5\u05E1\u05E3 \u05E2\u05DD \u05D4\u05EA\u05D5\u05EA\u05D7?"), /*#__PURE__*/React.createElement("span", {
    className: "cta-arrow",
    "aria-hidden": true
  }, "\u203A"))), showLb && /*#__PURE__*/React.createElement("div", {
    className: "gm-lb-modal",
    onClick: function onClick() {
      return setShowLb(false);
    }
  }, /*#__PURE__*/React.createElement("div", {
    className: "gm-lb-modal-card",
    onClick: function onClick(e) {
      return e.stopPropagation();
    }
  }, /*#__PURE__*/React.createElement("button", {
    className: "gm-lb-close",
    onClick: function onClick() {
      return setShowLb(false);
    },
    "aria-label": "\u05E1\u05D2\u05D5\u05E8"
  }, "\xD7"), /*#__PURE__*/React.createElement("div", {
    className: "gm-lb-title"
  }, /*#__PURE__*/React.createElement(I.trophy, null), /*#__PURE__*/React.createElement("span", null, "\u05D8\u05D1\u05DC\u05EA \u05D4\u05E9\u05D9\u05D0\u05D9\u05DD")), board.length === 0 ? /*#__PURE__*/React.createElement("div", {
    className: "gm-lb-empty"
  }, "\u05E2\u05D3\u05D9\u05D9\u05DF \u05D0\u05D9\u05DF \u05E9\u05D9\u05D0\u05D9\u05DD. \u05D0\u05EA\u05D4 \u05D9\u05DB\u05D5\u05DC \u05DC\u05D4\u05D9\u05D5\u05EA \u05D4\u05E8\u05D0\u05E9\u05D5\u05DF.") : /*#__PURE__*/React.createElement("ol", {
    className: "gm-lb-list"
  }, board.map(function (entry, i) {
    return /*#__PURE__*/React.createElement("li", {
      key: i,
      className: "gm-lb-row " + (submitted && entry.score === score && entry.name === (name.trim() || "אנונימי") ? "you" : "")
    }, /*#__PURE__*/React.createElement("span", {
      className: "rank"
    }, i + 1), /*#__PURE__*/React.createElement("span", {
      className: "name"
    }, entry.name), /*#__PURE__*/React.createElement("span", {
      className: "pts"
    }, entry.score));
  })))));
}

/* ──────────────────────────────────────────────
   Game
   ────────────────────────────────────────────── */
function Game() {
  var _useState15 = useState(false),
    _useState16 = _slicedToArray(_useState15, 2),
    started = _useState16[0],
    setStarted = _useState16[1];
  var _useState17 = useState(null),
    _useState18 = _slicedToArray(_useState17, 2),
    dict = _useState18[0],
    setDict = _useState18[1];
  var _useState19 = useState(""),
    _useState20 = _slicedToArray(_useState19, 2),
    dictName = _useState20[0],
    setDictName = _useState20[1];
  var _useState21 = useState([]),
    _useState22 = _slicedToArray(_useState21, 2),
    used = _useState22[0],
    setUsed = _useState22[1];
  var _useState23 = useState([]),
    _useState24 = _slicedToArray(_useState23, 2),
    missed = _useState24[0],
    setMissed = _useState24[1];
  var _useState25 = useState(null),
    _useState26 = _slicedToArray(_useState25, 2),
    question = _useState26[0],
    setQuestion = _useState26[1];
  var _useState27 = useState(3),
    _useState28 = _slicedToArray(_useState27, 2),
    lives = _useState28[0],
    setLives = _useState28[1];
  var _useState29 = useState(0),
    _useState30 = _slicedToArray(_useState29, 2),
    score = _useState30[0],
    setScore = _useState30[1];
  var _useState31 = useState(null),
    _useState32 = _slicedToArray(_useState31, 2),
    aimed = _useState32[0],
    setAimed = _useState32[1];
  var _useState33 = useState({}),
    _useState34 = _slicedToArray(_useState33, 2),
    resolved = _useState34[0],
    setResolved = _useState34[1];
  var _useState35 = useState(-18),
    _useState36 = _slicedToArray(_useState35, 2),
    angle = _useState36[0],
    setAngle = _useState36[1];
  var _useState37 = useState(null),
    _useState38 = _slicedToArray(_useState37, 2),
    shot = _useState38[0],
    setShot = _useState38[1];
  var _useState39 = useState(null),
    _useState40 = _slicedToArray(_useState39, 2),
    toast = _useState40[0],
    setToast = _useState40[1];
  var _useState41 = useState(false),
    _useState42 = _slicedToArray(_useState41, 2),
    missFx = _useState42[0],
    setMissFx = _useState42[1];
  var _useState43 = useState(false),
    _useState44 = _slicedToArray(_useState43, 2),
    recoil = _useState44[0],
    setRecoil = _useState44[1];
  var _useState45 = useState(null),
    _useState46 = _slicedToArray(_useState45, 2),
    levelUpInfo = _useState46[0],
    setLevelUpInfo = _useState46[1];
  var _useState47 = useState(false),
    _useState48 = _slicedToArray(_useState47, 2),
    audioUnlocked = _useState48[0],
    setAudioUnlocked = _useState48[1];
  var _useState49 = useState(true),
    _useState50 = _slicedToArray(_useState49, 2),
    autoSpeakEnabled = _useState50[0],
    setAutoSpeakEnabled = _useState50[1];
  // streak (consecutive correct answers), and the last time a streak bonus
  // fired — combo bonuses are gated to once per 5 minutes so they stay rare.
  var _useState51 = useState(0),
    _useState52 = _slicedToArray(_useState51, 2),
    streak = _useState52[0],
    setStreak = _useState52[1];
  var lastBonusTimeRef = useRef(0);
  var questionStartRef = useRef(Date.now());
  var _useState53 = useState(Sound.muted),
    _useState54 = _slicedToArray(_useState53, 2),
    muted = _useState54[0],
    setMuted = _useState54[1];
  // lifelines & bonuses
  var _useState55 = useState(true),
    _useState56 = _slicedToArray(_useState55, 2),
    fiftyAvailable = _useState56[0],
    setFiftyAvailable = _useState56[1];
  var _useState57 = useState(function () {
      return new Set();
    }),
    _useState58 = _slicedToArray(_useState57, 2),
    hiddenIdx = _useState58[0],
    setHiddenIdx = _useState58[1];
  var _useState59 = useState(null),
    _useState60 = _slicedToArray(_useState59, 2),
    kitState = _useState60[0],
    setKitState = _useState60[1];
  var prevQuestionEnRef = useRef(null);
  var prevLevelRef = useRef(0);
  var stageRef = useRef(null);
  var cannonRef = useRef(null);
  var rocketRefs = useRef([]);
  var scale = useStageScale(1600, 900);

  // ── level system: every 15 questions speeds up + raises points ──
  var level = Math.floor(used.length / 15);
  var rocketDur = Math.max(8, 22 - level * 3); // seconds, min 8s
  var pointsPerHit = 200 + level * 100;
  useEffect(function () {
    if (level > prevLevelRef.current && used.length > 0) {
      setLevelUpInfo({
        sub: "\u05D4\u05D8\u05D9\u05DC\u05D9\u05DD \u05DE\u05D4\u05D9\u05E8\u05D9\u05DD \u05D9\u05D5\u05EA\u05E8 \xB7 +".concat(pointsPerHit, " \u05DC\u05DB\u05DC \u05EA\u05E9\u05D5\u05D1\u05D4 \u05E0\u05DB\u05D5\u05E0\u05D4")
      });
      var t = setTimeout(function () {
        return setLevelUpInfo(null);
      }, 2600);
      prevLevelRef.current = level;
      return function () {
        return clearTimeout(t);
      };
    }
    prevLevelRef.current = level;
  }, [level, used.length, pointsPerHit]);

  // ── BOSS question + audio unlock ──
  // The 6th question (after 5 normal answers) is a one-time BOSS round. Hitting
  // it unlocks the per-word speaker icon for the rest of the run.
  var isBoss = used.length === 5 && !audioUnlocked;

  // Speak the current English word via the browser's SpeechSynthesis. Works
  // regardless of the game's mute toggle (those are SFX/music; this is content).
  var speakWord = useCallback(function (text) {
    if (!text) return;
    try {
      var synth = window.speechSynthesis;
      if (!synth) return;
      synth.cancel();
      var u = new SpeechSynthesisUtterance(String(text));
      u.lang = 'en-US';
      u.rate = 0.85;
      u.pitch = 1.0;
      u.volume = 1.0;
      // Prefer a real English voice if the browser has finished loading them.
      try {
        var voices = synth.getVoices ? synth.getVoices() : [];
        var en = voices.find(function (v) {
          return /^en[-_]/i.test(v.lang);
        }) || voices.find(function (v) {
          return /english/i.test(v.name);
        });
        if (en) u.voice = en;
      } catch (e) {}
      synth.speak(u);
    } catch (e) {/* ignore — TTS just won't fire */}
  }, []);

  // After the BOSS is beaten and audio is unlocked, auto-speak every new word.
  // Three independent guards: the audio must be unlocked (boss beaten), the
  // user must have opted in at the level-up screen, and the master sound
  // toggle must be unmuted.
  useEffect(function () {
    if (!audioUnlocked) return;
    if (!autoSpeakEnabled) return;
    if (muted) return;
    if (!(question !== null && question !== void 0 && question.en)) return;
    // Small delay so the new word has time to render and any in-flight SFX
    // (hit/levelup) doesn't compete with the TTS.
    var t = setTimeout(function () {
      return speakWord(question.en);
    }, 350);
    return function () {
      return clearTimeout(t);
    };
  }, [audioUnlocked, autoSpeakEnabled, muted, question === null || question === void 0 ? void 0 : question.en, speakWord]);

  // mouse-tracking aim when idle
  useEffect(function () {
    var stage = stageRef.current;
    var cannon = cannonRef.current;
    if (!stage || !cannon) return;
    var onMove = function onMove(ev) {
      if (aimed !== null) return; // a shot is in flight
      if (isRoundOver) return;
      var sR = stage.getBoundingClientRect();
      var cR = cannon.getBoundingClientRect();
      var mx = (ev.clientX - sR.left) / scale;
      var my = (ev.clientY - sR.top) / scale;
      var fromX = (cR.left - sR.left + cR.width * 0.5) / scale;
      var fromY = (cR.top - sR.top + cR.height * 0.42) / scale;
      var ang = Math.atan2(my - fromY, mx - fromX) * (180 / Math.PI);
      // clamp barrel rotation
      if (ang < -55) ang = -55;
      if (ang > 20) ang = 20;
      setAngle(ang);
    };
    stage.addEventListener("mousemove", onMove);
    return function () {
      return stage.removeEventListener("mousemove", onMove);
    };
  }, [aimed, isRoundOver, scale]);

  // fullscreen toggle — also locks orientation to landscape on mobile
  var toggleFullscreen = useCallback(function () {
    try {
      var target = window.frameElement ? window.frameElement : document.documentElement;
      var doc = window.frameElement ? window.parent.document : document;
      var isFs = doc.fullscreenElement || doc.webkitFullscreenElement;
      if (!isFs) {
        var req = target.requestFullscreen || target.webkitRequestFullscreen || target.mozRequestFullScreen || target.msRequestFullscreen;
        if (req) {
          var p = req.call(target);
          // attempt to lock landscape on mobile devices
          if (p && p.then) {
            p.then(function () {
              try {
                if (screen.orientation && screen.orientation.lock) {
                  screen.orientation.lock('landscape').catch(function () {});
                }
              } catch (e) {}
            }).catch(function () {});
          } else {
            try {
              if (screen.orientation && screen.orientation.lock) {
                screen.orientation.lock('landscape').catch(function () {});
              }
            } catch (e) {}
          }
        }
      } else {
        try {
          if (screen.orientation && screen.orientation.unlock) screen.orientation.unlock();
        } catch (e) {}
        var exit = doc.exitFullscreen || doc.webkitExitFullscreen || doc.mozCancelFullScreen || doc.msExitFullscreen;
        if (exit) exit.call(doc);
      }
    } catch (e) {/* permission blocked in iframe — silent */}
  }, []);

  // mute toggle — controls background music, sound FX, AND (after the BOSS
  // unlock) the per-word audio. This is the single source of truth for any
  // sound coming out of the game.
  var toggleMute = useCallback(function () {
    var next = !Sound.muted;
    Sound.setMuted(next);
    setMuted(next);
    if (next) {
      // muting → stop any in-flight TTS immediately
      try {
        var _window$speechSynthes;
        (_window$speechSynthes = window.speechSynthesis) === null || _window$speechSynthes === void 0 || _window$speechSynthes.cancel();
      } catch (e) {}
    }
  }, []);

  // hydrate dictionary — bundled words.js takes precedence over localStorage
  useEffect(function () {
    if (window.GAME_DICTIONARY && Array.isArray(window.GAME_DICTIONARY) && window.GAME_DICTIONARY.length >= 4) {
      setDict(window.GAME_DICTIONARY);
      setDictName("מילון המשחק");
      return;
    }
    try {
      var raw = localStorage.getItem(DICT_STORAGE_KEY);
      if (raw) {
        var arr = JSON.parse(raw);
        if (Array.isArray(arr) && arr.length >= 4) {
          setDict(arr);
          setDictName(localStorage.getItem(DICT_NAME_KEY) || "");
        }
      }
    } catch (e) {}
  }, []);

  // draw a question whenever dict changes or used grows
  useEffect(function () {
    if (!dict) return;
    var available = dict.map(function (_, i) {
      return i;
    }).filter(function (i) {
      return !used.includes(i);
    });
    if (available.length === 0) {
      setQuestion(null);
      return;
    }
    var correctIdx = available[Math.floor(Math.random() * available.length)];
    setQuestion(_objectSpread(_objectSpread({}, buildQuestion(dict, correctIdx)), {}, {
      correctDictIdx: correctIdx
    }));
  }, [dict, used]);
  var loadDict = useCallback(function (entries, name) {
    setDict(entries);
    setDictName(name);
    setUsed([]);
    setMissed([]);
    setLives(3);
    setScore(0);
    setResolved({});
    setAimed(null);
    try {
      localStorage.setItem(DICT_STORAGE_KEY, JSON.stringify(entries));
      localStorage.setItem(DICT_NAME_KEY, name);
    } catch (e) {}
  }, []);
  var resetDict = useCallback(function () {
    setDict(null);
    setDictName("");
    setUsed([]);
    setMissed([]);
    setLives(3);
    setScore(0);
    setResolved({});
    setAimed(null);
    setQuestion(null);
    try {
      localStorage.removeItem(DICT_STORAGE_KEY);
      localStorage.removeItem(DICT_NAME_KEY);
    } catch (e) {}
  }, []);
  var restartGame = useCallback(function () {
    setUsed([]);
    setMissed([]);
    setLives(3);
    setScore(0);
    setResolved({});
    setAimed(null);
    setFiftyAvailable(true);
    setHiddenIdx(new Set());
    setKitState(null);
    setAudioUnlocked(false);
    setAutoSpeakEnabled(true);
    setLevelUpInfo(null);
    setStreak(0);
    lastBonusTimeRef.current = 0;
    questionStartRef.current = Date.now();
    prevLevelRef.current = 0;
    Sound.startMusic();
  }, []);
  var correctIdx = question ? question.options.indexOf(question.correct) : -1;
  var isRoundOver = resolved[correctIdx] === "hit" || lives <= 0;

  // Reset 50/50 hidden distractors whenever a new question appears;
  // every 8th question, drop a first-aid kit (if not full lives + not already showing).
  useEffect(function () {
    if (!question) return;
    if (prevQuestionEnRef.current !== question.en) {
      setHiddenIdx(new Set());
      prevQuestionEnRef.current = question.en;
      // Stamp the new question's start time so the speed bonus can be computed
      // when the user finally shoots.
      questionStartRef.current = Date.now();
      if (used.length > 0 && used.length % 8 === 0 && !kitState && lives < 3) {
        setKitState({
          id: Date.now()
        });
      }
    }
  }, [question, used.length, lives, kitState]);

  // 50/50 lifeline: hide 2 of the 3 wrong distractors
  var useFifty = useCallback(function () {
    if (!fiftyAvailable || !question || isRoundOver) return;
    var wrongs = question.options.map(function (_, i) {
      return i;
    }).filter(function (i) {
      return i !== correctIdx;
    });
    var toHide = shuffleArr(wrongs).slice(0, 2);
    setHiddenIdx(new Set(toHide));
    setFiftyAvailable(false);
    Sound.play('fifty');
  }, [fiftyAvailable, question, correctIdx, isRoundOver]);

  // Shooting the first-aid kit grants a life back
  var onKitHit = useCallback(function () {
    if (!kitState) return;
    setLives(function (l) {
      return Math.min(3, l + 1);
    });
    setKitState(null);
    Sound.play('lifegain');
    setToast({
      kind: "win",
      text: "+1 לב · תיק עזרה ראשונה!"
    });
    setTimeout(function () {
      return setToast(null);
    }, 1800);
  }, [kitState]);

  // Kit auto-vanishes if not shot in time
  useEffect(function () {
    if (!kitState) return;
    var t = setTimeout(function () {
      return setKitState(null);
    }, 9000);
    return function () {
      return clearTimeout(t);
    };
  }, [kitState]);
  var nextQuestion = useCallback(function () {
    if (!question) return;
    setUsed(function (u) {
      return [].concat(_toConsumableArray(u), [question.correctDictIdx]);
    });
    setResolved({});
    setAimed(null);
    setAngle(-18);
  }, [question]);
  var onTarget = useCallback(function (i) {
    if (!question) return;
    if (hiddenIdx.has(i)) return;
    if (resolved[i] || isRoundOver || aimed !== null) return;
    setAimed(i);
    Sound.play('shoot');
    var stage = stageRef.current;
    var cannon = cannonRef.current;
    var target = rocketRefs.current[i];
    if (!stage || !cannon || !target) return;
    var sR = stage.getBoundingClientRect();
    var cR = cannon.getBoundingClientRect();
    var tR = target.getBoundingClientRect();
    var fromX = (cR.left - sR.left + cR.width * 0.5) / scale;
    var fromY = (cR.top - sR.top + cR.height * 0.42) / scale;
    var toX = (tR.left - sR.left + 70) / scale;
    var toY = (tR.top - sR.top + tR.height * 0.5) / scale;
    var ang = Math.atan2(toY - fromY, toX - fromX) * (180 / Math.PI);
    setAngle(ang);
    setTimeout(function () {
      setShot({
        fromX: fromX,
        fromY: fromY,
        toX: toX,
        toY: toY
      });
      setTimeout(function () {
        var correct = i === correctIdx;
        var isBossHit = isBoss && correct;
        setResolved(function (r) {
          return _objectSpread(_objectSpread({}, r), {}, _defineProperty({}, i, correct ? "hit" : "missed"));
        });
        if (correct) {
          // ── speed bonus: faster hits earn more points (linear 2× → 1×) ──
          var effectiveDur = isBoss ? rocketDur * 0.8 : rocketDur;
          var elapsed = (Date.now() - questionStartRef.current) / 1000;
          var speedMult = Math.max(1, Math.min(2, 2 - elapsed / Math.max(1, effectiveDur)));

          // ── streak bonus: every 5 in a row unlocks a special — but a special
          // bonus fires at most once per 5 minutes so it stays meaningful. ──
          var newStreak = streak + 1;
          var now = Date.now();
          var cooldownPassed = now - lastBonusTimeRef.current >= 5 * 60 * 1000;
          var comboMult = 1,
            comboBonus = 0,
            comboLabel = null;
          if (newStreak >= 5 && newStreak % 5 === 0 && cooldownPassed) {
            if (newStreak >= 20) {
              comboMult = 3;
              comboLabel = "\u05E1\u05D8\u05E8\u05D9\u05E7 ".concat(newStreak, " \u2726 \xD73 \u05E0\u05D9\u05E7\u05D5\u05D3");
            } else if (newStreak >= 10) {
              comboMult = 2;
              comboLabel = "\u05E1\u05D8\u05E8\u05D9\u05E7 ".concat(newStreak, " \u2726 \xD72 \u05E0\u05D9\u05E7\u05D5\u05D3");
            } else {
              comboBonus = 500;
              comboLabel = "\u05E1\u05D8\u05E8\u05D9\u05E7 ".concat(newStreak, " \u2726 +500 \u05D1\u05D5\u05E0\u05D5\u05E1");
            }
            lastBonusTimeRef.current = now;
          }
          var basePoints = isBossHit ? 500 : pointsPerHit;
          var points = Math.round(basePoints * speedMult * comboMult) + comboBonus;
          setScore(function (s) {
            return s + points;
          });
          setStreak(newStreak);
          Sound.play(comboLabel ? 'levelup' : 'hit');
          if (comboLabel) {
            setToast({
              kind: "win",
              text: "".concat(comboLabel, " \xB7 +").concat(points)
            });
          } else {
            var speedTag = speedMult >= 1.7 ? "מהיר! " : speedMult >= 1.35 ? "יפה! " : "";
            setToast({
              kind: "win",
              text: "".concat(speedTag, "\u05E4\u05D2\u05D9\u05E2\u05D4 \u05D9\u05E9\u05D9\u05E8\u05D4 +").concat(points)
            });
          }
          // BOSS pass → unlock the per-word audio, show a custom level-up overlay.
          // The overlay has its own continue buttons so we DON'T auto-advance here.
          if (isBossHit) {
            setAudioUnlocked(true);
            Sound.play('levelup');
            setTimeout(function () {
              setLevelUpInfo({
                mode: 'audio',
                sub: 'מעכשיו אפשר גם לשמוע כל מילה באנגלית.'
              });
            }, 500);
          }
        } else {
          setStreak(0);
          setLives(function (l) {
            return Math.max(0, l - 1);
          });
          setMissed(function (m) {
            return m.includes(question.correctDictIdx) ? m : [].concat(_toConsumableArray(m), [question.correctDictIdx]);
          });
          setMissFx(true);
          setTimeout(function () {
            return setMissFx(false);
          }, 5400);
          setRecoil(true);
          setTimeout(function () {
            return setRecoil(false);
          }, 500);
          Sound.play('miss');
          setToast({
            kind: "lose",
            text: "פספסת — לב אחד נפל"
          });
          setTimeout(function () {
            setResolved(function (r) {
              return _objectSpread(_objectSpread({}, r), {}, _defineProperty({}, correctIdx, r[correctIdx] || "correct-after"));
            });
          }, 700);
        }
        setShot(null);
        setAimed(null);
        setTimeout(function () {
          return setToast(null);
        }, 1800);
        // auto-advance to next question — skipped for the BOSS hit (the
        // unlock overlay's "Continue" button handles that)
        if (!isBossHit) {
          setTimeout(function () {
            setUsed(function (u) {
              return [].concat(_toConsumableArray(u), [question.correctDictIdx]);
            });
            setResolved({});
            setAimed(null);
            setAngle(-18);
          }, correct ? 1400 : 5600);
        }
      }, 380);
    }, 340);
  }, [resolved, isRoundOver, aimed, correctIdx, scale, question, pointsPerHit, hiddenIdx, isBoss, rocketDur, streak]);

  // Rocket reaches the cannon zone = wrong answer
  var onTravelEnd = useCallback(function (i, e) {
    if (e.animationName !== "rocketTravel") return;
    // Hard guard: once the correct rocket is resolved (hit, missed, or
    // revealed-after), no other rocket of the same round can deduct another
    // life. Without this, multiple rockets reaching the line in a row burned
    // through every heart in one round.
    if (!question || resolved[i] || isRoundOver || resolved[correctIdx]) return;
    setStreak(0);
    setLives(function (l) {
      return Math.max(0, l - 1);
    });
    setMissed(function (m) {
      return m.includes(question.correctDictIdx) ? m : [].concat(_toConsumableArray(m), [question.correctDictIdx]);
    });
    setResolved(function (r) {
      return _objectSpread(_objectSpread({}, r), {}, _defineProperty(_defineProperty({}, i, "missed"), correctIdx, r[correctIdx] || "correct-after"));
    });
    setMissFx(true);
    setTimeout(function () {
      return setMissFx(false);
    }, 5400);
    Sound.play('miss');
    setToast({
      kind: "lose",
      text: "הטיל הגיע — לב אחד נפל"
    });
    setTimeout(function () {
      return setToast(null);
    }, 1800);
    setTimeout(function () {
      setUsed(function (u) {
        return [].concat(_toConsumableArray(u), [question.correctDictIdx]);
      });
      setResolved({});
      setAimed(null);
      setAngle(-18);
    }, 5600);
  }, [question, resolved, isRoundOver, correctIdx]);
  var shotEl = null;
  if (shot) {
    var dx = shot.toX - shot.fromX;
    var dy = shot.toY - shot.fromY;
    shotEl = /*#__PURE__*/React.createElement("div", {
      className: "gm-shot active",
      style: {
        left: shot.fromX,
        top: shot.fromY,
        animation: "shotFly .4s linear forwards",
        "--dx": "".concat(dx, "px"),
        "--dy": "".concat(dy, "px")
      }
    });
  }

  // ── intro first ──
  if (!started) return /*#__PURE__*/React.createElement(IntroScreen, {
    onStart: function onStart() {
      setStarted(true);
      Sound.startMusic();
      // Prime SpeechSynthesis on user gesture so iOS will let later auto-speaks fire.
      // Also kicks the browser to start loading its voice list.
      try {
        var s = window.speechSynthesis;
        if (s) {
          var _s$getVoices;
          var primer = new SpeechSynthesisUtterance(' ');
          primer.volume = 0;
          primer.rate = 1;
          s.speak(primer);
          (_s$getVoices = s.getVoices) === null || _s$getVoices === void 0 || _s$getVoices.call(s);
        }
      } catch (e) {}
    },
    toggleFullscreen: toggleFullscreen,
    muted: muted,
    toggleMute: toggleMute
  });

  // ── no dict yet — only shown if bundled words.js missing AND no localStorage ──
  if (!dict) return /*#__PURE__*/React.createElement(UploadScreen, {
    onLoad: loadDict
  });

  // ── game over (lives exhausted) ──
  if (lives <= 0) {
    var missedWords = missed.map(function (idx) {
      return dict[idx];
    }).filter(Boolean);
    return /*#__PURE__*/React.createElement(EndScreen, {
      score: score,
      missedWords: missedWords,
      onRestart: restartGame
    });
  }

  // ── dict exhausted ──
  if (!question) {
    return /*#__PURE__*/React.createElement("div", {
      className: "gm-app gm-up-app"
    }, /*#__PURE__*/React.createElement("div", {
      className: "gm-up-wrap"
    }, /*#__PURE__*/React.createElement("div", {
      className: "gm-up-card"
    }, /*#__PURE__*/React.createElement("div", {
      className: "gm-up-eye"
    }, "\u05E1\u05D9\u05D9\u05DE\u05EA\u05DD \u05D0\u05EA \u05D4\u05DE\u05D9\u05DC\u05D5\u05DF"), /*#__PURE__*/React.createElement("h1", {
      className: "gm-up-h1"
    }, used.length, " \u05DE\u05D9\u05DC\u05D9\u05DD \xB7 ", score, " \u05E0\u05E7\u05D5\u05D3\u05D5\u05EA"), /*#__PURE__*/React.createElement("p", {
      className: "gm-up-sub"
    }, "\u05E2\u05D1\u05E8\u05EA \u05E2\u05DC \u05DB\u05DC \u05D4\u05DE\u05D9\u05DC\u05D9\u05DD \u05D1\u05DE\u05D9\u05DC\u05D5\u05DF \"", dictName, "\". \u05DE\u05D4 \u05D4\u05DC\u05D0\u05D4?"), /*#__PURE__*/React.createElement("button", {
      className: "gm-up-btn",
      onClick: function onClick() {
        setUsed([]);
        setLives(3);
        setScore(0);
      }
    }, "\u05E1\u05D9\u05D1\u05D5\u05D1 \u05E0\u05D5\u05E1\u05E3 \u05E2\u05DD \u05D0\u05D5\u05EA\u05DD \u05DE\u05D9\u05DC\u05D9\u05DD"), /*#__PURE__*/React.createElement("button", {
      className: "gm-up-btn-ghost",
      onClick: resetDict
    }, "\u05D8\u05E2\u05E0\u05D5 \u05DE\u05D9\u05DC\u05D5\u05DF \u05D0\u05D7\u05E8"))));
  }
  return /*#__PURE__*/React.createElement("div", {
    className: "gm-app"
  }, /*#__PURE__*/React.createElement("div", {
    className: "gm-stage",
    ref: stageRef,
    style: {
      "--gm-scale": scale,
      "--rocket-duration": "".concat((isBoss ? rocketDur * 0.8 : rocketDur).toFixed(2), "s")
    }
  }, /*#__PURE__*/React.createElement(SkyZ, null), /*#__PURE__*/React.createElement(Mountains, null), /*#__PURE__*/React.createElement("div", {
    className: "gm-ground"
  }), /*#__PURE__*/React.createElement("div", {
    className: "gm-hud-brand"
  }, /*#__PURE__*/React.createElement("img", {
    src: window.__resources.ezIcon,
    alt: ""
  }), /*#__PURE__*/React.createElement("span", {
    className: "brand-eazy"
  }, "eazy")), /*#__PURE__*/React.createElement("div", {
    className: "gm-hud"
  }, /*#__PURE__*/React.createElement("div", {
    className: "chip hearts"
  }, [0, 1, 2].map(function (i) {
    return /*#__PURE__*/React.createElement(Heart, {
      key: i,
      lost: i >= lives
    });
  })), /*#__PURE__*/React.createElement("div", {
    className: "chip score"
  }, /*#__PURE__*/React.createElement("span", {
    className: "label"
  }, "\u05E0\u05D9\u05E7\u05D5\u05D3"), /*#__PURE__*/React.createElement("span", null, score)), /*#__PURE__*/React.createElement("div", {
    className: "spacer"
  })), isBoss && /*#__PURE__*/React.createElement("div", {
    className: "gm-boss-banner",
    "aria-hidden": true
  }, /*#__PURE__*/React.createElement("svg", {
    viewBox: "0 0 24 24",
    width: "32",
    height: "32",
    fill: "currentColor"
  }, /*#__PURE__*/React.createElement("path", {
    d: "M13 2 L4 14 L11 14 L10 22 L20 9 L13 9 Z"
  })), /*#__PURE__*/React.createElement("span", null, "\u05E9\u05DC\u05D1 BOSS"), /*#__PURE__*/React.createElement("svg", {
    viewBox: "0 0 24 24",
    width: "32",
    height: "32",
    fill: "currentColor"
  }, /*#__PURE__*/React.createElement("path", {
    d: "M13 2 L4 14 L11 14 L10 22 L20 9 L13 9 Z"
  }))), /*#__PURE__*/React.createElement("div", {
    className: "gm-word" + (isBoss ? " is-boss" : "") + (used.length === 0 ? " is-first" : "")
  }, /*#__PURE__*/React.createElement("div", {
    className: "en-wrap"
  }, /*#__PURE__*/React.createElement("div", {
    className: "en"
  }, question.en))), /*#__PURE__*/React.createElement("div", {
    className: "gm-foot-actions"
  }, /*#__PURE__*/React.createElement("button", {
    className: "foot-btn",
    onClick: function onClick() {
      try {
        window.top.location.href = "https://www.ezway.co.il";
      } catch (e) {
        window.open("https://www.ezway.co.il", "_top");
      }
    },
    title: "\u05D0\u05EA\u05E8 \u05D4\u05D1\u05D9\u05EA"
  }, /*#__PURE__*/React.createElement(I.home, null)), /*#__PURE__*/React.createElement("button", {
    className: "foot-btn",
    onClick: toggleFullscreen,
    title: "\u05DE\u05E1\u05DA \u05DE\u05DC\u05D0"
  }, /*#__PURE__*/React.createElement(I.expand, null)), /*#__PURE__*/React.createElement("button", {
    className: "foot-btn lifeline" + (fiftyAvailable ? "" : " used"),
    onClick: useFifty,
    disabled: !fiftyAvailable,
    title: fiftyAvailable ? "גלגל הצלה 50/50" : "כבר השתמשת ב-50/50"
  }, /*#__PURE__*/React.createElement("span", {
    className: "fifty-text"
  }, "50", /*#__PURE__*/React.createElement("br", null), "50")), /*#__PURE__*/React.createElement("button", {
    className: "foot-btn" + (muted ? " muted" : ""),
    onClick: toggleMute,
    title: muted ? "השמע צלילים" : "השתק צלילים"
  }, muted ? /*#__PURE__*/React.createElement(I.speakerMute, null) : /*#__PURE__*/React.createElement(I.speaker, null))), /*#__PURE__*/React.createElement("div", {
    className: "gm-rockets"
  }, question.options.map(function (opt, i) {
    var state = resolved[i];
    var cls = "gm-rocket";
    if (isBoss) cls += " boss";
    if (aimed === i) cls += " aiming";
    if (state === "hit") cls += " hit";else if (state === "missed") cls += " missed";else if (state === "correct-after") cls += " correct-after";
    var paused = isRoundOver || aimed === i || resolved[i] && resolved[i] !== "correct-after"; // correct-after keeps drifting
    var hidden = hiddenIdx.has(i);
    return /*#__PURE__*/React.createElement("div", {
      key: "".concat(question.en, "-").concat(i),
      className: "gm-rocket-travel" + (paused ? " paused" : "") + (hidden ? " hidden5050" : ""),
      style: {
        animationDelay: "".concat(-i * 1.5, "s")
      },
      onAnimationEnd: function onAnimationEnd(e) {
        return onTravelEnd(i, e);
      }
    }, /*#__PURE__*/React.createElement("div", {
      ref: function ref(el) {
        return rocketRefs.current[i] = el;
      },
      className: cls,
      style: {
        "--mr": STAGGER[i] + "px"
      },
      onClick: function onClick() {
        return onTarget(i);
      }
    }, /*#__PURE__*/React.createElement(RocketSVG, {
      isBoss: isBoss
    }), /*#__PURE__*/React.createElement("div", {
      className: "label"
    }, opt), /*#__PURE__*/React.createElement("div", {
      className: "gm-burst"
    }, /*#__PURE__*/React.createElement(BurstSVG, null))));
  })), /*#__PURE__*/React.createElement("div", {
    className: "gm-cannon" + (recoil ? " recoil" : ""),
    ref: cannonRef
  }, /*#__PURE__*/React.createElement(CannonBase, null), /*#__PURE__*/React.createElement("div", {
    className: "barrel-wrap"
  }, /*#__PURE__*/React.createElement("svg", {
    style: {
      position: "absolute",
      width: "220px",
      height: "60px",
      top: "-30px",
      left: "-30px",
      transformOrigin: "30px 30px",
      transform: "rotate(".concat(angle, "deg)"),
      transition: "transform .08s linear",
      overflow: "visible"
    },
    viewBox: "0 0 220 60"
  }, /*#__PURE__*/React.createElement("defs", null, /*#__PURE__*/React.createElement("linearGradient", {
    id: "barG2",
    x1: "0",
    y1: "0",
    x2: "0",
    y2: "1"
  }, /*#__PURE__*/React.createElement("stop", {
    offset: "0",
    stopColor: "#3a3358"
  }), /*#__PURE__*/React.createElement("stop", {
    offset: "0.5",
    stopColor: "#1A1530"
  }), /*#__PURE__*/React.createElement("stop", {
    offset: "1",
    stopColor: "#0A0820"
  })), /*#__PURE__*/React.createElement("linearGradient", {
    id: "muzzleG2",
    x1: "0",
    y1: "0",
    x2: "0",
    y2: "1"
  }, /*#__PURE__*/React.createElement("stop", {
    offset: "0",
    stopColor: "#5a5470"
  }), /*#__PURE__*/React.createElement("stop", {
    offset: "1",
    stopColor: "#2A2547"
  }))), /*#__PURE__*/React.createElement("rect", {
    x: "14",
    y: "22",
    width: "36",
    height: "20",
    rx: "4",
    fill: "#1A1530"
  }), /*#__PURE__*/React.createElement("rect", {
    x: "14",
    y: "22",
    width: "36",
    height: "3",
    fill: "rgba(255,255,255,.18)"
  }), /*#__PURE__*/React.createElement("rect", {
    x: "40",
    y: "26",
    width: "150",
    height: "12",
    rx: "4",
    fill: "url(#barG2)"
  }), /*#__PURE__*/React.createElement("rect", {
    x: "42",
    y: "27",
    width: "146",
    height: "2",
    rx: "1",
    fill: "rgba(255,255,255,.25)"
  }), /*#__PURE__*/React.createElement("rect", {
    x: "184",
    y: "22",
    width: "22",
    height: "20",
    rx: "3",
    fill: "url(#muzzleG2)"
  }), /*#__PURE__*/React.createElement("rect", {
    x: "188",
    y: "26",
    width: "2",
    height: "12",
    fill: "#0A0820"
  }), /*#__PURE__*/React.createElement("rect", {
    x: "194",
    y: "26",
    width: "2",
    height: "12",
    fill: "#0A0820"
  }), /*#__PURE__*/React.createElement("rect", {
    x: "200",
    y: "26",
    width: "2",
    height: "12",
    fill: "#0A0820"
  }), /*#__PURE__*/React.createElement("rect", {
    x: "22",
    y: "14",
    width: "6",
    height: "10",
    fill: "#1A1530"
  }), /*#__PURE__*/React.createElement("circle", {
    cx: "25",
    cy: "13",
    r: "3",
    fill: "#F33F3F"
  })))), shotEl, kitState && /*#__PURE__*/React.createElement("div", {
    className: "gm-kit-travel",
    key: kitState.id,
    onAnimationEnd: function onAnimationEnd() {
      return setKitState(null);
    }
  }, /*#__PURE__*/React.createElement("button", {
    className: "gm-kit",
    onClick: onKitHit,
    title: "\u05D9\u05E8\u05D4 \u05D1\u05EA\u05D9\u05E7 \u05DC\u05E2\u05D5\u05D3 \u05DC\u05D1!"
  }, /*#__PURE__*/React.createElement("svg", {
    viewBox: "0 0 120 110",
    "aria-hidden": true
  }, /*#__PURE__*/React.createElement("defs", null, /*#__PURE__*/React.createElement("linearGradient", {
    id: "kitG",
    x1: "0",
    y1: "0",
    x2: "0",
    y2: "1"
  }, /*#__PURE__*/React.createElement("stop", {
    offset: "0",
    stopColor: "#FFFFFF"
  }), /*#__PURE__*/React.createElement("stop", {
    offset: "1",
    stopColor: "#E8E6F0"
  })), /*#__PURE__*/React.createElement("linearGradient", {
    id: "kitHandleG",
    x1: "0",
    y1: "0",
    x2: "0",
    y2: "1"
  }, /*#__PURE__*/React.createElement("stop", {
    offset: "0",
    stopColor: "#3a3358"
  }), /*#__PURE__*/React.createElement("stop", {
    offset: "1",
    stopColor: "#1A1530"
  }))), /*#__PURE__*/React.createElement("ellipse", {
    cx: "60",
    cy: "102",
    rx: "42",
    ry: "5",
    fill: "rgba(0,0,0,.3)"
  }), /*#__PURE__*/React.createElement("rect", {
    x: "44",
    y: "8",
    width: "32",
    height: "14",
    rx: "3",
    fill: "url(#kitHandleG)",
    stroke: "#0A0820",
    strokeWidth: "2"
  }), /*#__PURE__*/React.createElement("rect", {
    x: "48",
    y: "14",
    width: "24",
    height: "8",
    rx: "2",
    fill: "rgba(255,255,255,.15)"
  }), /*#__PURE__*/React.createElement("rect", {
    x: "14",
    y: "22",
    width: "92",
    height: "76",
    rx: "8",
    fill: "url(#kitG)",
    stroke: "#0A0820",
    strokeWidth: "2.5"
  }), /*#__PURE__*/React.createElement("rect", {
    x: "52",
    y: "34",
    width: "16",
    height: "52",
    rx: "2",
    fill: "#DC2626"
  }), /*#__PURE__*/React.createElement("rect", {
    x: "34",
    y: "52",
    width: "52",
    height: "16",
    rx: "2",
    fill: "#DC2626"
  }), /*#__PURE__*/React.createElement("rect", {
    x: "20",
    y: "28",
    width: "80",
    height: "3",
    rx: "1.5",
    fill: "rgba(255,255,255,.5)"
  }), /*#__PURE__*/React.createElement("rect", {
    x: "56",
    y: "20",
    width: "8",
    height: "6",
    fill: "#3a3358"
  })), /*#__PURE__*/React.createElement("div", {
    className: "gm-kit-label"
  }, "+1 \u05DC\u05D1"))), missFx && /*#__PURE__*/React.createElement("div", {
    className: "gm-miss-jam",
    "aria-hidden": true
  }, /*#__PURE__*/React.createElement("svg", {
    viewBox: "0 0 1600 900",
    preserveAspectRatio: "none"
  }, /*#__PURE__*/React.createElement("defs", null, /*#__PURE__*/React.createElement("linearGradient", {
    id: "jamG",
    x1: "0",
    y1: "0",
    x2: "0",
    y2: "1"
  }, /*#__PURE__*/React.createElement("stop", {
    offset: "0",
    stopColor: "#7C170F",
    stopOpacity: ".95"
  }), /*#__PURE__*/React.createElement("stop", {
    offset: ".35",
    stopColor: "#9C1E16",
    stopOpacity: ".92"
  }), /*#__PURE__*/React.createElement("stop", {
    offset: ".75",
    stopColor: "#B5251B",
    stopOpacity: ".88"
  }), /*#__PURE__*/React.createElement("stop", {
    offset: ".94",
    stopColor: "#C72A1F",
    stopOpacity: ".84"
  }), /*#__PURE__*/React.createElement("stop", {
    offset: ".95",
    stopColor: "#C72A1F",
    stopOpacity: "0"
  }), /*#__PURE__*/React.createElement("stop", {
    offset: "1",
    stopColor: "#C72A1F",
    stopOpacity: "0"
  })), /*#__PURE__*/React.createElement("linearGradient", {
    id: "curtainG",
    x1: "0",
    y1: "0",
    x2: "0",
    y2: "1"
  }, /*#__PURE__*/React.createElement("stop", {
    offset: "0",
    stopColor: "#8E1A12",
    stopOpacity: ".95"
  }), /*#__PURE__*/React.createElement("stop", {
    offset: ".5",
    stopColor: "#A8201A",
    stopOpacity: ".92"
  }), /*#__PURE__*/React.createElement("stop", {
    offset: ".9",
    stopColor: "#B5251B",
    stopOpacity: ".90"
  }), /*#__PURE__*/React.createElement("stop", {
    offset: "1",
    stopColor: "#7C170F",
    stopOpacity: ".95"
  })), /*#__PURE__*/React.createElement("filter", {
    id: "jamBlur",
    x: "-3%",
    y: "-3%",
    width: "106%",
    height: "106%"
  }, /*#__PURE__*/React.createElement("feGaussianBlur", {
    stdDeviation: ".8"
  }))), /*#__PURE__*/React.createElement("path", {
    className: "jam-splat",
    d: "M 0 0 L 1600 0 L 1600 180 C 1540 220 1490 175 1440 200 C 1380 230 1330 175 1280 215 C 1230 245 1180 185 1130 225 C 1080 255 1030 200 980 230 C 930 265 880 195 830 240 C 780 275 730 215 680 245 C 630 280 580 210 530 250 C 480 280 430 220 380 260 C 330 290 280 225 230 265 C 180 295 130 230 80 270 C 50 290 30 250 0 275 Z",
    fill: "url(#jamG)",
    filter: "url(#jamBlur)"
  }), [
  // x1, x2 define the horizontal span; depth = how far below the splat band; delay = stagger
  {
    x1: 0,
    x2: 360,
    depth: 540,
    delay: 0.05,
    dur: 2.4
  }, {
    x1: 280,
    x2: 660,
    depth: 460,
    delay: 0.45,
    dur: 2.6
  }, {
    x1: 580,
    x2: 940,
    depth: 580,
    delay: 0.20,
    dur: 2.5
  }, {
    x1: 860,
    x2: 1220,
    depth: 500,
    delay: 0.65,
    dur: 2.4
  }, {
    x1: 1140,
    x2: 1480,
    depth: 560,
    delay: 0.30,
    dur: 2.6
  }, {
    x1: 1400,
    x2: 1600,
    depth: 480,
    delay: 0.55,
    dur: 2.5
  }].map(function (c, i) {
    var topY = 175;
    var bottomY = topY + c.depth;
    // wavy bottom edge — 3 peaks/valleys for irregularity
    var span = c.x2 - c.x1;
    var p1 = c.x1 + span * 0.20;
    var p2 = c.x1 + span * 0.45;
    var p3 = c.x1 + span * 0.72;
    var dip = c.depth * 0.18;
    var path = "\n                  M ".concat(c.x1, " ").concat(topY, "\n                  L ").concat(c.x2, " ").concat(topY, "\n                  L ").concat(c.x2, " ").concat(bottomY - dip * 0.6, "\n                  C ").concat(c.x2 - 40, " ").concat(bottomY + dip * 0.4, ", ").concat(p3 + 40, " ").concat(bottomY - dip, ", ").concat(p3, " ").concat(bottomY + dip * 0.6, "\n                  C ").concat(p3 - 40, " ").concat(bottomY + dip * 1.2, ", ").concat(p2 + 50, " ").concat(bottomY - dip * 0.8, ", ").concat(p2, " ").concat(bottomY + dip * 0.3, "\n                  C ").concat(p2 - 50, " ").concat(bottomY + dip * 0.9, ", ").concat(p1 + 40, " ").concat(bottomY - dip * 0.5, ", ").concat(p1, " ").concat(bottomY + dip * 0.5, "\n                  C ").concat(p1 - 40, " ").concat(bottomY + dip * 1.1, ", ").concat(c.x1 + 40, " ").concat(bottomY - dip * 0.3, ", ").concat(c.x1, " ").concat(bottomY - dip * 0.4, "\n                  Z\n                ");
    return /*#__PURE__*/React.createElement("path", {
      key: i,
      className: "jam-curtain",
      d: path,
      fill: "url(#curtainG)",
      filter: "url(#jamBlur)",
      style: {
        animationDelay: "".concat(c.delay, "s"),
        animationDuration: "".concat(c.dur, "s")
      }
    });
  }))), levelUpInfo && /*#__PURE__*/React.createElement("div", {
    className: "gm-levelup" + (levelUpInfo.mode === 'audio' ? " gm-levelup-audio" : "")
  }, /*#__PURE__*/React.createElement("div", {
    className: "gm-levelup-title"
  }, "\u05E2\u05DC\u05D9\u05EA \u05E9\u05DC\u05D1", /*#__PURE__*/React.createElement("span", {
    className: "dot"
  }, "!")), /*#__PURE__*/React.createElement("div", {
    className: "gm-levelup-sub"
  }, levelUpInfo.sub), levelUpInfo.mode === 'audio' && /*#__PURE__*/React.createElement(React.Fragment, null, /*#__PURE__*/React.createElement("div", {
    className: "gm-levelup-buttons"
  }, /*#__PURE__*/React.createElement("button", {
    className: "gm-levelup-cta",
    onClick: function onClick() {
      setAutoSpeakEnabled(true);
      // If the master sound was muted, unmute so the chosen word audio actually plays.
      if (Sound.muted) {
        Sound.setMuted(false);
        setMuted(false);
      }
      setLevelUpInfo(null);
      nextQuestion();
    }
  }, "\u05E8\u05D5\u05E6\u05D4 \u05DC\u05D4\u05DE\u05E9\u05D9\u05DA \u05E2\u05DD \u05D4\u05E9\u05DE\u05E2\u05EA \u05DE\u05D9\u05DC\u05D9\u05DD"), /*#__PURE__*/React.createElement("button", {
    className: "gm-levelup-cta secondary",
    onClick: function onClick() {
      setAutoSpeakEnabled(false);
      setLevelUpInfo(null);
      nextQuestion();
    }
  }, "\u05E8\u05D5\u05E6\u05D4 \u05DC\u05D4\u05DE\u05E9\u05D9\u05DA \u05DC\u05DC\u05D0 \u05D4\u05E9\u05DE\u05E2\u05EA \u05DE\u05D9\u05DC\u05D9\u05DD")), /*#__PURE__*/React.createElement("div", {
    className: "gm-levelup-note"
  }, /*#__PURE__*/React.createElement("span", {
    className: "star"
  }, "*"), " \u05EA\u05DE\u05D9\u05D3 \u05E0\u05D9\u05EA\u05DF \u05DC\u05D1\u05D8\u05DC \u05D4\u05E9\u05DE\u05E2\u05EA \u05DE\u05D9\u05DC\u05D9\u05DD \u05E2\u05DD \u05DC\u05D7\u05E6\u05DF \u05D4\u05E1\u05D0\u05D5\u05E0\u05D3"))), toast && /*#__PURE__*/React.createElement("div", {
    className: "gm-toast " + toast.kind
  }, /*#__PURE__*/React.createElement("span", {
    className: "dot"
  }), toast.text), /*#__PURE__*/React.createElement("style", null, "\n          @keyframes shotFly {\n            from { transform: translate(-50%, -50%) translate(0, 0); opacity: 1; }\n            to   { transform: translate(-50%, -50%) translate(var(--dx, 0px), var(--dy, 0px)); opacity: 1; }\n          }\n        ")));
}
window.Game = Game;
/* === mount === */
ReactDOM.createRoot(document.getElementById("root")).render(React.createElement(Game));
})(); } catch (e) { __ds_ns.__errors.push({ path: "quiz-game/dist/game.js", error: String((e && e.message) || e) }); }

// quiz-game/dist/words.js
try { (() => {
/* eazy · משחק תותח־מילים — מילון המשחק
   ─────────────────────────────────────────────────────────────
   זהו הדטה־בייס של המשחק. לכל שורה:
     en — המילה באנגלית
     he — הפירוש בעברית
   המשחק יטען את הרשימה הזו אוטומטית בכל מכשיר, ללא צורך בהעלאה.

   להוסיף/לערוך מילים — פשוט ערוך את הקובץ הזה ושמור.
   מספר הערכים הנוכחי: 637
*/
window.GAME_DICTIONARY = [{
  en: "a fortnight ago",
  he: "לפני שבועיים"
}, {
  en: "abduct",
  he: "לחטוף"
}, {
  en: "abolish",
  he: "לבטל"
}, {
  en: "accelerate",
  he: "להאיץ"
}, {
  en: "accent",
  he: "מבטא"
}, {
  en: "access",
  he: "גישה"
}, {
  en: "acclaim",
  he: "הכרה / הוקרה"
}, {
  en: "ache",
  he: "כאב / לכאוב"
}, {
  en: "activity",
  he: "פעילות"
}, {
  en: "acute",
  he: "חריף"
}, {
  en: "admiration",
  he: "הערצה"
}, {
  en: "admission process",
  he: "תהליך ההרשמה"
}, {
  en: "advertisement",
  he: "פרסומת"
}, {
  en: "adviser",
  he: "יועץ"
}, {
  en: "affirmative action",
  he: "העדפה מתקנת"
}, {
  en: "ague",
  he: "צמרמורת / קדחת"
}, {
  en: "aid",
  he: "עזרה"
}, {
  en: "ailment",
  he: "מחלה"
}, {
  en: "aimed at",
  he: "המכוון אל..."
}, {
  en: "alert",
  he: "כוננות"
}, {
  en: "allegation",
  he: "האשמה"
}, {
  en: "allegedly",
  he: "לכאורה"
}, {
  en: "ally",
  he: "בעל ברית"
}, {
  en: "along with",
  he: "לצד"
}, {
  en: "along side",
  he: "לצד / ליד"
}, {
  en: "ambassador",
  he: "שגריר"
}, {
  en: "ambiguous",
  he: "מעורפל"
}, {
  en: "ambition",
  he: "שאיפה"
}, {
  en: "ambitious",
  he: "שאפתן"
}, {
  en: "amnesia",
  he: "שכחה / נשייה"
}, {
  en: "ample",
  he: "הרבה / שפע"
}, {
  en: "analyze",
  he: "לנתח"
}, {
  en: "animosity",
  he: "עוינות"
}, {
  en: "annihilation",
  he: "השמדה מוחלטת"
}, {
  en: "anniversary",
  he: "יום השנה"
}, {
  en: "annoyance",
  he: "מטרד"
}, {
  en: "annulment",
  he: "ביטול נישואין"
}, {
  en: "anonymous",
  he: "אלמוני"
}, {
  en: "anthem",
  he: "המנון"
}, {
  en: "anticipation",
  he: "ציפייה"
}, {
  en: "anxious",
  he: "עצבני / מודאג"
}, {
  en: "any given moment",
  he: "כל רגע נתון"
}, {
  en: "apology",
  he: "התנצלות"
}, {
  en: "appear",
  he: "מופיע"
}, {
  en: "appliance",
  he: "כלי/מתקן"
}, {
  en: "application",
  he: "בקשה לקבלה"
}, {
  en: "approve",
  he: "לאשר"
}, {
  en: "arena",
  he: "זירה / מגרש"
}, {
  en: "argument",
  he: "ויכוח / טיעון"
}, {
  en: "arrogance",
  he: "שחצנות"
}, {
  en: "assessment",
  he: "הערכה"
}, {
  en: "associate",
  he: "עמית / שותף"
}, {
  en: "assumption",
  he: "הנחה"
}, {
  en: "astonishment",
  he: "תדהמה"
}, {
  en: "attack",
  he: "התקפה"
}, {
  en: "attendance",
  he: "נוכחות"
}, {
  en: "attention",
  he: "תשומת לב"
}, {
  en: "attribution",
  he: "ייחוס / תכונה"
}, {
  en: "awe-inspiring",
  he: "מעורר השתאות"
}, {
  en: "bark",
  he: "לנבוח"
}, {
  en: "barrier",
  he: "מחסום, סייג"
}, {
  en: "beforehand",
  he: "מראש"
}, {
  en: "bench",
  he: "ספסל"
}, {
  en: "beneficial",
  he: "מועיל / מיטיב"
}, {
  en: "beneficiary",
  he: "המוטב / הנהנה"
}, {
  en: "benefit",
  he: "להרוויח"
}, {
  en: "benign",
  he: "שפיר"
}, {
  en: "bequeath",
  he: "להוריש"
}, {
  en: "bereavement",
  he: "אבל / שכול"
}, {
  en: "bigotry",
  he: "גזענות"
}, {
  en: "birth",
  he: "לידה / ללדת"
}, {
  en: "blink",
  he: "מצמוץ"
}, {
  en: "blizzard",
  he: "סופה / סערה"
}, {
  en: "block",
  he: "לחסום"
}, {
  en: "board",
  he: "מועצה / לוח"
}, {
  en: "boldly",
  he: "באופן נועז"
}, {
  en: "bone-marrow",
  he: "מוח עצם"
}, {
  en: "border",
  he: "גבול / גבולי"
}, {
  en: "boredom",
  he: "שעמום"
}, {
  en: "boundless",
  he: "חסר גבולות"
}, {
  en: "brash",
  he: "פזיז / נמהר"
}, {
  en: "breast",
  he: "שד / חזה"
}, {
  en: "briefing",
  he: "תדריך"
}, {
  en: "brisk",
  he: "בחטף / במהרה"
}, {
  en: "broadcast",
  he: "לשדר / שידור"
}, {
  en: "broker",
  he: "מתווך / סוכן"
}, {
  en: "budget",
  he: "תקציב"
}, {
  en: "bulks",
  he: "כמויות גדולות"
}, {
  en: "buried",
  he: "קבור"
}, {
  en: "campaign",
  he: "מסע בחירות"
}, {
  en: "canal",
  he: "תעלה"
}, {
  en: "cancel",
  he: "לבטל"
}, {
  en: "candidate",
  he: "מועמד"
}, {
  en: "capsized",
  he: "מתהפך / מתבטל"
}, {
  en: "captions",
  he: "כתוביות"
}, {
  en: "capture",
  he: "ללכוד / לשבות"
}, {
  en: "careful consideration",
  he: "מחשבה מרובה"
}, {
  en: "cargo",
  he: "מטען"
}, {
  en: "cell",
  he: "תא"
}, {
  en: "cemeteries",
  he: "בתי קברות"
}, {
  en: "centric",
  he: "מרכזי"
}, {
  en: "chairman",
  he: "יו\"ר"
}, {
  en: "challenge",
  he: "אתגר"
}, {
  en: "charity",
  he: "צדקה"
}, {
  en: "charming",
  he: "מקסים"
}, {
  en: "chauvinistic",
  he: "שוביניסטי"
}, {
  en: "chronic illness",
  he: "מחלה כרונית"
}, {
  en: "circulated",
  he: "סבב / נפוץ"
}, {
  en: "civil",
  he: "אזרחי"
}, {
  en: "clarify",
  he: "להבהיר / לחדד"
}, {
  en: "clash",
  he: "עימות"
}, {
  en: "classified material",
  he: "חומר מסווג"
}, {
  en: "classify",
  he: "לסווג / למיין"
}, {
  en: "classified",
  he: "מסווג"
}, {
  en: "cloning",
  he: "לשכפל"
}, {
  en: "coach",
  he: "מאמן"
}, {
  en: "coating",
  he: "ציפוי"
}, {
  en: "coercion",
  he: "כפייה"
}, {
  en: "cognition",
  he: "תפישה"
}, {
  en: "colleague",
  he: "עמית"
}, {
  en: "collision",
  he: "התנגשות"
}, {
  en: "come to a halt",
  he: "לעצור / לחדול"
}, {
  en: "come to light",
  he: "נודע / הופיע"
}, {
  en: "comet",
  he: "כוכב שביט"
}, {
  en: "comfort",
  he: "הטבה / נוחיות"
}, {
  en: "commitment",
  he: "מחויבות"
}, {
  en: "committed to",
  he: "מסור ל..."
}, {
  en: "committee",
  he: "ועדה"
}, {
  en: "companion",
  he: "בן זוג / שותף"
}, {
  en: "compel",
  he: "לאלץ / לכפות"
}, {
  en: "complaint",
  he: "תלונה"
}, {
  en: "comprehensive",
  he: "מקיף וכוללני"
}, {
  en: "compromise",
  he: "להתפשר / לסכן"
}, {
  en: "compulsive",
  he: "כפייתי"
}, {
  en: "concentration",
  he: "ריכוז"
}, {
  en: "conditioning",
  he: "התניה"
}, {
  en: "confess",
  he: "להתוודות"
}, {
  en: "confronted",
  he: "מעומת למול"
}, {
  en: "connection",
  he: "קשר"
}, {
  en: "conniving",
  he: "תככן וחתרן"
}, {
  en: "conquest",
  he: "כיבוש"
}, {
  en: "consecutive",
  he: "רציף / רצוף"
}, {
  en: "considering",
  he: "בהתחשב"
}, {
  en: "consortium",
  he: "תאגיד"
}, {
  en: "construct",
  he: "לבנות"
}, {
  en: "continent",
  he: "יבשת"
}, {
  en: "continuity",
  he: "המשכיות"
}, {
  en: "continuously",
  he: "מתמשך"
}, {
  en: "contradiction",
  he: "סתירה"
}, {
  en: "contrary to",
  he: "בניגוד ל..."
}, {
  en: "conviction",
  he: "הרשעה / שכנוע"
}, {
  en: "convince",
  he: "לשכנע"
}, {
  en: "copyrights",
  he: "זכויות יוצרים"
}, {
  en: "coral",
  he: "אלמוג"
}, {
  en: "correspondent",
  he: "מתכתב / כתב"
}, {
  en: "co-star",
  he: "כוכב משנה"
}, {
  en: "counterfeit",
  he: "מזויף"
}, {
  en: "county judge",
  he: "שופט מחוזי"
}, {
  en: "courage",
  he: "אומץ"
}, {
  en: "court ruling",
  he: "פסיקת ביהמ\"ש"
}, {
  en: "cover story",
  he: "סיפור שער"
}, {
  en: "covert operation",
  he: "מבצע חשאי"
}, {
  en: "covertly",
  he: "בחשאיות"
}, {
  en: "covet",
  he: "לחמוד"
}, {
  en: "creativity",
  he: "יצירתיות"
}, {
  en: "credential",
  he: "מסמך / אישור"
}, {
  en: "credible",
  he: "מהימן / אמין"
}, {
  en: "crime prevention",
  he: "מניעת פשע"
}, {
  en: "crops",
  he: "יבולים"
}, {
  en: "crusade",
  he: "מסע צלב"
}, {
  en: "cumbersome",
  he: "מסורבל"
}, {
  en: "curse",
  he: "קללה"
}, {
  en: "debased",
  he: "פוגע / מעליב"
}, {
  en: "debut",
  he: "סרט ביכורים"
}, {
  en: "deceitfulness",
  he: "מרמה והונאה"
}, {
  en: "decentralized",
  he: "דה-צנטרליסטי"
}, {
  en: "decisive",
  he: "החלטי / מכריע"
}, {
  en: "debrief",
  he: "לתחקר"
}, {
  en: "decipher",
  he: "לפענח"
}, {
  en: "deduction",
  he: "דדוקציה"
}, {
  en: "defeat",
  he: "מפלה"
}, {
  en: "defect",
  he: "פגם / \"דפקט\""
}, {
  en: "defendant",
  he: "הנאשם"
}, {
  en: "defended",
  he: "הגן על..."
}, {
  en: "deform",
  he: "לעוות צורה"
}, {
  en: "defrost",
  he: "להפשיר"
}, {
  en: "denounce",
  he: "לגנות"
}, {
  en: "density",
  he: "צפיפות"
}, {
  en: "deny",
  he: "להכחיש"
}, {
  en: "depict",
  he: "לתאר"
}, {
  en: "deportation",
  he: "גירוש"
}, {
  en: "depression",
  he: "שפל"
}, {
  en: "descendant",
  he: "צאצא"
}, {
  en: "desirable",
  he: "נחשק"
}, {
  en: "deterrence",
  he: "הרתעה"
}, {
  en: "detest",
  he: "לתעב / לשנוא"
}, {
  en: "devastatingly",
  he: "באופן הרסני"
}, {
  en: "diminutive",
  he: "מקטין / זעיר"
}, {
  en: "disarray",
  he: "תוהו ובוהו"
}, {
  en: "discipline",
  he: "משמעת"
}, {
  en: "disclose",
  he: "לחשוף / לגלות"
}, {
  en: "disclosure",
  he: "חשיפה"
}, {
  en: "discount",
  he: "הנחה"
}, {
  en: "discovery",
  he: "תגלית"
}, {
  en: "disgusted",
  he: "נגעל"
}, {
  en: "disqualify",
  he: "לפסול"
}, {
  en: "disrupt",
  he: "להפריע"
}, {
  en: "distinguish",
  he: "להבחין"
}, {
  en: "distribute",
  he: "לחלק / להפיץ"
}, {
  en: "district",
  he: "מחוז / אזור"
}, {
  en: "disturbance",
  he: "הפרעה"
}, {
  en: "diver",
  he: "צוללן"
}, {
  en: "divulge",
  he: "לחשוף"
}, {
  en: "documentation",
  he: "תיעוד"
}, {
  en: "dodge",
  he: "להתחמק"
}, {
  en: "domain",
  he: "תחום"
}, {
  en: "dominated",
  he: "נשלט"
}, {
  en: "dormant",
  he: "רדום"
}, {
  en: "dosage",
  he: "מינון"
}, {
  en: "dot",
  he: "נקודה"
}, {
  en: "draw back",
  he: "לסגת / להירתע"
}, {
  en: "eager",
  he: "להוט"
}, {
  en: "earnest",
  he: "רציני"
}, {
  en: "echo",
  he: "הד"
}, {
  en: "editor",
  he: "עורך"
}, {
  en: "editorial",
  he: "מאמר מערכת"
}, {
  en: "educate",
  he: "לחנך"
}, {
  en: "efficient",
  he: "יעיל"
}, {
  en: "effort",
  he: "מאמץ / ניסיון"
}, {
  en: "elderly",
  he: "קשיש"
}, {
  en: "embezzle",
  he: "למעול / מעילה"
}, {
  en: "embrace",
  he: "לחבק"
}, {
  en: "emigrate",
  he: "להגר / לרדת"
}, {
  en: "employee",
  he: "עובד שכיר"
}, {
  en: "enclosure",
  he: "סגירת שטח"
}, {
  en: "encouragement",
  he: "עידוד"
}, {
  en: "endeavor",
  he: "מאמץ"
}, {
  en: "endorsement",
  he: "תמיכה / חסות"
}, {
  en: "enhance",
  he: "להרחיב"
}, {
  en: "enrollment",
  he: "הרשמה"
}, {
  en: "enthusiasm",
  he: "התלהבות"
}, {
  en: "eruption",
  he: "התפרצות"
}, {
  en: "espionage",
  he: "ריגול"
}, {
  en: "establishment",
  he: "מוסד / ממסד"
}, {
  en: "ethical",
  he: "אתי / מוסרי"
}, {
  en: "evaluation",
  he: "הערכה"
}, {
  en: "eventful",
  he: "מלא אירועים"
}, {
  en: "evolution",
  he: "אבולוציה"
}, {
  en: "excessive",
  he: "מוגזם"
}, {
  en: "excuse",
  he: "תירוץ"
}, {
  en: "expose",
  he: "לחשוף"
}, {
  en: "extend",
  he: "להאריך"
}, {
  en: "extensive",
  he: "מקיף"
}, {
  en: "extinction",
  he: "הכחדה"
}, {
  en: "facial features",
  he: "תווי פנים"
}, {
  en: "factor",
  he: "גורם"
}, {
  en: "faculty",
  he: "פקולטה"
}, {
  en: "fancy",
  he: "מהודר"
}, {
  en: "fan",
  he: "אוהד / מניפה"
}, {
  en: "favor",
  he: "טובה / העדפה"
}, {
  en: "feminine",
  he: "נשי"
}, {
  en: "ferocious",
  he: "פראי / אכזר"
}, {
  en: "ferociously",
  he: "באכזריות"
}, {
  en: "fertility",
  he: "פוריות"
}, {
  en: "feud",
  he: "משטמה"
}, {
  en: "fidelity",
  he: "נאמנות"
}, {
  en: "first aid",
  he: "עזרה ראשונה"
}, {
  en: "fixture",
  he: "משהו קבוע"
}, {
  en: "flat",
  he: "שטוח / דירה"
}, {
  en: "flaw",
  he: "חסרון / פגם"
}, {
  en: "flexibility",
  he: "גמישות"
}, {
  en: "foe",
  he: "אויב"
}, {
  en: "forge",
  he: "לזייף"
}, {
  en: "forming",
  he: "מייסדים"
}, {
  en: "fortify",
  he: "לבצר / לחזק"
}, {
  en: "foster",
  he: "לטפח / לאמץ"
}, {
  en: "found",
  he: "לייסד / להקים"
}, {
  en: "fraud",
  he: "הונאה / מרמה"
}, {
  en: "frown",
  he: "להזעיף פנים"
}, {
  en: "fruitful",
  he: "פורה"
}, {
  en: "frustrated",
  he: "מתוסכל"
}, {
  en: "function",
  he: "תפקוד"
}, {
  en: "fundamental",
  he: "בסיסי / יסודי"
}, {
  en: "furious",
  he: "זועם / \"רותח\""
}, {
  en: "gag order",
  he: "צו איסור פרסום"
}, {
  en: "gap",
  he: "פער"
}, {
  en: "genetic information",
  he: "מידע גנטי"
}, {
  en: "genuine",
  he: "מקורי / אמיתי"
}, {
  en: "get under way",
  he: "לצאת לדרך"
}, {
  en: "giant",
  he: "ענק"
}, {
  en: "glance",
  he: "מבט חטוף"
}, {
  en: "glimpse",
  he: "הצצה רגעית"
}, {
  en: "global economy",
  he: "כלכלה עולמית"
}, {
  en: "gown",
  he: "שמלה / חלוק"
}, {
  en: "graduate degree",
  he: "תואר אקדמאי"
}, {
  en: "greed",
  he: "תאוות בצע"
}, {
  en: "grief",
  he: "יגון"
}, {
  en: "guarded",
  he: "שמור"
}, {
  en: "guidance",
  he: "הנחיה"
}, {
  en: "gulf",
  he: "מפרץ"
}, {
  en: "halt",
  he: "לעצור / לחדול"
}, {
  en: "handcuffs",
  he: "אזיקים"
}, {
  en: "handy",
  he: "יעיל"
}, {
  en: "harbor",
  he: "נמל"
}, {
  en: "hearing",
  he: "שימוע / שומע"
}, {
  en: "heir",
  he: "יורש"
}, {
  en: "hint",
  he: "רמז"
}, {
  en: "holocaust survivor",
  he: "ניצול שואה"
}, {
  en: "honorable",
  he: "מכובד"
}, {
  en: "hopefulness",
  he: "מלא תקווה"
}, {
  en: "hostage",
  he: "בן ערובה"
}, {
  en: "hostile",
  he: "עוין"
}, {
  en: "hostility",
  he: "עוינות"
}, {
  en: "humidity",
  he: "לחות"
}, {
  en: "humiliation",
  he: "השפלה / בושה"
}, {
  en: "identical",
  he: "זהה"
}, {
  en: "identity",
  he: "זהות"
}, {
  en: "ignoring",
  he: "להתעלם"
}, {
  en: "ill-fated",
  he: "מסתיים בכי רע"
}, {
  en: "image",
  he: "תמונה / דמות"
}, {
  en: "imaginable",
  he: "ניתן לדמיון"
}, {
  en: "immunity",
  he: "חסינות"
}, {
  en: "impede",
  he: "להאט / להפריע"
}, {
  en: "implant",
  he: "לשתול"
}, {
  en: "imply",
  he: "לרמוז"
}, {
  en: "imprison",
  he: "לכלוא / לאסור"
}, {
  en: "improbable",
  he: "בלתי סביר"
}, {
  en: "in accordance",
  he: "בהתאם ל..."
}, {
  en: "in contradiction",
  he: "בסתירה"
}, {
  en: "incapable",
  he: "לא מסוגל"
}, {
  en: "incautious",
  he: "בלתי זהיר"
}, {
  en: "incentive",
  he: "תמריץ"
}, {
  en: "incident",
  he: "תקרית"
}, {
  en: "inclination",
  he: "נטייה ל..."
}, {
  en: "in common",
  he: "במשותף"
}, {
  en: "incompatible",
  he: "בלתי מתאים"
}, {
  en: "incompetence",
  he: "חוסר יכולת"
}, {
  en: "inconceivable",
  he: "בלתי נתפש"
}, {
  en: "indication",
  he: "אינדיקציה"
}, {
  en: "indicator",
  he: "אינדיקטור"
}, {
  en: "indictment",
  he: "כתב אישום"
}, {
  en: "infant",
  he: "תינוק קטן"
}, {
  en: "infectious",
  he: "מדבק"
}, {
  en: "infer",
  he: "להסיק / להבין"
}, {
  en: "infinitesimal",
  he: "מזערי"
}, {
  en: "inherent",
  he: "טבוע"
}, {
  en: "inheritance",
  he: "ירושה"
}, {
  en: "initial",
  he: "ראשוני"
}, {
  en: "initiate",
  he: "ליזום"
}, {
  en: "insanity",
  he: "שיגעון"
}, {
  en: "insect",
  he: "חרק"
}, {
  en: "inspiration",
  he: "השראה"
}, {
  en: "institution",
  he: "מוסד"
}, {
  en: "insufferable",
  he: "בלתי נסבל"
}, {
  en: "insufficient",
  he: "בלתי מספק"
}, {
  en: "insurance evaluators",
  he: "שמאי ביטוח"
}, {
  en: "insurance policy",
  he: "פוליסת ביטוח"
}, {
  en: "insure",
  he: "להבטיח"
}, {
  en: "integrity",
  he: "יושר / אמינות"
}, {
  en: "intelligence officer",
  he: "קצין מודיעין"
}, {
  en: "intended effect",
  he: "אפקט מיועד"
}, {
  en: "intent",
  he: "כוונה"
}, {
  en: "interaction",
  he: "אינטראקציה"
}, {
  en: "interrogation",
  he: "חקירה"
}, {
  en: "investigation",
  he: "חקירה (בלשית)"
}, {
  en: "investor",
  he: "משקיע"
}, {
  en: "invincible",
  he: "בלתי מנוצח"
}, {
  en: "invisible",
  he: "בלתי נראה"
}, {
  en: "invitation",
  he: "הזמנה"
}, {
  en: "isolate",
  he: "לבודד / לנתק"
}, {
  en: "isolationism",
  he: "בדלנות"
}, {
  en: "issue a declaration",
  he: "לפרסם הצהרה"
}, {
  en: "journey",
  he: "מסע"
}, {
  en: "judgment",
  he: "יכולת שיפוט"
}, {
  en: "jump-start",
  he: "להתניע"
}, {
  en: "justify",
  he: "להצדיק"
}, {
  en: "kidnapping",
  he: "חטיפה"
}, {
  en: "lab",
  he: "מעבדה"
}, {
  en: "lap",
  he: "הקפה / ירך"
}, {
  en: "launch",
  he: "להשיק / לשגר"
}, {
  en: "lavishly",
  he: "בהידור"
}, {
  en: "lawyer",
  he: "עורך דין"
}, {
  en: "layoffs",
  he: "פיטורין"
}, {
  en: "lecture",
  he: "הרצאה"
}, {
  en: "legacy",
  he: "מורשת"
}, {
  en: "lethal",
  he: "קטלני"
}, {
  en: "likeness",
  he: "דמיון"
}, {
  en: "limitation",
  he: "מגבלה"
}, {
  en: "line of research",
  he: "קו מחקרי"
}, {
  en: "link",
  he: "קשר"
}, {
  en: "loathe",
  he: "מתעב"
}, {
  en: "makes sense",
  he: "נשמע הגיוני"
}, {
  en: "malfunction",
  he: "תקלה"
}, {
  en: "management position",
  he: "תפקיד ניהולי"
}, {
  en: "mandatory",
  he: "חובה"
}, {
  en: "manner",
  he: "אופן"
}, {
  en: "marginal element",
  he: "גורם שולי"
}, {
  en: "markedly",
  he: "באופן ניכר"
}, {
  en: "masculine",
  he: "גברי"
}, {
  en: "massacre",
  he: "טבח"
}, {
  en: "meager",
  he: "זעום"
}, {
  en: "meaningless",
  he: "חסר משמעות"
}, {
  en: "means of deterrence",
  he: "אמצעי הרתעה"
}, {
  en: "mediator",
  he: "מתווך"
}, {
  en: "mediocre",
  he: "בינוני"
}, {
  en: "meek",
  he: "חלש / קלוש"
}, {
  en: "meet these goals",
  he: "לעמוד ביעדים"
}, {
  en: "mental",
  he: "נפשי / מנטאלי"
}, {
  en: "merger",
  he: "איחוד / מיזוג"
}, {
  en: "meticulous",
  he: "קפדני ודקדקני"
}, {
  en: "middleman",
  he: "מתווך"
}, {
  en: "mild",
  he: "מתון"
}, {
  en: "minister",
  he: "שר"
}, {
  en: "minute",
  he: "זעיר / דקה"
}, {
  en: "miracle",
  he: "נס"
}, {
  en: "misconception",
  he: "תפישה שגויה"
}, {
  en: "misinterpret",
  he: "לפרש לא נכון"
}, {
  en: "missionary",
  he: "מיסיונר"
}, {
  en: "moral question",
  he: "שאלה מוסרית"
}, {
  en: "mortal danger",
  he: "סכנת חיים"
}, {
  en: "motion",
  he: "תנועה"
}, {
  en: "motive",
  he: "מניע"
}, {
  en: "mutual",
  he: "הדדי"
}, {
  en: "mysteriousness",
  he: "מסתוריות"
}, {
  en: "mystical",
  he: "מיסטי"
}, {
  en: "mystify",
  he: "לערפל"
}, {
  en: "naive",
  he: "נאיבי / תמים"
}, {
  en: "narcissist",
  he: "נרקיסיסט"
}, {
  en: "navigate",
  he: "לנווט"
}, {
  en: "nerve cell",
  he: "תא עצב"
}, {
  en: "neutral",
  he: "נייטראלי"
}, {
  en: "next of kin",
  he: "קרוב משפחה"
}, {
  en: "nightmare",
  he: "סיוט"
}, {
  en: "novel",
  he: "חדשני"
}, {
  en: "novelist",
  he: "סופר"
}, {
  en: "obligation",
  he: "התחייבות"
}, {
  en: "offspring",
  he: "צאצא"
}, {
  en: "ongoing",
  he: "מתמשך"
}, {
  en: "oppose",
  he: "להתנגד ל..."
}, {
  en: "opposite",
  he: "הפוך"
}, {
  en: "oppression",
  he: "דיכוי"
}, {
  en: "oral",
  he: "בעל פה"
}, {
  en: "orbit",
  he: "מסלול היקפי"
}, {
  en: "originates from",
  he: "נובע מ..."
}, {
  en: "outcome",
  he: "תוצאה"
}, {
  en: "overshadow",
  he: "להאפיל"
}, {
  en: "overt",
  he: "גלוי, פומבי"
}, {
  en: "overwhelmed",
  he: "המום"
}, {
  en: "pamper",
  he: "לפנק"
}, {
  en: "parade",
  he: "מצעד / להצעיד"
}, {
  en: "paralyze",
  he: "לשתק"
}, {
  en: "participant",
  he: "משתתף"
}, {
  en: "particle",
  he: "חלקיק"
}, {
  en: "pave",
  he: "לסלול"
}, {
  en: "peacefulness",
  he: "שקט ושלווה"
}, {
  en: "penetration",
  he: "חדירה"
}, {
  en: "percent",
  he: "אחוז"
}, {
  en: "perception",
  he: "תפישה"
}, {
  en: "persist",
  he: "להתמיד"
}, {
  en: "personnel",
  he: "כוח אדם"
}, {
  en: "persuasion",
  he: "שכנוע"
}, {
  en: "phase",
  he: "שלב"
}, {
  en: "pipeline",
  he: "צינור"
}, {
  en: "plagiarism",
  he: "גניבה ספרותית"
}, {
  en: "plain",
  he: "פשוט / ברור"
}, {
  en: "plaintiff",
  he: "תובע / מאשים"
}, {
  en: "planet",
  he: "כוכב לכת"
}, {
  en: "plea",
  he: "טענה"
}, {
  en: "pledge",
  he: "התחייבות"
}, {
  en: "plenty",
  he: "שפע"
}, {
  en: "point out",
  he: "לציין"
}, {
  en: "pollute",
  he: "לזהם"
}, {
  en: "popular belief",
  he: "אמונה מקובלת"
}, {
  en: "port",
  he: "נמל"
}, {
  en: "precaution",
  he: "אמצעי זהירות"
}, {
  en: "precious",
  he: "יקר"
}, {
  en: "precisely",
  he: "בדיוק"
}, {
  en: "preclude",
  he: "להוציא מהכלל"
}, {
  en: "preference",
  he: "העדפה"
}, {
  en: "premise",
  he: "הנחת יסוד"
}, {
  en: "preparation",
  he: "הכנה"
}, {
  en: "preserved bodies",
  he: "גופות משומרות"
}, {
  en: "prestigious",
  he: "יוקרתי"
}, {
  en: "probable successor",
  he: "יורש אפשרי"
}, {
  en: "probation",
  he: "תקופת מבחן"
}, {
  en: "probe",
  he: "סקירה מעמיקה"
}, {
  en: "profit",
  he: "להרוויח"
}, {
  en: "projected",
  he: "צפוי / מתוכנן"
}, {
  en: "prolonged",
  he: "מוארך / ממושך"
}, {
  en: "prominent",
  he: "בולט"
}, {
  en: "promotion",
  he: "קידום"
}, {
  en: "pronunciation",
  he: "היגוי / מבטא"
}, {
  en: "prophecy",
  he: "נבואה"
}, {
  en: "proponent",
  he: "תומך"
}, {
  en: "proposal",
  he: "הצעה"
}, {
  en: "prosperity",
  he: "שגשוג ורווחה"
}, {
  en: "protest",
  he: "מחאה / הפגנה"
}, {
  en: "punishment",
  he: "עונש / ענישה"
}, {
  en: "purify",
  he: "לטהר"
}, {
  en: "purloined material",
  he: "חומר \"מושאל\""
}, {
  en: "purposeful",
  he: "מלא כוונה"
}, {
  en: "pursuit",
  he: "מרדף"
}, {
  en: "puzzled",
  he: "תמוה"
}, {
  en: "qualified",
  he: "מתאים / מוסמך"
}, {
  en: "quarter",
  he: "רבע"
}, {
  en: "quiz",
  he: "בוחן / חידון"
}, {
  en: "racism",
  he: "גזענות"
}, {
  en: "racist",
  he: "גזען"
}, {
  en: "radiation",
  he: "קרינה"
}, {
  en: "reaction",
  he: "תגובה"
}, {
  en: "reasonable",
  he: "סביר / הגיוני"
}, {
  en: "reassembled",
  he: "מורכב מחדש"
}, {
  en: "rebuttal",
  he: "הפרכה"
}, {
  en: "recipe",
  he: "מתכון"
}, {
  en: "rectify",
  he: "לתקן"
}, {
  en: "refuel",
  he: "לתדלק מחדש"
}, {
  en: "regardless",
  he: "ללא קשר"
}, {
  en: "regime",
  he: "משטר"
}, {
  en: "regiment",
  he: "גדוד"
}, {
  en: "region",
  he: "אזור / תחום"
}, {
  en: "reinforce",
  he: "לתגבר / לחזק"
}, {
  en: "reluctance",
  he: "חוסר רצון"
}, {
  en: "remarkable",
  he: "ראוי לציון"
}, {
  en: "remorse",
  he: "חרטה / צער"
}, {
  en: "reprehensible",
  he: "ראוי לגינוי"
}, {
  en: "reptile",
  he: "זוחל"
}, {
  en: "requester",
  he: "המבקש"
}, {
  en: "residency",
  he: "מקום מגורים"
}, {
  en: "respiration",
  he: "נשימה"
}, {
  en: "restoration",
  he: "שחזור"
}, {
  en: "restore",
  he: "לשחזר"
}, {
  en: "retirement",
  he: "פרישה"
}, {
  en: "reveal",
  he: "לחשוף / לגלות"
}, {
  en: "review",
  he: "לבדוק שנית"
}, {
  en: "revive",
  he: "להחיות"
}, {
  en: "revolutionize",
  he: "לחולל מהפיכה"
}, {
  en: "role",
  he: "תפקיד"
}, {
  en: "root",
  he: "שורש"
}, {
  en: "routine",
  he: "רוטינה / שגרה"
}, {
  en: "rural",
  he: "כפרי"
}, {
  en: "sacred",
  he: "קדוש"
}, {
  en: "satellite",
  he: "לוויין"
}, {
  en: "scatter",
  he: "לפזר / להתפזר"
}, {
  en: "scenario",
  he: "תרחיש"
}, {
  en: "schooling",
  he: "חינוך"
}, {
  en: "scroll",
  he: "מגילה"
}, {
  en: "self-preservation",
  he: "שימור עצמי"
}, {
  en: "self-restraint",
  he: "שליטה עצמית"
}, {
  en: "semi",
  he: "למחצה"
}, {
  en: "seminar",
  he: "סמינר"
}, {
  en: "sensible",
  he: "הגיוני"
}, {
  en: "sensuous",
  he: "חושני"
}, {
  en: "serenity",
  he: "שלווה"
}, {
  en: "server",
  he: "שרת מחשב"
}, {
  en: "session",
  he: "פגישה /סדנא"
}, {
  en: "shortage",
  he: "מחסור"
}, {
  en: "similarly",
  he: "באופן דומה"
}, {
  en: "simulate",
  he: "לדמות"
}, {
  en: "site",
  he: "אתר"
}, {
  en: "skinny",
  he: "רזה מאוד"
}, {
  en: "sleepiness",
  he: "ישנוניות"
}, {
  en: "slim",
  he: "רזה / קלוש"
}, {
  en: "slips of the tongue",
  he: "מעידות בלשון"
}, {
  en: "sober",
  he: "פיכח"
}, {
  en: "software patches",
  he: "טלאי תוכנה"
}, {
  en: "sought after",
  he: "מחפשים אחריו"
}, {
  en: "specialist",
  he: "מומחה"
}, {
  en: "specialize",
  he: "מתמחה ב..."
}, {
  en: "spectator",
  he: "צופה"
}, {
  en: "spokesperson",
  he: "דובר"
}, {
  en: "spokeswoman",
  he: "דוברת"
}, {
  en: "sporadic",
  he: "בלתי סדיר"
}, {
  en: "spot",
  he: "נקודה"
}, {
  en: "squeeze",
  he: "ללחוץ / למחוץ"
}, {
  en: "stage",
  he: "שלב"
}, {
  en: "stakes",
  he: "סיכונים"
}, {
  en: "stand",
  he: "לעמוד / יציע"
}, {
  en: "startling",
  he: "מפתיע / מדהים"
}, {
  en: "stems from",
  he: "נובע מ..."
}, {
  en: "stock",
  he: "מניה בורסאית"
}, {
  en: "stomach",
  he: "קיבה / בטן"
}, {
  en: "storm",
  he: "סופה / סערה"
}, {
  en: "straight-forward",
  he: "ישיר"
}, {
  en: "strict",
  he: "נוקשה / קפדני"
}, {
  en: "suburban",
  he: "פרברי"
}, {
  en: "superstition",
  he: "אמונה טפלה"
}, {
  en: "supervision",
  he: "פיקוח"
}, {
  en: "surface variance",
  he: "משתנה חיצוני"
}, {
  en: "surrogate mother",
  he: "אם פונדקאית"
}, {
  en: "suspended",
  he: "מושעה / מושהה"
}, {
  en: "tantalizing",
  he: "מרגש / מרעיד"
}, {
  en: "tempt fate",
  he: "להתגרות בגורל"
}, {
  en: "testify",
  he: "להעיד"
}, {
  en: "testimony",
  he: "עדות"
}, {
  en: "therapy",
  he: "תרפיה / טיפול"
}, {
  en: "tide",
  he: "גאות ושפל"
}, {
  en: "timeliness",
  he: "דייקנות"
}, {
  en: "tool",
  he: "כלי"
}, {
  en: "topic",
  he: "הנושא"
}, {
  en: "topple",
  he: "למוטט"
}, {
  en: "tournament",
  he: "טורניר"
}, {
  en: "trade-offs",
  he: "החלפות"
}, {
  en: "traditional",
  he: "מסורתי"
}, {
  en: "traitorous",
  he: "בוגדני"
}, {
  en: "tranquility",
  he: "שלווה"
}, {
  en: "transaction",
  he: "עסקה"
}, {
  en: "transfer",
  he: "להעביר"
}, {
  en: "translucent",
  he: "מעט שקוף"
}, {
  en: "transparent",
  he: "שקוף / ברור"
}, {
  en: "tremendous",
  he: "עצום"
}, {
  en: "trend",
  he: "אופנה"
}, {
  en: "trial and error",
  he: "ניסוי וטעייה"
}, {
  en: "truthfully",
  he: "בכנות"
}, {
  en: "unbearable",
  he: "בלתי נסבל"
}, {
  en: "under dispute",
  he: "נתון במחלוקת"
}, {
  en: "undeterred",
  he: "לא נרתע מ..."
}, {
  en: "unravel",
  he: "לחשוף"
}, {
  en: "unstable",
  he: "בלתי יציב"
}, {
  en: "usable",
  he: "ניתן לשימוש"
}, {
  en: "vacancy",
  he: "מקום פנוי"
}, {
  en: "varies",
  he: "משתנה"
}, {
  en: "vast majority",
  he: "הרוב המוחלט"
}, {
  en: "veil",
  he: "הינומה"
}, {
  en: "violate",
  he: "להפר"
}, {
  en: "voyage",
  he: "מסע"
}, {
  en: "wage",
  he: "שכר / משכורת"
}, {
  en: "want of understanding",
  he: "העדר הבנה"
}, {
  en: "waver",
  he: "לוותר"
}, {
  en: "will",
  he: "רצון / צוואה"
}, {
  en: "willingness",
  he: "מוכנות"
}, {
  en: "wiped out",
  he: "למחוק"
}, {
  en: "work ethic",
  he: "מוסר עבודה"
}, {
  en: "worship",
  he: "לסגוד ל..."
}, {
  en: "wrapped up",
  he: "עטוף"
}, {
  en: "wrist",
  he: "פרק יד"
}, {
  en: "yearn",
  he: "להשתוקק"
}, {
  en: "youth",
  he: "נעורים"
}];
})(); } catch (e) { __ds_ns.__errors.push({ path: "quiz-game/dist/words.js", error: String((e && e.message) || e) }); }

// quiz-game/end-sketches.jsx
try { (() => {
// End-screen sketches — 4 directions for the post-round summary.
// Each artboard renders at 852×393 (iPhone landscape) so we can compare
// inside the design canvas.

const SCORE = 47;
const MISSED = [{
  en: 'enhance',
  he: 'להעצים, לשפר'
}, {
  en: 'mitigate',
  he: 'להקל, למתן'
}, {
  en: 'ambiguous',
  he: 'דו־משמעי'
}, {
  en: 'feasible',
  he: 'אפשרי, ישים'
}, {
  en: 'concur',
  he: 'להסכים'
}];

/* ============================================================
   Sketch A — "Stage end"
   The game world stays visible. Sky / mountains / ground are the
   backdrop; the cannon is idle on the ground. Score floats in the
   sky; missed words appear as fallen rocket cards on the right.
   ============================================================ */
function SketchA() {
  return /*#__PURE__*/React.createElement("div", {
    className: "sk",
    style: {
      background: "linear-gradient(180deg, #C9C5EE 0%, #E1DEF6 38%, #F1EFFB 65%, #F4F2EE 80%)",
      fontFamily: "var(--font-display)"
    }
  }, /*#__PURE__*/React.createElement("svg", {
    viewBox: "0 0 852 200",
    preserveAspectRatio: "none",
    style: {
      position: "absolute",
      left: 0,
      right: 0,
      bottom: "22%",
      width: "100%",
      height: "30%"
    }
  }, /*#__PURE__*/React.createElement("path", {
    d: "M 0,200 L 0,140 L 90,80 L 170,120 L 240,60 L 320,110 L 410,40 L 500,90 L 590,60 L 680,100 L 770,70 L 852,110 L 852,200 Z",
    fill: "#B6B1E0"
  }), /*#__PURE__*/React.createElement("path", {
    d: "M 0,200 L 0,170 L 70,120 L 140,150 L 220,100 L 320,140 L 410,90 L 490,130 L 570,100 L 660,135 L 740,110 L 852,140 L 852,200 Z",
    fill: "#8E89C8"
  })), /*#__PURE__*/React.createElement("div", {
    style: {
      position: "absolute",
      left: 0,
      right: 0,
      bottom: 0,
      height: "22%",
      background: "linear-gradient(180deg, #2A2547 0%, #1A1530 40%, #0E0A1F 100%)"
    }
  }), /*#__PURE__*/React.createElement("svg", {
    viewBox: "0 0 280 230",
    width: "180",
    height: "148",
    style: {
      position: "absolute",
      left: 24,
      bottom: -12
    }
  }, /*#__PURE__*/React.createElement("ellipse", {
    cx: "140",
    cy: "200",
    rx: "100",
    ry: "10",
    fill: "rgba(0,0,0,.35)"
  }), /*#__PURE__*/React.createElement("path", {
    d: "M 20,168 L 260,168 L 250,216 L 30,216 Z",
    fill: "#0A0820",
    stroke: "#000",
    strokeWidth: "1"
  }), /*#__PURE__*/React.createElement("path", {
    d: "M 70,140 Q 140,40 210,140 Z",
    fill: "#F37327"
  }), /*#__PURE__*/React.createElement("path", {
    d: "M 85,128 Q 110,76 138,68",
    stroke: "rgba(255,255,255,.45)",
    strokeWidth: "4",
    fill: "none",
    strokeLinecap: "round"
  }), /*#__PURE__*/React.createElement("rect", {
    x: "60",
    y: "138",
    width: "160",
    height: "14",
    rx: "6",
    fill: "#1A1530"
  }), /*#__PURE__*/React.createElement("g", {
    transform: "translate(140 100) rotate(-32) translate(-30 -30)"
  }, /*#__PURE__*/React.createElement("rect", {
    x: "14",
    y: "22",
    width: "36",
    height: "20",
    rx: "4",
    fill: "#1A1530"
  }), /*#__PURE__*/React.createElement("rect", {
    x: "40",
    y: "26",
    width: "150",
    height: "12",
    rx: "4",
    fill: "#2A2547"
  }), /*#__PURE__*/React.createElement("rect", {
    x: "184",
    y: "22",
    width: "22",
    height: "20",
    rx: "3",
    fill: "#3a3358"
  }))), /*#__PURE__*/React.createElement("div", {
    style: {
      position: "absolute",
      right: 36,
      top: 46,
      textAlign: "right"
    }
  }, /*#__PURE__*/React.createElement("div", {
    style: {
      fontFamily: "var(--font-display)",
      fontWeight: 700,
      fontSize: 14,
      letterSpacing: ".15em",
      color: "#F37327",
      textTransform: "uppercase"
    }
  }, "\u05E1\u05D5\u05E3 \u05E1\u05D9\u05D1\u05D5\u05D1"), /*#__PURE__*/React.createElement("div", {
    style: {
      fontFamily: "var(--font-en-disp), var(--font-display)",
      fontWeight: 900,
      fontSize: 140,
      lineHeight: .85,
      color: "#1A1530",
      margin: "6px 0 2px"
    }
  }, SCORE), /*#__PURE__*/React.createElement("div", {
    style: {
      fontFamily: "var(--font-display)",
      fontWeight: 700,
      fontSize: 18,
      color: "#1A1530",
      letterSpacing: "-.01em"
    }
  }, "\u05E0\u05E7\u05D5\u05D3\u05D5\u05EA", /*#__PURE__*/React.createElement("span", {
    style: {
      color: "#F37327"
    }
  }, "."))), /*#__PURE__*/React.createElement("div", {
    style: {
      position: "absolute",
      left: 36,
      top: 32,
      bottom: 120,
      width: 368,
      display: "grid",
      gap: 7,
      alignContent: "start"
    }
  }, /*#__PURE__*/React.createElement("div", {
    style: {
      fontFamily: "var(--font-display)",
      fontWeight: 700,
      fontSize: 13,
      color: "#3F4197",
      letterSpacing: ".06em",
      marginBottom: 2
    }
  }, "\u05D0\u05DC\u05D5 5 \u05D4\u05DE\u05D9\u05DC\u05D9\u05DD \u05E9\u05E4\u05E1\u05E4\u05E1\u05EA \u2193"), MISSED.map((w, i) => /*#__PURE__*/React.createElement("div", {
    key: i,
    style: {
      position: "relative",
      background: "rgba(255,255,255,.92)",
      border: "1px solid rgba(40,30,80,.10)",
      borderRadius: 6,
      padding: "7px 14px 7px 26px",
      display: "grid",
      gridTemplateColumns: "auto 1fr",
      alignItems: "center",
      gap: 12,
      boxShadow: "0 6px 14px -8px rgba(40,30,80,.18)"
    }
  }, /*#__PURE__*/React.createElement("span", {
    style: {
      position: "absolute",
      left: 0,
      top: "50%",
      transform: "translateY(-50%)",
      width: 0,
      height: 0,
      borderTop: "12px solid transparent",
      borderBottom: "12px solid transparent",
      borderRight: "14px solid #F37327"
    }
  }), /*#__PURE__*/React.createElement("span", {
    style: {
      fontFamily: "var(--font-en-disp), var(--font-display)",
      fontWeight: 900,
      fontSize: 14,
      color: "#C9531A",
      direction: "ltr",
      textAlign: "left",
      letterSpacing: ".02em"
    }
  }, w.en.toUpperCase()), /*#__PURE__*/React.createElement("span", {
    style: {
      fontFamily: "var(--font-display)",
      fontWeight: 700,
      fontSize: 14,
      color: "#1A1530",
      textAlign: "right",
      borderRight: "1px solid rgba(20,15,40,.18)",
      paddingRight: 12
    }
  }, w.he)))), /*#__PURE__*/React.createElement("div", {
    style: {
      position: "absolute",
      right: 36,
      bottom: 18,
      display: "flex",
      gap: 10,
      alignItems: "center"
    }
  }, /*#__PURE__*/React.createElement("button", {
    style: {
      background: "transparent",
      color: "#fff",
      border: "1.5px solid rgba(255,255,255,.6)",
      borderRadius: 999,
      padding: "9px 18px",
      fontFamily: "var(--font-display)",
      fontWeight: 700,
      fontSize: 13,
      cursor: "pointer"
    }
  }, "\u05D8\u05D1\u05DC\u05EA \u05D4\u05E9\u05D9\u05D0\u05D9\u05DD"), /*#__PURE__*/React.createElement("button", {
    style: {
      background: "linear-gradient(180deg,#FF8C42 0%,#F37327 50%,#C9531A 100%)",
      color: "#fff",
      border: 0,
      borderRadius: 999,
      padding: "11px 22px",
      fontFamily: "var(--font-display)",
      fontWeight: 700,
      fontSize: 15,
      cursor: "pointer",
      boxShadow: "0 8px 20px -6px rgba(243,115,39,.7), inset 0 1.5px 0 rgba(255,255,255,.4)",
      display: "inline-flex",
      alignItems: "center",
      gap: 8
    }
  }, /*#__PURE__*/React.createElement("span", null, "\u05E1\u05D9\u05D1\u05D5\u05D1 \u05E0\u05D5\u05E1\u05E3"), /*#__PURE__*/React.createElement("span", {
    style: {
      fontSize: 18,
      lineHeight: 1
    }
  }, "\u203A"))));
}

/* ============================================================
   Sketch B — "Z-poster"
   Cream paper. Giant lavender Z on the right with the score
   stamped on it. Left side is a clean column of missed words
   with chevron bullets — feels like an eazy print flyer.
   ============================================================ */
function SketchB() {
  return /*#__PURE__*/React.createElement("div", {
    className: "sk",
    style: {
      background: "#F4F2EE",
      fontFamily: "var(--font-display)"
    }
  }, /*#__PURE__*/React.createElement("svg", {
    viewBox: "0 0 600 400",
    preserveAspectRatio: "none",
    style: {
      position: "absolute",
      right: -40,
      top: 0,
      width: 520,
      height: "100%"
    }
  }, /*#__PURE__*/React.createElement("polygon", {
    points: "80,40 540,40 480,180 20,180",
    fill: "#A9A4EC"
  }), /*#__PURE__*/React.createElement("polygon", {
    points: "120,80 500,80 440,180 60,180",
    fill: "#D9D6F4"
  }), /*#__PURE__*/React.createElement("polygon", {
    points: "60,220 520,220 460,360 0,360",
    fill: "#A9A4EC"
  }), /*#__PURE__*/React.createElement("polygon", {
    points: "100,260 480,260 420,360 40,360",
    fill: "#D9D6F4"
  })), /*#__PURE__*/React.createElement("div", {
    style: {
      position: "absolute",
      right: 60,
      top: 24,
      textAlign: "center",
      width: 280
    }
  }, /*#__PURE__*/React.createElement("div", {
    style: {
      fontFamily: "var(--font-display)",
      fontWeight: 700,
      fontSize: 12,
      letterSpacing: ".18em",
      color: "#3F4197",
      textTransform: "uppercase"
    }
  }, "\u05E1\u05D5\u05E3 \u05E1\u05D9\u05D1\u05D5\u05D1")), /*#__PURE__*/React.createElement("div", {
    style: {
      position: "absolute",
      right: 60,
      top: 64,
      width: 280,
      textAlign: "center"
    }
  }, /*#__PURE__*/React.createElement("div", {
    style: {
      fontFamily: "var(--font-en-disp), var(--font-display)",
      fontWeight: 900,
      fontSize: 170,
      lineHeight: .9,
      color: "#F37327",
      textShadow: "0 6px 0 rgba(63,65,151,.18)"
    }
  }, SCORE), /*#__PURE__*/React.createElement("div", {
    style: {
      fontFamily: "var(--font-display)",
      fontWeight: 700,
      fontSize: 22,
      color: "#1A1530",
      marginTop: 8
    }
  }, "\u05E0\u05E7\u05D5\u05D3\u05D5\u05EA", /*#__PURE__*/React.createElement("span", {
    style: {
      color: "#F37327"
    }
  }, "."))), /*#__PURE__*/React.createElement("div", {
    style: {
      position: "absolute",
      left: 28,
      top: 22,
      right: 380,
      bottom: 18,
      display: "flex",
      flexDirection: "column"
    }
  }, /*#__PURE__*/React.createElement("div", {
    style: {
      display: "flex",
      alignItems: "center",
      gap: 8,
      marginBottom: 14
    }
  }, /*#__PURE__*/React.createElement("span", {
    style: {
      display: "inline-block",
      width: 22,
      height: 26,
      background: "#F37327",
      clipPath: "polygon(0 0, 100% 0, 100% 30%, 35% 30%, 35% 42%, 80% 42%, 80% 58%, 35% 58%, 35% 70%, 100% 70%, 100% 100%, 0 100%)"
    }
  }), /*#__PURE__*/React.createElement("span", {
    style: {
      fontFamily: "var(--font-display)",
      fontWeight: 700,
      fontSize: 15,
      color: "#1A1530"
    }
  }, "eazy", /*#__PURE__*/React.createElement("span", {
    style: {
      color: "#F37327"
    }
  }, "."))), /*#__PURE__*/React.createElement("div", {
    style: {
      fontFamily: "var(--font-display)",
      fontWeight: 700,
      fontSize: 18,
      color: "#1A1530",
      lineHeight: 1.1,
      marginBottom: 10
    }
  }, "\u05D0\u05DC\u05D5 ", /*#__PURE__*/React.createElement("span", {
    style: {
      color: "#F37327"
    }
  }, "5"), " \u05D4\u05DE\u05D9\u05DC\u05D9\u05DD \u05E9\u05E4\u05E1\u05E4\u05E1\u05EA", /*#__PURE__*/React.createElement("span", {
    style: {
      color: "#F37327"
    }
  }, ".")), /*#__PURE__*/React.createElement("div", {
    style: {
      display: "grid",
      gap: 6,
      alignContent: "start"
    }
  }, MISSED.map((w, i) => /*#__PURE__*/React.createElement("div", {
    key: i,
    style: {
      display: "grid",
      gridTemplateColumns: "14px 1fr auto",
      alignItems: "baseline",
      gap: 10
    }
  }, /*#__PURE__*/React.createElement("svg", {
    viewBox: "0 0 32 32",
    width: "12",
    height: "12"
  }, /*#__PURE__*/React.createElement("path", {
    d: "M22 6 L10 16 L22 26",
    stroke: "#F37327",
    strokeWidth: "6",
    strokeLinecap: "round",
    strokeLinejoin: "round",
    fill: "none"
  })), /*#__PURE__*/React.createElement("span", {
    style: {
      fontFamily: "var(--font-display)",
      fontWeight: 700,
      fontSize: 16,
      color: "#1A1530"
    }
  }, w.he), /*#__PURE__*/React.createElement("span", {
    style: {
      fontFamily: "var(--font-en-disp), var(--font-display)",
      fontWeight: 900,
      fontSize: 14,
      color: "#3F4197",
      direction: "ltr",
      letterSpacing: ".04em"
    }
  }, w.en.toUpperCase())))), /*#__PURE__*/React.createElement("div", {
    style: {
      flex: 1
    }
  }), /*#__PURE__*/React.createElement("div", {
    style: {
      display: "flex",
      gap: 8
    }
  }, /*#__PURE__*/React.createElement("button", {
    style: {
      flex: "0 0 auto",
      background: "transparent",
      color: "#C9531A",
      border: "1.5px solid #F37327",
      borderRadius: 999,
      padding: "9px 16px",
      fontFamily: "var(--font-display)",
      fontWeight: 700,
      fontSize: 13
    }
  }, "\u05D8\u05D1\u05DC\u05EA \u05D4\u05E9\u05D9\u05D0\u05D9\u05DD"), /*#__PURE__*/React.createElement("button", {
    style: {
      flex: 1,
      background: "linear-gradient(180deg,#FF8C42 0%,#F37327 50%,#C9531A 100%)",
      color: "#fff",
      border: 0,
      borderRadius: 999,
      padding: "11px 18px",
      fontFamily: "var(--font-display)",
      fontWeight: 700,
      fontSize: 14,
      boxShadow: "0 8px 20px -6px rgba(243,115,39,.5)",
      display: "inline-flex",
      alignItems: "center",
      justifyContent: "center",
      gap: 8
    }
  }, /*#__PURE__*/React.createElement("span", null, "\u05D9\u05D5\u05E6\u05D0\u05D9\u05DD \u05DC\u05E1\u05D9\u05D1\u05D5\u05D1 \u05E0\u05D5\u05E1\u05E3"), /*#__PURE__*/React.createElement("span", {
    style: {
      fontSize: 18
    }
  }, "\u203A")))));
}

/* ============================================================
   Sketch C — "Dark scoreboard"
   Full dark navy (game's ground colour). Score is the hero —
   massive cream number, missed words are tight rows on dark.
   Cinematic. Echoes the game's ground / night feel.
   ============================================================ */
function SketchC() {
  return /*#__PURE__*/React.createElement("div", {
    className: "sk",
    style: {
      background: "radial-gradient(120% 90% at 30% 20%, #2A2547 0%, #1A1530 55%, #0A0820 100%)",
      fontFamily: "var(--font-display)",
      color: "#F4F2EE"
    }
  }, /*#__PURE__*/React.createElement("svg", {
    viewBox: "0 0 120 120",
    width: "180",
    height: "180",
    style: {
      position: "absolute",
      right: -30,
      top: -30,
      opacity: .18
    }
  }, /*#__PURE__*/React.createElement("circle", {
    cx: "20",
    cy: "40",
    r: "6",
    fill: "#F37327"
  }), /*#__PURE__*/React.createElement("circle", {
    cx: "60",
    cy: "20",
    r: "10",
    fill: "#F37327"
  }), /*#__PURE__*/React.createElement("circle", {
    cx: "92",
    cy: "55",
    r: "5",
    fill: "#FBD9C2"
  }), /*#__PURE__*/React.createElement("circle", {
    cx: "40",
    cy: "80",
    r: "4",
    fill: "#FBD9C2"
  }), /*#__PURE__*/React.createElement("circle", {
    cx: "80",
    cy: "95",
    r: "7",
    fill: "#F37327"
  })), /*#__PURE__*/React.createElement("div", {
    style: {
      position: "absolute",
      left: 0,
      top: 0,
      bottom: 0,
      width: "45%",
      display: "flex",
      flexDirection: "column",
      alignItems: "center",
      justifyContent: "center",
      textAlign: "center",
      padding: "0 24px"
    }
  }, /*#__PURE__*/React.createElement("div", {
    style: {
      fontFamily: "var(--font-display)",
      fontWeight: 700,
      fontSize: 13,
      letterSpacing: ".22em",
      color: "#F37327",
      textTransform: "uppercase",
      marginBottom: 6
    }
  }, "\u05E1\u05D5\u05E3 \u05E1\u05D9\u05D1\u05D5\u05D1"), /*#__PURE__*/React.createElement("div", {
    style: {
      fontFamily: "var(--font-en-disp), var(--font-display)",
      fontWeight: 900,
      fontSize: 180,
      lineHeight: .82,
      color: "#F4F2EE",
      textShadow: "0 0 60px rgba(169,164,236,.35)"
    }
  }, SCORE), /*#__PURE__*/React.createElement("div", {
    style: {
      fontFamily: "var(--font-display)",
      fontWeight: 700,
      fontSize: 18,
      color: "#A9A4EC",
      marginTop: 6
    }
  }, "\u05E0\u05E7\u05D5\u05D3\u05D5\u05EA", /*#__PURE__*/React.createElement("span", {
    style: {
      color: "#F37327"
    }
  }, "."))), /*#__PURE__*/React.createElement("div", {
    style: {
      position: "absolute",
      right: "55%",
      top: 36,
      bottom: 60,
      width: 1,
      background: "linear-gradient(180deg, transparent, rgba(169,164,236,.35), transparent)"
    }
  }), /*#__PURE__*/React.createElement("div", {
    style: {
      position: "absolute",
      right: 36,
      top: 32,
      bottom: 78,
      left: "50%",
      display: "flex",
      flexDirection: "column"
    }
  }, /*#__PURE__*/React.createElement("div", {
    style: {
      fontFamily: "var(--font-display)",
      fontWeight: 700,
      fontSize: 14,
      color: "#A9A4EC",
      letterSpacing: ".04em",
      marginBottom: 10
    }
  }, "\u05D0\u05DC\u05D5 \u05D4\u05DE\u05D9\u05DC\u05D9\u05DD \u05E9\u05E4\u05E1\u05E4\u05E1\u05EA"), /*#__PURE__*/React.createElement("div", {
    style: {
      display: "grid",
      gap: 6,
      alignContent: "start",
      flex: 1
    }
  }, MISSED.map((w, i) => /*#__PURE__*/React.createElement("div", {
    key: i,
    style: {
      display: "grid",
      gridTemplateColumns: "auto 1fr",
      alignItems: "center",
      gap: 14,
      padding: "7px 0",
      borderTop: i === 0 ? "1px solid rgba(169,164,236,.18)" : "0",
      borderBottom: "1px solid rgba(169,164,236,.18)"
    }
  }, /*#__PURE__*/React.createElement("span", {
    style: {
      fontFamily: "var(--font-en-disp), var(--font-display)",
      fontWeight: 900,
      fontSize: 15,
      color: "#F37327",
      direction: "ltr",
      letterSpacing: ".06em",
      minWidth: 90,
      textAlign: "left"
    }
  }, w.en.toUpperCase()), /*#__PURE__*/React.createElement("span", {
    style: {
      fontFamily: "var(--font-display)",
      fontWeight: 700,
      fontSize: 15,
      color: "#F4F2EE",
      textAlign: "right"
    }
  }, w.he))))), /*#__PURE__*/React.createElement("div", {
    style: {
      position: "absolute",
      left: 36,
      right: 36,
      bottom: 18,
      display: "flex",
      gap: 10,
      alignItems: "center",
      justifyContent: "flex-end"
    }
  }, /*#__PURE__*/React.createElement("button", {
    style: {
      background: "transparent",
      color: "#F4F2EE",
      border: "1.5px solid rgba(244,242,238,.35)",
      borderRadius: 999,
      padding: "9px 18px",
      fontFamily: "var(--font-display)",
      fontWeight: 700,
      fontSize: 13
    }
  }, "\u05D8\u05D1\u05DC\u05EA \u05D4\u05E9\u05D9\u05D0\u05D9\u05DD"), /*#__PURE__*/React.createElement("button", {
    style: {
      background: "linear-gradient(180deg,#FF8C42 0%,#F37327 50%,#C9531A 100%)",
      color: "#fff",
      border: 0,
      borderRadius: 999,
      padding: "12px 24px",
      fontFamily: "var(--font-display)",
      fontWeight: 700,
      fontSize: 15,
      boxShadow: "0 10px 24px -6px rgba(243,115,39,.65), inset 0 1.5px 0 rgba(255,255,255,.4)",
      display: "inline-flex",
      alignItems: "center",
      gap: 8
    }
  }, /*#__PURE__*/React.createElement("span", null, "\u05D9\u05D5\u05E6\u05D0\u05D9\u05DD \u05DC\u05E1\u05D9\u05D1\u05D5\u05D1 \u05E0\u05D5\u05E1\u05E3"), /*#__PURE__*/React.createElement("span", {
    style: {
      fontSize: 18
    }
  }, "\u203A"))));
}

/* ============================================================
   Sketch D — "Score sheet"
   A printed report card. Cream paper, ledger lines, eazy mark
   stamped in the corner. Very calm, brand-true print look.
   ============================================================ */
function SketchD() {
  return /*#__PURE__*/React.createElement("div", {
    className: "sk",
    style: {
      background: "#F4F2EE",
      fontFamily: "var(--font-display)"
    }
  }, /*#__PURE__*/React.createElement("div", {
    style: {
      position: "absolute",
      inset: "24px 28px",
      border: "1px solid rgba(20,15,40,.08)"
    }
  }), /*#__PURE__*/React.createElement("div", {
    style: {
      position: "absolute",
      left: 48,
      right: 48,
      top: 42,
      display: "flex",
      alignItems: "center",
      justifyContent: "space-between"
    }
  }, /*#__PURE__*/React.createElement("div", {
    style: {
      display: "flex",
      alignItems: "center",
      gap: 8
    }
  }, /*#__PURE__*/React.createElement("span", {
    style: {
      display: "inline-block",
      width: 18,
      height: 22,
      background: "#F37327",
      clipPath: "polygon(0 0, 100% 0, 100% 30%, 35% 30%, 35% 42%, 80% 42%, 80% 58%, 35% 58%, 35% 70%, 100% 70%, 100% 100%, 0 100%)"
    }
  }), /*#__PURE__*/React.createElement("span", {
    style: {
      fontFamily: "var(--font-display)",
      fontWeight: 700,
      fontSize: 13,
      color: "#1A1530"
    }
  }, "eazy", /*#__PURE__*/React.createElement("span", {
    style: {
      color: "#F37327"
    }
  }, "."))), /*#__PURE__*/React.createElement("div", {
    style: {
      fontFamily: "var(--font-display)",
      fontWeight: 700,
      fontSize: 11,
      letterSpacing: ".22em",
      color: "#F37327",
      textTransform: "uppercase"
    }
  }, "\u05DB\u05E8\u05D8\u05D9\u05E1 \u05EA\u05D5\u05E6\u05D0\u05D4 \xB7 \u05E1\u05D5\u05E3 \u05E1\u05D9\u05D1\u05D5\u05D1")), /*#__PURE__*/React.createElement("div", {
    style: {
      position: "absolute",
      right: 48,
      top: 88,
      display: "flex",
      alignItems: "baseline",
      gap: 14
    }
  }, /*#__PURE__*/React.createElement("span", {
    style: {
      fontFamily: "var(--font-display)",
      fontWeight: 700,
      fontSize: 18,
      color: "#3F4197"
    }
  }, "\u05D4\u05E9\u05D2\u05EA"), /*#__PURE__*/React.createElement("span", {
    style: {
      fontFamily: "var(--font-en-disp), var(--font-display)",
      fontWeight: 900,
      fontSize: 130,
      lineHeight: .82,
      color: "#F37327"
    }
  }, SCORE), /*#__PURE__*/React.createElement("span", {
    style: {
      fontFamily: "var(--font-display)",
      fontWeight: 700,
      fontSize: 20,
      color: "#1A1530"
    }
  }, "\u05E0\u05E7\u05D5\u05D3\u05D5\u05EA", /*#__PURE__*/React.createElement("span", {
    style: {
      color: "#F37327"
    }
  }, "."))), /*#__PURE__*/React.createElement("div", {
    style: {
      position: "absolute",
      left: 48,
      right: 48,
      top: 200,
      height: 2,
      backgroundImage: "linear-gradient(90deg, #F37327 50%, transparent 50%)",
      backgroundSize: "10px 2px",
      backgroundRepeat: "repeat-x"
    }
  }), /*#__PURE__*/React.createElement("div", {
    style: {
      position: "absolute",
      left: 48,
      right: 48,
      top: 214,
      bottom: 80,
      display: "flex",
      flexDirection: "column"
    }
  }, /*#__PURE__*/React.createElement("div", {
    style: {
      fontFamily: "var(--font-display)",
      fontWeight: 700,
      fontSize: 14,
      color: "#1A1530",
      marginBottom: 8
    }
  }, "5 \u05DE\u05D9\u05DC\u05D9\u05DD \u05DC\u05D7\u05D6\u05E8\u05D4", /*#__PURE__*/React.createElement("span", {
    style: {
      color: "#F37327"
    }
  }, ":")), /*#__PURE__*/React.createElement("div", {
    style: {
      display: "grid",
      gridTemplateColumns: "1fr 1fr",
      gap: "4px 32px",
      alignContent: "start"
    }
  }, MISSED.map((w, i) => /*#__PURE__*/React.createElement("div", {
    key: i,
    style: {
      display: "grid",
      gridTemplateColumns: "auto 1fr auto",
      alignItems: "baseline",
      gap: 10,
      padding: "4px 0",
      borderBottom: "1px dotted rgba(20,15,40,.18)"
    }
  }, /*#__PURE__*/React.createElement("span", {
    style: {
      fontFamily: "var(--font-display)",
      fontWeight: 700,
      fontSize: 11,
      color: "rgba(20,15,40,.4)",
      minWidth: 14,
      textAlign: "left"
    }
  }, String(i + 1).padStart(2, '0')), /*#__PURE__*/React.createElement("span", {
    style: {
      fontFamily: "var(--font-display)",
      fontWeight: 700,
      fontSize: 14,
      color: "#1A1530"
    }
  }, w.he), /*#__PURE__*/React.createElement("span", {
    style: {
      fontFamily: "var(--font-en-disp), var(--font-display)",
      fontWeight: 900,
      fontSize: 12,
      color: "#C9531A",
      direction: "ltr",
      letterSpacing: ".06em"
    }
  }, w.en.toUpperCase()))))), /*#__PURE__*/React.createElement("div", {
    style: {
      position: "absolute",
      left: 48,
      right: 48,
      bottom: 32,
      display: "flex",
      gap: 10,
      alignItems: "center",
      justifyContent: "space-between"
    }
  }, /*#__PURE__*/React.createElement("button", {
    style: {
      background: "transparent",
      color: "#3F4197",
      border: "1.5px solid #3F4197",
      borderRadius: 6,
      padding: "9px 18px",
      fontFamily: "var(--font-display)",
      fontWeight: 700,
      fontSize: 13
    }
  }, "\u05D8\u05D1\u05DC\u05EA \u05D4\u05E9\u05D9\u05D0\u05D9\u05DD"), /*#__PURE__*/React.createElement("button", {
    style: {
      background: "#F37327",
      color: "#fff",
      border: 0,
      borderRadius: 6,
      padding: "11px 24px",
      fontFamily: "var(--font-display)",
      fontWeight: 700,
      fontSize: 15,
      display: "inline-flex",
      alignItems: "center",
      gap: 10
    }
  }, /*#__PURE__*/React.createElement("span", null, "\u05D9\u05D5\u05E6\u05D0\u05D9\u05DD \u05DC\u05E1\u05D9\u05D1\u05D5\u05D1 \u05E0\u05D5\u05E1\u05E3"), /*#__PURE__*/React.createElement("span", {
    style: {
      fontSize: 18,
      lineHeight: 1
    }
  }, "\u203A"))));
}

/* ============================================================
   App — wraps the sketches in the design canvas
   ============================================================ */
function EndSketchesApp() {
  const W = 852,
    H = 393;
  return /*#__PURE__*/React.createElement(DesignCanvas, {
    title: "End-screen sketches",
    subtitle: "4 directions for the post-round summary \u2014 landscape mobile (852\xD7393)"
  }, /*#__PURE__*/React.createElement(DCSection, {
    id: "end-screens",
    title: "\u05DE\u05E1\u05DA \u05E1\u05D9\u05DB\u05D5\u05DD \xB7 4 \u05DB\u05D9\u05D5\u05D5\u05E0\u05D9\u05DD",
    subtitle: "\u05DB\u05DC \u05E1\u05E7\u05D9\u05E6\u05D4 \u05D1-852\xD7393 \u2014 \u05D0\u05D5\u05EA\u05D5 \u05D0\u05D5\u05E8\u05D9\u05E0\u05D8\u05E6\u05D9\u05D4 \u05DB\u05DE\u05D5 \u05D4\u05DE\u05E9\u05D7\u05E7"
  }, /*#__PURE__*/React.createElement(DCArtboard, {
    id: "a",
    label: "A \xB7 \u05D4\u05DE\u05E9\u05DA \u05D4\u05DE\u05E9\u05D7\u05E7",
    width: W,
    height: H
  }, /*#__PURE__*/React.createElement(SketchA, null)), /*#__PURE__*/React.createElement(DCArtboard, {
    id: "b",
    label: "B \xB7 \u05E4\u05D5\u05E1\u05D8\u05E8 Z",
    width: W,
    height: H
  }, /*#__PURE__*/React.createElement(SketchB, null)), /*#__PURE__*/React.createElement(DCArtboard, {
    id: "c",
    label: "C \xB7 \u05DC\u05D5\u05D7 \u05EA\u05D5\u05E6\u05D0\u05D5\u05EA",
    width: W,
    height: H
  }, /*#__PURE__*/React.createElement(SketchC, null)), /*#__PURE__*/React.createElement(DCArtboard, {
    id: "d",
    label: "D \xB7 \u05DB\u05E8\u05D8\u05D9\u05E1 \u05EA\u05D5\u05E6\u05D0\u05D4",
    width: W,
    height: H
  }, /*#__PURE__*/React.createElement(SketchD, null))));
}
Object.assign(window, {
  EndSketchesApp,
  SketchA,
  SketchB,
  SketchC,
  SketchD
});
})(); } catch (e) { __ds_ns.__errors.push({ path: "quiz-game/end-sketches.jsx", error: String((e && e.message) || e) }); }

// quiz-game/ios-frame.jsx
try { (() => {
// iOS.jsx — Simplified iOS 26 (Liquid Glass) device frame
// Based on the iOS 26 UI Kit + Figma status bar spec. No assets, no deps.
// Exports: IOSDevice, IOSStatusBar, IOSNavBar, IOSGlassPill, IOSList, IOSListRow, IOSKeyboard

// ─────────────────────────────────────────────────────────────
// Status bar
// ─────────────────────────────────────────────────────────────
function IOSStatusBar({
  dark = false,
  time = '9:41'
}) {
  const c = dark ? '#fff' : '#000';
  return /*#__PURE__*/React.createElement("div", {
    style: {
      display: 'flex',
      gap: 154,
      alignItems: 'center',
      justifyContent: 'center',
      padding: '21px 24px 19px',
      boxSizing: 'border-box',
      position: 'relative',
      zIndex: 20,
      width: '100%'
    }
  }, /*#__PURE__*/React.createElement("div", {
    style: {
      flex: 1,
      height: 22,
      display: 'flex',
      alignItems: 'center',
      justifyContent: 'center',
      paddingTop: 1.5
    }
  }, /*#__PURE__*/React.createElement("span", {
    style: {
      fontFamily: '-apple-system, "SF Pro", system-ui',
      fontWeight: 590,
      fontSize: 17,
      lineHeight: '22px',
      color: c
    }
  }, time)), /*#__PURE__*/React.createElement("div", {
    style: {
      flex: 1,
      height: 22,
      display: 'flex',
      alignItems: 'center',
      justifyContent: 'center',
      gap: 7,
      paddingTop: 1,
      paddingRight: 1
    }
  }, /*#__PURE__*/React.createElement("svg", {
    width: "19",
    height: "12",
    viewBox: "0 0 19 12"
  }, /*#__PURE__*/React.createElement("rect", {
    x: "0",
    y: "7.5",
    width: "3.2",
    height: "4.5",
    rx: "0.7",
    fill: c
  }), /*#__PURE__*/React.createElement("rect", {
    x: "4.8",
    y: "5",
    width: "3.2",
    height: "7",
    rx: "0.7",
    fill: c
  }), /*#__PURE__*/React.createElement("rect", {
    x: "9.6",
    y: "2.5",
    width: "3.2",
    height: "9.5",
    rx: "0.7",
    fill: c
  }), /*#__PURE__*/React.createElement("rect", {
    x: "14.4",
    y: "0",
    width: "3.2",
    height: "12",
    rx: "0.7",
    fill: c
  })), /*#__PURE__*/React.createElement("svg", {
    width: "17",
    height: "12",
    viewBox: "0 0 17 12"
  }, /*#__PURE__*/React.createElement("path", {
    d: "M8.5 3.2C10.8 3.2 12.9 4.1 14.4 5.6L15.5 4.5C13.7 2.7 11.2 1.5 8.5 1.5C5.8 1.5 3.3 2.7 1.5 4.5L2.6 5.6C4.1 4.1 6.2 3.2 8.5 3.2Z",
    fill: c
  }), /*#__PURE__*/React.createElement("path", {
    d: "M8.5 6.8C9.9 6.8 11.1 7.3 12 8.2L13.1 7.1C11.8 5.9 10.2 5.1 8.5 5.1C6.8 5.1 5.2 5.9 3.9 7.1L5 8.2C5.9 7.3 7.1 6.8 8.5 6.8Z",
    fill: c
  }), /*#__PURE__*/React.createElement("circle", {
    cx: "8.5",
    cy: "10.5",
    r: "1.5",
    fill: c
  })), /*#__PURE__*/React.createElement("svg", {
    width: "27",
    height: "13",
    viewBox: "0 0 27 13"
  }, /*#__PURE__*/React.createElement("rect", {
    x: "0.5",
    y: "0.5",
    width: "23",
    height: "12",
    rx: "3.5",
    stroke: c,
    strokeOpacity: "0.35",
    fill: "none"
  }), /*#__PURE__*/React.createElement("rect", {
    x: "2",
    y: "2",
    width: "20",
    height: "9",
    rx: "2",
    fill: c
  }), /*#__PURE__*/React.createElement("path", {
    d: "M25 4.5V8.5C25.8 8.2 26.5 7.2 26.5 6.5C26.5 5.8 25.8 4.8 25 4.5Z",
    fill: c,
    fillOpacity: "0.4"
  }))));
}

// ─────────────────────────────────────────────────────────────
// Liquid glass pill — blur + tint + shine
// ─────────────────────────────────────────────────────────────
function IOSGlassPill({
  children,
  dark = false,
  style = {}
}) {
  return /*#__PURE__*/React.createElement("div", {
    style: {
      height: 44,
      minWidth: 44,
      borderRadius: 9999,
      position: 'relative',
      overflow: 'hidden',
      display: 'flex',
      alignItems: 'center',
      justifyContent: 'center',
      boxShadow: dark ? '0 2px 6px rgba(0,0,0,0.35), 0 6px 16px rgba(0,0,0,0.2)' : '0 1px 3px rgba(0,0,0,0.07), 0 3px 10px rgba(0,0,0,0.06)',
      ...style
    }
  }, /*#__PURE__*/React.createElement("div", {
    style: {
      position: 'absolute',
      inset: 0,
      borderRadius: 9999,
      backdropFilter: 'blur(12px) saturate(180%)',
      WebkitBackdropFilter: 'blur(12px) saturate(180%)',
      background: dark ? 'rgba(120,120,128,0.28)' : 'rgba(255,255,255,0.5)'
    }
  }), /*#__PURE__*/React.createElement("div", {
    style: {
      position: 'absolute',
      inset: 0,
      borderRadius: 9999,
      boxShadow: dark ? 'inset 1.5px 1.5px 1px rgba(255,255,255,0.15), inset -1px -1px 1px rgba(255,255,255,0.08)' : 'inset 1.5px 1.5px 1px rgba(255,255,255,0.7), inset -1px -1px 1px rgba(255,255,255,0.4)',
      border: dark ? '0.5px solid rgba(255,255,255,0.15)' : '0.5px solid rgba(0,0,0,0.06)'
    }
  }), /*#__PURE__*/React.createElement("div", {
    style: {
      position: 'relative',
      zIndex: 1,
      display: 'flex',
      alignItems: 'center',
      padding: '0 4px'
    }
  }, children));
}

// ─────────────────────────────────────────────────────────────
// Navigation bar — glass pills + large title
// ─────────────────────────────────────────────────────────────
function IOSNavBar({
  title = 'Title',
  dark = false,
  trailingIcon = true
}) {
  const muted = dark ? 'rgba(255,255,255,0.6)' : '#404040';
  const text = dark ? '#fff' : '#000';
  const pillIcon = content => /*#__PURE__*/React.createElement(IOSGlassPill, {
    dark: dark
  }, /*#__PURE__*/React.createElement("div", {
    style: {
      width: 36,
      height: 36,
      display: 'flex',
      alignItems: 'center',
      justifyContent: 'center'
    }
  }, content));
  return /*#__PURE__*/React.createElement("div", {
    style: {
      display: 'flex',
      flexDirection: 'column',
      gap: 10,
      paddingTop: 62,
      paddingBottom: 10,
      position: 'relative',
      zIndex: 5
    }
  }, /*#__PURE__*/React.createElement("div", {
    style: {
      display: 'flex',
      alignItems: 'center',
      justifyContent: 'space-between',
      padding: '0 16px'
    }
  }, pillIcon(/*#__PURE__*/React.createElement("svg", {
    width: "12",
    height: "20",
    viewBox: "0 0 12 20",
    fill: "none",
    style: {
      marginLeft: -1
    }
  }, /*#__PURE__*/React.createElement("path", {
    d: "M10 2L2 10l8 8",
    stroke: muted,
    strokeWidth: "2.5",
    strokeLinecap: "round",
    strokeLinejoin: "round"
  }))), trailingIcon && pillIcon(/*#__PURE__*/React.createElement("svg", {
    width: "22",
    height: "6",
    viewBox: "0 0 22 6"
  }, /*#__PURE__*/React.createElement("circle", {
    cx: "3",
    cy: "3",
    r: "2.5",
    fill: muted
  }), /*#__PURE__*/React.createElement("circle", {
    cx: "11",
    cy: "3",
    r: "2.5",
    fill: muted
  }), /*#__PURE__*/React.createElement("circle", {
    cx: "19",
    cy: "3",
    r: "2.5",
    fill: muted
  })))), /*#__PURE__*/React.createElement("div", {
    style: {
      padding: '0 16px',
      fontFamily: '-apple-system, system-ui',
      fontSize: 34,
      fontWeight: 700,
      lineHeight: '41px',
      color: text,
      letterSpacing: 0.4
    }
  }, title));
}

// ─────────────────────────────────────────────────────────────
// Grouped list (inset card, r:26) + row (52px)
// ─────────────────────────────────────────────────────────────
function IOSListRow({
  title,
  detail,
  icon,
  chevron = true,
  isLast = false,
  dark = false
}) {
  const text = dark ? '#fff' : '#000';
  const sec = dark ? 'rgba(235,235,245,0.6)' : 'rgba(60,60,67,0.6)';
  const ter = dark ? 'rgba(235,235,245,0.3)' : 'rgba(60,60,67,0.3)';
  const sep = dark ? 'rgba(84,84,88,0.65)' : 'rgba(60,60,67,0.12)';
  return /*#__PURE__*/React.createElement("div", {
    style: {
      display: 'flex',
      alignItems: 'center',
      minHeight: 52,
      padding: '0 16px',
      position: 'relative',
      fontFamily: '-apple-system, system-ui',
      fontSize: 17,
      letterSpacing: -0.43
    }
  }, icon && /*#__PURE__*/React.createElement("div", {
    style: {
      width: 30,
      height: 30,
      borderRadius: 7,
      background: icon,
      marginRight: 12,
      flexShrink: 0
    }
  }), /*#__PURE__*/React.createElement("div", {
    style: {
      flex: 1,
      color: text
    }
  }, title), detail && /*#__PURE__*/React.createElement("span", {
    style: {
      color: sec,
      marginRight: 6
    }
  }, detail), chevron && /*#__PURE__*/React.createElement("svg", {
    width: "8",
    height: "14",
    viewBox: "0 0 8 14",
    style: {
      flexShrink: 0
    }
  }, /*#__PURE__*/React.createElement("path", {
    d: "M1 1l6 6-6 6",
    stroke: ter,
    strokeWidth: "2",
    fill: "none",
    strokeLinecap: "round",
    strokeLinejoin: "round"
  })), !isLast && /*#__PURE__*/React.createElement("div", {
    style: {
      position: 'absolute',
      bottom: 0,
      right: 0,
      left: icon ? 58 : 16,
      height: 0.5,
      background: sep
    }
  }));
}
function IOSList({
  header,
  children,
  dark = false
}) {
  const hc = dark ? 'rgba(235,235,245,0.6)' : 'rgba(60,60,67,0.6)';
  const bg = dark ? '#1C1C1E' : '#fff';
  return /*#__PURE__*/React.createElement("div", null, header && /*#__PURE__*/React.createElement("div", {
    style: {
      fontFamily: '-apple-system, system-ui',
      fontSize: 13,
      color: hc,
      textTransform: 'uppercase',
      padding: '8px 36px 6px',
      letterSpacing: -0.08
    }
  }, header), /*#__PURE__*/React.createElement("div", {
    style: {
      background: bg,
      borderRadius: 26,
      margin: '0 16px',
      overflow: 'hidden'
    }
  }, children));
}

// ─────────────────────────────────────────────────────────────
// Device frame
// ─────────────────────────────────────────────────────────────
function IOSDevice({
  children,
  width = 402,
  height = 874,
  dark = false,
  title,
  keyboard = false
}) {
  const landscape = width > height;
  return /*#__PURE__*/React.createElement("div", {
    style: {
      width,
      height,
      borderRadius: 48,
      overflow: 'hidden',
      position: 'relative',
      background: dark ? '#000' : '#F2F2F7',
      boxShadow: '0 40px 80px rgba(0,0,0,0.18), 0 0 0 1px rgba(0,0,0,0.12)',
      fontFamily: '-apple-system, system-ui, sans-serif',
      WebkitFontSmoothing: 'antialiased'
    }
  }, landscape ? /*#__PURE__*/React.createElement("div", {
    style: {
      position: 'absolute',
      left: 11,
      top: '50%',
      transform: 'translateY(-50%)',
      width: 37,
      height: 126,
      borderRadius: 24,
      background: '#000',
      zIndex: 50
    }
  }) : /*#__PURE__*/React.createElement("div", {
    style: {
      position: 'absolute',
      top: 11,
      left: '50%',
      transform: 'translateX(-50%)',
      width: 126,
      height: 37,
      borderRadius: 24,
      background: '#000',
      zIndex: 50
    }
  }), !landscape && /*#__PURE__*/React.createElement("div", {
    style: {
      position: 'absolute',
      top: 0,
      left: 0,
      right: 0,
      zIndex: 10
    }
  }, /*#__PURE__*/React.createElement(IOSStatusBar, {
    dark: dark
  })), /*#__PURE__*/React.createElement("div", {
    style: {
      height: '100%',
      display: 'flex',
      flexDirection: 'column'
    }
  }, title !== undefined && /*#__PURE__*/React.createElement(IOSNavBar, {
    title: title,
    dark: dark
  }), /*#__PURE__*/React.createElement("div", {
    style: {
      flex: 1,
      overflow: 'auto'
    }
  }, children), keyboard && /*#__PURE__*/React.createElement(IOSKeyboard, {
    dark: dark
  })), landscape ? /*#__PURE__*/React.createElement("div", {
    style: {
      position: 'absolute',
      right: 0,
      top: 0,
      bottom: 0,
      zIndex: 60,
      width: 34,
      display: 'flex',
      justifyContent: 'flex-end',
      alignItems: 'center',
      paddingRight: 8,
      pointerEvents: 'none'
    }
  }, /*#__PURE__*/React.createElement("div", {
    style: {
      width: 5,
      height: 139,
      borderRadius: 100,
      background: dark ? 'rgba(255,255,255,0.7)' : 'rgba(0,0,0,0.25)'
    }
  })) : /*#__PURE__*/React.createElement("div", {
    style: {
      position: 'absolute',
      bottom: 0,
      left: 0,
      right: 0,
      zIndex: 60,
      height: 34,
      display: 'flex',
      justifyContent: 'center',
      alignItems: 'flex-end',
      paddingBottom: 8,
      pointerEvents: 'none'
    }
  }, /*#__PURE__*/React.createElement("div", {
    style: {
      width: 139,
      height: 5,
      borderRadius: 100,
      background: dark ? 'rgba(255,255,255,0.7)' : 'rgba(0,0,0,0.25)'
    }
  })));
}

// ─────────────────────────────────────────────────────────────
// Keyboard — iOS 26 liquid glass
// ─────────────────────────────────────────────────────────────
function IOSKeyboard({
  dark = false
}) {
  const glyph = dark ? 'rgba(255,255,255,0.7)' : '#595959';
  const sugg = dark ? 'rgba(255,255,255,0.6)' : '#333';
  const keyBg = dark ? 'rgba(255,255,255,0.22)' : 'rgba(255,255,255,0.85)';

  // special-key icons
  const icons = {
    shift: /*#__PURE__*/React.createElement("svg", {
      width: "19",
      height: "17",
      viewBox: "0 0 19 17"
    }, /*#__PURE__*/React.createElement("path", {
      d: "M9.5 1L1 9.5h4.5V16h8V9.5H18L9.5 1z",
      fill: glyph
    })),
    del: /*#__PURE__*/React.createElement("svg", {
      width: "23",
      height: "17",
      viewBox: "0 0 23 17"
    }, /*#__PURE__*/React.createElement("path", {
      d: "M7 1h13a2 2 0 012 2v11a2 2 0 01-2 2H7l-6-7.5L7 1z",
      fill: "none",
      stroke: glyph,
      strokeWidth: "1.6",
      strokeLinejoin: "round"
    }), /*#__PURE__*/React.createElement("path", {
      d: "M10 5l7 7M17 5l-7 7",
      stroke: glyph,
      strokeWidth: "1.6",
      strokeLinecap: "round"
    })),
    ret: /*#__PURE__*/React.createElement("svg", {
      width: "20",
      height: "14",
      viewBox: "0 0 20 14"
    }, /*#__PURE__*/React.createElement("path", {
      d: "M18 1v6H4m0 0l4-4M4 7l4 4",
      fill: "none",
      stroke: "#fff",
      strokeWidth: "1.8",
      strokeLinecap: "round",
      strokeLinejoin: "round"
    }))
  };
  const key = (content, {
    w,
    flex,
    ret,
    fs = 25,
    k
  } = {}) => /*#__PURE__*/React.createElement("div", {
    key: k,
    style: {
      height: 42,
      borderRadius: 8.5,
      flex: flex ? 1 : undefined,
      width: w,
      minWidth: 0,
      background: ret ? '#08f' : keyBg,
      boxShadow: '0 1px 0 rgba(0,0,0,0.075)',
      display: 'flex',
      alignItems: 'center',
      justifyContent: 'center',
      fontFamily: '-apple-system, "SF Compact", system-ui',
      fontSize: fs,
      fontWeight: 458,
      color: ret ? '#fff' : glyph
    }
  }, content);
  const row = (keys, pad = 0) => /*#__PURE__*/React.createElement("div", {
    style: {
      display: 'flex',
      gap: 6.5,
      justifyContent: 'center',
      padding: `0 ${pad}px`
    }
  }, keys.map(l => key(l, {
    flex: true,
    k: l
  })));
  return /*#__PURE__*/React.createElement("div", {
    style: {
      position: 'relative',
      zIndex: 15,
      borderRadius: 27,
      overflow: 'hidden',
      padding: '11px 0 2px',
      display: 'flex',
      flexDirection: 'column',
      alignItems: 'center',
      boxShadow: dark ? '0 -2px 20px rgba(0,0,0,0.09)' : '0 -1px 6px rgba(0,0,0,0.018), 0 -3px 20px rgba(0,0,0,0.012)'
    }
  }, /*#__PURE__*/React.createElement("div", {
    style: {
      position: 'absolute',
      inset: 0,
      borderRadius: 27,
      backdropFilter: 'blur(12px) saturate(180%)',
      WebkitBackdropFilter: 'blur(12px) saturate(180%)',
      background: dark ? 'rgba(120,120,128,0.14)' : 'rgba(255,255,255,0.25)'
    }
  }), /*#__PURE__*/React.createElement("div", {
    style: {
      position: 'absolute',
      inset: 0,
      borderRadius: 27,
      boxShadow: dark ? 'inset 1.5px 1.5px 1px rgba(255,255,255,0.15)' : 'inset 1.5px 1.5px 1px rgba(255,255,255,0.7), inset -1px -1px 1px rgba(255,255,255,0.4)',
      border: dark ? '0.5px solid rgba(255,255,255,0.15)' : '0.5px solid rgba(0,0,0,0.06)',
      pointerEvents: 'none'
    }
  }), /*#__PURE__*/React.createElement("div", {
    style: {
      display: 'flex',
      gap: 20,
      alignItems: 'center',
      padding: '8px 22px 13px',
      width: '100%',
      boxSizing: 'border-box',
      position: 'relative'
    }
  }, ['"The"', 'the', 'to'].map((w, i) => /*#__PURE__*/React.createElement(React.Fragment, {
    key: i
  }, i > 0 && /*#__PURE__*/React.createElement("div", {
    style: {
      width: 1,
      height: 25,
      background: '#ccc',
      opacity: 0.3
    }
  }), /*#__PURE__*/React.createElement("div", {
    style: {
      flex: 1,
      textAlign: 'center',
      fontFamily: '-apple-system, system-ui',
      fontSize: 17,
      color: sugg,
      letterSpacing: -0.43,
      lineHeight: '22px'
    }
  }, w)))), /*#__PURE__*/React.createElement("div", {
    style: {
      display: 'flex',
      flexDirection: 'column',
      gap: 13,
      padding: '0 6.5px',
      width: '100%',
      boxSizing: 'border-box',
      position: 'relative'
    }
  }, row(['q', 'w', 'e', 'r', 't', 'y', 'u', 'i', 'o', 'p']), row(['a', 's', 'd', 'f', 'g', 'h', 'j', 'k', 'l'], 20), /*#__PURE__*/React.createElement("div", {
    style: {
      display: 'flex',
      gap: 14.25,
      alignItems: 'center'
    }
  }, key(icons.shift, {
    w: 45,
    k: 'shift'
  }), /*#__PURE__*/React.createElement("div", {
    style: {
      display: 'flex',
      gap: 6.5,
      flex: 1
    }
  }, ['z', 'x', 'c', 'v', 'b', 'n', 'm'].map(l => key(l, {
    flex: true,
    k: l
  }))), key(icons.del, {
    w: 45,
    k: 'del'
  })), /*#__PURE__*/React.createElement("div", {
    style: {
      display: 'flex',
      gap: 6,
      alignItems: 'center'
    }
  }, key('ABC', {
    w: 92.25,
    fs: 18,
    k: 'abc'
  }), key('', {
    flex: true,
    k: 'space'
  }), key(icons.ret, {
    w: 92.25,
    ret: true,
    k: 'ret'
  }))), /*#__PURE__*/React.createElement("div", {
    style: {
      height: 56,
      width: '100%',
      position: 'relative'
    }
  }));
}
Object.assign(window, {
  IOSDevice,
  IOSStatusBar,
  IOSNavBar,
  IOSGlassPill,
  IOSList,
  IOSListRow,
  IOSKeyboard
});
})(); } catch (e) { __ds_ns.__errors.push({ path: "quiz-game/ios-frame.jsx", error: String((e && e.message) || e) }); }

// quiz-game/words.js
try { (() => {
/* eazy · משחק תותח־מילים — מילון המשחק
   ─────────────────────────────────────────────────────────────
   זהו הדטה־בייס של המשחק. לכל שורה:
     en — המילה באנגלית
     he — הפירוש בעברית
   המשחק יטען את הרשימה הזו אוטומטית בכל מכשיר, ללא צורך בהעלאה.

   להוסיף/לערוך מילים — פשוט ערוך את הקובץ הזה ושמור.
   מספר הערכים הנוכחי: 637
*/
window.GAME_DICTIONARY = [{
  en: "a fortnight ago",
  he: "לפני שבועיים"
}, {
  en: "abduct",
  he: "לחטוף"
}, {
  en: "abolish",
  he: "לבטל"
}, {
  en: "accelerate",
  he: "להאיץ"
}, {
  en: "accent",
  he: "מבטא"
}, {
  en: "access",
  he: "גישה"
}, {
  en: "acclaim",
  he: "הכרה / הוקרה"
}, {
  en: "ache",
  he: "כאב / לכאוב"
}, {
  en: "activity",
  he: "פעילות"
}, {
  en: "acute",
  he: "חריף"
}, {
  en: "admiration",
  he: "הערצה"
}, {
  en: "admission process",
  he: "תהליך ההרשמה"
}, {
  en: "advertisement",
  he: "פרסומת"
}, {
  en: "adviser",
  he: "יועץ"
}, {
  en: "affirmative action",
  he: "העדפה מתקנת"
}, {
  en: "ague",
  he: "צמרמורת / קדחת"
}, {
  en: "aid",
  he: "עזרה"
}, {
  en: "ailment",
  he: "מחלה"
}, {
  en: "aimed at",
  he: "המכוון אל..."
}, {
  en: "alert",
  he: "כוננות"
}, {
  en: "allegation",
  he: "האשמה"
}, {
  en: "allegedly",
  he: "לכאורה"
}, {
  en: "ally",
  he: "בעל ברית"
}, {
  en: "along with",
  he: "לצד"
}, {
  en: "along side",
  he: "לצד / ליד"
}, {
  en: "ambassador",
  he: "שגריר"
}, {
  en: "ambiguous",
  he: "מעורפל"
}, {
  en: "ambition",
  he: "שאיפה"
}, {
  en: "ambitious",
  he: "שאפתן"
}, {
  en: "amnesia",
  he: "שכחה / נשייה"
}, {
  en: "ample",
  he: "הרבה / שפע"
}, {
  en: "analyze",
  he: "לנתח"
}, {
  en: "animosity",
  he: "עוינות"
}, {
  en: "annihilation",
  he: "השמדה מוחלטת"
}, {
  en: "anniversary",
  he: "יום השנה"
}, {
  en: "annoyance",
  he: "מטרד"
}, {
  en: "annulment",
  he: "ביטול נישואין"
}, {
  en: "anonymous",
  he: "אלמוני"
}, {
  en: "anthem",
  he: "המנון"
}, {
  en: "anticipation",
  he: "ציפייה"
}, {
  en: "anxious",
  he: "עצבני / מודאג"
}, {
  en: "any given moment",
  he: "כל רגע נתון"
}, {
  en: "apology",
  he: "התנצלות"
}, {
  en: "appear",
  he: "מופיע"
}, {
  en: "appliance",
  he: "כלי/מתקן"
}, {
  en: "application",
  he: "בקשה לקבלה"
}, {
  en: "approve",
  he: "לאשר"
}, {
  en: "arena",
  he: "זירה / מגרש"
}, {
  en: "argument",
  he: "ויכוח / טיעון"
}, {
  en: "arrogance",
  he: "שחצנות"
}, {
  en: "assessment",
  he: "הערכה"
}, {
  en: "associate",
  he: "עמית / שותף"
}, {
  en: "assumption",
  he: "הנחה"
}, {
  en: "astonishment",
  he: "תדהמה"
}, {
  en: "attack",
  he: "התקפה"
}, {
  en: "attendance",
  he: "נוכחות"
}, {
  en: "attention",
  he: "תשומת לב"
}, {
  en: "attribution",
  he: "ייחוס / תכונה"
}, {
  en: "awe-inspiring",
  he: "מעורר השתאות"
}, {
  en: "bark",
  he: "לנבוח"
}, {
  en: "barrier",
  he: "מחסום, סייג"
}, {
  en: "beforehand",
  he: "מראש"
}, {
  en: "bench",
  he: "ספסל"
}, {
  en: "beneficial",
  he: "מועיל / מיטיב"
}, {
  en: "beneficiary",
  he: "המוטב / הנהנה"
}, {
  en: "benefit",
  he: "להרוויח"
}, {
  en: "benign",
  he: "שפיר"
}, {
  en: "bequeath",
  he: "להוריש"
}, {
  en: "bereavement",
  he: "אבל / שכול"
}, {
  en: "bigotry",
  he: "גזענות"
}, {
  en: "birth",
  he: "לידה / ללדת"
}, {
  en: "blink",
  he: "מצמוץ"
}, {
  en: "blizzard",
  he: "סופה / סערה"
}, {
  en: "block",
  he: "לחסום"
}, {
  en: "board",
  he: "מועצה / לוח"
}, {
  en: "boldly",
  he: "באופן נועז"
}, {
  en: "bone-marrow",
  he: "מוח עצם"
}, {
  en: "border",
  he: "גבול / גבולי"
}, {
  en: "boredom",
  he: "שעמום"
}, {
  en: "boundless",
  he: "חסר גבולות"
}, {
  en: "brash",
  he: "פזיז / נמהר"
}, {
  en: "breast",
  he: "שד / חזה"
}, {
  en: "briefing",
  he: "תדריך"
}, {
  en: "brisk",
  he: "בחטף / במהרה"
}, {
  en: "broadcast",
  he: "לשדר / שידור"
}, {
  en: "broker",
  he: "מתווך / סוכן"
}, {
  en: "budget",
  he: "תקציב"
}, {
  en: "bulks",
  he: "כמויות גדולות"
}, {
  en: "buried",
  he: "קבור"
}, {
  en: "campaign",
  he: "מסע בחירות"
}, {
  en: "canal",
  he: "תעלה"
}, {
  en: "cancel",
  he: "לבטל"
}, {
  en: "candidate",
  he: "מועמד"
}, {
  en: "capsized",
  he: "מתהפך / מתבטל"
}, {
  en: "captions",
  he: "כתוביות"
}, {
  en: "capture",
  he: "ללכוד / לשבות"
}, {
  en: "careful consideration",
  he: "מחשבה מרובה"
}, {
  en: "cargo",
  he: "מטען"
}, {
  en: "cell",
  he: "תא"
}, {
  en: "cemeteries",
  he: "בתי קברות"
}, {
  en: "centric",
  he: "מרכזי"
}, {
  en: "chairman",
  he: "יו\"ר"
}, {
  en: "challenge",
  he: "אתגר"
}, {
  en: "charity",
  he: "צדקה"
}, {
  en: "charming",
  he: "מקסים"
}, {
  en: "chauvinistic",
  he: "שוביניסטי"
}, {
  en: "chronic illness",
  he: "מחלה כרונית"
}, {
  en: "circulated",
  he: "סבב / נפוץ"
}, {
  en: "civil",
  he: "אזרחי"
}, {
  en: "clarify",
  he: "להבהיר / לחדד"
}, {
  en: "clash",
  he: "עימות"
}, {
  en: "classified material",
  he: "חומר מסווג"
}, {
  en: "classify",
  he: "לסווג / למיין"
}, {
  en: "classified",
  he: "מסווג"
}, {
  en: "cloning",
  he: "לשכפל"
}, {
  en: "coach",
  he: "מאמן"
}, {
  en: "coating",
  he: "ציפוי"
}, {
  en: "coercion",
  he: "כפייה"
}, {
  en: "cognition",
  he: "תפישה"
}, {
  en: "colleague",
  he: "עמית"
}, {
  en: "collision",
  he: "התנגשות"
}, {
  en: "come to a halt",
  he: "לעצור / לחדול"
}, {
  en: "come to light",
  he: "נודע / הופיע"
}, {
  en: "comet",
  he: "כוכב שביט"
}, {
  en: "comfort",
  he: "הטבה / נוחיות"
}, {
  en: "commitment",
  he: "מחויבות"
}, {
  en: "committed to",
  he: "מסור ל..."
}, {
  en: "committee",
  he: "ועדה"
}, {
  en: "companion",
  he: "בן זוג / שותף"
}, {
  en: "compel",
  he: "לאלץ / לכפות"
}, {
  en: "complaint",
  he: "תלונה"
}, {
  en: "comprehensive",
  he: "מקיף וכוללני"
}, {
  en: "compromise",
  he: "להתפשר / לסכן"
}, {
  en: "compulsive",
  he: "כפייתי"
}, {
  en: "concentration",
  he: "ריכוז"
}, {
  en: "conditioning",
  he: "התניה"
}, {
  en: "confess",
  he: "להתוודות"
}, {
  en: "confronted",
  he: "מעומת למול"
}, {
  en: "connection",
  he: "קשר"
}, {
  en: "conniving",
  he: "תככן וחתרן"
}, {
  en: "conquest",
  he: "כיבוש"
}, {
  en: "consecutive",
  he: "רציף / רצוף"
}, {
  en: "considering",
  he: "בהתחשב"
}, {
  en: "consortium",
  he: "תאגיד"
}, {
  en: "construct",
  he: "לבנות"
}, {
  en: "continent",
  he: "יבשת"
}, {
  en: "continuity",
  he: "המשכיות"
}, {
  en: "continuously",
  he: "מתמשך"
}, {
  en: "contradiction",
  he: "סתירה"
}, {
  en: "contrary to",
  he: "בניגוד ל..."
}, {
  en: "conviction",
  he: "הרשעה / שכנוע"
}, {
  en: "convince",
  he: "לשכנע"
}, {
  en: "copyrights",
  he: "זכויות יוצרים"
}, {
  en: "coral",
  he: "אלמוג"
}, {
  en: "correspondent",
  he: "מתכתב / כתב"
}, {
  en: "co-star",
  he: "כוכב משנה"
}, {
  en: "counterfeit",
  he: "מזויף"
}, {
  en: "county judge",
  he: "שופט מחוזי"
}, {
  en: "courage",
  he: "אומץ"
}, {
  en: "court ruling",
  he: "פסיקת ביהמ\"ש"
}, {
  en: "cover story",
  he: "סיפור שער"
}, {
  en: "covert operation",
  he: "מבצע חשאי"
}, {
  en: "covertly",
  he: "בחשאיות"
}, {
  en: "covet",
  he: "לחמוד"
}, {
  en: "creativity",
  he: "יצירתיות"
}, {
  en: "credential",
  he: "מסמך / אישור"
}, {
  en: "credible",
  he: "מהימן / אמין"
}, {
  en: "crime prevention",
  he: "מניעת פשע"
}, {
  en: "crops",
  he: "יבולים"
}, {
  en: "crusade",
  he: "מסע צלב"
}, {
  en: "cumbersome",
  he: "מסורבל"
}, {
  en: "curse",
  he: "קללה"
}, {
  en: "debased",
  he: "פוגע / מעליב"
}, {
  en: "debut",
  he: "סרט ביכורים"
}, {
  en: "deceitfulness",
  he: "מרמה והונאה"
}, {
  en: "decentralized",
  he: "דה-צנטרליסטי"
}, {
  en: "decisive",
  he: "החלטי / מכריע"
}, {
  en: "debrief",
  he: "לתחקר"
}, {
  en: "decipher",
  he: "לפענח"
}, {
  en: "deduction",
  he: "דדוקציה"
}, {
  en: "defeat",
  he: "מפלה"
}, {
  en: "defect",
  he: "פגם / \"דפקט\""
}, {
  en: "defendant",
  he: "הנאשם"
}, {
  en: "defended",
  he: "הגן על..."
}, {
  en: "deform",
  he: "לעוות צורה"
}, {
  en: "defrost",
  he: "להפשיר"
}, {
  en: "denounce",
  he: "לגנות"
}, {
  en: "density",
  he: "צפיפות"
}, {
  en: "deny",
  he: "להכחיש"
}, {
  en: "depict",
  he: "לתאר"
}, {
  en: "deportation",
  he: "גירוש"
}, {
  en: "depression",
  he: "שפל"
}, {
  en: "descendant",
  he: "צאצא"
}, {
  en: "desirable",
  he: "נחשק"
}, {
  en: "deterrence",
  he: "הרתעה"
}, {
  en: "detest",
  he: "לתעב / לשנוא"
}, {
  en: "devastatingly",
  he: "באופן הרסני"
}, {
  en: "diminutive",
  he: "מקטין / זעיר"
}, {
  en: "disarray",
  he: "תוהו ובוהו"
}, {
  en: "discipline",
  he: "משמעת"
}, {
  en: "disclose",
  he: "לחשוף / לגלות"
}, {
  en: "disclosure",
  he: "חשיפה"
}, {
  en: "discount",
  he: "הנחה"
}, {
  en: "discovery",
  he: "תגלית"
}, {
  en: "disgusted",
  he: "נגעל"
}, {
  en: "disqualify",
  he: "לפסול"
}, {
  en: "disrupt",
  he: "להפריע"
}, {
  en: "distinguish",
  he: "להבחין"
}, {
  en: "distribute",
  he: "לחלק / להפיץ"
}, {
  en: "district",
  he: "מחוז / אזור"
}, {
  en: "disturbance",
  he: "הפרעה"
}, {
  en: "diver",
  he: "צוללן"
}, {
  en: "divulge",
  he: "לחשוף"
}, {
  en: "documentation",
  he: "תיעוד"
}, {
  en: "dodge",
  he: "להתחמק"
}, {
  en: "domain",
  he: "תחום"
}, {
  en: "dominated",
  he: "נשלט"
}, {
  en: "dormant",
  he: "רדום"
}, {
  en: "dosage",
  he: "מינון"
}, {
  en: "dot",
  he: "נקודה"
}, {
  en: "draw back",
  he: "לסגת / להירתע"
}, {
  en: "eager",
  he: "להוט"
}, {
  en: "earnest",
  he: "רציני"
}, {
  en: "echo",
  he: "הד"
}, {
  en: "editor",
  he: "עורך"
}, {
  en: "editorial",
  he: "מאמר מערכת"
}, {
  en: "educate",
  he: "לחנך"
}, {
  en: "efficient",
  he: "יעיל"
}, {
  en: "effort",
  he: "מאמץ / ניסיון"
}, {
  en: "elderly",
  he: "קשיש"
}, {
  en: "embezzle",
  he: "למעול / מעילה"
}, {
  en: "embrace",
  he: "לחבק"
}, {
  en: "emigrate",
  he: "להגר / לרדת"
}, {
  en: "employee",
  he: "עובד שכיר"
}, {
  en: "enclosure",
  he: "סגירת שטח"
}, {
  en: "encouragement",
  he: "עידוד"
}, {
  en: "endeavor",
  he: "מאמץ"
}, {
  en: "endorsement",
  he: "תמיכה / חסות"
}, {
  en: "enhance",
  he: "להרחיב"
}, {
  en: "enrollment",
  he: "הרשמה"
}, {
  en: "enthusiasm",
  he: "התלהבות"
}, {
  en: "eruption",
  he: "התפרצות"
}, {
  en: "espionage",
  he: "ריגול"
}, {
  en: "establishment",
  he: "מוסד / ממסד"
}, {
  en: "ethical",
  he: "אתי / מוסרי"
}, {
  en: "evaluation",
  he: "הערכה"
}, {
  en: "eventful",
  he: "מלא אירועים"
}, {
  en: "evolution",
  he: "אבולוציה"
}, {
  en: "excessive",
  he: "מוגזם"
}, {
  en: "excuse",
  he: "תירוץ"
}, {
  en: "expose",
  he: "לחשוף"
}, {
  en: "extend",
  he: "להאריך"
}, {
  en: "extensive",
  he: "מקיף"
}, {
  en: "extinction",
  he: "הכחדה"
}, {
  en: "facial features",
  he: "תווי פנים"
}, {
  en: "factor",
  he: "גורם"
}, {
  en: "faculty",
  he: "פקולטה"
}, {
  en: "fancy",
  he: "מהודר"
}, {
  en: "fan",
  he: "אוהד / מניפה"
}, {
  en: "favor",
  he: "טובה / העדפה"
}, {
  en: "feminine",
  he: "נשי"
}, {
  en: "ferocious",
  he: "פראי / אכזר"
}, {
  en: "ferociously",
  he: "באכזריות"
}, {
  en: "fertility",
  he: "פוריות"
}, {
  en: "feud",
  he: "משטמה"
}, {
  en: "fidelity",
  he: "נאמנות"
}, {
  en: "first aid",
  he: "עזרה ראשונה"
}, {
  en: "fixture",
  he: "משהו קבוע"
}, {
  en: "flat",
  he: "שטוח / דירה"
}, {
  en: "flaw",
  he: "חסרון / פגם"
}, {
  en: "flexibility",
  he: "גמישות"
}, {
  en: "foe",
  he: "אויב"
}, {
  en: "forge",
  he: "לזייף"
}, {
  en: "forming",
  he: "מייסדים"
}, {
  en: "fortify",
  he: "לבצר / לחזק"
}, {
  en: "foster",
  he: "לטפח / לאמץ"
}, {
  en: "found",
  he: "לייסד / להקים"
}, {
  en: "fraud",
  he: "הונאה / מרמה"
}, {
  en: "frown",
  he: "להזעיף פנים"
}, {
  en: "fruitful",
  he: "פורה"
}, {
  en: "frustrated",
  he: "מתוסכל"
}, {
  en: "function",
  he: "תפקוד"
}, {
  en: "fundamental",
  he: "בסיסי / יסודי"
}, {
  en: "furious",
  he: "זועם / \"רותח\""
}, {
  en: "gag order",
  he: "צו איסור פרסום"
}, {
  en: "gap",
  he: "פער"
}, {
  en: "genetic information",
  he: "מידע גנטי"
}, {
  en: "genuine",
  he: "מקורי / אמיתי"
}, {
  en: "get under way",
  he: "לצאת לדרך"
}, {
  en: "giant",
  he: "ענק"
}, {
  en: "glance",
  he: "מבט חטוף"
}, {
  en: "glimpse",
  he: "הצצה רגעית"
}, {
  en: "global economy",
  he: "כלכלה עולמית"
}, {
  en: "gown",
  he: "שמלה / חלוק"
}, {
  en: "graduate degree",
  he: "תואר אקדמאי"
}, {
  en: "greed",
  he: "תאוות בצע"
}, {
  en: "grief",
  he: "יגון"
}, {
  en: "guarded",
  he: "שמור"
}, {
  en: "guidance",
  he: "הנחיה"
}, {
  en: "gulf",
  he: "מפרץ"
}, {
  en: "halt",
  he: "לעצור / לחדול"
}, {
  en: "handcuffs",
  he: "אזיקים"
}, {
  en: "handy",
  he: "יעיל"
}, {
  en: "harbor",
  he: "נמל"
}, {
  en: "hearing",
  he: "שימוע / שומע"
}, {
  en: "heir",
  he: "יורש"
}, {
  en: "hint",
  he: "רמז"
}, {
  en: "holocaust survivor",
  he: "ניצול שואה"
}, {
  en: "honorable",
  he: "מכובד"
}, {
  en: "hopefulness",
  he: "מלא תקווה"
}, {
  en: "hostage",
  he: "בן ערובה"
}, {
  en: "hostile",
  he: "עוין"
}, {
  en: "hostility",
  he: "עוינות"
}, {
  en: "humidity",
  he: "לחות"
}, {
  en: "humiliation",
  he: "השפלה / בושה"
}, {
  en: "identical",
  he: "זהה"
}, {
  en: "identity",
  he: "זהות"
}, {
  en: "ignoring",
  he: "להתעלם"
}, {
  en: "ill-fated",
  he: "מסתיים בכי רע"
}, {
  en: "image",
  he: "תמונה / דמות"
}, {
  en: "imaginable",
  he: "ניתן לדמיון"
}, {
  en: "immunity",
  he: "חסינות"
}, {
  en: "impede",
  he: "להאט / להפריע"
}, {
  en: "implant",
  he: "לשתול"
}, {
  en: "imply",
  he: "לרמוז"
}, {
  en: "imprison",
  he: "לכלוא / לאסור"
}, {
  en: "improbable",
  he: "בלתי סביר"
}, {
  en: "in accordance",
  he: "בהתאם ל..."
}, {
  en: "in contradiction",
  he: "בסתירה"
}, {
  en: "incapable",
  he: "לא מסוגל"
}, {
  en: "incautious",
  he: "בלתי זהיר"
}, {
  en: "incentive",
  he: "תמריץ"
}, {
  en: "incident",
  he: "תקרית"
}, {
  en: "inclination",
  he: "נטייה ל..."
}, {
  en: "in common",
  he: "במשותף"
}, {
  en: "incompatible",
  he: "בלתי מתאים"
}, {
  en: "incompetence",
  he: "חוסר יכולת"
}, {
  en: "inconceivable",
  he: "בלתי נתפש"
}, {
  en: "indication",
  he: "אינדיקציה"
}, {
  en: "indicator",
  he: "אינדיקטור"
}, {
  en: "indictment",
  he: "כתב אישום"
}, {
  en: "infant",
  he: "תינוק קטן"
}, {
  en: "infectious",
  he: "מדבק"
}, {
  en: "infer",
  he: "להסיק / להבין"
}, {
  en: "infinitesimal",
  he: "מזערי"
}, {
  en: "inherent",
  he: "טבוע"
}, {
  en: "inheritance",
  he: "ירושה"
}, {
  en: "initial",
  he: "ראשוני"
}, {
  en: "initiate",
  he: "ליזום"
}, {
  en: "insanity",
  he: "שיגעון"
}, {
  en: "insect",
  he: "חרק"
}, {
  en: "inspiration",
  he: "השראה"
}, {
  en: "institution",
  he: "מוסד"
}, {
  en: "insufferable",
  he: "בלתי נסבל"
}, {
  en: "insufficient",
  he: "בלתי מספק"
}, {
  en: "insurance evaluators",
  he: "שמאי ביטוח"
}, {
  en: "insurance policy",
  he: "פוליסת ביטוח"
}, {
  en: "insure",
  he: "להבטיח"
}, {
  en: "integrity",
  he: "יושר / אמינות"
}, {
  en: "intelligence officer",
  he: "קצין מודיעין"
}, {
  en: "intended effect",
  he: "אפקט מיועד"
}, {
  en: "intent",
  he: "כוונה"
}, {
  en: "interaction",
  he: "אינטראקציה"
}, {
  en: "interrogation",
  he: "חקירה"
}, {
  en: "investigation",
  he: "חקירה (בלשית)"
}, {
  en: "investor",
  he: "משקיע"
}, {
  en: "invincible",
  he: "בלתי מנוצח"
}, {
  en: "invisible",
  he: "בלתי נראה"
}, {
  en: "invitation",
  he: "הזמנה"
}, {
  en: "isolate",
  he: "לבודד / לנתק"
}, {
  en: "isolationism",
  he: "בדלנות"
}, {
  en: "issue a declaration",
  he: "לפרסם הצהרה"
}, {
  en: "journey",
  he: "מסע"
}, {
  en: "judgment",
  he: "יכולת שיפוט"
}, {
  en: "jump-start",
  he: "להתניע"
}, {
  en: "justify",
  he: "להצדיק"
}, {
  en: "kidnapping",
  he: "חטיפה"
}, {
  en: "lab",
  he: "מעבדה"
}, {
  en: "lap",
  he: "הקפה / ירך"
}, {
  en: "launch",
  he: "להשיק / לשגר"
}, {
  en: "lavishly",
  he: "בהידור"
}, {
  en: "lawyer",
  he: "עורך דין"
}, {
  en: "layoffs",
  he: "פיטורין"
}, {
  en: "lecture",
  he: "הרצאה"
}, {
  en: "legacy",
  he: "מורשת"
}, {
  en: "lethal",
  he: "קטלני"
}, {
  en: "likeness",
  he: "דמיון"
}, {
  en: "limitation",
  he: "מגבלה"
}, {
  en: "line of research",
  he: "קו מחקרי"
}, {
  en: "link",
  he: "קשר"
}, {
  en: "loathe",
  he: "מתעב"
}, {
  en: "makes sense",
  he: "נשמע הגיוני"
}, {
  en: "malfunction",
  he: "תקלה"
}, {
  en: "management position",
  he: "תפקיד ניהולי"
}, {
  en: "mandatory",
  he: "חובה"
}, {
  en: "manner",
  he: "אופן"
}, {
  en: "marginal element",
  he: "גורם שולי"
}, {
  en: "markedly",
  he: "באופן ניכר"
}, {
  en: "masculine",
  he: "גברי"
}, {
  en: "massacre",
  he: "טבח"
}, {
  en: "meager",
  he: "זעום"
}, {
  en: "meaningless",
  he: "חסר משמעות"
}, {
  en: "means of deterrence",
  he: "אמצעי הרתעה"
}, {
  en: "mediator",
  he: "מתווך"
}, {
  en: "mediocre",
  he: "בינוני"
}, {
  en: "meek",
  he: "חלש / קלוש"
}, {
  en: "meet these goals",
  he: "לעמוד ביעדים"
}, {
  en: "mental",
  he: "נפשי / מנטאלי"
}, {
  en: "merger",
  he: "איחוד / מיזוג"
}, {
  en: "meticulous",
  he: "קפדני ודקדקני"
}, {
  en: "middleman",
  he: "מתווך"
}, {
  en: "mild",
  he: "מתון"
}, {
  en: "minister",
  he: "שר"
}, {
  en: "minute",
  he: "זעיר / דקה"
}, {
  en: "miracle",
  he: "נס"
}, {
  en: "misconception",
  he: "תפישה שגויה"
}, {
  en: "misinterpret",
  he: "לפרש לא נכון"
}, {
  en: "missionary",
  he: "מיסיונר"
}, {
  en: "moral question",
  he: "שאלה מוסרית"
}, {
  en: "mortal danger",
  he: "סכנת חיים"
}, {
  en: "motion",
  he: "תנועה"
}, {
  en: "motive",
  he: "מניע"
}, {
  en: "mutual",
  he: "הדדי"
}, {
  en: "mysteriousness",
  he: "מסתוריות"
}, {
  en: "mystical",
  he: "מיסטי"
}, {
  en: "mystify",
  he: "לערפל"
}, {
  en: "naive",
  he: "נאיבי / תמים"
}, {
  en: "narcissist",
  he: "נרקיסיסט"
}, {
  en: "navigate",
  he: "לנווט"
}, {
  en: "nerve cell",
  he: "תא עצב"
}, {
  en: "neutral",
  he: "נייטראלי"
}, {
  en: "next of kin",
  he: "קרוב משפחה"
}, {
  en: "nightmare",
  he: "סיוט"
}, {
  en: "novel",
  he: "חדשני"
}, {
  en: "novelist",
  he: "סופר"
}, {
  en: "obligation",
  he: "התחייבות"
}, {
  en: "offspring",
  he: "צאצא"
}, {
  en: "ongoing",
  he: "מתמשך"
}, {
  en: "oppose",
  he: "להתנגד ל..."
}, {
  en: "opposite",
  he: "הפוך"
}, {
  en: "oppression",
  he: "דיכוי"
}, {
  en: "oral",
  he: "בעל פה"
}, {
  en: "orbit",
  he: "מסלול היקפי"
}, {
  en: "originates from",
  he: "נובע מ..."
}, {
  en: "outcome",
  he: "תוצאה"
}, {
  en: "overshadow",
  he: "להאפיל"
}, {
  en: "overt",
  he: "גלוי, פומבי"
}, {
  en: "overwhelmed",
  he: "המום"
}, {
  en: "pamper",
  he: "לפנק"
}, {
  en: "parade",
  he: "מצעד / להצעיד"
}, {
  en: "paralyze",
  he: "לשתק"
}, {
  en: "participant",
  he: "משתתף"
}, {
  en: "particle",
  he: "חלקיק"
}, {
  en: "pave",
  he: "לסלול"
}, {
  en: "peacefulness",
  he: "שקט ושלווה"
}, {
  en: "penetration",
  he: "חדירה"
}, {
  en: "percent",
  he: "אחוז"
}, {
  en: "perception",
  he: "תפישה"
}, {
  en: "persist",
  he: "להתמיד"
}, {
  en: "personnel",
  he: "כוח אדם"
}, {
  en: "persuasion",
  he: "שכנוע"
}, {
  en: "phase",
  he: "שלב"
}, {
  en: "pipeline",
  he: "צינור"
}, {
  en: "plagiarism",
  he: "גניבה ספרותית"
}, {
  en: "plain",
  he: "פשוט / ברור"
}, {
  en: "plaintiff",
  he: "תובע / מאשים"
}, {
  en: "planet",
  he: "כוכב לכת"
}, {
  en: "plea",
  he: "טענה"
}, {
  en: "pledge",
  he: "התחייבות"
}, {
  en: "plenty",
  he: "שפע"
}, {
  en: "point out",
  he: "לציין"
}, {
  en: "pollute",
  he: "לזהם"
}, {
  en: "popular belief",
  he: "אמונה מקובלת"
}, {
  en: "port",
  he: "נמל"
}, {
  en: "precaution",
  he: "אמצעי זהירות"
}, {
  en: "precious",
  he: "יקר"
}, {
  en: "precisely",
  he: "בדיוק"
}, {
  en: "preclude",
  he: "להוציא מהכלל"
}, {
  en: "preference",
  he: "העדפה"
}, {
  en: "premise",
  he: "הנחת יסוד"
}, {
  en: "preparation",
  he: "הכנה"
}, {
  en: "preserved bodies",
  he: "גופות משומרות"
}, {
  en: "prestigious",
  he: "יוקרתי"
}, {
  en: "probable successor",
  he: "יורש אפשרי"
}, {
  en: "probation",
  he: "תקופת מבחן"
}, {
  en: "probe",
  he: "סקירה מעמיקה"
}, {
  en: "profit",
  he: "להרוויח"
}, {
  en: "projected",
  he: "צפוי / מתוכנן"
}, {
  en: "prolonged",
  he: "מוארך / ממושך"
}, {
  en: "prominent",
  he: "בולט"
}, {
  en: "promotion",
  he: "קידום"
}, {
  en: "pronunciation",
  he: "היגוי / מבטא"
}, {
  en: "prophecy",
  he: "נבואה"
}, {
  en: "proponent",
  he: "תומך"
}, {
  en: "proposal",
  he: "הצעה"
}, {
  en: "prosperity",
  he: "שגשוג ורווחה"
}, {
  en: "protest",
  he: "מחאה / הפגנה"
}, {
  en: "punishment",
  he: "עונש / ענישה"
}, {
  en: "purify",
  he: "לטהר"
}, {
  en: "purloined material",
  he: "חומר \"מושאל\""
}, {
  en: "purposeful",
  he: "מלא כוונה"
}, {
  en: "pursuit",
  he: "מרדף"
}, {
  en: "puzzled",
  he: "תמוה"
}, {
  en: "qualified",
  he: "מתאים / מוסמך"
}, {
  en: "quarter",
  he: "רבע"
}, {
  en: "quiz",
  he: "בוחן / חידון"
}, {
  en: "racism",
  he: "גזענות"
}, {
  en: "racist",
  he: "גזען"
}, {
  en: "radiation",
  he: "קרינה"
}, {
  en: "reaction",
  he: "תגובה"
}, {
  en: "reasonable",
  he: "סביר / הגיוני"
}, {
  en: "reassembled",
  he: "מורכב מחדש"
}, {
  en: "rebuttal",
  he: "הפרכה"
}, {
  en: "recipe",
  he: "מתכון"
}, {
  en: "rectify",
  he: "לתקן"
}, {
  en: "refuel",
  he: "לתדלק מחדש"
}, {
  en: "regardless",
  he: "ללא קשר"
}, {
  en: "regime",
  he: "משטר"
}, {
  en: "regiment",
  he: "גדוד"
}, {
  en: "region",
  he: "אזור / תחום"
}, {
  en: "reinforce",
  he: "לתגבר / לחזק"
}, {
  en: "reluctance",
  he: "חוסר רצון"
}, {
  en: "remarkable",
  he: "ראוי לציון"
}, {
  en: "remorse",
  he: "חרטה / צער"
}, {
  en: "reprehensible",
  he: "ראוי לגינוי"
}, {
  en: "reptile",
  he: "זוחל"
}, {
  en: "requester",
  he: "המבקש"
}, {
  en: "residency",
  he: "מקום מגורים"
}, {
  en: "respiration",
  he: "נשימה"
}, {
  en: "restoration",
  he: "שחזור"
}, {
  en: "restore",
  he: "לשחזר"
}, {
  en: "retirement",
  he: "פרישה"
}, {
  en: "reveal",
  he: "לחשוף / לגלות"
}, {
  en: "review",
  he: "לבדוק שנית"
}, {
  en: "revive",
  he: "להחיות"
}, {
  en: "revolutionize",
  he: "לחולל מהפיכה"
}, {
  en: "role",
  he: "תפקיד"
}, {
  en: "root",
  he: "שורש"
}, {
  en: "routine",
  he: "רוטינה / שגרה"
}, {
  en: "rural",
  he: "כפרי"
}, {
  en: "sacred",
  he: "קדוש"
}, {
  en: "satellite",
  he: "לוויין"
}, {
  en: "scatter",
  he: "לפזר / להתפזר"
}, {
  en: "scenario",
  he: "תרחיש"
}, {
  en: "schooling",
  he: "חינוך"
}, {
  en: "scroll",
  he: "מגילה"
}, {
  en: "self-preservation",
  he: "שימור עצמי"
}, {
  en: "self-restraint",
  he: "שליטה עצמית"
}, {
  en: "semi",
  he: "למחצה"
}, {
  en: "seminar",
  he: "סמינר"
}, {
  en: "sensible",
  he: "הגיוני"
}, {
  en: "sensuous",
  he: "חושני"
}, {
  en: "serenity",
  he: "שלווה"
}, {
  en: "server",
  he: "שרת מחשב"
}, {
  en: "session",
  he: "פגישה /סדנא"
}, {
  en: "shortage",
  he: "מחסור"
}, {
  en: "similarly",
  he: "באופן דומה"
}, {
  en: "simulate",
  he: "לדמות"
}, {
  en: "site",
  he: "אתר"
}, {
  en: "skinny",
  he: "רזה מאוד"
}, {
  en: "sleepiness",
  he: "ישנוניות"
}, {
  en: "slim",
  he: "רזה / קלוש"
}, {
  en: "slips of the tongue",
  he: "מעידות בלשון"
}, {
  en: "sober",
  he: "פיכח"
}, {
  en: "software patches",
  he: "טלאי תוכנה"
}, {
  en: "sought after",
  he: "מחפשים אחריו"
}, {
  en: "specialist",
  he: "מומחה"
}, {
  en: "specialize",
  he: "מתמחה ב..."
}, {
  en: "spectator",
  he: "צופה"
}, {
  en: "spokesperson",
  he: "דובר"
}, {
  en: "spokeswoman",
  he: "דוברת"
}, {
  en: "sporadic",
  he: "בלתי סדיר"
}, {
  en: "spot",
  he: "נקודה"
}, {
  en: "squeeze",
  he: "ללחוץ / למחוץ"
}, {
  en: "stage",
  he: "שלב"
}, {
  en: "stakes",
  he: "סיכונים"
}, {
  en: "stand",
  he: "לעמוד / יציע"
}, {
  en: "startling",
  he: "מפתיע / מדהים"
}, {
  en: "stems from",
  he: "נובע מ..."
}, {
  en: "stock",
  he: "מניה בורסאית"
}, {
  en: "stomach",
  he: "קיבה / בטן"
}, {
  en: "storm",
  he: "סופה / סערה"
}, {
  en: "straight-forward",
  he: "ישיר"
}, {
  en: "strict",
  he: "נוקשה / קפדני"
}, {
  en: "suburban",
  he: "פרברי"
}, {
  en: "superstition",
  he: "אמונה טפלה"
}, {
  en: "supervision",
  he: "פיקוח"
}, {
  en: "surface variance",
  he: "משתנה חיצוני"
}, {
  en: "surrogate mother",
  he: "אם פונדקאית"
}, {
  en: "suspended",
  he: "מושעה / מושהה"
}, {
  en: "tantalizing",
  he: "מרגש / מרעיד"
}, {
  en: "tempt fate",
  he: "להתגרות בגורל"
}, {
  en: "testify",
  he: "להעיד"
}, {
  en: "testimony",
  he: "עדות"
}, {
  en: "therapy",
  he: "תרפיה / טיפול"
}, {
  en: "tide",
  he: "גאות ושפל"
}, {
  en: "timeliness",
  he: "דייקנות"
}, {
  en: "tool",
  he: "כלי"
}, {
  en: "topic",
  he: "הנושא"
}, {
  en: "topple",
  he: "למוטט"
}, {
  en: "tournament",
  he: "טורניר"
}, {
  en: "trade-offs",
  he: "החלפות"
}, {
  en: "traditional",
  he: "מסורתי"
}, {
  en: "traitorous",
  he: "בוגדני"
}, {
  en: "tranquility",
  he: "שלווה"
}, {
  en: "transaction",
  he: "עסקה"
}, {
  en: "transfer",
  he: "להעביר"
}, {
  en: "translucent",
  he: "מעט שקוף"
}, {
  en: "transparent",
  he: "שקוף / ברור"
}, {
  en: "tremendous",
  he: "עצום"
}, {
  en: "trend",
  he: "אופנה"
}, {
  en: "trial and error",
  he: "ניסוי וטעייה"
}, {
  en: "truthfully",
  he: "בכנות"
}, {
  en: "unbearable",
  he: "בלתי נסבל"
}, {
  en: "under dispute",
  he: "נתון במחלוקת"
}, {
  en: "undeterred",
  he: "לא נרתע מ..."
}, {
  en: "unravel",
  he: "לחשוף"
}, {
  en: "unstable",
  he: "בלתי יציב"
}, {
  en: "usable",
  he: "ניתן לשימוש"
}, {
  en: "vacancy",
  he: "מקום פנוי"
}, {
  en: "varies",
  he: "משתנה"
}, {
  en: "vast majority",
  he: "הרוב המוחלט"
}, {
  en: "veil",
  he: "הינומה"
}, {
  en: "violate",
  he: "להפר"
}, {
  en: "voyage",
  he: "מסע"
}, {
  en: "wage",
  he: "שכר / משכורת"
}, {
  en: "want of understanding",
  he: "העדר הבנה"
}, {
  en: "waver",
  he: "לוותר"
}, {
  en: "will",
  he: "רצון / צוואה"
}, {
  en: "willingness",
  he: "מוכנות"
}, {
  en: "wiped out",
  he: "למחוק"
}, {
  en: "work ethic",
  he: "מוסר עבודה"
}, {
  en: "worship",
  he: "לסגוד ל..."
}, {
  en: "wrapped up",
  he: "עטוף"
}, {
  en: "wrist",
  he: "פרק יד"
}, {
  en: "yearn",
  he: "להשתוקק"
}, {
  en: "youth",
  he: "נעורים"
}];
})(); } catch (e) { __ds_ns.__errors.push({ path: "quiz-game/words.js", error: String((e && e.message) || e) }); }

// quiz/Quiz.jsx
try { (() => {
function _extends() { return _extends = Object.assign ? Object.assign.bind() : function (n) { for (var e = 1; e < arguments.length; e++) { var t = arguments[e]; for (var r in t) ({}).hasOwnProperty.call(t, r) && (n[r] = t[r]); } return n; }, _extends.apply(null, arguments); }
/* global React, QUIZ_DECK, QUIZ_OPPONENTS, useTweaks, TweaksPanel, TweakSection, TweakRadio, TweakColor, TweakToggle */
const {
  useState,
  useEffect,
  useRef,
  useMemo,
  useCallback
} = React;
const TWEAK_DEFAULTS = /*EDITMODE-BEGIN*/{
  "mode": "solo",
  "accent": "orange",
  "showTimer": true,
  "shuffle": true,
  "wallpaper": "slashes"
} /*EDITMODE-END*/;

/* ---------- icons ---------- */
const I = {
  speaker: p => /*#__PURE__*/React.createElement("svg", _extends({
    viewBox: "0 0 24 24",
    width: "18",
    height: "18",
    fill: "currentColor"
  }, p), /*#__PURE__*/React.createElement("path", {
    d: "M3 10v4a1 1 0 0 0 1 1h3l4 3.5a1 1 0 0 0 1.6-.8V6.3a1 1 0 0 0-1.6-.8L7 9H4a1 1 0 0 0-1 1Zm13.5-1.7a1 1 0 0 0-1.4 1.4 4 4 0 0 1 0 4.6 1 1 0 0 0 1.4 1.4 6 6 0 0 0 0-7.4Zm2.8-2.8a1 1 0 0 0-1.4 1.4 8 8 0 0 1 0 10.2 1 1 0 0 0 1.4 1.4 10 10 0 0 0 0-13Z"
  })),
  check: p => /*#__PURE__*/React.createElement("svg", _extends({
    viewBox: "0 0 24 24",
    width: "14",
    height: "14",
    fill: "none",
    stroke: "currentColor",
    strokeWidth: "3",
    strokeLinecap: "round",
    strokeLinejoin: "round"
  }, p), /*#__PURE__*/React.createElement("path", {
    d: "m5 12 5 5L20 7"
  })),
  x: p => /*#__PURE__*/React.createElement("svg", _extends({
    viewBox: "0 0 24 24",
    width: "14",
    height: "14",
    fill: "none",
    stroke: "currentColor",
    strokeWidth: "3",
    strokeLinecap: "round",
    strokeLinejoin: "round"
  }, p), /*#__PURE__*/React.createElement("path", {
    d: "M6 6l12 12M18 6L6 18"
  })),
  reset: p => /*#__PURE__*/React.createElement("svg", _extends({
    viewBox: "0 0 24 24",
    width: "20",
    height: "20",
    fill: "none",
    stroke: "currentColor",
    strokeWidth: "2",
    strokeLinecap: "round",
    strokeLinejoin: "round"
  }, p), /*#__PURE__*/React.createElement("path", {
    d: "M3 12a9 9 0 1 0 3-6.7L3 8"
  }), /*#__PURE__*/React.createElement("path", {
    d: "M3 3v5h5"
  })),
  exit: p => /*#__PURE__*/React.createElement("svg", _extends({
    viewBox: "0 0 24 24",
    width: "20",
    height: "20",
    fill: "none",
    stroke: "currentColor",
    strokeWidth: "2",
    strokeLinecap: "round",
    strokeLinejoin: "round"
  }, p), /*#__PURE__*/React.createElement("path", {
    d: "m12 19-7-7 7-7"
  }), /*#__PURE__*/React.createElement("path", {
    d: "M5 12h14"
  }))
};
function speak(text) {
  if (!("speechSynthesis" in window)) return;
  try {
    window.speechSynthesis.cancel();
    const u = new SpeechSynthesisUtterance(text);
    u.lang = "en-US";
    u.rate = .92;
    window.speechSynthesis.speak(u);
  } catch (e) {}
}
function shuffleArr(a) {
  const x = [...a];
  for (let i = x.length - 1; i > 0; i--) {
    const j = Math.floor(Math.random() * (i + 1));
    [x[i], x[j]] = [x[j], x[i]];
  }
  return x;
}
function ZBg() {
  return /*#__PURE__*/React.createElement("div", {
    className: "qz-z",
    "aria-hidden": true
  }, /*#__PURE__*/React.createElement("div", {
    className: "slash",
    style: {
      top: "-30px",
      right: "-8%",
      width: "62%",
      background: "var(--ez-lavender-soft)"
    }
  }), /*#__PURE__*/React.createElement("div", {
    className: "slash",
    style: {
      top: "55px",
      right: "18%",
      width: "68%",
      background: "var(--ez-lavender)",
      opacity: .32
    }
  }), /*#__PURE__*/React.createElement("div", {
    className: "slash",
    style: {
      bottom: "110px",
      right: "-8%",
      width: "78%",
      background: "var(--ez-lavender-soft)"
    }
  }), /*#__PURE__*/React.createElement("div", {
    className: "slash",
    style: {
      bottom: "50px",
      right: "30%",
      width: "60%",
      background: "var(--ez-lavender)",
      opacity: .22
    }
  }));
}
function DuelBg({
  opponent
}) {
  return /*#__PURE__*/React.createElement("div", {
    className: "qz-duelbg",
    "aria-hidden": true
  }, /*#__PURE__*/React.createElement("div", {
    className: "qz-duelbg-half right"
  }), /*#__PURE__*/React.createElement("div", {
    className: "qz-duelbg-half left",
    style: opponent ? {
      "--opp-tint": opponent.color || "#9C9CDC"
    } : null
  }), /*#__PURE__*/React.createElement("div", {
    className: "qz-duelbg-seam"
  }), /*#__PURE__*/React.createElement("div", {
    className: "qz-duelbg-dots right"
  }), /*#__PURE__*/React.createElement("div", {
    className: "qz-duelbg-dots left"
  }), /*#__PURE__*/React.createElement("svg", {
    className: "qz-duelbg-vs",
    viewBox: "0 0 200 110",
    preserveAspectRatio: "xMidYMid meet"
  }, /*#__PURE__*/React.createElement("text", {
    x: "100",
    y: "92",
    textAnchor: "middle",
    fontFamily: "ui-sans-serif, system-ui",
    fontWeight: "900",
    fontSize: "120",
    letterSpacing: "-6",
    fill: "none",
    stroke: "currentColor",
    strokeWidth: "2"
  }, "VS")), /*#__PURE__*/React.createElement("div", {
    className: "qz-duelbg-streak s1"
  }), /*#__PURE__*/React.createElement("div", {
    className: "qz-duelbg-streak s2"
  }), /*#__PURE__*/React.createElement("div", {
    className: "qz-duelbg-streak s3"
  }));
}

/* ---------- start / mode select ---------- */
function StartScreen({
  onStart,
  onPickDuel
}) {
  return /*#__PURE__*/React.createElement("div", {
    className: "qz-start"
  }, /*#__PURE__*/React.createElement("div", {
    className: "qz-start-card"
  }, /*#__PURE__*/React.createElement("div", {
    className: "eyebrow"
  }, "\u05DE\u05D1\u05D7\u05DF \u05D0\u05DE\u05E8\u05D9\u05E7\u05D0\u05D9 \xB7 \u05D9\u05D7\u05D9\u05D3\u05D4 01"), /*#__PURE__*/React.createElement("h1", null, "\u05DE\u05D9\u05DC\u05D9\u05DD \u05DC\u05E4\u05E1\u05D9\u05DB\u05D5\u05DE\u05D8\u05E8\u05D9.", /*#__PURE__*/React.createElement("br", null), QUIZ_DECK.length, " \u05E9\u05D0\u05DC\u05D5\u05EA, 4 \u05D0\u05E4\u05E9\u05E8\u05D5\u05D9\u05D5\u05EA."), /*#__PURE__*/React.createElement("div", {
    className: "meta"
  }, /*#__PURE__*/React.createElement("span", null, /*#__PURE__*/React.createElement("strong", null, QUIZ_DECK.length), " \u05E9\u05D0\u05DC\u05D5\u05EA"), /*#__PURE__*/React.createElement("span", null, "\xB7"), /*#__PURE__*/React.createElement("span", null, "~", /*#__PURE__*/React.createElement("strong", null, "3"), " \u05D3\u05E7\u05D5\u05EA"), /*#__PURE__*/React.createElement("span", null, "\xB7"), /*#__PURE__*/React.createElement("span", null, "\u05E7\u05D5\u05E9\u05D9 ", /*#__PURE__*/React.createElement("strong", null, "\u05D1\u05D9\u05E0\u05D5\u05E0\u05D9"))), /*#__PURE__*/React.createElement("div", {
    className: "qz-mode-pick"
  }, /*#__PURE__*/React.createElement("button", {
    className: "qz-mode solo",
    onClick: onStart
  }, /*#__PURE__*/React.createElement("div", {
    className: "icon"
  }, /*#__PURE__*/React.createElement("img", {
    src: "../assets/icons/ez-icon-02-checklist-tap.png",
    alt: ""
  })), /*#__PURE__*/React.createElement("div", {
    className: "name"
  }, "\u05EA\u05E8\u05D2\u05D5\u05DC \u05E2\u05E6\u05DE\u05D9"), /*#__PURE__*/React.createElement("div", {
    className: "sub"
  }, "\u05D1\u05E7\u05E6\u05D1 \u05E9\u05DC\u05DB\u05DD")), /*#__PURE__*/React.createElement("button", {
    className: "qz-mode duel",
    onClick: onPickDuel
  }, /*#__PURE__*/React.createElement("div", {
    className: "icon"
  }, /*#__PURE__*/React.createElement("img", {
    src: "../assets/icons/ez-icon-06-mentor-chat.png",
    alt: ""
  })), /*#__PURE__*/React.createElement("div", {
    className: "name"
  }, "\u05D3\u05D5-\u05E7\u05E8\u05D1 \u05D7\u05D1\u05E8"), /*#__PURE__*/React.createElement("div", {
    className: "sub"
  }, "\u05D7\u05D1\u05E8\u05D5 \u05D6\u05D4 \u05DE\u05D5\u05DC \u05D6\u05D4")))));
}

/* ---------- duel modal ---------- */
function DuelModal({
  onClose,
  onStart
}) {
  const [picked, setPicked] = useState(null);
  const [copied, setCopied] = useState(false);
  const link = "ezway.co.il/quiz/duel/8K2P";
  const copy = () => {
    try {
      navigator.clipboard.writeText("https://" + link);
      setCopied(true);
      setTimeout(() => setCopied(false), 1600);
    } catch (e) {
      setCopied(true);
      setTimeout(() => setCopied(false), 1600);
    }
  };
  return /*#__PURE__*/React.createElement("div", {
    className: "qz-modal-back",
    onClick: onClose
  }, /*#__PURE__*/React.createElement("div", {
    className: "qz-modal",
    onClick: e => e.stopPropagation()
  }, /*#__PURE__*/React.createElement("h2", null, "\u05D6\u05DE\u05E0\u05D5 \u05D0\u05EA \u05D4\u05D7\u05D1\u05E8/\u05D4 \u05DC\u05D3\u05D5-\u05E7\u05E8\u05D1."), /*#__PURE__*/React.createElement("div", {
    className: "sub"
  }, "\u05D1\u05D7\u05E8\u05D5 \u05DE\u05D4\u05E8\u05E9\u05D9\u05DE\u05D4 \u05D0\u05D5 \u05E9\u05DC\u05D7\u05D5 \u05DC\u05D9\u05E0\u05E7. \u05E9\u05E0\u05D9\u05DB\u05DD \u05EA\u05E7\u05D1\u05DC\u05D5 \u05D0\u05EA \u05D0\u05D5\u05EA\u05DF \u05D4\u05E9\u05D0\u05DC\u05D5\u05EA, \u05D1\u05D0\u05D5\u05EA\u05D5 \u05E1\u05D3\u05E8."), /*#__PURE__*/React.createElement("div", {
    className: "friends"
  }, QUIZ_OPPONENTS.map(o => /*#__PURE__*/React.createElement("div", {
    key: o.id,
    className: "qz-friend " + (picked && picked.id === o.id ? "selected" : ""),
    onClick: () => setPicked(o)
  }, /*#__PURE__*/React.createElement("div", {
    className: "ava",
    style: {
      background: o.color + "22",
      color: o.color
    }
  }, o.emoji), /*#__PURE__*/React.createElement("div", {
    className: "name"
  }, o.name)))), /*#__PURE__*/React.createElement("div", null, /*#__PURE__*/React.createElement("div", {
    style: {
      fontFamily: "var(--font-display)",
      fontWeight: 700,
      fontSize: 12,
      color: "var(--ez-fg-3)",
      textTransform: "uppercase",
      letterSpacing: ".08em",
      marginBottom: 8
    }
  }, "\u05D0\u05D5 \u05E9\u05DC\u05D7\u05D5 \u05DC\u05D9\u05E0\u05E7:"), /*#__PURE__*/React.createElement("div", {
    className: "qz-link-row"
  }, /*#__PURE__*/React.createElement("input", {
    value: "https://" + link,
    readOnly: true,
    onFocus: e => e.target.select()
  }), /*#__PURE__*/React.createElement("button", {
    className: copied ? "copied" : "",
    onClick: copy
  }, copied ? "הועתק ✓" : "העתק"))), /*#__PURE__*/React.createElement("div", {
    className: "actions"
  }, /*#__PURE__*/React.createElement("button", {
    className: "btn-ghost",
    onClick: onClose
  }, "\u05D1\u05D9\u05D8\u05D5\u05DC"), /*#__PURE__*/React.createElement("button", {
    className: "btn-primary",
    disabled: !picked,
    onClick: () => onStart(picked)
  }, picked ? `הזמינו את ${picked.name}` : "בחרו יריב/ה"))));
}

/* ---------- main quiz ---------- */
function Quiz() {
  const [t, setTweak] = useTweaks(TWEAK_DEFAULTS);

  // accent
  useEffect(() => {
    const map = {
      orange: {
        o: "#F37327",
        od: "#D55B12",
        os: "#FBD9C2"
      },
      indigo: {
        o: "#3F4197",
        od: "#2A2C73",
        os: "#D5D6EC"
      },
      teal: {
        o: "#1F8A8A",
        od: "#10696B",
        os: "#CDE7E7"
      }
    };
    const c = map[t.accent] || map.orange;
    document.documentElement.style.setProperty("--ez-orange", c.o);
    document.documentElement.style.setProperty("--ez-orange-deep", c.od);
    document.documentElement.style.setProperty("--ez-orange-soft", c.os);
  }, [t.accent]);

  // wallpaper
  useEffect(() => {
    document.body.dataset.wallpaper = t.wallpaper || "slashes";
  }, [t.wallpaper]);
  const [phase, setPhase] = useState("start"); // start | duel-pick | playing | done
  const [opponent, setOpponent] = useState(null);
  const [questions, setQuestions] = useState([]);
  const [order, setOrder] = useState([]); // shuffled options per question
  const [idx, setIdx] = useState(0);
  const [picked, setPicked] = useState(null); // option index user picked
  const [oppPicked, setOppPicked] = useState(null);
  const [oppCorrect, setOppCorrect] = useState(null);
  const [score, setScore] = useState(0);
  const [oppScore, setOppScore] = useState(0);
  const [results, setResults] = useState([]); // [{id, correct: bool}]
  const [oppReact, setOppReact] = useState(null); // string
  const [timer, setTimer] = useState(15);
  const timerRef = useRef(null);
  const beginQuiz = useCallback(opp => {
    const qs = t.shuffle ? shuffleArr(QUIZ_DECK) : [...QUIZ_DECK];
    const opts = qs.map(q => t.shuffle ? shuffleArr([0, 1, 2, 3]) : [0, 1, 2, 3]);
    setQuestions(qs);
    setOrder(opts);
    setIdx(0);
    setPicked(null);
    setOppPicked(null);
    setOppCorrect(null);
    setScore(0);
    setOppScore(0);
    setResults([]);
    setOppReact(null);
    setOpponent(opp || null);
    setPhase("playing");
    setTimer(15);
  }, [t.shuffle]);
  const q = questions[idx];
  const optOrder = order[idx] || [0, 1, 2, 3];

  // simulate opponent: picks an answer 1-7s in
  useEffect(() => {
    if (phase !== "playing" || !opponent || !q || oppPicked !== null) return;
    const delay = 1500 + Math.random() * 4500;
    const correct = Math.random() < 0.7; // opponent gets ~70% right
    const correctIdx = q.options.indexOf(q.correct);
    const wrongIdx = [0, 1, 2, 3].filter(i => i !== correctIdx);
    const choice = correct ? correctIdx : wrongIdx[Math.floor(Math.random() * wrongIdx.length)];
    const handle = setTimeout(() => {
      setOppPicked(choice);
      setOppCorrect(correct);
      if (correct) setOppScore(s => s + 1);
      setOppReact(correct ? "ענה נכון ✓" : "ענה לא נכון");
      setTimeout(() => setOppReact(null), 2200);
    }, delay);
    return () => clearTimeout(handle);
  }, [phase, opponent, q, idx, oppPicked]);

  // timer (duel only)
  useEffect(() => {
    if (phase !== "playing" || !opponent || !t.showTimer) return;
    if (picked !== null) return;
    setTimer(15);
    if (timerRef.current) clearInterval(timerRef.current);
    timerRef.current = setInterval(() => {
      setTimer(s => {
        if (s <= 1) {
          clearInterval(timerRef.current);
          return 0;
        }
        return s - 1;
      });
    }, 1000);
    return () => clearInterval(timerRef.current);
  }, [phase, opponent, idx, picked, t.showTimer]);
  const pick = i => {
    if (picked !== null) return;
    setPicked(i);
    const correct = q.options[i] === q.correct;
    if (correct) setScore(s => s + 1);
    setResults(r => [...r, {
      id: q.id,
      correct
    }]);
    if (timerRef.current) clearInterval(timerRef.current);
  };
  const next = () => {
    if (idx + 1 >= questions.length) {
      setPhase("done");
      return;
    }
    setIdx(idx + 1);
    setPicked(null);
    setOppPicked(null);
    setOppCorrect(null);
  };

  // keyboard 1-4
  useEffect(() => {
    if (phase !== "playing") return;
    const onKey = e => {
      if (picked !== null && (e.key === "Enter" || e.key === " ")) {
        e.preventDefault();
        next();
        return;
      }
      if (picked !== null) return;
      const idx = ["1", "2", "3", "4"].indexOf(e.key);
      if (idx >= 0 && idx < optOrder.length) pick(optOrder[idx]);
    };
    window.addEventListener("keydown", onKey);
    return () => window.removeEventListener("keydown", onKey);
  }, [phase, picked, optOrder]);
  const correctIdx = q ? q.options.indexOf(q.correct) : -1;
  const isAnswered = picked !== null;
  const isCorrect = isAnswered && q && q.options[picked] === q.correct;
  return /*#__PURE__*/React.createElement("div", {
    className: "qz-app" + (phase === "start" || phase === "duel-pick" ? " qz-app--home" : "")
  }, (phase === "start" || phase === "duel-pick") && /*#__PURE__*/React.createElement("div", {
    className: "qz-home-bg",
    "aria-hidden": true
  }, /*#__PURE__*/React.createElement("div", {
    className: "qz-home-bg__img"
  }), /*#__PURE__*/React.createElement("div", {
    className: "qz-home-bg__tint"
  })), phase !== "start" && phase !== "duel-pick" && /*#__PURE__*/React.createElement(React.Fragment, null, t.wallpaper === "slashes" && /*#__PURE__*/React.createElement(ZBg, null), t.wallpaper === "zoom-e" && /*#__PURE__*/React.createElement("div", {
    className: "qz-wallpaper",
    "aria-hidden": true
  })), /*#__PURE__*/React.createElement("div", {
    className: "qz-top"
  }, /*#__PURE__*/React.createElement("a", {
    href: "#",
    className: "logo",
    onClick: e => e.preventDefault()
  }, /*#__PURE__*/React.createElement("img", {
    src: "../assets/ez-icon.png",
    alt: ""
  }), /*#__PURE__*/React.createElement("span", {
    className: "word"
  }, "eazy")), /*#__PURE__*/React.createElement("div", {
    className: "deck-name"
  }, phase === "playing" && opponent ? "דו-קרב · יחידה 01" : "מבחן אמריקאי · יחידה 01"), phase === "playing" && questions.length > 0 && /*#__PURE__*/React.createElement("div", {
    className: "counter"
  }, idx + 1, " / ", questions.length), phase !== "start" && /*#__PURE__*/React.createElement("button", {
    className: "icon-btn",
    title: "\u05D4\u05EA\u05D7\u05DC \u05DE\u05D7\u05D3\u05E9",
    onClick: () => setPhase("start")
  }, /*#__PURE__*/React.createElement(I.exit, null))), phase === "playing" && /*#__PURE__*/React.createElement("div", {
    className: "qz-progress"
  }, /*#__PURE__*/React.createElement("div", {
    className: "fill",
    style: {
      width: `${idx / questions.length * 100}%`
    }
  })), phase === "playing" && opponent && /*#__PURE__*/React.createElement("div", {
    className: "qz-duel-bar"
  }, /*#__PURE__*/React.createElement("div", {
    className: "player"
  }, /*#__PURE__*/React.createElement("div", {
    className: "ava"
  }, "\uD83D\uDE0E"), /*#__PURE__*/React.createElement("span", null, "\u05D0\u05EA\u05DD"), /*#__PURE__*/React.createElement("span", {
    className: "score"
  }, score)), /*#__PURE__*/React.createElement("div", {
    className: "vs"
  }, "VS"), /*#__PURE__*/React.createElement("div", {
    className: "player opp"
  }, /*#__PURE__*/React.createElement("span", {
    className: "score opp"
  }, oppScore), /*#__PURE__*/React.createElement("span", null, opponent.name), /*#__PURE__*/React.createElement("div", {
    className: "ava",
    style: {
      background: opponent.color + "33"
    }
  }, opponent.emoji)), t.showTimer && !isAnswered && /*#__PURE__*/React.createElement("div", {
    className: "timer"
  }, timer, "s")), phase === "playing" && opponent && oppReact && /*#__PURE__*/React.createElement("div", {
    className: "qz-opp-react"
  }, /*#__PURE__*/React.createElement("div", {
    className: "ava",
    style: {
      background: opponent.color + "44"
    }
  }, opponent.emoji), /*#__PURE__*/React.createElement("span", null, opponent.name, " ", oppReact)), phase === "start" && /*#__PURE__*/React.createElement(StartScreen, {
    onStart: () => beginQuiz(null),
    onPickDuel: () => setPhase("duel-pick")
  }), phase === "duel-pick" && /*#__PURE__*/React.createElement(React.Fragment, null, /*#__PURE__*/React.createElement(StartScreen, {
    onStart: () => beginQuiz(null),
    onPickDuel: () => {}
  }), /*#__PURE__*/React.createElement(DuelModal, {
    onClose: () => setPhase("start"),
    onStart: opp => beginQuiz(opp)
  })), phase === "playing" && q && /*#__PURE__*/React.createElement(React.Fragment, null, /*#__PURE__*/React.createElement("div", {
    className: "qz-stage"
  }, /*#__PURE__*/React.createElement("div", {
    className: "qz-card"
  }, /*#__PURE__*/React.createElement("div", {
    className: "pos"
  }, /*#__PURE__*/React.createElement("span", null, q.pos, " \xB7 \u05D1\u05D7\u05E8\u05D5 \u05D0\u05EA \u05D4\u05E4\u05D9\u05E8\u05D5\u05E9 \u05D4\u05E0\u05DB\u05D5\u05DF"), /*#__PURE__*/React.createElement("button", {
    className: "audio",
    onClick: () => speak(q.word),
    "aria-label": "\u05D4\u05E9\u05DE\u05E2 \u05DE\u05D9\u05DC\u05D4"
  }, /*#__PURE__*/React.createElement(I.speaker, null))), /*#__PURE__*/React.createElement("div", {
    className: "word"
  }, q.word), /*#__PURE__*/React.createElement("div", {
    className: "qz-options"
  }, optOrder.map((origIdx, i) => {
    const text = q.options[origIdx];
    const isThisCorrect = origIdx === correctIdx;
    let cls = "qz-opt";
    if (isAnswered) {
      if (isThisCorrect) cls += " correct";else if (origIdx === picked) cls += " wrong";else cls += " dimmed";
    }
    return /*#__PURE__*/React.createElement("button", {
      key: origIdx,
      className: cls,
      disabled: isAnswered,
      onClick: () => pick(origIdx)
    }, /*#__PURE__*/React.createElement("span", {
      className: "key"
    }, i + 1), /*#__PURE__*/React.createElement("span", {
      className: "label"
    }, text), isAnswered && isThisCorrect && /*#__PURE__*/React.createElement("span", {
      className: "check"
    }, /*#__PURE__*/React.createElement(I.check, null)), isAnswered && origIdx === picked && !isThisCorrect && /*#__PURE__*/React.createElement("span", {
      className: "check"
    }, /*#__PURE__*/React.createElement(I.x, null)));
  })), isAnswered && /*#__PURE__*/React.createElement("div", {
    className: "qz-explain"
  }, /*#__PURE__*/React.createElement("div", {
    className: "label"
  }, isCorrect ? "✓ נכון מאוד" : "✕ הפעם לא"), /*#__PURE__*/React.createElement("div", {
    className: "body"
  }, q.explain)))), /*#__PURE__*/React.createElement("div", {
    className: "qz-foot"
  }, isAnswered ? /*#__PURE__*/React.createElement("button", {
    className: "qz-next",
    onClick: next
  }, idx + 1 >= questions.length ? "ראו תוצאה" : "המילה הבאה →") : /*#__PURE__*/React.createElement("button", {
    className: "qz-skip",
    onClick: () => {
      setPicked(-1);
      setResults(r => [...r, {
        id: q.id,
        correct: false
      }]);
    }
  }, "\u05D3\u05DC\u05D2\u05D5 \u05E2\u05DC \u05D4\u05E9\u05D0\u05DC\u05D4"))), phase === "done" && /*#__PURE__*/React.createElement("div", {
    className: "qz-end"
  }, /*#__PURE__*/React.createElement("div", {
    className: "qz-end-card"
  }, opponent ? /*#__PURE__*/React.createElement(React.Fragment, null, /*#__PURE__*/React.createElement("div", {
    className: "ribbon " + (score > oppScore ? "win" : score < oppScore ? "lose" : "")
  }, score > oppScore ? "ניצחון" : score < oppScore ? "הפסד" : "תיקו"), /*#__PURE__*/React.createElement("h2", null, score > oppScore ? "זה איזי. ניצחתם." : score < oppScore ? `${opponent.name} ניצח/ה הפעם.` : "תיקו צמוד."), /*#__PURE__*/React.createElement("div", {
    className: "duel-final"
  }, /*#__PURE__*/React.createElement("div", {
    className: "player " + (score >= oppScore ? "win" : "lose")
  }, /*#__PURE__*/React.createElement("div", {
    className: "ava",
    style: {
      background: "var(--ez-orange-soft)"
    }
  }, "\uD83D\uDE0E"), /*#__PURE__*/React.createElement("div", {
    className: "name"
  }, "\u05D0\u05EA\u05DD"), /*#__PURE__*/React.createElement("div", {
    className: "pts"
  }, score)), /*#__PURE__*/React.createElement("div", {
    className: "vs-x"
  }, "VS"), /*#__PURE__*/React.createElement("div", {
    className: "player " + (oppScore > score ? "win" : "lose")
  }, /*#__PURE__*/React.createElement("div", {
    className: "ava",
    style: {
      background: opponent.color + "33"
    }
  }, opponent.emoji), /*#__PURE__*/React.createElement("div", {
    className: "name"
  }, opponent.name), /*#__PURE__*/React.createElement("div", {
    className: "pts"
  }, oppScore)))) : /*#__PURE__*/React.createElement(React.Fragment, null, /*#__PURE__*/React.createElement("div", {
    className: "ribbon"
  }, "\u05E1\u05D9\u05D5\u05DD"), /*#__PURE__*/React.createElement("h2", null, score, " \u05DE\u05EA\u05D5\u05DA ", questions.length, " \u05E0\u05DB\u05D5\u05DF."), /*#__PURE__*/React.createElement("div", {
    className: "scoreline"
  }, score === questions.length ? "מושלם — כל הכבוד." : score >= questions.length * 0.7 ? "כיוון מצוין. עוד טיפה ואתם שם." : "הזמן לחזור על המילים שפיספסתם.")), /*#__PURE__*/React.createElement("div", {
    className: "actions"
  }, /*#__PURE__*/React.createElement("button", {
    className: "btn-primary",
    onClick: () => beginQuiz(opponent)
  }, "\u05E1\u05D9\u05D1\u05D5\u05D1 \u05E0\u05D5\u05E1\u05E3"), /*#__PURE__*/React.createElement("button", {
    className: "btn-ghost",
    onClick: () => setPhase("start")
  }, "\u05D7\u05D6\u05E8\u05D4 \u05DC\u05DE\u05E1\u05DA \u05D4\u05D1\u05D9\u05EA")))), /*#__PURE__*/React.createElement(TweaksPanel, {
    title: "Tweaks"
  }, /*#__PURE__*/React.createElement(TweakSection, {
    title: "\u05DE\u05E6\u05D1 \u05DE\u05E9\u05D7\u05E7"
  }, /*#__PURE__*/React.createElement(TweakRadio, {
    value: t.mode,
    onChange: v => setTweak("mode", v),
    options: [{
      value: "solo",
      label: "תרגול"
    }, {
      value: "duel",
      label: "דו-קרב"
    }]
  })), /*#__PURE__*/React.createElement(TweakSection, {
    title: "\u05E6\u05D1\u05E2 \u05DE\u05D1\u05D8\u05D0"
  }, /*#__PURE__*/React.createElement(TweakColor, {
    value: t.accent,
    onChange: v => setTweak("accent", v),
    options: [{
      value: "orange",
      color: "#F37327"
    }, {
      value: "indigo",
      color: "#3F4197"
    }, {
      value: "teal",
      color: "#1F8A8A"
    }]
  })), /*#__PURE__*/React.createElement(TweakSection, {
    title: "\u05D0\u05E4\u05E9\u05E8\u05D5\u05D9\u05D5\u05EA"
  }, /*#__PURE__*/React.createElement(TweakToggle, {
    label: "\u05D8\u05D9\u05D9\u05DE\u05E8 \u05D1\u05D3\u05D5-\u05E7\u05E8\u05D1",
    value: t.showTimer,
    onChange: v => setTweak("showTimer", v)
  }), /*#__PURE__*/React.createElement(TweakToggle, {
    label: "\u05E2\u05E8\u05D1\u05D5\u05D1 \u05E9\u05D0\u05DC\u05D5\u05EA \u05D5\u05EA\u05E9\u05D5\u05D1\u05D5\u05EA",
    value: t.shuffle,
    onChange: v => setTweak("shuffle", v)
  })), /*#__PURE__*/React.createElement(TweakSection, {
    title: "\u05E8\u05E7\u05E2"
  }, /*#__PURE__*/React.createElement(TweakRadio, {
    value: t.wallpaper,
    onChange: v => setTweak("wallpaper", v),
    options: [{
      value: "slashes",
      label: "לוכסנים"
    }, {
      value: "zoom-e",
      label: "E גדול"
    }, {
      value: "none",
      label: "נקי"
    }]
  }))));
}
window.Quiz = Quiz;
})(); } catch (e) { __ds_ns.__errors.push({ path: "quiz/Quiz.jsx", error: String((e && e.message) || e) }); }

// quiz/ios-frame.jsx
try { (() => {
// iOS.jsx — Simplified iOS 26 (Liquid Glass) device frame
// Based on the iOS 26 UI Kit + Figma status bar spec. No assets, no deps.
// Exports: IOSDevice, IOSStatusBar, IOSNavBar, IOSGlassPill, IOSList, IOSListRow, IOSKeyboard

// ─────────────────────────────────────────────────────────────
// Status bar
// ─────────────────────────────────────────────────────────────
function IOSStatusBar({
  dark = false,
  time = '9:41'
}) {
  const c = dark ? '#fff' : '#000';
  return /*#__PURE__*/React.createElement("div", {
    style: {
      display: 'flex',
      gap: 154,
      alignItems: 'center',
      justifyContent: 'center',
      padding: '21px 24px 19px',
      boxSizing: 'border-box',
      position: 'relative',
      zIndex: 20,
      width: '100%'
    }
  }, /*#__PURE__*/React.createElement("div", {
    style: {
      flex: 1,
      height: 22,
      display: 'flex',
      alignItems: 'center',
      justifyContent: 'center',
      paddingTop: 1.5
    }
  }, /*#__PURE__*/React.createElement("span", {
    style: {
      fontFamily: '-apple-system, "SF Pro", system-ui',
      fontWeight: 590,
      fontSize: 17,
      lineHeight: '22px',
      color: c
    }
  }, time)), /*#__PURE__*/React.createElement("div", {
    style: {
      flex: 1,
      height: 22,
      display: 'flex',
      alignItems: 'center',
      justifyContent: 'center',
      gap: 7,
      paddingTop: 1,
      paddingRight: 1
    }
  }, /*#__PURE__*/React.createElement("svg", {
    width: "19",
    height: "12",
    viewBox: "0 0 19 12"
  }, /*#__PURE__*/React.createElement("rect", {
    x: "0",
    y: "7.5",
    width: "3.2",
    height: "4.5",
    rx: "0.7",
    fill: c
  }), /*#__PURE__*/React.createElement("rect", {
    x: "4.8",
    y: "5",
    width: "3.2",
    height: "7",
    rx: "0.7",
    fill: c
  }), /*#__PURE__*/React.createElement("rect", {
    x: "9.6",
    y: "2.5",
    width: "3.2",
    height: "9.5",
    rx: "0.7",
    fill: c
  }), /*#__PURE__*/React.createElement("rect", {
    x: "14.4",
    y: "0",
    width: "3.2",
    height: "12",
    rx: "0.7",
    fill: c
  })), /*#__PURE__*/React.createElement("svg", {
    width: "17",
    height: "12",
    viewBox: "0 0 17 12"
  }, /*#__PURE__*/React.createElement("path", {
    d: "M8.5 3.2C10.8 3.2 12.9 4.1 14.4 5.6L15.5 4.5C13.7 2.7 11.2 1.5 8.5 1.5C5.8 1.5 3.3 2.7 1.5 4.5L2.6 5.6C4.1 4.1 6.2 3.2 8.5 3.2Z",
    fill: c
  }), /*#__PURE__*/React.createElement("path", {
    d: "M8.5 6.8C9.9 6.8 11.1 7.3 12 8.2L13.1 7.1C11.8 5.9 10.2 5.1 8.5 5.1C6.8 5.1 5.2 5.9 3.9 7.1L5 8.2C5.9 7.3 7.1 6.8 8.5 6.8Z",
    fill: c
  }), /*#__PURE__*/React.createElement("circle", {
    cx: "8.5",
    cy: "10.5",
    r: "1.5",
    fill: c
  })), /*#__PURE__*/React.createElement("svg", {
    width: "27",
    height: "13",
    viewBox: "0 0 27 13"
  }, /*#__PURE__*/React.createElement("rect", {
    x: "0.5",
    y: "0.5",
    width: "23",
    height: "12",
    rx: "3.5",
    stroke: c,
    strokeOpacity: "0.35",
    fill: "none"
  }), /*#__PURE__*/React.createElement("rect", {
    x: "2",
    y: "2",
    width: "20",
    height: "9",
    rx: "2",
    fill: c
  }), /*#__PURE__*/React.createElement("path", {
    d: "M25 4.5V8.5C25.8 8.2 26.5 7.2 26.5 6.5C26.5 5.8 25.8 4.8 25 4.5Z",
    fill: c,
    fillOpacity: "0.4"
  }))));
}

// ─────────────────────────────────────────────────────────────
// Liquid glass pill — blur + tint + shine
// ─────────────────────────────────────────────────────────────
function IOSGlassPill({
  children,
  dark = false,
  style = {}
}) {
  return /*#__PURE__*/React.createElement("div", {
    style: {
      height: 44,
      minWidth: 44,
      borderRadius: 9999,
      position: 'relative',
      overflow: 'hidden',
      display: 'flex',
      alignItems: 'center',
      justifyContent: 'center',
      boxShadow: dark ? '0 2px 6px rgba(0,0,0,0.35), 0 6px 16px rgba(0,0,0,0.2)' : '0 1px 3px rgba(0,0,0,0.07), 0 3px 10px rgba(0,0,0,0.06)',
      ...style
    }
  }, /*#__PURE__*/React.createElement("div", {
    style: {
      position: 'absolute',
      inset: 0,
      borderRadius: 9999,
      backdropFilter: 'blur(12px) saturate(180%)',
      WebkitBackdropFilter: 'blur(12px) saturate(180%)',
      background: dark ? 'rgba(120,120,128,0.28)' : 'rgba(255,255,255,0.5)'
    }
  }), /*#__PURE__*/React.createElement("div", {
    style: {
      position: 'absolute',
      inset: 0,
      borderRadius: 9999,
      boxShadow: dark ? 'inset 1.5px 1.5px 1px rgba(255,255,255,0.15), inset -1px -1px 1px rgba(255,255,255,0.08)' : 'inset 1.5px 1.5px 1px rgba(255,255,255,0.7), inset -1px -1px 1px rgba(255,255,255,0.4)',
      border: dark ? '0.5px solid rgba(255,255,255,0.15)' : '0.5px solid rgba(0,0,0,0.06)'
    }
  }), /*#__PURE__*/React.createElement("div", {
    style: {
      position: 'relative',
      zIndex: 1,
      display: 'flex',
      alignItems: 'center',
      padding: '0 4px'
    }
  }, children));
}

// ─────────────────────────────────────────────────────────────
// Navigation bar — glass pills + large title
// ─────────────────────────────────────────────────────────────
function IOSNavBar({
  title = 'Title',
  dark = false,
  trailingIcon = true
}) {
  const muted = dark ? 'rgba(255,255,255,0.6)' : '#404040';
  const text = dark ? '#fff' : '#000';
  const pillIcon = content => /*#__PURE__*/React.createElement(IOSGlassPill, {
    dark: dark
  }, /*#__PURE__*/React.createElement("div", {
    style: {
      width: 36,
      height: 36,
      display: 'flex',
      alignItems: 'center',
      justifyContent: 'center'
    }
  }, content));
  return /*#__PURE__*/React.createElement("div", {
    style: {
      display: 'flex',
      flexDirection: 'column',
      gap: 10,
      paddingTop: 62,
      paddingBottom: 10,
      position: 'relative',
      zIndex: 5
    }
  }, /*#__PURE__*/React.createElement("div", {
    style: {
      display: 'flex',
      alignItems: 'center',
      justifyContent: 'space-between',
      padding: '0 16px'
    }
  }, pillIcon(/*#__PURE__*/React.createElement("svg", {
    width: "12",
    height: "20",
    viewBox: "0 0 12 20",
    fill: "none",
    style: {
      marginLeft: -1
    }
  }, /*#__PURE__*/React.createElement("path", {
    d: "M10 2L2 10l8 8",
    stroke: muted,
    strokeWidth: "2.5",
    strokeLinecap: "round",
    strokeLinejoin: "round"
  }))), trailingIcon && pillIcon(/*#__PURE__*/React.createElement("svg", {
    width: "22",
    height: "6",
    viewBox: "0 0 22 6"
  }, /*#__PURE__*/React.createElement("circle", {
    cx: "3",
    cy: "3",
    r: "2.5",
    fill: muted
  }), /*#__PURE__*/React.createElement("circle", {
    cx: "11",
    cy: "3",
    r: "2.5",
    fill: muted
  }), /*#__PURE__*/React.createElement("circle", {
    cx: "19",
    cy: "3",
    r: "2.5",
    fill: muted
  })))), /*#__PURE__*/React.createElement("div", {
    style: {
      padding: '0 16px',
      fontFamily: '-apple-system, system-ui',
      fontSize: 34,
      fontWeight: 700,
      lineHeight: '41px',
      color: text,
      letterSpacing: 0.4
    }
  }, title));
}

// ─────────────────────────────────────────────────────────────
// Grouped list (inset card, r:26) + row (52px)
// ─────────────────────────────────────────────────────────────
function IOSListRow({
  title,
  detail,
  icon,
  chevron = true,
  isLast = false,
  dark = false
}) {
  const text = dark ? '#fff' : '#000';
  const sec = dark ? 'rgba(235,235,245,0.6)' : 'rgba(60,60,67,0.6)';
  const ter = dark ? 'rgba(235,235,245,0.3)' : 'rgba(60,60,67,0.3)';
  const sep = dark ? 'rgba(84,84,88,0.65)' : 'rgba(60,60,67,0.12)';
  return /*#__PURE__*/React.createElement("div", {
    style: {
      display: 'flex',
      alignItems: 'center',
      minHeight: 52,
      padding: '0 16px',
      position: 'relative',
      fontFamily: '-apple-system, system-ui',
      fontSize: 17,
      letterSpacing: -0.43
    }
  }, icon && /*#__PURE__*/React.createElement("div", {
    style: {
      width: 30,
      height: 30,
      borderRadius: 7,
      background: icon,
      marginRight: 12,
      flexShrink: 0
    }
  }), /*#__PURE__*/React.createElement("div", {
    style: {
      flex: 1,
      color: text
    }
  }, title), detail && /*#__PURE__*/React.createElement("span", {
    style: {
      color: sec,
      marginRight: 6
    }
  }, detail), chevron && /*#__PURE__*/React.createElement("svg", {
    width: "8",
    height: "14",
    viewBox: "0 0 8 14",
    style: {
      flexShrink: 0
    }
  }, /*#__PURE__*/React.createElement("path", {
    d: "M1 1l6 6-6 6",
    stroke: ter,
    strokeWidth: "2",
    fill: "none",
    strokeLinecap: "round",
    strokeLinejoin: "round"
  })), !isLast && /*#__PURE__*/React.createElement("div", {
    style: {
      position: 'absolute',
      bottom: 0,
      right: 0,
      left: icon ? 58 : 16,
      height: 0.5,
      background: sep
    }
  }));
}
function IOSList({
  header,
  children,
  dark = false
}) {
  const hc = dark ? 'rgba(235,235,245,0.6)' : 'rgba(60,60,67,0.6)';
  const bg = dark ? '#1C1C1E' : '#fff';
  return /*#__PURE__*/React.createElement("div", null, header && /*#__PURE__*/React.createElement("div", {
    style: {
      fontFamily: '-apple-system, system-ui',
      fontSize: 13,
      color: hc,
      textTransform: 'uppercase',
      padding: '8px 36px 6px',
      letterSpacing: -0.08
    }
  }, header), /*#__PURE__*/React.createElement("div", {
    style: {
      background: bg,
      borderRadius: 26,
      margin: '0 16px',
      overflow: 'hidden'
    }
  }, children));
}

// ─────────────────────────────────────────────────────────────
// Device frame
// ─────────────────────────────────────────────────────────────
function IOSDevice({
  children,
  width = 402,
  height = 874,
  dark = false,
  title,
  keyboard = false
}) {
  return /*#__PURE__*/React.createElement("div", {
    style: {
      width,
      height,
      borderRadius: 48,
      overflow: 'hidden',
      position: 'relative',
      background: dark ? '#000' : '#F2F2F7',
      boxShadow: '0 40px 80px rgba(0,0,0,0.18), 0 0 0 1px rgba(0,0,0,0.12)',
      fontFamily: '-apple-system, system-ui, sans-serif',
      WebkitFontSmoothing: 'antialiased'
    }
  }, /*#__PURE__*/React.createElement("div", {
    style: {
      position: 'absolute',
      top: 11,
      left: '50%',
      transform: 'translateX(-50%)',
      width: 126,
      height: 37,
      borderRadius: 24,
      background: '#000',
      zIndex: 50
    }
  }), /*#__PURE__*/React.createElement("div", {
    style: {
      position: 'absolute',
      top: 0,
      left: 0,
      right: 0,
      zIndex: 10
    }
  }, /*#__PURE__*/React.createElement(IOSStatusBar, {
    dark: dark
  })), /*#__PURE__*/React.createElement("div", {
    style: {
      height: '100%',
      display: 'flex',
      flexDirection: 'column'
    }
  }, title !== undefined && /*#__PURE__*/React.createElement(IOSNavBar, {
    title: title,
    dark: dark
  }), /*#__PURE__*/React.createElement("div", {
    style: {
      flex: 1,
      overflow: 'auto'
    }
  }, children), keyboard && /*#__PURE__*/React.createElement(IOSKeyboard, {
    dark: dark
  })), /*#__PURE__*/React.createElement("div", {
    style: {
      position: 'absolute',
      bottom: 0,
      left: 0,
      right: 0,
      zIndex: 60,
      height: 34,
      display: 'flex',
      justifyContent: 'center',
      alignItems: 'flex-end',
      paddingBottom: 8,
      pointerEvents: 'none'
    }
  }, /*#__PURE__*/React.createElement("div", {
    style: {
      width: 139,
      height: 5,
      borderRadius: 100,
      background: dark ? 'rgba(255,255,255,0.7)' : 'rgba(0,0,0,0.25)'
    }
  })));
}

// ─────────────────────────────────────────────────────────────
// Keyboard — iOS 26 liquid glass
// ─────────────────────────────────────────────────────────────
function IOSKeyboard({
  dark = false
}) {
  const glyph = dark ? 'rgba(255,255,255,0.7)' : '#595959';
  const sugg = dark ? 'rgba(255,255,255,0.6)' : '#333';
  const keyBg = dark ? 'rgba(255,255,255,0.22)' : 'rgba(255,255,255,0.85)';

  // special-key icons
  const icons = {
    shift: /*#__PURE__*/React.createElement("svg", {
      width: "19",
      height: "17",
      viewBox: "0 0 19 17"
    }, /*#__PURE__*/React.createElement("path", {
      d: "M9.5 1L1 9.5h4.5V16h8V9.5H18L9.5 1z",
      fill: glyph
    })),
    del: /*#__PURE__*/React.createElement("svg", {
      width: "23",
      height: "17",
      viewBox: "0 0 23 17"
    }, /*#__PURE__*/React.createElement("path", {
      d: "M7 1h13a2 2 0 012 2v11a2 2 0 01-2 2H7l-6-7.5L7 1z",
      fill: "none",
      stroke: glyph,
      strokeWidth: "1.6",
      strokeLinejoin: "round"
    }), /*#__PURE__*/React.createElement("path", {
      d: "M10 5l7 7M17 5l-7 7",
      stroke: glyph,
      strokeWidth: "1.6",
      strokeLinecap: "round"
    })),
    ret: /*#__PURE__*/React.createElement("svg", {
      width: "20",
      height: "14",
      viewBox: "0 0 20 14"
    }, /*#__PURE__*/React.createElement("path", {
      d: "M18 1v6H4m0 0l4-4M4 7l4 4",
      fill: "none",
      stroke: "#fff",
      strokeWidth: "1.8",
      strokeLinecap: "round",
      strokeLinejoin: "round"
    }))
  };
  const key = (content, {
    w,
    flex,
    ret,
    fs = 25,
    k
  } = {}) => /*#__PURE__*/React.createElement("div", {
    key: k,
    style: {
      height: 42,
      borderRadius: 8.5,
      flex: flex ? 1 : undefined,
      width: w,
      minWidth: 0,
      background: ret ? '#08f' : keyBg,
      boxShadow: '0 1px 0 rgba(0,0,0,0.075)',
      display: 'flex',
      alignItems: 'center',
      justifyContent: 'center',
      fontFamily: '-apple-system, "SF Compact", system-ui',
      fontSize: fs,
      fontWeight: 458,
      color: ret ? '#fff' : glyph
    }
  }, content);
  const row = (keys, pad = 0) => /*#__PURE__*/React.createElement("div", {
    style: {
      display: 'flex',
      gap: 6.5,
      justifyContent: 'center',
      padding: `0 ${pad}px`
    }
  }, keys.map(l => key(l, {
    flex: true,
    k: l
  })));
  return /*#__PURE__*/React.createElement("div", {
    style: {
      position: 'relative',
      zIndex: 15,
      borderRadius: 27,
      overflow: 'hidden',
      padding: '11px 0 2px',
      display: 'flex',
      flexDirection: 'column',
      alignItems: 'center',
      boxShadow: dark ? '0 -2px 20px rgba(0,0,0,0.09)' : '0 -1px 6px rgba(0,0,0,0.018), 0 -3px 20px rgba(0,0,0,0.012)'
    }
  }, /*#__PURE__*/React.createElement("div", {
    style: {
      position: 'absolute',
      inset: 0,
      borderRadius: 27,
      backdropFilter: 'blur(12px) saturate(180%)',
      WebkitBackdropFilter: 'blur(12px) saturate(180%)',
      background: dark ? 'rgba(120,120,128,0.14)' : 'rgba(255,255,255,0.25)'
    }
  }), /*#__PURE__*/React.createElement("div", {
    style: {
      position: 'absolute',
      inset: 0,
      borderRadius: 27,
      boxShadow: dark ? 'inset 1.5px 1.5px 1px rgba(255,255,255,0.15)' : 'inset 1.5px 1.5px 1px rgba(255,255,255,0.7), inset -1px -1px 1px rgba(255,255,255,0.4)',
      border: dark ? '0.5px solid rgba(255,255,255,0.15)' : '0.5px solid rgba(0,0,0,0.06)',
      pointerEvents: 'none'
    }
  }), /*#__PURE__*/React.createElement("div", {
    style: {
      display: 'flex',
      gap: 20,
      alignItems: 'center',
      padding: '8px 22px 13px',
      width: '100%',
      boxSizing: 'border-box',
      position: 'relative'
    }
  }, ['"The"', 'the', 'to'].map((w, i) => /*#__PURE__*/React.createElement(React.Fragment, {
    key: i
  }, i > 0 && /*#__PURE__*/React.createElement("div", {
    style: {
      width: 1,
      height: 25,
      background: '#ccc',
      opacity: 0.3
    }
  }), /*#__PURE__*/React.createElement("div", {
    style: {
      flex: 1,
      textAlign: 'center',
      fontFamily: '-apple-system, system-ui',
      fontSize: 17,
      color: sugg,
      letterSpacing: -0.43,
      lineHeight: '22px'
    }
  }, w)))), /*#__PURE__*/React.createElement("div", {
    style: {
      display: 'flex',
      flexDirection: 'column',
      gap: 13,
      padding: '0 6.5px',
      width: '100%',
      boxSizing: 'border-box',
      position: 'relative'
    }
  }, row(['q', 'w', 'e', 'r', 't', 'y', 'u', 'i', 'o', 'p']), row(['a', 's', 'd', 'f', 'g', 'h', 'j', 'k', 'l'], 20), /*#__PURE__*/React.createElement("div", {
    style: {
      display: 'flex',
      gap: 14.25,
      alignItems: 'center'
    }
  }, key(icons.shift, {
    w: 45,
    k: 'shift'
  }), /*#__PURE__*/React.createElement("div", {
    style: {
      display: 'flex',
      gap: 6.5,
      flex: 1
    }
  }, ['z', 'x', 'c', 'v', 'b', 'n', 'm'].map(l => key(l, {
    flex: true,
    k: l
  }))), key(icons.del, {
    w: 45,
    k: 'del'
  })), /*#__PURE__*/React.createElement("div", {
    style: {
      display: 'flex',
      gap: 6,
      alignItems: 'center'
    }
  }, key('ABC', {
    w: 92.25,
    fs: 18,
    k: 'abc'
  }), key('', {
    flex: true,
    k: 'space'
  }), key(icons.ret, {
    w: 92.25,
    ret: true,
    k: 'ret'
  }))), /*#__PURE__*/React.createElement("div", {
    style: {
      height: 56,
      width: '100%',
      position: 'relative'
    }
  }));
}
Object.assign(window, {
  IOSDevice,
  IOSStatusBar,
  IOSNavBar,
  IOSGlassPill,
  IOSList,
  IOSListRow,
  IOSKeyboard
});
})(); } catch (e) { __ds_ns.__errors.push({ path: "quiz/ios-frame.jsx", error: String((e && e.message) || e) }); }

// quiz/quiz-data.js
try { (() => {
/* global window */
// Multiple-choice questions: same words as flashcards, but each has 3 distractor meanings.
// Distractors are intentionally chosen to be plausible/related — not random.
window.QUIZ_DECK = [{
  id: "enhance",
  word: "ENHANCE",
  pos: "פועל",
  correct: "להעצים, לשפר",
  options: ["להעצים, לשפר", "להחליש, לפגום", "להחליף, להמיר", "לחזור על משהו"],
  explain: "ENHANCE = להוסיף ערך, לחזק או לשפר משהו קיים. לא יוצרים מאפס — משפרים מה שיש."
}, {
  id: "mitigate",
  word: "MITIGATE",
  pos: "פועל",
  correct: "להקל, למתן",
  options: ["להקל, למתן", "להחמיר, להגביר", "לבחון לעומק", "להתנגד בתוקף"],
  explain: "MITIGATE = להפחית את חומרת התוצאה השלילית. תמיד אחרי בעיה — ממתנים נזק או סיכון."
}, {
  id: "ambiguous",
  word: "AMBIGUOUS",
  pos: "תואר",
  correct: "דו־משמעי, עמום",
  options: ["דו־משמעי, עמום", "ברור וחד משמעי", "אמיתי, מדויק", "מסובך, מורכב"],
  explain: "AMBI = שניים. AMBIGUOUS = שאפשר להבין ביותר מדרך אחת. ההפך מ-clear."
}, {
  id: "advocate",
  word: "ADVOCATE",
  pos: "פועל / שם",
  correct: "לתמוך, להמליץ",
  options: ["לתמוך, להמליץ", "להתנגד, לבקר", "להזהיר מפני סכנה", "להישאר נייטרלי"],
  explain: "ADVOCATE קשור ל-VOCAL. מי שמרים את הקול בעד רעיון או בעד מישהו."
}, {
  id: "scrutinize",
  word: "SCRUTINIZE",
  pos: "פועל",
  correct: "לבחון בקפדנות",
  options: ["לבחון בקפדנות", "לדפדף בחטף", "להעתיק במדויק", "לסכם בתמצית"],
  explain: "SCRUTINIZE חזק יותר מ-examine. בודקים עם זכוכית-מגדלת, לרוב מתוך חשדנות."
}, {
  id: "inevitable",
  word: "INEVITABLE",
  pos: "תואר",
  correct: "בלתי נמנע",
  options: ["בלתי נמנע", "בלתי הפיך", "בלתי מובן", "בלתי רלוונטי"],
  explain: "IN (לא) + EVIT (להימנע) + ABLE (יכול) → לא יכול להימנע. ודאות לגבי העתיד."
}, {
  id: "diligent",
  word: "DILIGENT",
  pos: "תואר",
  correct: "חרוץ, שקדן",
  options: ["חרוץ, שקדן", "עצלן, רשלן", "חכם, נבון", "כֵּן, ישיר"],
  explain: "DILIGENT הוא לא רק עובד קשה — הוא עובד בקפידה ובהתמדה. תכונה חיובית מאוד."
}, {
  id: "obsolete",
  word: "OBSOLETE",
  pos: "תואר",
  correct: "מיושן, יצא משימוש",
  options: ["מיושן, יצא משימוש", "חדשני, מתקדם", "נדיר ויקר", "פגום, שבור"],
  explain: "OBSOLETE = שעבר זמנו ויצא משימוש. הקלטת, הפלאפון בעל הכפתורים — all obsolete."
}, {
  id: "candid",
  word: "CANDID",
  pos: "תואר",
  correct: "כֵּן, ישיר, ספונטני",
  options: ["כֵּן, ישיר, ספונטני", "מתחזה, צבוע", "מבויש, נסוג", "פורמלי, רשמי"],
  explain: "תמונת candid באינסטגרם = ספונטנית, לא מבוימת. אדם candid = אומר את האמת בלי לסנן."
}, {
  id: "tenacious",
  word: "TENACIOUS",
  pos: "תואר",
  correct: "עיקש, דבק במטרה",
  options: ["עיקש, דבק במטרה", "מהיר וזריז", "ותרן, סלחן", "חצוף, חוצפן"],
  explain: "TENACIOUS חזק מ-determined. מחזיק חזק במטרה ולא מוותר גם בפני קושי גדול."
}];

// Avatars for opponents in duel mode
window.QUIZ_OPPONENTS = [{
  id: "noa",
  name: "נועה כ.",
  emoji: "👩🏻‍🎓",
  color: "#F37327"
}, {
  id: "yotam",
  name: "יותם ב.",
  emoji: "🧑🏼‍🎓",
  color: "#3F4197"
}, {
  id: "shira",
  name: "שירה ל.",
  emoji: "👩🏽‍🦱",
  color: "#1F8A8A"
}, {
  id: "amit",
  name: "עמית ר.",
  emoji: "🧑🏻",
  color: "#7E5BAF"
}];
})(); } catch (e) { __ds_ns.__errors.push({ path: "quiz/quiz-data.js", error: String((e && e.message) || e) }); }

// quiz/tweaks-panel.jsx
try { (() => {
// tweaks-panel.jsx
// Reusable Tweaks shell + form-control helpers.
//
// Owns the host protocol (listens for __activate_edit_mode / __deactivate_edit_mode,
// posts __edit_mode_available / __edit_mode_set_keys / __edit_mode_dismissed) so
// individual prototypes don't re-roll it. Ships a consistent set of controls so you
// don't hand-draw <input type="range">, segmented radios, steppers, etc.
//
// Usage (in an HTML file that loads React + Babel):
//
//   const TWEAK_DEFAULTS = /*EDITMODE-BEGIN*/{
//     "primaryColor": "#D97757",
//     "palette": ["#D97757", "#29261b", "#f6f4ef"],
//     "fontSize": 16,
//     "density": "regular",
//     "dark": false
//   }/*EDITMODE-END*/;
//
//   function App() {
//     const [t, setTweak] = useTweaks(TWEAK_DEFAULTS);
//     return (
//       <div style={{ fontSize: t.fontSize, color: t.primaryColor }}>
//         Hello
//         <TweaksPanel>
//           <TweakSection label="Typography" />
//           <TweakSlider label="Font size" value={t.fontSize} min={10} max={32} unit="px"
//                        onChange={(v) => setTweak('fontSize', v)} />
//           <TweakRadio  label="Density" value={t.density}
//                        options={['compact', 'regular', 'comfy']}
//                        onChange={(v) => setTweak('density', v)} />
//           <TweakSection label="Theme" />
//           <TweakColor  label="Primary" value={t.primaryColor}
//                        options={['#D97757', '#2A6FDB', '#1F8A5B', '#7A5AE0']}
//                        onChange={(v) => setTweak('primaryColor', v)} />
//           <TweakColor  label="Palette" value={t.palette}
//                        options={[['#D97757', '#29261b', '#f6f4ef'],
//                                  ['#475569', '#0f172a', '#f1f5f9']]}
//                        onChange={(v) => setTweak('palette', v)} />
//           <TweakToggle label="Dark mode" value={t.dark}
//                        onChange={(v) => setTweak('dark', v)} />
//         </TweaksPanel>
//       </div>
//     );
//   }
//
// ─────────────────────────────────────────────────────────────────────────────

const __TWEAKS_STYLE = `
  .twk-panel{position:fixed;right:16px;bottom:16px;z-index:2147483646;width:280px;
    max-height:calc(100vh - 32px);display:flex;flex-direction:column;
    transform:scale(var(--dc-inv-zoom,1));transform-origin:bottom right;
    background:rgba(250,249,247,.78);color:#29261b;
    -webkit-backdrop-filter:blur(24px) saturate(160%);backdrop-filter:blur(24px) saturate(160%);
    border:.5px solid rgba(255,255,255,.6);border-radius:14px;
    box-shadow:0 1px 0 rgba(255,255,255,.5) inset,0 12px 40px rgba(0,0,0,.18);
    font:11.5px/1.4 ui-sans-serif,system-ui,-apple-system,sans-serif;overflow:hidden}
  .twk-hd{display:flex;align-items:center;justify-content:space-between;
    padding:10px 8px 10px 14px;cursor:move;user-select:none}
  .twk-hd b{font-size:12px;font-weight:600;letter-spacing:.01em}
  .twk-x{appearance:none;border:0;background:transparent;color:rgba(41,38,27,.55);
    width:22px;height:22px;border-radius:6px;cursor:default;font-size:13px;line-height:1}
  .twk-x:hover{background:rgba(0,0,0,.06);color:#29261b}
  .twk-body{padding:2px 14px 14px;display:flex;flex-direction:column;gap:10px;
    overflow-y:auto;overflow-x:hidden;min-height:0;
    scrollbar-width:thin;scrollbar-color:rgba(0,0,0,.15) transparent}
  .twk-body::-webkit-scrollbar{width:8px}
  .twk-body::-webkit-scrollbar-track{background:transparent;margin:2px}
  .twk-body::-webkit-scrollbar-thumb{background:rgba(0,0,0,.15);border-radius:4px;
    border:2px solid transparent;background-clip:content-box}
  .twk-body::-webkit-scrollbar-thumb:hover{background:rgba(0,0,0,.25);
    border:2px solid transparent;background-clip:content-box}
  .twk-row{display:flex;flex-direction:column;gap:5px}
  .twk-row-h{flex-direction:row;align-items:center;justify-content:space-between;gap:10px}
  .twk-lbl{display:flex;justify-content:space-between;align-items:baseline;
    color:rgba(41,38,27,.72)}
  .twk-lbl>span:first-child{font-weight:500}
  .twk-val{color:rgba(41,38,27,.5);font-variant-numeric:tabular-nums}

  .twk-sect{font-size:10px;font-weight:600;letter-spacing:.06em;text-transform:uppercase;
    color:rgba(41,38,27,.45);padding:10px 0 0}
  .twk-sect:first-child{padding-top:0}

  .twk-field{appearance:none;width:100%;height:26px;padding:0 8px;
    border:.5px solid rgba(0,0,0,.1);border-radius:7px;
    background:rgba(255,255,255,.6);color:inherit;font:inherit;outline:none}
  .twk-field:focus{border-color:rgba(0,0,0,.25);background:rgba(255,255,255,.85)}
  select.twk-field{padding-right:22px;
    background-image:url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='10' height='6' viewBox='0 0 10 6'><path fill='rgba(0,0,0,.5)' d='M0 0h10L5 6z'/></svg>");
    background-repeat:no-repeat;background-position:right 8px center}

  .twk-slider{appearance:none;-webkit-appearance:none;width:100%;height:4px;margin:6px 0;
    border-radius:999px;background:rgba(0,0,0,.12);outline:none}
  .twk-slider::-webkit-slider-thumb{-webkit-appearance:none;appearance:none;
    width:14px;height:14px;border-radius:50%;background:#fff;
    border:.5px solid rgba(0,0,0,.12);box-shadow:0 1px 3px rgba(0,0,0,.2);cursor:default}
  .twk-slider::-moz-range-thumb{width:14px;height:14px;border-radius:50%;
    background:#fff;border:.5px solid rgba(0,0,0,.12);box-shadow:0 1px 3px rgba(0,0,0,.2);cursor:default}

  .twk-seg{position:relative;display:flex;padding:2px;border-radius:8px;
    background:rgba(0,0,0,.06);user-select:none}
  .twk-seg-thumb{position:absolute;top:2px;bottom:2px;border-radius:6px;
    background:rgba(255,255,255,.9);box-shadow:0 1px 2px rgba(0,0,0,.12);
    transition:left .15s cubic-bezier(.3,.7,.4,1),width .15s}
  .twk-seg.dragging .twk-seg-thumb{transition:none}
  .twk-seg button{appearance:none;position:relative;z-index:1;flex:1;border:0;
    background:transparent;color:inherit;font:inherit;font-weight:500;min-height:22px;
    border-radius:6px;cursor:default;padding:4px 6px;line-height:1.2;
    overflow-wrap:anywhere}

  .twk-toggle{position:relative;width:32px;height:18px;border:0;border-radius:999px;
    background:rgba(0,0,0,.15);transition:background .15s;cursor:default;padding:0}
  .twk-toggle[data-on="1"]{background:#34c759}
  .twk-toggle i{position:absolute;top:2px;left:2px;width:14px;height:14px;border-radius:50%;
    background:#fff;box-shadow:0 1px 2px rgba(0,0,0,.25);transition:transform .15s}
  .twk-toggle[data-on="1"] i{transform:translateX(14px)}

  .twk-num{display:flex;align-items:center;height:26px;padding:0 0 0 8px;
    border:.5px solid rgba(0,0,0,.1);border-radius:7px;background:rgba(255,255,255,.6)}
  .twk-num-lbl{font-weight:500;color:rgba(41,38,27,.6);cursor:ew-resize;
    user-select:none;padding-right:8px}
  .twk-num input{flex:1;min-width:0;height:100%;border:0;background:transparent;
    font:inherit;font-variant-numeric:tabular-nums;text-align:right;padding:0 8px 0 0;
    outline:none;color:inherit;-moz-appearance:textfield}
  .twk-num input::-webkit-inner-spin-button,.twk-num input::-webkit-outer-spin-button{
    -webkit-appearance:none;margin:0}
  .twk-num-unit{padding-right:8px;color:rgba(41,38,27,.45)}

  .twk-btn{appearance:none;height:26px;padding:0 12px;border:0;border-radius:7px;
    background:rgba(0,0,0,.78);color:#fff;font:inherit;font-weight:500;cursor:default}
  .twk-btn:hover{background:rgba(0,0,0,.88)}
  .twk-btn.secondary{background:rgba(0,0,0,.06);color:inherit}
  .twk-btn.secondary:hover{background:rgba(0,0,0,.1)}

  .twk-swatch{appearance:none;-webkit-appearance:none;width:56px;height:22px;
    border:.5px solid rgba(0,0,0,.1);border-radius:6px;padding:0;cursor:default;
    background:transparent;flex-shrink:0}
  .twk-swatch::-webkit-color-swatch-wrapper{padding:0}
  .twk-swatch::-webkit-color-swatch{border:0;border-radius:5.5px}
  .twk-swatch::-moz-color-swatch{border:0;border-radius:5.5px}

  .twk-chips{display:flex;gap:6px}
  .twk-chip{position:relative;appearance:none;flex:1;min-width:0;height:46px;
    padding:0;border:0;border-radius:6px;overflow:hidden;cursor:default;
    box-shadow:0 0 0 .5px rgba(0,0,0,.12),0 1px 2px rgba(0,0,0,.06);
    transition:transform .12s cubic-bezier(.3,.7,.4,1),box-shadow .12s}
  .twk-chip:hover{transform:translateY(-1px);
    box-shadow:0 0 0 .5px rgba(0,0,0,.18),0 4px 10px rgba(0,0,0,.12)}
  .twk-chip[data-on="1"]{box-shadow:0 0 0 1.5px rgba(0,0,0,.85),
    0 2px 6px rgba(0,0,0,.15)}
  .twk-chip>span{position:absolute;top:0;bottom:0;right:0;width:34%;
    display:flex;flex-direction:column;box-shadow:-1px 0 0 rgba(0,0,0,.1)}
  .twk-chip>span>i{flex:1;box-shadow:0 -1px 0 rgba(0,0,0,.1)}
  .twk-chip>span>i:first-child{box-shadow:none}
  .twk-chip svg{position:absolute;top:6px;left:6px;width:13px;height:13px;
    filter:drop-shadow(0 1px 1px rgba(0,0,0,.3))}
`;

// ── useTweaks ───────────────────────────────────────────────────────────────
// Single source of truth for tweak values. setTweak persists via the host
// (__edit_mode_set_keys → host rewrites the EDITMODE block on disk).
function useTweaks(defaults) {
  const [values, setValues] = React.useState(defaults);
  // Accepts either setTweak('key', value) or setTweak({ key: value, ... }) so a
  // useState-style call doesn't write a "[object Object]" key into the persisted
  // JSON block.
  const setTweak = React.useCallback((keyOrEdits, val) => {
    const edits = typeof keyOrEdits === 'object' && keyOrEdits !== null ? keyOrEdits : {
      [keyOrEdits]: val
    };
    setValues(prev => ({
      ...prev,
      ...edits
    }));
    window.parent.postMessage({
      type: '__edit_mode_set_keys',
      edits
    }, '*');
    // Same-window signal so in-page listeners (deck-stage rail thumbnails)
    // can react — the parent message only reaches the host, not peers.
    window.dispatchEvent(new CustomEvent('tweakchange', {
      detail: edits
    }));
  }, []);
  return [values, setTweak];
}

// ── TweaksPanel ─────────────────────────────────────────────────────────────
// Floating shell. Registers the protocol listener BEFORE announcing
// availability — if the announce ran first, the host's activate could land
// before our handler exists and the toolbar toggle would silently no-op.
// The close button posts __edit_mode_dismissed so the host's toolbar toggle
// flips off in lockstep; the host echoes __deactivate_edit_mode back which
// is what actually hides the panel.
function TweaksPanel({
  title = 'Tweaks',
  noDeckControls = false,
  children
}) {
  const [open, setOpen] = React.useState(false);
  const dragRef = React.useRef(null);
  // Auto-inject a rail toggle when a <deck-stage> is on the page. The
  // toggle drives the deck's per-viewer _railVisible via window message;
  // state is mirrored from the same localStorage key the deck reads so
  // the control reflects reality across reloads. The mechanism is the
  // message — authors who want custom placement can post it directly
  // and pass noDeckControls to suppress this one.
  const hasDeckStage = React.useMemo(() => typeof document !== 'undefined' && !!document.querySelector('deck-stage'), []);
  // Hide the toggle until the host has actually enabled the rail (the
  // __omelette_rail_enabled window message, posted only when the
  // omelette_deck_rail_enabled flag is on for this user). The initial read
  // covers TweaksPanel mounting after the message already arrived; the
  // listener covers the common case of mounting first.
  const [railEnabled, setRailEnabled] = React.useState(() => hasDeckStage && !!document.querySelector('deck-stage')?._railEnabled);
  React.useEffect(() => {
    if (!hasDeckStage || railEnabled) return undefined;
    const onMsg = e => {
      if (e.data && e.data.type === '__omelette_rail_enabled') setRailEnabled(true);
    };
    window.addEventListener('message', onMsg);
    return () => window.removeEventListener('message', onMsg);
  }, [hasDeckStage, railEnabled]);
  const [railVisible, setRailVisible] = React.useState(() => {
    try {
      return localStorage.getItem('deck-stage.railVisible') !== '0';
    } catch (e) {
      return true;
    }
  });
  const toggleRail = on => {
    setRailVisible(on);
    window.postMessage({
      type: '__deck_rail_visible',
      on
    }, '*');
  };
  const offsetRef = React.useRef({
    x: 16,
    y: 16
  });
  const PAD = 16;
  const clampToViewport = React.useCallback(() => {
    const panel = dragRef.current;
    if (!panel) return;
    const w = panel.offsetWidth,
      h = panel.offsetHeight;
    const maxRight = Math.max(PAD, window.innerWidth - w - PAD);
    const maxBottom = Math.max(PAD, window.innerHeight - h - PAD);
    offsetRef.current = {
      x: Math.min(maxRight, Math.max(PAD, offsetRef.current.x)),
      y: Math.min(maxBottom, Math.max(PAD, offsetRef.current.y))
    };
    panel.style.right = offsetRef.current.x + 'px';
    panel.style.bottom = offsetRef.current.y + 'px';
  }, []);
  React.useEffect(() => {
    if (!open) return;
    clampToViewport();
    if (typeof ResizeObserver === 'undefined') {
      window.addEventListener('resize', clampToViewport);
      return () => window.removeEventListener('resize', clampToViewport);
    }
    const ro = new ResizeObserver(clampToViewport);
    ro.observe(document.documentElement);
    return () => ro.disconnect();
  }, [open, clampToViewport]);
  React.useEffect(() => {
    const onMsg = e => {
      const t = e?.data?.type;
      if (t === '__activate_edit_mode') setOpen(true);else if (t === '__deactivate_edit_mode') setOpen(false);
    };
    window.addEventListener('message', onMsg);
    window.parent.postMessage({
      type: '__edit_mode_available'
    }, '*');
    return () => window.removeEventListener('message', onMsg);
  }, []);
  const dismiss = () => {
    setOpen(false);
    window.parent.postMessage({
      type: '__edit_mode_dismissed'
    }, '*');
  };
  const onDragStart = e => {
    const panel = dragRef.current;
    if (!panel) return;
    const r = panel.getBoundingClientRect();
    const sx = e.clientX,
      sy = e.clientY;
    const startRight = window.innerWidth - r.right;
    const startBottom = window.innerHeight - r.bottom;
    const move = ev => {
      offsetRef.current = {
        x: startRight - (ev.clientX - sx),
        y: startBottom - (ev.clientY - sy)
      };
      clampToViewport();
    };
    const up = () => {
      window.removeEventListener('mousemove', move);
      window.removeEventListener('mouseup', up);
    };
    window.addEventListener('mousemove', move);
    window.addEventListener('mouseup', up);
  };
  if (!open) return null;
  return /*#__PURE__*/React.createElement(React.Fragment, null, /*#__PURE__*/React.createElement("style", null, __TWEAKS_STYLE), /*#__PURE__*/React.createElement("div", {
    ref: dragRef,
    className: "twk-panel",
    "data-noncommentable": "",
    style: {
      right: offsetRef.current.x,
      bottom: offsetRef.current.y
    }
  }, /*#__PURE__*/React.createElement("div", {
    className: "twk-hd",
    onMouseDown: onDragStart
  }, /*#__PURE__*/React.createElement("b", null, title), /*#__PURE__*/React.createElement("button", {
    className: "twk-x",
    "aria-label": "Close tweaks",
    onMouseDown: e => e.stopPropagation(),
    onClick: dismiss
  }, "\u2715")), /*#__PURE__*/React.createElement("div", {
    className: "twk-body"
  }, children, hasDeckStage && railEnabled && !noDeckControls && /*#__PURE__*/React.createElement(TweakSection, {
    label: "Deck"
  }, /*#__PURE__*/React.createElement(TweakToggle, {
    label: "Thumbnail rail",
    value: railVisible,
    onChange: toggleRail
  })))));
}

// ── Layout helpers ──────────────────────────────────────────────────────────

function TweakSection({
  label,
  children
}) {
  return /*#__PURE__*/React.createElement(React.Fragment, null, /*#__PURE__*/React.createElement("div", {
    className: "twk-sect"
  }, label), children);
}
function TweakRow({
  label,
  value,
  children,
  inline = false
}) {
  return /*#__PURE__*/React.createElement("div", {
    className: inline ? 'twk-row twk-row-h' : 'twk-row'
  }, /*#__PURE__*/React.createElement("div", {
    className: "twk-lbl"
  }, /*#__PURE__*/React.createElement("span", null, label), value != null && /*#__PURE__*/React.createElement("span", {
    className: "twk-val"
  }, value)), children);
}

// ── Controls ────────────────────────────────────────────────────────────────

function TweakSlider({
  label,
  value,
  min = 0,
  max = 100,
  step = 1,
  unit = '',
  onChange
}) {
  return /*#__PURE__*/React.createElement(TweakRow, {
    label: label,
    value: `${value}${unit}`
  }, /*#__PURE__*/React.createElement("input", {
    type: "range",
    className: "twk-slider",
    min: min,
    max: max,
    step: step,
    value: value,
    onChange: e => onChange(Number(e.target.value))
  }));
}
function TweakToggle({
  label,
  value,
  onChange
}) {
  return /*#__PURE__*/React.createElement("div", {
    className: "twk-row twk-row-h"
  }, /*#__PURE__*/React.createElement("div", {
    className: "twk-lbl"
  }, /*#__PURE__*/React.createElement("span", null, label)), /*#__PURE__*/React.createElement("button", {
    type: "button",
    className: "twk-toggle",
    "data-on": value ? '1' : '0',
    role: "switch",
    "aria-checked": !!value,
    onClick: () => onChange(!value)
  }, /*#__PURE__*/React.createElement("i", null)));
}
function TweakRadio({
  label,
  value,
  options,
  onChange
}) {
  const trackRef = React.useRef(null);
  const [dragging, setDragging] = React.useState(false);
  // The active value is read by pointer-move handlers attached for the lifetime
  // of a drag — ref it so a stale closure doesn't fire onChange for every move.
  const valueRef = React.useRef(value);
  valueRef.current = value;

  // Segments wrap mid-word once per-segment width runs out. The track is
  // ~248px (280 panel − 28 body pad − 4 seg pad), each button loses 12px
  // to its own padding, and 11.5px system-ui averages ~6.3px/char — so 2
  // options fit ~16 chars each, 3 fit ~10. Past that (or >3 options), fall
  // back to a dropdown rather than wrap.
  const labelLen = o => String(typeof o === 'object' ? o.label : o).length;
  const maxLen = options.reduce((m, o) => Math.max(m, labelLen(o)), 0);
  const fitsAsSegments = maxLen <= ({
    2: 16,
    3: 10
  }[options.length] ?? 0);
  if (!fitsAsSegments) {
    // <select> emits strings — map back to the original option value so the
    // fallback stays type-preserving (numbers, booleans) like the segment path.
    const resolve = s => {
      const m = options.find(o => String(typeof o === 'object' ? o.value : o) === s);
      return m === undefined ? s : typeof m === 'object' ? m.value : m;
    };
    return /*#__PURE__*/React.createElement(TweakSelect, {
      label: label,
      value: value,
      options: options,
      onChange: s => onChange(resolve(s))
    });
  }
  const opts = options.map(o => typeof o === 'object' ? o : {
    value: o,
    label: o
  });
  const idx = Math.max(0, opts.findIndex(o => o.value === value));
  const n = opts.length;
  const segAt = clientX => {
    const r = trackRef.current.getBoundingClientRect();
    const inner = r.width - 4;
    const i = Math.floor((clientX - r.left - 2) / inner * n);
    return opts[Math.max(0, Math.min(n - 1, i))].value;
  };
  const onPointerDown = e => {
    setDragging(true);
    const v0 = segAt(e.clientX);
    if (v0 !== valueRef.current) onChange(v0);
    const move = ev => {
      if (!trackRef.current) return;
      const v = segAt(ev.clientX);
      if (v !== valueRef.current) onChange(v);
    };
    const up = () => {
      setDragging(false);
      window.removeEventListener('pointermove', move);
      window.removeEventListener('pointerup', up);
    };
    window.addEventListener('pointermove', move);
    window.addEventListener('pointerup', up);
  };
  return /*#__PURE__*/React.createElement(TweakRow, {
    label: label
  }, /*#__PURE__*/React.createElement("div", {
    ref: trackRef,
    role: "radiogroup",
    onPointerDown: onPointerDown,
    className: dragging ? 'twk-seg dragging' : 'twk-seg'
  }, /*#__PURE__*/React.createElement("div", {
    className: "twk-seg-thumb",
    style: {
      left: `calc(2px + ${idx} * (100% - 4px) / ${n})`,
      width: `calc((100% - 4px) / ${n})`
    }
  }), opts.map(o => /*#__PURE__*/React.createElement("button", {
    key: o.value,
    type: "button",
    role: "radio",
    "aria-checked": o.value === value
  }, o.label))));
}
function TweakSelect({
  label,
  value,
  options,
  onChange
}) {
  return /*#__PURE__*/React.createElement(TweakRow, {
    label: label
  }, /*#__PURE__*/React.createElement("select", {
    className: "twk-field",
    value: value,
    onChange: e => onChange(e.target.value)
  }, options.map(o => {
    const v = typeof o === 'object' ? o.value : o;
    const l = typeof o === 'object' ? o.label : o;
    return /*#__PURE__*/React.createElement("option", {
      key: v,
      value: v
    }, l);
  })));
}
function TweakText({
  label,
  value,
  placeholder,
  onChange
}) {
  return /*#__PURE__*/React.createElement(TweakRow, {
    label: label
  }, /*#__PURE__*/React.createElement("input", {
    className: "twk-field",
    type: "text",
    value: value,
    placeholder: placeholder,
    onChange: e => onChange(e.target.value)
  }));
}
function TweakNumber({
  label,
  value,
  min,
  max,
  step = 1,
  unit = '',
  onChange
}) {
  const clamp = n => {
    if (min != null && n < min) return min;
    if (max != null && n > max) return max;
    return n;
  };
  const startRef = React.useRef({
    x: 0,
    val: 0
  });
  const onScrubStart = e => {
    e.preventDefault();
    startRef.current = {
      x: e.clientX,
      val: value
    };
    const decimals = (String(step).split('.')[1] || '').length;
    const move = ev => {
      const dx = ev.clientX - startRef.current.x;
      const raw = startRef.current.val + dx * step;
      const snapped = Math.round(raw / step) * step;
      onChange(clamp(Number(snapped.toFixed(decimals))));
    };
    const up = () => {
      window.removeEventListener('pointermove', move);
      window.removeEventListener('pointerup', up);
    };
    window.addEventListener('pointermove', move);
    window.addEventListener('pointerup', up);
  };
  return /*#__PURE__*/React.createElement("div", {
    className: "twk-num"
  }, /*#__PURE__*/React.createElement("span", {
    className: "twk-num-lbl",
    onPointerDown: onScrubStart
  }, label), /*#__PURE__*/React.createElement("input", {
    type: "number",
    value: value,
    min: min,
    max: max,
    step: step,
    onChange: e => onChange(clamp(Number(e.target.value)))
  }), unit && /*#__PURE__*/React.createElement("span", {
    className: "twk-num-unit"
  }, unit));
}

// Relative-luminance contrast pick — checkmarks drawn over a swatch need to
// read on both #111 and #fafafa without per-option configuration. Hex input
// only (#rgb / #rrggbb); named or rgb()/hsl() colors fall through to "light".
function __twkIsLight(hex) {
  const h = String(hex).replace('#', '');
  const x = h.length === 3 ? h.replace(/./g, c => c + c) : h.padEnd(6, '0');
  const n = parseInt(x.slice(0, 6), 16);
  if (Number.isNaN(n)) return true;
  const r = n >> 16 & 255,
    g = n >> 8 & 255,
    b = n & 255;
  return r * 299 + g * 587 + b * 114 > 148000;
}
const __TwkCheck = ({
  light
}) => /*#__PURE__*/React.createElement("svg", {
  viewBox: "0 0 14 14",
  "aria-hidden": "true"
}, /*#__PURE__*/React.createElement("path", {
  d: "M3 7.2 5.8 10 11 4.2",
  fill: "none",
  strokeWidth: "2.2",
  strokeLinecap: "round",
  strokeLinejoin: "round",
  stroke: light ? 'rgba(0,0,0,.78)' : '#fff'
}));

// TweakColor — curated color/palette picker. Each option is either a single
// hex string or an array of 1-5 hex strings; the card adapts — a lone color
// renders solid, a palette renders colors[0] as the hero (left ~2/3) with the
// rest stacked in a sharp column on the right. onChange emits the
// option in the shape it was passed (string stays string, array stays array).
// Without options it falls back to the native color input for back-compat.
function TweakColor({
  label,
  value,
  options,
  onChange
}) {
  if (!options || !options.length) {
    return /*#__PURE__*/React.createElement("div", {
      className: "twk-row twk-row-h"
    }, /*#__PURE__*/React.createElement("div", {
      className: "twk-lbl"
    }, /*#__PURE__*/React.createElement("span", null, label)), /*#__PURE__*/React.createElement("input", {
      type: "color",
      className: "twk-swatch",
      value: value,
      onChange: e => onChange(e.target.value)
    }));
  }
  // Native <input type=color> emits lowercase hex per the HTML spec, so
  // compare case-insensitively. String() guards JSON.stringify(undefined),
  // which returns the primitive undefined (no .toLowerCase).
  const key = o => String(JSON.stringify(o)).toLowerCase();
  const cur = key(value);
  return /*#__PURE__*/React.createElement(TweakRow, {
    label: label
  }, /*#__PURE__*/React.createElement("div", {
    className: "twk-chips",
    role: "radiogroup"
  }, options.map((o, i) => {
    const colors = Array.isArray(o) ? o : [o];
    const [hero, ...rest] = colors;
    const sup = rest.slice(0, 4);
    const on = key(o) === cur;
    return /*#__PURE__*/React.createElement("button", {
      key: i,
      type: "button",
      className: "twk-chip",
      role: "radio",
      "aria-checked": on,
      "data-on": on ? '1' : '0',
      "aria-label": colors.join(', '),
      title: colors.join(' · '),
      style: {
        background: hero
      },
      onClick: () => onChange(o)
    }, sup.length > 0 && /*#__PURE__*/React.createElement("span", null, sup.map((c, j) => /*#__PURE__*/React.createElement("i", {
      key: j,
      style: {
        background: c
      }
    }))), on && /*#__PURE__*/React.createElement(__TwkCheck, {
      light: __twkIsLight(hero)
    }));
  })));
}
function TweakButton({
  label,
  onClick,
  secondary = false
}) {
  return /*#__PURE__*/React.createElement("button", {
    type: "button",
    className: secondary ? 'twk-btn secondary' : 'twk-btn',
    onClick: onClick
  }, label);
}
Object.assign(window, {
  useTweaks,
  TweaksPanel,
  TweakSection,
  TweakRow,
  TweakSlider,
  TweakToggle,
  TweakRadio,
  TweakSelect,
  TweakText,
  TweakNumber,
  TweakColor,
  TweakButton
});
})(); } catch (e) { __ds_ns.__errors.push({ path: "quiz/tweaks-panel.jsx", error: String((e && e.message) || e) }); }

// role-game/RoleGame.jsx
try { (() => {
/* global React, ROLE_LEVELS, ROLE_QUESTIONS, useTweaks, TweaksPanel, TweakSection, TweakRadio, TweakSlider, TweakToggle, TweakSelect, LevelUpV2 */
const {
  useState,
  useEffect,
  useRef,
  useCallback,
  useMemo
} = React;

/* ── Tweak defaults — persisted via the host on the parent file. ── */
const TWEAK_DEFAULTS = /*EDITMODE-BEGIN*/{
  "layout": "card",
  "celebration": "auto",
  "timerSecs": 60,
  "toLevelUp": 4,
  "showTimer": true,
  "showHints": true,
  "showScoreScale": true
} /*EDITMODE-END*/;

/* ── Leaderboard ──────────────────────────────────────────────────
   Top-5 high scores stored in localStorage. Same pattern used in the
   quiz-game. Score = ציון פסיכומטרי משוער (200–800). */
const LB_KEY = "ez-rolegame-lb-v1";
const LB_MAX = 5;
function getLeaderboard() {
  try {
    return JSON.parse(localStorage.getItem(LB_KEY) || "[]");
  } catch (e) {
    return [];
  }
}
function addToLeaderboard(name, score, reached) {
  const lb = getLeaderboard();
  lb.push({
    name: (name || "אנונימי").slice(0, 20),
    score,
    reached,
    date: new Date().toISOString()
  });
  lb.sort((a, b) => b.score - a.score);
  const top = lb.slice(0, LB_MAX);
  try {
    localStorage.setItem(LB_KEY, JSON.stringify(top));
  } catch (e) {}
  return top;
}
function qualifiesForLeaderboard(score) {
  if (score <= 0) return false;
  const lb = getLeaderboard();
  if (lb.length < LB_MAX) return true;
  return score > lb[lb.length - 1].score;
}

/* Trophy SVG — shared by EndScreen + leaderboard button */
const TrophySVG = () => /*#__PURE__*/React.createElement("svg", {
  viewBox: "0 0 24 24",
  width: "20",
  height: "20",
  fill: "none",
  stroke: "currentColor",
  strokeWidth: "2",
  strokeLinecap: "round",
  strokeLinejoin: "round",
  "aria-hidden": true
}, /*#__PURE__*/React.createElement("path", {
  d: "M8 21h8M12 17v4M7 4h10v5a5 5 0 0 1-10 0V4z"
}), /*#__PURE__*/React.createElement("path", {
  d: "M17 6h3v2a3 3 0 0 1-3 3"
}), /*#__PURE__*/React.createElement("path", {
  d: "M7 6H4v2a3 3 0 0 0 3 3"
}));

/* ── small inline icons ───────────────────────────────────────── */
const HeartSVG = ({
  lost
}) => /*#__PURE__*/React.createElement("svg", {
  viewBox: "0 0 24 24",
  "aria-hidden": true
}, /*#__PURE__*/React.createElement("path", {
  fill: lost ? "#C8362A" : "#F37327",
  d: "M12 21s-7.5-4.7-9.6-9.5C.9 7.7 3.5 4 7.2 4c2 0 3.6 1 4.8 2.6C13.2 5 14.8 4 16.8 4c3.7 0 6.3 3.7 4.8 7.5C19.5 16.3 12 21 12 21z"
}));
const ArrowSVG = () => /*#__PURE__*/React.createElement("svg", {
  viewBox: "0 0 24 24",
  width: "22",
  height: "22",
  fill: "none",
  stroke: "currentColor",
  strokeWidth: "2.6",
  strokeLinecap: "round",
  strokeLinejoin: "round"
}, /*#__PURE__*/React.createElement("path", {
  d: "M19 12H5"
}), /*#__PURE__*/React.createElement("path", {
  d: "M12 19l-7-7 7-7"
}));

/* Footer icons — outlined / inline so they tint by currentColor */
const FootIcon = {
  home: () => /*#__PURE__*/React.createElement("svg", {
    viewBox: "0 0 24 24",
    fill: "none",
    stroke: "currentColor",
    strokeWidth: "2.2",
    strokeLinecap: "round",
    strokeLinejoin: "round",
    "aria-hidden": true
  }, /*#__PURE__*/React.createElement("path", {
    d: "M3 11.5 12 4l9 7.5"
  }), /*#__PURE__*/React.createElement("path", {
    d: "M5 10v10h14V10"
  }), /*#__PURE__*/React.createElement("path", {
    d: "M10 20v-6h4v6"
  })),
  soundOn: () => /*#__PURE__*/React.createElement("svg", {
    viewBox: "0 0 24 24",
    fill: "none",
    stroke: "currentColor",
    strokeWidth: "2.2",
    strokeLinecap: "round",
    strokeLinejoin: "round",
    "aria-hidden": true
  }, /*#__PURE__*/React.createElement("path", {
    d: "M5 9v6h4l5 4V5L9 9H5z"
  }), /*#__PURE__*/React.createElement("path", {
    d: "M16.5 8.5a5 5 0 0 1 0 7"
  }), /*#__PURE__*/React.createElement("path", {
    d: "M19 6a8.5 8.5 0 0 1 0 12"
  })),
  soundOff: () => /*#__PURE__*/React.createElement("svg", {
    viewBox: "0 0 24 24",
    fill: "none",
    stroke: "currentColor",
    strokeWidth: "2.2",
    strokeLinecap: "round",
    strokeLinejoin: "round",
    "aria-hidden": true
  }, /*#__PURE__*/React.createElement("path", {
    d: "M5 9v6h4l5 4V5L9 9H5z"
  }), /*#__PURE__*/React.createElement("path", {
    d: "M17 9l5 6"
  }), /*#__PURE__*/React.createElement("path", {
    d: "M22 9l-5 6"
  })),
  expand: () => /*#__PURE__*/React.createElement("svg", {
    viewBox: "0 0 24 24",
    fill: "none",
    stroke: "currentColor",
    strokeWidth: "2.2",
    strokeLinecap: "round",
    strokeLinejoin: "round",
    "aria-hidden": true
  }, /*#__PURE__*/React.createElement("polyline", {
    points: "4 9 4 4 9 4"
  }), /*#__PURE__*/React.createElement("polyline", {
    points: "20 9 20 4 15 4"
  }), /*#__PURE__*/React.createElement("polyline", {
    points: "4 15 4 20 9 20"
  }), /*#__PURE__*/React.createElement("polyline", {
    points: "20 15 20 20 15 20"
  }))
};

/* ── Persistent action footer ─────────────────────────────────────
   Three round buttons in the bottom-right, on top of every screen:
     • home → ezway.co.il (opens top window so an iframe-embedded game
       breaks out and lands on the marketing site).
     • sound → toggles a background-music audio element if present.
     • fullscreen → toggles document fullscreen.
*/
function FootBar({
  muted,
  onToggleMute,
  fifty
}) {
  function reqFs() {
    try {
      const el = document.documentElement;
      if (document.fullscreenElement || document.webkitFullscreenElement) {
        (document.exitFullscreen || document.webkitExitFullscreen || function () {}).call(document);
      } else {
        const req = el.requestFullscreen || el.webkitRequestFullscreen || el.msRequestFullscreen;
        if (req) {
          const p = req.call(el);
          if (p && typeof p.catch === "function") p.catch(() => {});
        }
      }
    } catch (e) {}
  }
  function goHome() {
    try {
      window.top.location.href = "https://www.ezway.co.il";
    } catch (e) {
      window.open("https://www.ezway.co.il", "_top");
    }
  }
  return /*#__PURE__*/React.createElement("div", {
    className: "rg-footbar"
  }, /*#__PURE__*/React.createElement("button", {
    className: "rg-footbtn",
    onClick: goHome,
    title: "\u05DC\u05D0\u05EA\u05E8 eazy",
    "aria-label": "\u05DC\u05D0\u05EA\u05E8 eazy"
  }, /*#__PURE__*/React.createElement(FootIcon.home, null)), /*#__PURE__*/React.createElement("button", {
    className: "rg-footbtn",
    onClick: onToggleMute,
    title: muted ? "הפעלת סאונד" : "ביטול סאונד",
    "aria-label": "\u05E1\u05D0\u05D5\u05E0\u05D3"
  }, muted ? /*#__PURE__*/React.createElement(FootIcon.soundOff, null) : /*#__PURE__*/React.createElement(FootIcon.soundOn, null)), /*#__PURE__*/React.createElement("button", {
    className: "rg-footbtn",
    onClick: reqFs,
    title: "\u05DE\u05E1\u05DA \u05DE\u05DC\u05D0",
    "aria-label": "\u05DE\u05E1\u05DA \u05DE\u05DC\u05D0"
  }, /*#__PURE__*/React.createElement(FootIcon.expand, null)), fifty && /*#__PURE__*/React.createElement("button", {
    className: "rg-footbtn rg-fifty" + (fifty.available ? "" : " used"),
    onClick: fifty.available ? fifty.onUse : undefined,
    disabled: !fifty.available,
    title: fifty.available ? "גלגל הצלה 50/50" : "כבר השתמשתם ב-50/50",
    "aria-label": "50/50"
  }, /*#__PURE__*/React.createElement("span", {
    className: "rg-fifty-text"
  }, "50", /*#__PURE__*/React.createElement("br", null), "50")));
}

/* ── tiny shuffle + sample helpers ────────────────────────────── */
function shuffle(a) {
  const x = [...a];
  for (let i = x.length - 1; i > 0; i--) {
    const j = Math.floor(Math.random() * (i + 1));
    [x[i], x[j]] = [x[j], x[i]];
  }
  return x;
}

/* Pick a question with category rotation — avoids the recent few
   question IDs AND the last 2 categories used so the player gets
   variety from the very first question (the source file labels all
   analogies as "easy", so the old `difficulty <= levelId` filter
   forced level 1 to be analogies-only). Difficulty is still respected
   as a soft cap: easy + medium are allowed from level 1, hard kicks in
   at level 3+. */
function pickQuestion(levelId, recent) {
  const recentIds = new Set(recent.map(r => r.id || r));
  const lastCats = new Set(recent.slice(0, 2).map(r => typeof r === "object" ? r.category : null).filter(Boolean));
  const diffCap = levelId >= 3 ? 3 : 2;
  const eligible = ROLE_QUESTIONS.filter(q => q.difficulty <= diffCap);

  // Primary: not recent + not in the last 2 categories.
  const primary = eligible.filter(q => !recentIds.has(q.id) && !lastCats.has(q.category));
  // Fallback 1: not recent (category may repeat).
  const fallback1 = eligible.filter(q => !recentIds.has(q.id));
  // Last resort: anything eligible.
  const set = primary.length ? primary : fallback1.length ? fallback1 : eligible;
  return set[Math.floor(Math.random() * set.length)];
}

/* Encouragement copy per outcome — eazy voice (plural, calm). */
const PRAISE = ["כל הכבוד!", "תפסתם!", "אש על המסיחים.", "ככה זה איזי.", "שורה ישרה."];
const PUSH = ["לא נורא — שאלה הבאה.", "ממשיכים בלי לעצור.", "טעות אחת לא מוציאה מהמשחק.", "מתאוששים. תורכם."];
const pick = arr => arr[Math.floor(Math.random() * arr.length)];

/* ── Intro screen ─────────────────────────────────────────────── */
function Intro({
  onStart,
  levels
}) {
  // Three avatars for the journey strip: first, middle, last
  const journey = [levels[0], levels[Math.floor(levels.length / 2)], levels[levels.length - 1]];
  return /*#__PURE__*/React.createElement("div", {
    className: "rg-intro"
  }, /*#__PURE__*/React.createElement("div", {
    className: "rg-intro-logo"
  }, /*#__PURE__*/React.createElement("img", {
    className: "rg-intro-logomark",
    src: "../assets/ez-icon.png",
    alt: ""
  }), /*#__PURE__*/React.createElement("span", {
    className: "rg-intro-wordmark brand-eazy"
  }, "eazy")), /*#__PURE__*/React.createElement("div", {
    className: "rg-intro-hero"
  }, /*#__PURE__*/React.createElement("h1", {
    className: "rg-intro-title"
  }, /*#__PURE__*/React.createElement("span", {
    className: "line line-1"
  }, "\u05DE\u05D9 \u05E4\u05E8\u05D5\u05E4\u05E1\u05D5\u05E8"), /*#__PURE__*/React.createElement("span", {
    className: "line line-2"
  }, "\u05DC\u05E4\u05E1\u05D9\u05DB\u05D5\u05DE\u05D8\u05E8\u05D9", /*#__PURE__*/React.createElement("span", {
    className: "qmark"
  }, "?"))), /*#__PURE__*/React.createElement("div", {
    className: "rg-intro-journey",
    "aria-hidden": true
  }, journey.map((lv, i) => /*#__PURE__*/React.createElement(React.Fragment, {
    key: lv.id
  }, /*#__PURE__*/React.createElement("div", {
    className: "rg-intro-journey-cell",
    "data-pos": i === 0 ? "start" : i === journey.length - 1 ? "end" : "mid"
  }, /*#__PURE__*/React.createElement(lv.Avatar, null), /*#__PURE__*/React.createElement("span", {
    className: "lbl"
  }, lv.name)), i < journey.length - 1 && /*#__PURE__*/React.createElement("span", {
    className: "rg-intro-journey-arrow"
  }, "\u203A")))), /*#__PURE__*/React.createElement("p", {
    className: "rg-intro-lead"
  }, "\u05DB\u05DC ", /*#__PURE__*/React.createElement("b", null, "4 \u05EA\u05E9\u05D5\u05D1\u05D5\u05EA \u05E0\u05DB\u05D5\u05E0\u05D5\u05EA"), " \u05EA\u05E2\u05DC\u05D5 \u05E9\u05DC\u05D1. \u05D1\u05EA\u05D5\u05DD ", /*#__PURE__*/React.createElement("b", null, "15 \u05E9\u05DC\u05D1\u05D9\u05DD"), " \u05DE\u05D2\u05D9\u05E2\u05D9\u05DD \u05DC\u05D3\u05E8\u05D2\u05EA \u05E4\u05E8\u05D5\u05E4\u05E1\u05D5\u05E8 \u05D5\u05E6\u05D9\u05D5\u05DF 800.", /*#__PURE__*/React.createElement("br", null), /*#__PURE__*/React.createElement("span", {
    className: "rg-intro-lead-good"
  }, "\u05D1\u05D4\u05E6\u05DC\u05D7\u05D4!")), /*#__PURE__*/React.createElement("button", {
    className: "rg-intro-cta",
    onClick: onStart
  }, /*#__PURE__*/React.createElement("span", null, "\u05E7\u05D3\u05D9\u05DE\u05D4!"), /*#__PURE__*/React.createElement(ArrowSVG, null))));
}

/* ── psychometric score scale (200 → 800) ─────────────────────── */
/*  One tick per question in the whole game. Number of ticks always
    equals (levels.length × toLevelUp), so the scale rescales when the
    streak-per-level tweak changes. Last correct answer = score 800. */
/* ── psychometric score scale (200 → 800) — Mountain Climb ────────
   A mountain silhouette climbed by the player's avatar. The peak
   (800) sits on the LEFT (matching the score axis when read in RTL
   order — value grows as you read leftward), the base (200) on the
   RIGHT.

   Ticks-per-question and milestones are unchanged so the existing
   levelUp animations + scale logic continue to work; only the
   visual chrome is replaced. */
function ScoreScale({
  correctSoFar,
  totalQuestions,
  toLevelUp,
  level
}) {
  const pct = Math.min(1, correctSoFar / totalQuestions);
  // Trail runs from x=20 (base, LEFT) to x=580 (peak, RIGHT). The
  // mountain rises left → right so the "high score" (800) reads at
  // the right edge — matches the natural reading of a chart.
  const X_BASE = 20,
    X_PEAK = 580;
  const Y_BASE = 90,
    Y_PEAK = 18;
  const trailY = t => {
    const eased = Math.pow(t, 1.1);
    return Y_BASE - (Y_BASE - Y_PEAK) * eased;
  };
  const walkerX = X_BASE + (X_PEAK - X_BASE) * pct;
  const walkerY = trailY(pct);
  const scoreNow = Math.round((200 + 600 * pct) / 10) * 10;
  const Avatar = level && level.Avatar;
  return /*#__PURE__*/React.createElement("div", {
    className: "rg-scale rg-scale-mtn",
    "aria-label": "\u05E6\u05D9\u05D5\u05DF \u05E4\u05E1\u05D9\u05DB\u05D5\u05DE\u05D8\u05E8\u05D9 \u05DE\u05E9\u05D5\u05E2\u05E8"
  }, /*#__PURE__*/React.createElement("div", {
    className: "rg-mtn-ends",
    "aria-hidden": true
  }, /*#__PURE__*/React.createElement("span", {
    className: "rg-mtn-base"
  }, /*#__PURE__*/React.createElement("span", {
    className: "num"
  }, "200"), /*#__PURE__*/React.createElement("span", {
    className: "dot"
  }, "\xB7"), /*#__PURE__*/React.createElement("span", {
    className: "lbl"
  }, "\u05D1\u05E1\u05D9\u05E1")), /*#__PURE__*/React.createElement("span", {
    className: "rg-mtn-now"
  }, scoreNow, " \xB7 \u05E6\u05D9\u05D5\u05DF \u05E0\u05D5\u05DB\u05D7\u05D9"), /*#__PURE__*/React.createElement("span", {
    className: "rg-mtn-peak"
  }, /*#__PURE__*/React.createElement("span", {
    className: "num"
  }, "800"), /*#__PURE__*/React.createElement("span", {
    className: "flag"
  }, "\uD83C\uDFD4"))), /*#__PURE__*/React.createElement("div", {
    className: "rg-mtn-canvas"
  }, /*#__PURE__*/React.createElement("svg", {
    viewBox: "0 0 600 100",
    preserveAspectRatio: "none",
    "aria-hidden": true
  }, /*#__PURE__*/React.createElement("defs", null, /*#__PURE__*/React.createElement("linearGradient", {
    id: "mtnFar",
    x1: "0",
    y1: "0",
    x2: "0",
    y2: "1"
  }, /*#__PURE__*/React.createElement("stop", {
    offset: "0",
    stopColor: "#A9A4EC",
    stopOpacity: ".60"
  }), /*#__PURE__*/React.createElement("stop", {
    offset: "1",
    stopColor: "#A9A4EC",
    stopOpacity: ".22"
  })), /*#__PURE__*/React.createElement("linearGradient", {
    id: "mtnNear",
    x1: "0",
    y1: "0",
    x2: "0",
    y2: "1"
  }, /*#__PURE__*/React.createElement("stop", {
    offset: "0",
    stopColor: "#7A72C8",
    stopOpacity: ".55"
  }), /*#__PURE__*/React.createElement("stop", {
    offset: "1",
    stopColor: "#7A72C8",
    stopOpacity: ".20"
  }))), /*#__PURE__*/React.createElement("path", {
    d: "M 0,100 L 60,55 L 140,72 L 240,40 L 360,62 L 480,30 L 600,18 L 600,100 Z",
    fill: "url(#mtnFar)"
  }), /*#__PURE__*/React.createElement("path", {
    d: "M 0,100 L 90,68 L 190,80 L 280,55 L 380,72 L 480,42 L 570,22 L 600,30 L 600,100 Z",
    fill: "url(#mtnNear)"
  }), /*#__PURE__*/React.createElement("path", {
    d: "M 20,90 Q 140,90 240,70 T 420,38 T 580,16",
    stroke: "rgba(243,115,39,.45)",
    strokeWidth: "2",
    strokeDasharray: "3 3",
    fill: "none",
    strokeLinecap: "round"
  }), /*#__PURE__*/React.createElement("path", {
    d: "M 20,90 Q 140,90 240,70 T 420,38 T 580,16",
    stroke: "#F37327",
    strokeWidth: "3",
    fill: "none",
    strokeLinecap: "round",
    strokeDasharray: "600",
    strokeDashoffset: 600 - 600 * pct,
    style: {
      transition: "stroke-dashoffset .6s cubic-bezier(.2,.7,.2,1)"
    }
  }), Array.from({
    length: Math.ceil(totalQuestions / toLevelUp)
  }).map((_, i) => {
    const mt = (i + 1) / Math.ceil(totalQuestions / toLevelUp);
    const mx = X_BASE + (X_PEAK - X_BASE) * mt;
    const my = trailY(mt);
    const passed = (i + 1) * toLevelUp <= correctSoFar;
    return /*#__PURE__*/React.createElement("circle", {
      key: i,
      cx: mx,
      cy: my,
      r: "3.5",
      fill: passed ? "#F37327" : "#fff",
      stroke: "#F37327",
      strokeWidth: "2"
    });
  }), /*#__PURE__*/React.createElement("g", {
    transform: `translate(${X_PEAK} ${Y_PEAK})`
  }, /*#__PURE__*/React.createElement("line", {
    x1: "0",
    y1: "0",
    x2: "0",
    y2: "-12",
    stroke: "#2A2155",
    strokeWidth: "1.6"
  }), /*#__PURE__*/React.createElement("path", {
    d: "M 0,-12 L 10,-9 L 0,-6 Z",
    fill: "#F37327"
  }))), /*#__PURE__*/React.createElement("div", {
    className: "rg-mtn-walker",
    style: {
      left: `calc(${walkerX / 600 * 100}% - 24px)`,
      bottom: `calc(${100 - walkerY / 100 * 100}% - 24px)`
    }
  }, Avatar ? /*#__PURE__*/React.createElement(Avatar, null) : /*#__PURE__*/React.createElement("div", {
    className: "rg-mtn-walker-emoji"
  }, "\uD83D\uDEB6")), (correctSoFar % toLevelUp !== 0 || correctSoFar === 0) && correctSoFar < totalQuestions && /*#__PURE__*/React.createElement("div", {
    className: "rg-mtn-nudge",
    style: {
      left: `calc(${walkerX / 600 * 100}% - 60px)`,
      bottom: `calc(${100 - walkerY / 100 * 100}% + 30px)`
    }
  }, "\u05E2\u05D5\u05D3 ", toLevelUp - correctSoFar % toLevelUp, " \u05D5\u05E2\u05D5\u05DC\u05D9\u05DD \u05E9\u05DC\u05D1", /*#__PURE__*/React.createElement("span", {
    className: "dot"
  }, "."))));
}

/* ── timer ring ───────────────────────────────────────────────── */
function TimerRing({
  seconds,
  total
}) {
  const C = 2 * Math.PI * 28; // r=28
  const pct = Math.max(0, seconds) / total;
  const offset = C * (1 - pct);
  const warn = seconds <= 10;
  return /*#__PURE__*/React.createElement("div", {
    className: "rg-timer" + (warn ? " warn" : "")
  }, /*#__PURE__*/React.createElement("svg", {
    viewBox: "0 0 64 64"
  }, /*#__PURE__*/React.createElement("circle", {
    cx: "32",
    cy: "32",
    r: "28",
    className: "rg-timer-track"
  }), /*#__PURE__*/React.createElement("circle", {
    cx: "32",
    cy: "32",
    r: "28",
    className: "rg-timer-bar",
    strokeDasharray: C,
    strokeDashoffset: offset
  })), /*#__PURE__*/React.createElement("div", {
    className: "rg-timer-num"
  }, Math.max(0, seconds)));
}

/* ── confetti shower (variant C) ──────────────────────────────── */
function Confetti() {
  const pieces = useMemo(() => Array.from({
    length: 60
  }, (_, i) => ({
    left: Math.random() * 100,
    delay: Math.random() * 1.4,
    dur: 1.6 + Math.random() * 1.6,
    color: ["#F37327", "#A9A4EC", "#3F4197", "#FBD9C2", "#FFFFFF"][i % 5],
    rot: Math.random() * 360
  })), []);
  return /*#__PURE__*/React.createElement("div", {
    className: "rg-confetti",
    "aria-hidden": true
  }, pieces.map((p, i) => /*#__PURE__*/React.createElement("i", {
    key: i,
    style: {
      left: p.left + "%",
      background: p.color,
      animationDelay: -p.delay + "s",
      animationDuration: p.dur + "s",
      transform: `rotate(${p.rot}deg)`
    }
  })));
}

/* ── Level-up overlay (3 variants) ────────────────────────────── */
function LevelUp({
  from,
  to,
  variant,
  onContinue
}) {
  const isBanner = variant === "banner";
  const isConfetti = variant === "confetti";
  return /*#__PURE__*/React.createElement("div", {
    className: "rg-levelup" + (isBanner ? " banner" : "")
  }, isConfetti && /*#__PURE__*/React.createElement(Confetti, null), /*#__PURE__*/React.createElement("div", {
    className: "rg-lu-card"
  }, /*#__PURE__*/React.createElement("div", {
    className: "rg-lu-eye"
  }, "\u05E2\u05DC\u05D9\u05D9\u05D4 \u05DC\u05E9\u05DC\u05D1 ", String(to.id).padStart(2, "0")), /*#__PURE__*/React.createElement("div", {
    className: "rg-lu-avatars"
  }, from && /*#__PURE__*/React.createElement(React.Fragment, null, /*#__PURE__*/React.createElement("div", {
    className: "from"
  }, /*#__PURE__*/React.createElement(from.Avatar, null)), /*#__PURE__*/React.createElement("span", {
    className: "rg-lu-arrow"
  }, "\u203A")), /*#__PURE__*/React.createElement("div", {
    className: "to"
  }, /*#__PURE__*/React.createElement(to.Avatar, null))), /*#__PURE__*/React.createElement("h2", {
    className: "rg-lu-title"
  }, to.kicker.replace(/[.!]$/, ""), /*#__PURE__*/React.createElement("span", {
    className: "dot"
  }, to.kicker.match(/[.!]$/)?.[0] || ".")), /*#__PURE__*/React.createElement("div", {
    className: "rg-lu-sub"
  }, "\u05D4\u05E4\u05DB\u05EA \u05DC", /*#__PURE__*/React.createElement("b", {
    style: {
      color: "var(--ez-ink)"
    }
  }, to.name), ". ", to.subKicker), /*#__PURE__*/React.createElement("button", {
    className: "rg-lu-btn",
    onClick: onContinue
  }, "\u05D4\u05DE\u05E9\u05DA \u05DC\u05E9\u05DC\u05D1 \u05D4\u05D1\u05D0 \u203A")));
}

/* ── End / Game-over screen ───────────────────────────────────── */

/* Format a millisecond duration as a friendly "12 שנ׳" string. */
function fmtSecs(ms) {
  if (ms == null || !isFinite(ms)) return "";
  const secs = Math.max(1, Math.round(ms / 1000));
  return secs + " שנ׳";
}

/* Friendly two-letter prefix per kind — used on the kind chip in the
   analysis rows so the player can see at a glance whether a category
   belongs to verbal / quantitative / English. */
const KIND_LABEL = {
  V: "מילולי",
  Q: "כמותי",
  E: "אנגלית"
};

/* Crunch the per-attempt log into a strengths/weaknesses analysis.

   Three buckets:
     · strong       — 100% accuracy AND avg-time ≤ overall median × 1.2
     · slowStrong   — 100% accuracy BUT avg-time > overall median × 1.35
                      (the "you know it, you're just slow" case the brief
                      called out explicitly)
     · weak         — any wrong answer (timeout counts as wrong)

   We sort strong by speed (fastest first), slowStrong by how slow they
   are (slowest first), and weak by accuracy (worst first). */
function analyzeAttempts(attempts) {
  if (!attempts || !attempts.length) return null;
  const byCat = {};
  for (const a of attempts) {
    const c = byCat[a.category] ||= {
      name: a.category,
      kind: a.kind,
      total: 0,
      correct: 0,
      wrong: 0,
      timedOut: 0,
      times: []
    };
    c.total++;
    if (a.correct) {
      c.correct++;
      if (!a.timedOut) c.times.push(a.timeMs);
    } else {
      c.wrong++;
      if (a.timedOut) c.timedOut++;
    }
  }
  // Reference time: median of every correct-answer time across the whole game.
  const allTimes = attempts.filter(a => a.correct && !a.timedOut).map(a => a.timeMs).sort((x, y) => x - y);
  const median = allTimes.length ? allTimes[Math.floor(allTimes.length / 2)] : 0;
  const strong = [],
    slowStrong = [],
    weak = [];
  for (const c of Object.values(byCat)) {
    c.accuracy = c.correct / c.total;
    c.avgTime = c.times.length ? c.times.reduce((s, n) => s + n, 0) / c.times.length : null;
    if (c.accuracy === 1) {
      if (median && c.avgTime != null && c.avgTime > median * 1.35) slowStrong.push(c);else strong.push(c);
    } else {
      weak.push(c);
    }
  }
  strong.sort((a, b) => (a.avgTime || 0) - (b.avgTime || 0));
  slowStrong.sort((a, b) => (b.avgTime || 0) - (a.avgTime || 0));
  weak.sort((a, b) => a.accuracy - b.accuracy || b.wrong - a.wrong);
  // One-line summary headline for the top of the card.
  let headline;
  if (!weak.length && !slowStrong.length) {
    headline = strong.length >= 3 ? "מהיר ומדויק בכל מה שעלה. מצוין." : "כל מה שענית — צדקת. כל הכבוד.";
  } else if (!weak.length && slowStrong.length) {
    const list = slowStrong.slice(0, 2).map(c => c.name).join(" ו");
    headline = `מדויק בהכל. רק לזרז את ${list}.`;
  } else if (weak.length === 1) {
    headline = `נקודה לחיזוק: ${weak[0].name}.`;
  } else if (weak.length === 2) {
    headline = `שתי נקודות לחיזוק: ${weak[0].name} ו${weak[1].name}.`;
  } else {
    headline = `${strong.length + slowStrong.length} חוזקות, ${weak.length} נקודות לחיזוק.`;
  }
  return {
    strong,
    slowStrong,
    weak,
    headline,
    median
  };
}

/* Inline SVG glyphs used inside the two zone heads & per-category rows. */
const LU_ICONS = {
  strong: /*#__PURE__*/React.createElement("svg", {
    viewBox: "0 0 24 24",
    width: "22",
    height: "22",
    fill: "none",
    stroke: "currentColor",
    strokeWidth: "2.3",
    strokeLinecap: "round",
    strokeLinejoin: "round",
    "aria-hidden": true
  }, /*#__PURE__*/React.createElement("path", {
    d: "M12 2 l2.4 6.5 6.6.4 -5.1 4.3 1.7 6.8 -5.6 -3.6 -5.6 3.6 1.7 -6.8 -5.1 -4.3 6.6 -.4z"
  })),
  weak: /*#__PURE__*/React.createElement("svg", {
    viewBox: "0 0 24 24",
    width: "22",
    height: "22",
    fill: "none",
    stroke: "currentColor",
    strokeWidth: "2.3",
    strokeLinecap: "round",
    strokeLinejoin: "round",
    "aria-hidden": true
  }, /*#__PURE__*/React.createElement("polyline", {
    points: "4 13 9 18 20 6",
    opacity: "0"
  }), /*#__PURE__*/React.createElement("path", {
    d: "M4 19 L11 5 L18 19 Z"
  }), /*#__PURE__*/React.createElement("path", {
    d: "M11 11 v3"
  }), /*#__PURE__*/React.createElement("circle", {
    cx: "11",
    cy: "17",
    r: ".6",
    fill: "currentColor"
  })),
  clock: /*#__PURE__*/React.createElement("svg", {
    viewBox: "0 0 24 24",
    width: "16",
    height: "16",
    fill: "none",
    stroke: "currentColor",
    strokeWidth: "2",
    strokeLinecap: "round",
    strokeLinejoin: "round",
    "aria-hidden": true
  }, /*#__PURE__*/React.createElement("circle", {
    cx: "12",
    cy: "12",
    r: "9"
  }), /*#__PURE__*/React.createElement("polyline", {
    points: "12 7 12 12 15 14"
  })),
  bolt: /*#__PURE__*/React.createElement("svg", {
    viewBox: "0 0 24 24",
    width: "16",
    height: "16",
    fill: "currentColor",
    "aria-hidden": true
  }, /*#__PURE__*/React.createElement("path", {
    d: "M13 2 L4 14 h6 l-2 8 9-12 h-6 l2-8 z"
  })),
  cross: /*#__PURE__*/React.createElement("svg", {
    viewBox: "0 0 24 24",
    width: "16",
    height: "16",
    fill: "none",
    stroke: "currentColor",
    strokeWidth: "2.6",
    strokeLinecap: "round",
    "aria-hidden": true
  }, /*#__PURE__*/React.createElement("line", {
    x1: "6",
    y1: "6",
    x2: "18",
    y2: "18"
  }), /*#__PURE__*/React.createElement("line", {
    x1: "18",
    y1: "6",
    x2: "6",
    y2: "18"
  })),
  check: /*#__PURE__*/React.createElement("svg", {
    viewBox: "0 0 24 24",
    width: "16",
    height: "16",
    fill: "none",
    stroke: "currentColor",
    strokeWidth: "2.6",
    strokeLinecap: "round",
    strokeLinejoin: "round",
    "aria-hidden": true
  }, /*#__PURE__*/React.createElement("polyline", {
    points: "4 13 10 19 20 6"
  }))
};

/* Compact category card used inside each analysis column.
   `relSpeed` is avg-time / overallMedian — used to render the speed bar. */
function AnalysisCatRow({
  cat,
  mode,
  median
}) {
  // The accuracy bar fills based on correct/total. Capped at 100%.
  const accPct = Math.max(0, Math.min(100, Math.round(cat.accuracy * 100)));
  // The speed bar fills based on how close to median (1.0 = exactly median).
  // We map 0→100% fast (above median, capped low) and >2x median → ~0%.
  let speedPct = null,
    speedLabel = null;
  if (cat.avgTime != null && median) {
    const rel = cat.avgTime / median; // 1.0 = median, lower = faster
    speedPct = Math.max(8, Math.min(100, Math.round(1 / rel * 100 * 0.85)));
    speedLabel = rel <= 0.85 ? "מהיר" : rel <= 1.15 ? "רגיל" : rel <= 1.35 ? "מתון" : "איטי";
  }
  const statusIcon = mode === "weak" ? LU_ICONS.cross : mode === "slow" ? LU_ICONS.clock : LU_ICONS.check;
  return /*#__PURE__*/React.createElement("div", {
    className: "rg-analysis-cat mode-" + mode
  }, /*#__PURE__*/React.createElement("div", {
    className: "row1"
  }, /*#__PURE__*/React.createElement("span", {
    className: "k-chip k-" + cat.kind
  }, KIND_LABEL[cat.kind] || cat.kind), /*#__PURE__*/React.createElement("span", {
    className: "name"
  }, cat.name), /*#__PURE__*/React.createElement("span", {
    className: "status-icon",
    "aria-hidden": true
  }, statusIcon)), /*#__PURE__*/React.createElement("div", {
    className: "meters"
  }, /*#__PURE__*/React.createElement("div", {
    className: "meter meter-acc"
  }, /*#__PURE__*/React.createElement("div", {
    className: "meter-lbl"
  }, /*#__PURE__*/React.createElement("span", null, "\u05D3\u05D9\u05D5\u05E7"), /*#__PURE__*/React.createElement("span", {
    className: "v"
  }, cat.correct, "/", cat.total)), /*#__PURE__*/React.createElement("div", {
    className: "meter-track"
  }, /*#__PURE__*/React.createElement("div", {
    className: "meter-fill",
    style: {
      width: accPct + "%"
    }
  }))), speedPct !== null && /*#__PURE__*/React.createElement("div", {
    className: "meter meter-speed"
  }, /*#__PURE__*/React.createElement("div", {
    className: "meter-lbl"
  }, /*#__PURE__*/React.createElement("span", null, "\u05E7\u05E6\u05D1"), /*#__PURE__*/React.createElement("span", {
    className: "v"
  }, speedLabel, " \xB7 ", fmtSecs(cat.avgTime))), /*#__PURE__*/React.createElement("div", {
    className: "meter-track"
  }, /*#__PURE__*/React.createElement("div", {
    className: "meter-fill",
    style: {
      width: speedPct + "%"
    }
  })))));
}
function Analysis({
  attempts
}) {
  const data = useMemo(() => analyzeAttempts(attempts), [attempts]);
  if (!data) return null;
  const {
    strong,
    slowStrong,
    weak,
    headline,
    median
  } = data;
  if (!strong.length && !slowStrong.length && !weak.length) return null;
  // "Strong" zone combines perfect-fast + perfect-slow — the slow ones get a
  // visual divider so the user can still see they're a separate sub-group.
  const strongCount = strong.length + slowStrong.length;
  return /*#__PURE__*/React.createElement("div", {
    className: "rg-analysis"
  }, /*#__PURE__*/React.createElement("div", {
    className: "rg-analysis-head"
  }, /*#__PURE__*/React.createElement("div", {
    className: "rg-analysis-brand"
  }, /*#__PURE__*/React.createElement("img", {
    src: "../assets/ez-icon.png",
    alt: ""
  }), /*#__PURE__*/React.createElement("span", {
    className: "brand-eazy"
  }, "eazy")), /*#__PURE__*/React.createElement("div", {
    className: "rg-analysis-eye"
  }, "\u05E0\u05D9\u05EA\u05D5\u05D7 \u05D4\u05DE\u05E9\u05D7\u05E7"), /*#__PURE__*/React.createElement("h2", {
    className: "rg-analysis-title"
  }, "\u05D4\u05E0\u05D9\u05EA\u05D5\u05D7 \u05E9\u05DC\u05D9", /*#__PURE__*/React.createElement("span", {
    className: "dot"
  }, ".")), /*#__PURE__*/React.createElement("div", {
    className: "rg-analysis-headline"
  }, headline), /*#__PURE__*/React.createElement("div", {
    className: "rg-analysis-sub"
  }, "\u05D0\u05D9\u05E4\u05D4 \u05D7\u05D6\u05E7, \u05D0\u05D9\u05E4\u05D4 \u05DC\u05D7\u05D6\u05E7, \u05D5\u05D0\u05D9\u05E4\u05D4 \u05E8\u05E7 \u05DC\u05D6\u05E8\u05D6 \u05D0\u05EA \u05D4\u05E7\u05E6\u05D1.")), /*#__PURE__*/React.createElement("div", {
    className: "rg-analysis-zones"
  }, strongCount > 0 && /*#__PURE__*/React.createElement("div", {
    className: "rg-analysis-zone zone-strong"
  }, /*#__PURE__*/React.createElement("div", {
    className: "zone-head"
  }, /*#__PURE__*/React.createElement("div", {
    className: "zone-icon"
  }, LU_ICONS.strong), /*#__PURE__*/React.createElement("div", {
    className: "zone-text"
  }, /*#__PURE__*/React.createElement("div", {
    className: "zone-cap"
  }, "\u05EA\u05D7\u05D5\u05DE\u05D9\u05DD \u05D7\u05D6\u05E7\u05D9\u05DD", /*#__PURE__*/React.createElement("span", {
    className: "dot"
  }, ".")), /*#__PURE__*/React.createElement("div", {
    className: "zone-sub"
  }, strongCount, " \u05E7\u05D8\u05D2\u05D5\u05E8\u05D9\u05D5\u05EA \u05E2\u05DD 100% \u05D3\u05D9\u05D5\u05E7")), /*#__PURE__*/React.createElement("div", {
    className: "zone-count"
  }, strongCount)), /*#__PURE__*/React.createElement("div", {
    className: "zone-list"
  }, strong.map(c => /*#__PURE__*/React.createElement(AnalysisCatRow, {
    key: c.name,
    cat: c,
    mode: "strong",
    median: median
  })), slowStrong.length > 0 && /*#__PURE__*/React.createElement(React.Fragment, null, /*#__PURE__*/React.createElement("div", {
    className: "zone-divider"
  }, /*#__PURE__*/React.createElement("span", {
    className: "divider-line"
  }), /*#__PURE__*/React.createElement("span", {
    className: "divider-text"
  }, "\u05E6\u05E8\u05D9\u05DA \u05E8\u05E7 \u05DC\u05D6\u05E8\u05D6 \u05D0\u05EA \u05D4\u05E7\u05E6\u05D1", /*#__PURE__*/React.createElement("span", {
    className: "dot"
  }, ".")), /*#__PURE__*/React.createElement("span", {
    className: "divider-line"
  })), slowStrong.map(c => /*#__PURE__*/React.createElement(AnalysisCatRow, {
    key: c.name,
    cat: c,
    mode: "slow",
    median: median
  }))))), weak.length > 0 && /*#__PURE__*/React.createElement("div", {
    className: "rg-analysis-zone zone-weak"
  }, /*#__PURE__*/React.createElement("div", {
    className: "zone-head"
  }, /*#__PURE__*/React.createElement("div", {
    className: "zone-icon"
  }, LU_ICONS.weak), /*#__PURE__*/React.createElement("div", {
    className: "zone-text"
  }, /*#__PURE__*/React.createElement("div", {
    className: "zone-cap"
  }, "\u05EA\u05D7\u05D5\u05DE\u05D9\u05DD \u05DC\u05D7\u05D9\u05D6\u05D5\u05E7", /*#__PURE__*/React.createElement("span", {
    className: "dot"
  }, ".")), /*#__PURE__*/React.createElement("div", {
    className: "zone-sub"
  }, weak.length, " \u05E7\u05D8\u05D2\u05D5\u05E8\u05D9\u05D5\u05EA \u05E2\u05DD \u05E9\u05D2\u05D9\u05D0\u05D5\u05EA")), /*#__PURE__*/React.createElement("div", {
    className: "zone-count"
  }, weak.length)), /*#__PURE__*/React.createElement("div", {
    className: "zone-list"
  }, weak.map(c => /*#__PURE__*/React.createElement(AnalysisCatRow, {
    key: c.name,
    cat: c,
    mode: "weak",
    median: median
  }))))));
}

/* Expose for end-screen smoke tests + dev preview. */
window.__Analysis = Analysis;
function EndScreen({
  reached,
  correct,
  total,
  score,
  missed,
  attempts,
  levels,
  onRestart,
  won
}) {
  const reachedLv = levels[Math.max(0, Math.min(levels.length - 1, reached - 1))];

  // Leaderboard state — same pattern as quiz-game.
  const [submitted, setSubmitted] = useState(false);
  const [name, setName] = useState("");
  const [board, setBoard] = useState(() => getLeaderboard());
  const [showLb, setShowLb] = useState(false);
  const [showMistakes, setShowMistakes] = useState(false);
  const qualifies = qualifiesForLeaderboard(score) && !submitted;
  const submitName = () => {
    const newBoard = addToLeaderboard(name.trim() || "אנונימי", score, reached);
    setBoard(newBoard);
    setSubmitted(true);
    setShowLb(true);
  };
  return /*#__PURE__*/React.createElement("div", {
    className: "rg-end"
  }, /*#__PURE__*/React.createElement("div", {
    className: "rg-end-hud"
  }, /*#__PURE__*/React.createElement("div", {
    className: "rg-hud-brand"
  }, /*#__PURE__*/React.createElement("img", {
    src: "../assets/ez-icon.png",
    alt: ""
  }), /*#__PURE__*/React.createElement("span", {
    className: "brand-eazy"
  }, "eazy")), /*#__PURE__*/React.createElement("div", {
    className: "rg-hud-stage"
  }, /*#__PURE__*/React.createElement("span", {
    className: "rg-hud-eye"
  }, won ? "פשוט הצלחתם" : "סוף הסיבוב"), /*#__PURE__*/React.createElement("span", {
    className: "rg-hud-name"
  }, "\u05DE\u05E1\u05DA \u05E1\u05D9\u05DB\u05D5\u05DD", /*#__PURE__*/React.createElement("span", {
    style: {
      color: "var(--ez-orange)"
    }
  }, "."))), missed && missed.length > 0 ? /*#__PURE__*/React.createElement("button", {
    className: "rg-end-hud-mistakes",
    onClick: () => setShowMistakes(true),
    type: "button"
  }, /*#__PURE__*/React.createElement("svg", {
    viewBox: "0 0 24 24",
    width: "18",
    height: "18",
    fill: "none",
    stroke: "currentColor",
    strokeWidth: "2.2",
    strokeLinecap: "round",
    strokeLinejoin: "round",
    "aria-hidden": true
  }, /*#__PURE__*/React.createElement("circle", {
    cx: "12",
    cy: "12",
    r: "9"
  }), /*#__PURE__*/React.createElement("path", {
    d: "M12 7v6"
  }), /*#__PURE__*/React.createElement("circle", {
    cx: "12",
    cy: "16.5",
    r: ".4",
    fill: "currentColor",
    stroke: "none"
  })), /*#__PURE__*/React.createElement("span", {
    className: "lbl"
  }, "\u05D0\u05D9\u05E4\u05D4 \u05D8\u05E2\u05D9\u05EA\u05D9"), /*#__PURE__*/React.createElement("span", {
    className: "badge"
  }, missed.length)) : /*#__PURE__*/React.createElement("span", {
    className: "rg-end-hud-spacer",
    "aria-hidden": true
  })), /*#__PURE__*/React.createElement("div", {
    className: "rg-end-body"
  }, /*#__PURE__*/React.createElement("div", {
    className: "rg-summary-hero"
  }, /*#__PURE__*/React.createElement("div", {
    className: "rg-summary-hero-avatar"
  }, /*#__PURE__*/React.createElement(reachedLv.Avatar, null)), /*#__PURE__*/React.createElement("div", {
    className: "rg-summary-hero-titles"
  }, /*#__PURE__*/React.createElement("span", {
    className: "rg-summary-eye"
  }, won ? "פשוט הצלחתם" : "סוף הסיבוב"), /*#__PURE__*/React.createElement("h1", {
    className: "rg-summary-title"
  }, won ? "הגעתם לפסגה" : "טוב, נסו שוב", /*#__PURE__*/React.createElement("span", {
    style: {
      color: "var(--ez-orange)"
    }
  }, won ? "!" : ".")), /*#__PURE__*/React.createElement("div", {
    className: "rg-summary-sub"
  }, "\u05E2\u05E6\u05E8\u05EA\u05DD \u05D1\u05E9\u05DC\u05D1 ", /*#__PURE__*/React.createElement("b", {
    style: {
      color: "var(--ez-lavender-deep)"
    }
  }, reachedLv.name), ".", " ", won ? "מגיעים לציון 800. בראבו!" : "טעות אחת לא מגדירה אתכם.")), /*#__PURE__*/React.createElement("div", {
    className: "rg-summary-score" + (won ? " won" : "")
  }, /*#__PURE__*/React.createElement("span", {
    className: "lbl"
  }, "\u05E6\u05D9\u05D5\u05DF \u05DE\u05E9\u05D5\u05E2\u05E8"), /*#__PURE__*/React.createElement("span", {
    className: "num"
  }, score), /*#__PURE__*/React.createElement("span", {
    className: "of"
  }, "/ 800"))), /*#__PURE__*/React.createElement("div", {
    className: "rg-end-stats"
  }, /*#__PURE__*/React.createElement("div", {
    className: "rg-end-stat"
  }, /*#__PURE__*/React.createElement("span", {
    className: "num"
  }, reached), /*#__PURE__*/React.createElement("span", {
    className: "lbl"
  }, "\u05E9\u05DC\u05D1")), /*#__PURE__*/React.createElement("div", {
    className: "rg-end-stat"
  }, /*#__PURE__*/React.createElement("span", {
    className: "num"
  }, correct), /*#__PURE__*/React.createElement("span", {
    className: "lbl"
  }, "\u05EA\u05E9\u05D5\u05D1\u05D5\u05EA \u05E0\u05DB\u05D5\u05E0\u05D5\u05EA")), /*#__PURE__*/React.createElement("div", {
    className: "rg-end-stat"
  }, /*#__PURE__*/React.createElement("span", {
    className: "num"
  }, total), /*#__PURE__*/React.createElement("span", {
    className: "lbl"
  }, "\u05E1\u05D4\u05F4\u05DB \u05E9\u05D0\u05DC\u05D5\u05EA"))), /*#__PURE__*/React.createElement(Analysis, {
    attempts: attempts
  }), /*#__PURE__*/React.createElement("div", {
    className: "rg-summary-actions"
  }, qualifies ? /*#__PURE__*/React.createElement("div", {
    className: "rg-lb-prompt"
  }, /*#__PURE__*/React.createElement("div", {
    className: "rg-lb-prompt-eye"
  }, /*#__PURE__*/React.createElement(TrophySVG, null), " \u05E0\u05DB\u05E0\u05E1\u05EA\u05DD \u05DC\u05D8\u05D1\u05DC\u05EA \u05D4\u05E9\u05D9\u05D0\u05D9\u05DD!"), /*#__PURE__*/React.createElement("div", {
    className: "rg-lb-prompt-row"
  }, /*#__PURE__*/React.createElement("input", {
    className: "rg-lb-input",
    type: "text",
    placeholder: "\u05D4\u05E9\u05DD \u05E9\u05DC\u05DB\u05DD",
    value: name,
    onChange: e => setName(e.target.value),
    onKeyDown: e => e.key === "Enter" && submitName(),
    maxLength: 20,
    autoFocus: true
  }), /*#__PURE__*/React.createElement("button", {
    className: "rg-lb-save",
    onClick: submitName
  }, "\u05E9\u05DE\u05D9\u05E8\u05D4"))) : /*#__PURE__*/React.createElement("button", {
    className: "rg-lb-open",
    onClick: () => setShowLb(true)
  }, /*#__PURE__*/React.createElement(TrophySVG, null), /*#__PURE__*/React.createElement("span", null, "\u05D8\u05D1\u05DC\u05EA \u05D4\u05E9\u05D9\u05D0\u05D9\u05DD")), /*#__PURE__*/React.createElement("button", {
    className: "rg-gameover-btn",
    onClick: onRestart
  }, "\u05E0\u05E1\u05D5 \u05E9\u05D5\u05D1", /*#__PURE__*/React.createElement("span", {
    className: "cta-arrow",
    "aria-hidden": true
  }, " \u203A")))), showMistakes && missed && missed.length > 0 && /*#__PURE__*/React.createElement("div", {
    className: "rg-mistakes-modal",
    onClick: () => setShowMistakes(false)
  }, /*#__PURE__*/React.createElement("div", {
    className: "rg-mistakes-card",
    onClick: e => e.stopPropagation()
  }, /*#__PURE__*/React.createElement("div", {
    className: "rg-mistakes-hud"
  }, /*#__PURE__*/React.createElement("div", {
    className: "rg-hud-brand"
  }, /*#__PURE__*/React.createElement("img", {
    src: "../assets/ez-icon.png",
    alt: ""
  }), /*#__PURE__*/React.createElement("span", {
    className: "brand-eazy"
  }, "eazy")), /*#__PURE__*/React.createElement("div", {
    className: "rg-hud-stage"
  }, /*#__PURE__*/React.createElement("span", {
    className: "rg-hud-eye"
  }, "\u05DC\u05D0 \u05D0\u05E4\u05D5\u05DC \u05E9\u05D5\u05D1"), /*#__PURE__*/React.createElement("span", {
    className: "rg-hud-name"
  }, "\u05D4\u05E9\u05D2\u05D9\u05D0\u05D5\u05EA \u05E9\u05DC\u05D9", /*#__PURE__*/React.createElement("span", {
    style: {
      color: "var(--ez-orange)"
    }
  }, "."))), /*#__PURE__*/React.createElement("button", {
    className: "rg-mistakes-close-btn",
    onClick: () => setShowMistakes(false),
    "aria-label": "\u05E1\u05D2\u05D5\u05E8",
    type: "button"
  }, /*#__PURE__*/React.createElement("svg", {
    viewBox: "0 0 24 24",
    width: "18",
    height: "18",
    fill: "none",
    stroke: "currentColor",
    strokeWidth: "2.4",
    strokeLinecap: "round",
    "aria-hidden": true
  }, /*#__PURE__*/React.createElement("path", {
    d: "M6 6 L18 18 M18 6 L6 18"
  })))), /*#__PURE__*/React.createElement("div", {
    className: "rg-mistakes-list"
  }, missed.map((m, i) => /*#__PURE__*/React.createElement("div", {
    key: i,
    className: "rg-mistakes-row"
  }, /*#__PURE__*/React.createElement("div", {
    className: "rg-mistakes-cat"
  }, m.category), /*#__PURE__*/React.createElement("div", {
    className: "rg-mistakes-q" + (m.ltr ? " ltr" : "")
  }, m.prompt), /*#__PURE__*/React.createElement("div", {
    className: "rg-mistakes-answers"
  }, m.timedOut ? /*#__PURE__*/React.createElement("div", {
    className: "rg-mistakes-chosen timeout"
  }, /*#__PURE__*/React.createElement("span", {
    className: "label"
  }, "\u05EA\u05E9\u05D5\u05D1\u05EA\u05D9:"), /*#__PURE__*/React.createElement("span", {
    className: "val"
  }, "\u05E0\u05D2\u05DE\u05E8 \u05D4\u05D6\u05DE\u05DF")) : /*#__PURE__*/React.createElement("div", {
    className: "rg-mistakes-chosen"
  }, /*#__PURE__*/React.createElement("span", {
    className: "label"
  }, "\u05EA\u05E9\u05D5\u05D1\u05EA\u05D9:"), /*#__PURE__*/React.createElement("span", {
    className: "val" + (m.ltr ? " ltr" : "")
  }, m.chosen)), /*#__PURE__*/React.createElement("div", {
    className: "rg-mistakes-correct"
  }, /*#__PURE__*/React.createElement("span", {
    className: "label"
  }, "\u05D4\u05EA\u05E9\u05D5\u05D1\u05D4 \u05D4\u05E0\u05DB\u05D5\u05E0\u05D4:"), /*#__PURE__*/React.createElement("span", {
    className: "val" + (m.ltr ? " ltr" : "")
  }, m.correct)))))))), showLb && /*#__PURE__*/React.createElement("div", {
    className: "rg-lb-modal",
    onClick: () => setShowLb(false)
  }, /*#__PURE__*/React.createElement("div", {
    className: "rg-lb-card",
    onClick: e => e.stopPropagation()
  }, /*#__PURE__*/React.createElement("button", {
    className: "rg-lb-close",
    onClick: () => setShowLb(false),
    "aria-label": "\u05E1\u05D2\u05D5\u05E8"
  }, "\xD7"), /*#__PURE__*/React.createElement("div", {
    className: "rg-lb-title"
  }, /*#__PURE__*/React.createElement(TrophySVG, null), /*#__PURE__*/React.createElement("span", null, "\u05D8\u05D1\u05DC\u05EA \u05D4\u05E9\u05D9\u05D0\u05D9\u05DD")), board.length === 0 ? /*#__PURE__*/React.createElement("div", {
    className: "rg-lb-empty"
  }, "\u05E2\u05D3\u05D9\u05D9\u05DF \u05D0\u05D9\u05DF \u05E9\u05D9\u05D0\u05D9\u05DD. \u05D0\u05EA\u05DD \u05D9\u05DB\u05D5\u05DC\u05D9\u05DD \u05DC\u05D4\u05D9\u05D5\u05EA \u05D4\u05E8\u05D0\u05E9\u05D5\u05E0\u05D9\u05DD.") : /*#__PURE__*/React.createElement("ol", {
    className: "rg-lb-list"
  }, board.map((entry, i) => {
    const isYou = submitted && entry.score === score && entry.name === (name.trim() || "אנונימי");
    return /*#__PURE__*/React.createElement("li", {
      key: i,
      className: "rg-lb-row " + (isYou ? "you" : "")
    }, /*#__PURE__*/React.createElement("span", {
      className: "rank"
    }, i + 1), /*#__PURE__*/React.createElement("span", {
      className: "name"
    }, entry.name), /*#__PURE__*/React.createElement("span", {
      className: "lvl"
    }, "\u05E9\u05DC\u05D1 ", entry.reached || "—"), /*#__PURE__*/React.createElement("span", {
      className: "pts"
    }, entry.score));
  })))));
}

/* ── Main Game ────────────────────────────────────────────────── */
function RoleGame() {
  const [t, setTweak] = useTweaks(TWEAK_DEFAULTS);
  const levels = ROLE_LEVELS;
  const [phase, setPhase] = useState("intro"); // intro | play | levelup | end
  const [levelIdx, setLevelIdx] = useState(0); // 0..11
  const [lives, setLives] = useState(3);
  const [streak, setStreak] = useState(0); // correct-in-current-level
  const [question, setQuestion] = useState(null);
  const [chosenIdx, setChosenIdx] = useState(null);
  const [feedback, setFeedback] = useState(null); // {kind:"good"|"bad", text}
  const [flash, setFlash] = useState(false);
  const [recent, setRecent] = useState([]);

  /* stats */
  const [totalAsked, setTotalAsked] = useState(0);
  const [totalCorrect, setTotalCorrect] = useState(0);
  /* List of missed questions — used by the end screen to show the
     player what they got wrong (with the correct answer next to each).
     Pattern mirrors the quiz-game's "missed words" feature. */
  const [missed, setMissed] = useState([]);

  /* Per-attempt log used by the end-screen analysis. Every answered
     question — right OR wrong — lands here so we can compute per-category
     accuracy AND per-category answer time at the end of the game.
     `missed` (above) stays derivable from this for the existing modal. */
  const [attempts, setAttempts] = useState([]);

  /* Wall-clock when the current question first became visible. Used to
     compute time-to-answer per question. Reset on every drawNext + on
     every play-phase entry. */
  const qStartTimeRef = useRef(0);

  /* timer */
  const [timeLeft, setTimeLeft] = useState(t.timerSecs);
  const tickRef = useRef(null);

  /* derived */
  const level = levels[levelIdx];
  const totalQuestions = levels.length * t.toLevelUp;
  const correctSoFar = Math.min(totalQuestions, levelIdx * t.toLevelUp + streak);
  const scoreNow = Math.round((200 + 600 * (correctSoFar / totalQuestions)) / 10) * 10;

  /* ---- start a fresh question on every play-state transition ---- */
  const drawNext = useCallback(() => {
    const q = pickQuestion(level.id, recent);
    if (!q) return;
    setQuestion({
      ...q,
      // shuffle option order so the correct index is not always the same
      shuffledOptions: shuffleOptions(q)
    });
    setChosenIdx(null);
    setFeedback(null);
    setTimeLeft(t.timerSecs);
    setRecent(r => [{
      id: q.id,
      category: q.category
    }, ...r].slice(0, 6));
    qStartTimeRef.current = Date.now();
  }, [level, recent, t.timerSecs]);
  function shuffleOptions(q) {
    const idxs = q.options.map((_, i) => i);
    const order = shuffle(idxs);
    return order.map(i => ({
      text: q.options[i],
      origIdx: i
    }));
  }

  /* ---- countdown ---- */
  useEffect(() => {
    if (phase !== "play") return;
    if (chosenIdx !== null || feedback) return; // pause after answer
    if (timeLeft <= 0) {
      handleTimeout();
      return;
    }
    tickRef.current = setTimeout(() => setTimeLeft(s => s - 1), 1000);
    return () => clearTimeout(tickRef.current);
  }, [phase, timeLeft, chosenIdx, feedback]);

  /* ---- start a level ---- */
  useEffect(() => {
    if (phase === "play" && question === null) drawNext();
  }, [phase, question, drawNext]);

  /* ---- answer handlers ---- */
  function handleAnswer(opt) {
    if (chosenIdx !== null || feedback) return;
    setChosenIdx(opt.origIdx);
    setTotalAsked(n => n + 1);
    const isCorrect = opt.origIdx === question.correct;
    const elapsedMs = Math.max(0, Date.now() - qStartTimeRef.current);
    // Record this attempt for end-screen analysis. We capture EVERY answer,
    // not just wrong ones, so we can compute per-category strength + speed.
    setAttempts(a => [...a, {
      id: question.id,
      prompt: question.prompt,
      category: question.category,
      kind: question.kind,
      ltr: !!question.ltr,
      correct: isCorrect,
      timedOut: false,
      timeMs: elapsedMs,
      correctAnswer: question.options[question.correct],
      chosen: question.options[opt.origIdx]
    }]);
    if (isCorrect) {
      setTotalCorrect(n => n + 1);
      setFeedback({
        kind: "good",
        text: pick(PRAISE)
      });
      const next = streak + 1;
      setStreak(next);
      if (next >= t.toLevelUp) {
        setTimeout(() => {
          if (levelIdx >= levels.length - 1) {
            setPhase("end");
          } else {
            setPhase("levelup");
          }
        }, 900);
      } else {
        setTimeout(() => {
          setQuestion(null); /* triggers drawNext */
        }, 900);
      }
    } else {
      // Wrong answer — record it for the end-screen review.
      setMissed(m => [...m, {
        prompt: question.prompt,
        category: question.category,
        kind: question.kind,
        ltr: !!question.ltr,
        correct: question.options[question.correct],
        chosen: question.options[opt.origIdx],
        timedOut: false
      }]);
      loseLife("bad", pick(PUSH));
    }
  }
  function handleTimeout() {
    if (chosenIdx !== null || feedback) return;
    setChosenIdx(-2); // sentinel — show correct
    setTotalAsked(n => n + 1);
    const elapsedMs = Math.max(0, Date.now() - qStartTimeRef.current);
    // Timeout — record as a missed question with no chosen answer.
    setAttempts(a => [...a, {
      id: question.id,
      prompt: question.prompt,
      category: question.category,
      kind: question.kind,
      ltr: !!question.ltr,
      correct: false,
      timedOut: true,
      timeMs: elapsedMs,
      correctAnswer: question.options[question.correct],
      chosen: null
    }]);
    setMissed(m => [...m, {
      prompt: question.prompt,
      category: question.category,
      kind: question.kind,
      ltr: !!question.ltr,
      correct: question.options[question.correct],
      chosen: null,
      timedOut: true
    }]);
    loseLife("bad", "נגמר הזמן. ממשיכים.");
  }
  function loseLife(kind, text) {
    setFeedback({
      kind,
      text
    });
    setFlash(true);
    setTimeout(() => setFlash(false), 450);
    const newLives = lives - 1;
    setLives(newLives);
    setTimeout(() => {
      if (newLives <= 0) {
        setPhase("end");
      } else {
        setQuestion(null); // draw next
      }
    }, 1300);
  }

  /* ---- level up continue ---- */
  function continueAfterLevelUp() {
    const nextIdx = levelIdx + 1;
    if (nextIdx >= levels.length) {
      setPhase("end");
      return;
    }
    setLevelIdx(nextIdx);
    setStreak(0);
    setQuestion(null);
    setPhase("play");
  }
  const [muted, setMuted] = useState(false);
  const bgMusicRef = useRef(null);

  /* 50/50 lifeline — one use per game. When fired we randomly hide
     two of the three wrong distractors on the current question only;
     the hidden set is reset for every new question, but the lifeline
     itself does not refresh — it's a once-per-round budget. */
  const [fiftyAvailable, setFiftyAvailable] = useState(true);
  const [hiddenIdx, setHiddenIdx] = useState(() => new Set());
  /* Reset the hidden distractors whenever a new question shows up. */
  useEffect(() => {
    setHiddenIdx(new Set());
  }, [question]);
  const useFifty = useCallback(() => {
    if (!fiftyAvailable || !question) return;
    const wrongs = question.shuffledOptions.map(opt => opt.origIdx).filter(i => i !== question.correct);
    // pick 2 random wrong indices to hide
    const shuffled = [...wrongs].sort(() => Math.random() - 0.5).slice(0, 2);
    setHiddenIdx(new Set(shuffled));
    setFiftyAvailable(false);
  }, [fiftyAvailable, question]);

  /* ---- start / restart ---- */
  function startGame() {
    // First user gesture — request fullscreen so the game fills the
    // viewport on phones (browsers require a gesture to grant FS).
    try {
      const el = document.documentElement;
      const req = el.requestFullscreen || el.webkitRequestFullscreen || el.msRequestFullscreen;
      if (req && !document.fullscreenElement && !document.webkitFullscreenElement) {
        const p = req.call(el);
        if (p && typeof p.catch === "function") p.catch(() => {});
      }
    } catch (e) {}
    // Try to kick off bg music too (same gesture unlocks audio).
    try {
      const a = bgMusicRef.current;
      if (a && !muted) {
        a.volume = 0.45;
        a.play().catch(() => {});
      }
    } catch (e) {}
    setLevelIdx(0);
    setLives(3);
    setStreak(0);
    setTotalAsked(0);
    setTotalCorrect(0);
    setMissed([]);
    setAttempts([]);
    setQuestion(null);
    setRecent([]);
    setFeedback(null);
    setChosenIdx(null);
    setFiftyAvailable(true);
    setHiddenIdx(new Set());
    setPhase("play");
  }

  /* ---- audio mute reactor — pause/resume the bg music whenever the
         mute toggle changes. */
  useEffect(() => {
    const a = bgMusicRef.current;
    if (!a) return;
    if (muted) {
      a.pause();
    } else if (phase !== "intro") {
      a.volume = 0.45;
      a.play().catch(() => {});
    }
  }, [muted, phase]);

  /* ---- options render ---- */
  const renderOptions = () => {
    if (!question) return null;
    return question.shuffledOptions.map((opt, i) => {
      let cls = "rg-opt";
      if (question.ltr) cls += " ltr";
      // 50/50 lifeline — fade-and-disable the two distractors selected
      // for hiding. We don't remove them from the DOM so the grid layout
      // stays stable.
      const isHidden = hiddenIdx.has(opt.origIdx);
      if (isHidden) cls += " hidden5050 disabled";
      const answered = chosenIdx !== null || feedback;
      if (answered) {
        if (opt.origIdx === question.correct) cls += " correct";else if (opt.origIdx === chosenIdx) cls += " wrong";else cls += " disabled";
      }
      const letter = ["1", "2", "3", "4"][i];
      return /*#__PURE__*/React.createElement("button", {
        key: i,
        className: cls,
        onClick: () => handleAnswer(opt)
      }, /*#__PURE__*/React.createElement("span", {
        className: "rg-opt-mark"
      }, letter), /*#__PURE__*/React.createElement("span", null, opt.text));
    });
  };

  /* ---- HUD pieces ---- */
  const Hearts = () => /*#__PURE__*/React.createElement("div", {
    className: "rg-hud-lives"
  }, [0, 1, 2].map(i => /*#__PURE__*/React.createElement("div", {
    key: i,
    className: "rg-heart" + (i >= lives ? " lost" : "")
  }, /*#__PURE__*/React.createElement(HeartSVG, {
    lost: i >= lives
  }))));
  const Progress = () => /*#__PURE__*/React.createElement("div", {
    className: "rg-progress"
  }, Array.from({
    length: t.toLevelUp
  }).map((_, i) => {
    const cls = i < streak ? "done" : i === streak ? "now" : "";
    return /*#__PURE__*/React.createElement("div", {
      key: i,
      className: "rg-progress-dot " + cls
    });
  }));

  /* ---- screen switch ---- */
  return /*#__PURE__*/React.createElement("div", {
    className: "rg-app" + (phase !== "intro" && phase !== "end" && t.showScoreScale ? " has-scale" : "")
  }, /*#__PURE__*/React.createElement("audio", {
    ref: bgMusicRef,
    src: "bg-music.mp3",
    loop: true,
    preload: "auto"
  }), /*#__PURE__*/React.createElement(FootBar, {
    muted: muted,
    onToggleMute: () => setMuted(m => !m),
    fifty: phase === "play" ? {
      available: fiftyAvailable,
      onUse: useFifty
    } : null
  }), /*#__PURE__*/React.createElement("div", {
    className: "rg-bg-z",
    "aria-hidden": true
  }, /*#__PURE__*/React.createElement("div", {
    className: "slash",
    style: {
      top: "-30px",
      right: "-8%",
      width: "62%",
      background: "var(--ez-lavender-soft)"
    }
  }), /*#__PURE__*/React.createElement("div", {
    className: "slash",
    style: {
      top: "55px",
      right: "18%",
      width: "68%",
      background: "var(--ez-lavender)",
      opacity: .35
    }
  }), /*#__PURE__*/React.createElement("div", {
    className: "slash",
    style: {
      bottom: "120px",
      right: "-8%",
      width: "78%",
      background: "var(--ez-lavender-soft)"
    }
  }), /*#__PURE__*/React.createElement("div", {
    className: "slash",
    style: {
      bottom: "60px",
      right: "30%",
      width: "60%",
      background: "var(--ez-lavender)",
      opacity: .25
    }
  })), phase === "intro" && /*#__PURE__*/React.createElement(Intro, {
    onStart: startGame,
    levels: levels
  }), phase !== "intro" && phase !== "end" && /*#__PURE__*/React.createElement(React.Fragment, null, /*#__PURE__*/React.createElement("div", {
    className: "rg-hud"
  }, /*#__PURE__*/React.createElement("div", {
    className: "rg-hud-brand"
  }, /*#__PURE__*/React.createElement("img", {
    src: "../assets/ez-icon.png",
    alt: ""
  }), /*#__PURE__*/React.createElement("span", {
    className: "brand-eazy"
  }, "eazy")), /*#__PURE__*/React.createElement("div", {
    className: "rg-hud-stage"
  }, /*#__PURE__*/React.createElement("span", {
    className: "rg-hud-eye"
  }, level.eyebrow), /*#__PURE__*/React.createElement("span", {
    className: "rg-hud-name"
  }, level.name, /*#__PURE__*/React.createElement("span", {
    style: {
      color: "var(--ez-orange)"
    }
  }, "."))), /*#__PURE__*/React.createElement(Hearts, null)), /*#__PURE__*/React.createElement(Progress, null)), phase === "play" && question && /*#__PURE__*/React.createElement(React.Fragment, null, /*#__PURE__*/React.createElement("div", {
    className: "rg-play"
  }, /*#__PURE__*/React.createElement("div", {
    className: "rg-avatar-wrap"
  }, /*#__PURE__*/React.createElement(level.Avatar, null), /*#__PURE__*/React.createElement("div", {
    className: "rg-avatar-name"
  }, level.name, /*#__PURE__*/React.createElement("span", {
    className: "dot"
  }, ".")), t.showTimer && /*#__PURE__*/React.createElement("div", {
    className: "rg-avatar-timer"
  }, /*#__PURE__*/React.createElement(TimerRing, {
    seconds: timeLeft,
    total: t.timerSecs
  }))), /*#__PURE__*/React.createElement("div", {
    className: "rg-q"
  }, /*#__PURE__*/React.createElement("div", {
    className: "rg-q-head"
  }, /*#__PURE__*/React.createElement("span", {
    className: "rg-q-kind k-" + question.kind
  }, question.category || (question.kind === "V" ? "מילולי" : question.kind === "Q" ? "כמותי" : "אנגלית")), t.showHints && /*#__PURE__*/React.createElement("span", {
    style: {
      fontFamily: "var(--font-mono)",
      fontSize: 12,
      color: "var(--ez-ink-mute)"
    }
  }, streak, "/", t.toLevelUp, " \u05E0\u05DB\u05D5\u05E0\u05D5\u05EA \u05DC\u05E2\u05DC\u05D9\u05D9\u05D4")), /*#__PURE__*/React.createElement("div", {
    className: "rg-q-prompt" + (question.ltr ? " ltr" : "")
  }, question.prompt), /*#__PURE__*/React.createElement("div", {
    className: "rg-options"
  }, renderOptions()), feedback && /*#__PURE__*/React.createElement("div", {
    className: "rg-feedback " + feedback.kind
  }, /*#__PURE__*/React.createElement("span", null, feedback.text)))), /*#__PURE__*/React.createElement("div", {
    className: "rg-play-stats",
    "aria-hidden": true
  }, /*#__PURE__*/React.createElement("div", {
    className: "rg-play-stat"
  }, /*#__PURE__*/React.createElement("span", {
    className: "lbl"
  }, "\u05E1\u05D5\u05D2 \u05D4\u05E9\u05D0\u05DC\u05D4"), /*#__PURE__*/React.createElement("span", {
    className: "val k-" + question.kind
  }, question.category || (question.kind === "V" ? "מילולי" : question.kind === "Q" ? "כמותי" : "אנגלית"))), /*#__PURE__*/React.createElement("div", {
    className: "rg-play-stat"
  }, /*#__PURE__*/React.createElement("span", {
    className: "lbl"
  }, "\u05E6\u05D9\u05D5\u05DF \u05E0\u05D5\u05DB\u05D7\u05D9"), /*#__PURE__*/React.createElement("span", {
    className: "val num"
  }, scoreNow)), /*#__PURE__*/React.createElement("div", {
    className: "rg-play-stat"
  }, /*#__PURE__*/React.createElement("span", {
    className: "lbl"
  }, "\u05E9\u05DC\u05D1 \u05E0\u05D5\u05DB\u05D7\u05D9"), /*#__PURE__*/React.createElement("span", {
    className: "val num"
  }, String(levelIdx + 1).padStart(2, "0"), /*#__PURE__*/React.createElement("span", {
    className: "of"
  }, "/", levels.length))), /*#__PURE__*/React.createElement("div", {
    className: "rg-play-stat"
  }, /*#__PURE__*/React.createElement("span", {
    className: "lbl"
  }, "\u05E9\u05DD \u05D4\u05E8\u05DE\u05D4"), /*#__PURE__*/React.createElement("span", {
    className: "val"
  }, level.name, /*#__PURE__*/React.createElement("span", {
    className: "dot"
  }, ".")))), flash && /*#__PURE__*/React.createElement("div", {
    className: "rg-flash"
  })), phase === "levelup" && /*#__PURE__*/React.createElement(LevelUpV2, {
    from: levels[levelIdx],
    to: levels[Math.min(levels.length - 1, levelIdx + 1)],
    forceVariant: t.celebration,
    onContinue: continueAfterLevelUp
  }), phase === "end" && /*#__PURE__*/React.createElement(EndScreen, {
    reached: levelIdx + 1,
    correct: totalCorrect,
    total: totalAsked,
    score: scoreNow,
    missed: missed,
    attempts: attempts,
    levels: levels,
    won: lives > 0 && levelIdx >= levels.length - 1,
    onRestart: startGame
  }), phase !== "intro" && phase !== "end" && t.showScoreScale && /*#__PURE__*/React.createElement(ScoreScale, {
    correctSoFar: correctSoFar,
    totalQuestions: totalQuestions,
    toLevelUp: t.toLevelUp,
    level: level
  }), /*#__PURE__*/React.createElement(TweaksPanel, {
    title: "Tweaks"
  }, /*#__PURE__*/React.createElement(TweakSection, {
    label: "\u05E4\u05E8\u05D9\u05E1\u05D4"
  }), /*#__PURE__*/React.createElement(TweakRadio, {
    label: "\u05E2\u05D9\u05E6\u05D5\u05D1 \u05E9\u05D0\u05DC\u05D4",
    value: t.layout,
    options: ["card", "plain"],
    onChange: v => setTweak("layout", v)
  }), /*#__PURE__*/React.createElement(TweakToggle, {
    label: "\u05D4\u05E8\u05D0\u05D4 \u05D8\u05D9\u05D9\u05DE\u05E8",
    value: t.showTimer,
    onChange: v => setTweak("showTimer", v)
  }), /*#__PURE__*/React.createElement(TweakToggle, {
    label: "\u05D4\u05E8\u05D0\u05D4 \u05DE\u05D3 \u05D4\u05EA\u05E7\u05D3\u05DE\u05D5\u05EA (X/3)",
    value: t.showHints,
    onChange: v => setTweak("showHints", v)
  }), /*#__PURE__*/React.createElement(TweakToggle, {
    label: "\u05D4\u05E8\u05D0\u05D4 \u05E1\u05E7\u05DC\u05EA \u05E6\u05D9\u05D5\u05DF (200\u2013800)",
    value: t.showScoreScale,
    onChange: v => setTweak("showScoreScale", v)
  }), /*#__PURE__*/React.createElement(TweakSection, {
    label: "\u05D7\u05D5\u05D5\u05D9\u05D9\u05EA \u05E2\u05DC\u05D9\u05D9\u05D4"
  }), /*#__PURE__*/React.createElement(TweakSelect, {
    label: "\u05E1\u05D2\u05E0\u05D5\u05DF \u05D7\u05D2\u05D9\u05D2\u05D4",
    value: t.celebration,
    options: [{
      value: "auto",
      label: "אוטומטי (לפי שלב)"
    }, {
      value: "title",
      label: "כותרת קולנועית"
    }, {
      value: "metamorph",
      label: "מטמורפוזה"
    }, {
      value: "diploma",
      label: "תעודה נגללת"
    }, {
      value: "sign",
      label: "שלט כביש"
    }, {
      value: "frontpage",
      label: "כותרת ראשית"
    }, {
      value: "stamp",
      label: "חותמת אישור"
    }],
    onChange: v => setTweak("celebration", v)
  }), /*#__PURE__*/React.createElement(TweakSection, {
    label: "\u05E7\u05E6\u05D1 \u05D4\u05DE\u05E9\u05D7\u05E7"
  }), /*#__PURE__*/React.createElement(TweakSlider, {
    label: "\u05E9\u05E0\u05D9\u05D5\u05EA \u05DC\u05E9\u05D0\u05DC\u05D4",
    value: t.timerSecs,
    min: 15,
    max: 120,
    step: 5,
    unit: "s",
    onChange: v => {
      setTweak("timerSecs", v);
      setTimeLeft(v);
    }
  }), /*#__PURE__*/React.createElement(TweakSlider, {
    label: "\u05E0\u05DB\u05D5\u05E0\u05D5\u05EA \u05DC\u05E2\u05DC\u05D9\u05D9\u05D4",
    value: t.toLevelUp,
    min: 2,
    max: 6,
    step: 1,
    onChange: v => setTweak("toLevelUp", v)
  })));
}
window.Game = RoleGame;
})(); } catch (e) { __ds_ns.__errors.push({ path: "role-game/RoleGame.jsx", error: String((e && e.message) || e) }); }

// role-game/ios-frame.jsx
try { (() => {
// iOS.jsx — Simplified iOS 26 (Liquid Glass) device frame
// Based on the iOS 26 UI Kit + Figma status bar spec. No assets, no deps.
// Exports: IOSDevice, IOSStatusBar, IOSNavBar, IOSGlassPill, IOSList, IOSListRow, IOSKeyboard

// ─────────────────────────────────────────────────────────────
// Status bar
// ─────────────────────────────────────────────────────────────
function IOSStatusBar({
  dark = false,
  time = '9:41'
}) {
  const c = dark ? '#fff' : '#000';
  return /*#__PURE__*/React.createElement("div", {
    style: {
      display: 'flex',
      gap: 154,
      alignItems: 'center',
      justifyContent: 'center',
      padding: '21px 24px 19px',
      boxSizing: 'border-box',
      position: 'relative',
      zIndex: 20,
      width: '100%'
    }
  }, /*#__PURE__*/React.createElement("div", {
    style: {
      flex: 1,
      height: 22,
      display: 'flex',
      alignItems: 'center',
      justifyContent: 'center',
      paddingTop: 1.5
    }
  }, /*#__PURE__*/React.createElement("span", {
    style: {
      fontFamily: '-apple-system, "SF Pro", system-ui',
      fontWeight: 590,
      fontSize: 17,
      lineHeight: '22px',
      color: c
    }
  }, time)), /*#__PURE__*/React.createElement("div", {
    style: {
      flex: 1,
      height: 22,
      display: 'flex',
      alignItems: 'center',
      justifyContent: 'center',
      gap: 7,
      paddingTop: 1,
      paddingRight: 1
    }
  }, /*#__PURE__*/React.createElement("svg", {
    width: "19",
    height: "12",
    viewBox: "0 0 19 12"
  }, /*#__PURE__*/React.createElement("rect", {
    x: "0",
    y: "7.5",
    width: "3.2",
    height: "4.5",
    rx: "0.7",
    fill: c
  }), /*#__PURE__*/React.createElement("rect", {
    x: "4.8",
    y: "5",
    width: "3.2",
    height: "7",
    rx: "0.7",
    fill: c
  }), /*#__PURE__*/React.createElement("rect", {
    x: "9.6",
    y: "2.5",
    width: "3.2",
    height: "9.5",
    rx: "0.7",
    fill: c
  }), /*#__PURE__*/React.createElement("rect", {
    x: "14.4",
    y: "0",
    width: "3.2",
    height: "12",
    rx: "0.7",
    fill: c
  })), /*#__PURE__*/React.createElement("svg", {
    width: "17",
    height: "12",
    viewBox: "0 0 17 12"
  }, /*#__PURE__*/React.createElement("path", {
    d: "M8.5 3.2C10.8 3.2 12.9 4.1 14.4 5.6L15.5 4.5C13.7 2.7 11.2 1.5 8.5 1.5C5.8 1.5 3.3 2.7 1.5 4.5L2.6 5.6C4.1 4.1 6.2 3.2 8.5 3.2Z",
    fill: c
  }), /*#__PURE__*/React.createElement("path", {
    d: "M8.5 6.8C9.9 6.8 11.1 7.3 12 8.2L13.1 7.1C11.8 5.9 10.2 5.1 8.5 5.1C6.8 5.1 5.2 5.9 3.9 7.1L5 8.2C5.9 7.3 7.1 6.8 8.5 6.8Z",
    fill: c
  }), /*#__PURE__*/React.createElement("circle", {
    cx: "8.5",
    cy: "10.5",
    r: "1.5",
    fill: c
  })), /*#__PURE__*/React.createElement("svg", {
    width: "27",
    height: "13",
    viewBox: "0 0 27 13"
  }, /*#__PURE__*/React.createElement("rect", {
    x: "0.5",
    y: "0.5",
    width: "23",
    height: "12",
    rx: "3.5",
    stroke: c,
    strokeOpacity: "0.35",
    fill: "none"
  }), /*#__PURE__*/React.createElement("rect", {
    x: "2",
    y: "2",
    width: "20",
    height: "9",
    rx: "2",
    fill: c
  }), /*#__PURE__*/React.createElement("path", {
    d: "M25 4.5V8.5C25.8 8.2 26.5 7.2 26.5 6.5C26.5 5.8 25.8 4.8 25 4.5Z",
    fill: c,
    fillOpacity: "0.4"
  }))));
}

// ─────────────────────────────────────────────────────────────
// Liquid glass pill — blur + tint + shine
// ─────────────────────────────────────────────────────────────
function IOSGlassPill({
  children,
  dark = false,
  style = {}
}) {
  return /*#__PURE__*/React.createElement("div", {
    style: {
      height: 44,
      minWidth: 44,
      borderRadius: 9999,
      position: 'relative',
      overflow: 'hidden',
      display: 'flex',
      alignItems: 'center',
      justifyContent: 'center',
      boxShadow: dark ? '0 2px 6px rgba(0,0,0,0.35), 0 6px 16px rgba(0,0,0,0.2)' : '0 1px 3px rgba(0,0,0,0.07), 0 3px 10px rgba(0,0,0,0.06)',
      ...style
    }
  }, /*#__PURE__*/React.createElement("div", {
    style: {
      position: 'absolute',
      inset: 0,
      borderRadius: 9999,
      backdropFilter: 'blur(12px) saturate(180%)',
      WebkitBackdropFilter: 'blur(12px) saturate(180%)',
      background: dark ? 'rgba(120,120,128,0.28)' : 'rgba(255,255,255,0.5)'
    }
  }), /*#__PURE__*/React.createElement("div", {
    style: {
      position: 'absolute',
      inset: 0,
      borderRadius: 9999,
      boxShadow: dark ? 'inset 1.5px 1.5px 1px rgba(255,255,255,0.15), inset -1px -1px 1px rgba(255,255,255,0.08)' : 'inset 1.5px 1.5px 1px rgba(255,255,255,0.7), inset -1px -1px 1px rgba(255,255,255,0.4)',
      border: dark ? '0.5px solid rgba(255,255,255,0.15)' : '0.5px solid rgba(0,0,0,0.06)'
    }
  }), /*#__PURE__*/React.createElement("div", {
    style: {
      position: 'relative',
      zIndex: 1,
      display: 'flex',
      alignItems: 'center',
      padding: '0 4px'
    }
  }, children));
}

// ─────────────────────────────────────────────────────────────
// Navigation bar — glass pills + large title
// ─────────────────────────────────────────────────────────────
function IOSNavBar({
  title = 'Title',
  dark = false,
  trailingIcon = true
}) {
  const muted = dark ? 'rgba(255,255,255,0.6)' : '#404040';
  const text = dark ? '#fff' : '#000';
  const pillIcon = content => /*#__PURE__*/React.createElement(IOSGlassPill, {
    dark: dark
  }, /*#__PURE__*/React.createElement("div", {
    style: {
      width: 36,
      height: 36,
      display: 'flex',
      alignItems: 'center',
      justifyContent: 'center'
    }
  }, content));
  return /*#__PURE__*/React.createElement("div", {
    style: {
      display: 'flex',
      flexDirection: 'column',
      gap: 10,
      paddingTop: 62,
      paddingBottom: 10,
      position: 'relative',
      zIndex: 5
    }
  }, /*#__PURE__*/React.createElement("div", {
    style: {
      display: 'flex',
      alignItems: 'center',
      justifyContent: 'space-between',
      padding: '0 16px'
    }
  }, pillIcon(/*#__PURE__*/React.createElement("svg", {
    width: "12",
    height: "20",
    viewBox: "0 0 12 20",
    fill: "none",
    style: {
      marginLeft: -1
    }
  }, /*#__PURE__*/React.createElement("path", {
    d: "M10 2L2 10l8 8",
    stroke: muted,
    strokeWidth: "2.5",
    strokeLinecap: "round",
    strokeLinejoin: "round"
  }))), trailingIcon && pillIcon(/*#__PURE__*/React.createElement("svg", {
    width: "22",
    height: "6",
    viewBox: "0 0 22 6"
  }, /*#__PURE__*/React.createElement("circle", {
    cx: "3",
    cy: "3",
    r: "2.5",
    fill: muted
  }), /*#__PURE__*/React.createElement("circle", {
    cx: "11",
    cy: "3",
    r: "2.5",
    fill: muted
  }), /*#__PURE__*/React.createElement("circle", {
    cx: "19",
    cy: "3",
    r: "2.5",
    fill: muted
  })))), /*#__PURE__*/React.createElement("div", {
    style: {
      padding: '0 16px',
      fontFamily: '-apple-system, system-ui',
      fontSize: 34,
      fontWeight: 700,
      lineHeight: '41px',
      color: text,
      letterSpacing: 0.4
    }
  }, title));
}

// ─────────────────────────────────────────────────────────────
// Grouped list (inset card, r:26) + row (52px)
// ─────────────────────────────────────────────────────────────
function IOSListRow({
  title,
  detail,
  icon,
  chevron = true,
  isLast = false,
  dark = false
}) {
  const text = dark ? '#fff' : '#000';
  const sec = dark ? 'rgba(235,235,245,0.6)' : 'rgba(60,60,67,0.6)';
  const ter = dark ? 'rgba(235,235,245,0.3)' : 'rgba(60,60,67,0.3)';
  const sep = dark ? 'rgba(84,84,88,0.65)' : 'rgba(60,60,67,0.12)';
  return /*#__PURE__*/React.createElement("div", {
    style: {
      display: 'flex',
      alignItems: 'center',
      minHeight: 52,
      padding: '0 16px',
      position: 'relative',
      fontFamily: '-apple-system, system-ui',
      fontSize: 17,
      letterSpacing: -0.43
    }
  }, icon && /*#__PURE__*/React.createElement("div", {
    style: {
      width: 30,
      height: 30,
      borderRadius: 7,
      background: icon,
      marginRight: 12,
      flexShrink: 0
    }
  }), /*#__PURE__*/React.createElement("div", {
    style: {
      flex: 1,
      color: text
    }
  }, title), detail && /*#__PURE__*/React.createElement("span", {
    style: {
      color: sec,
      marginRight: 6
    }
  }, detail), chevron && /*#__PURE__*/React.createElement("svg", {
    width: "8",
    height: "14",
    viewBox: "0 0 8 14",
    style: {
      flexShrink: 0
    }
  }, /*#__PURE__*/React.createElement("path", {
    d: "M1 1l6 6-6 6",
    stroke: ter,
    strokeWidth: "2",
    fill: "none",
    strokeLinecap: "round",
    strokeLinejoin: "round"
  })), !isLast && /*#__PURE__*/React.createElement("div", {
    style: {
      position: 'absolute',
      bottom: 0,
      right: 0,
      left: icon ? 58 : 16,
      height: 0.5,
      background: sep
    }
  }));
}
function IOSList({
  header,
  children,
  dark = false
}) {
  const hc = dark ? 'rgba(235,235,245,0.6)' : 'rgba(60,60,67,0.6)';
  const bg = dark ? '#1C1C1E' : '#fff';
  return /*#__PURE__*/React.createElement("div", null, header && /*#__PURE__*/React.createElement("div", {
    style: {
      fontFamily: '-apple-system, system-ui',
      fontSize: 13,
      color: hc,
      textTransform: 'uppercase',
      padding: '8px 36px 6px',
      letterSpacing: -0.08
    }
  }, header), /*#__PURE__*/React.createElement("div", {
    style: {
      background: bg,
      borderRadius: 26,
      margin: '0 16px',
      overflow: 'hidden'
    }
  }, children));
}

// ─────────────────────────────────────────────────────────────
// Device frame
// ─────────────────────────────────────────────────────────────
function IOSDevice({
  children,
  width = 402,
  height = 874,
  dark = false,
  title,
  keyboard = false
}) {
  return /*#__PURE__*/React.createElement("div", {
    style: {
      width,
      height,
      borderRadius: 48,
      overflow: 'hidden',
      position: 'relative',
      background: dark ? '#000' : '#F2F2F7',
      boxShadow: '0 40px 80px rgba(0,0,0,0.18), 0 0 0 1px rgba(0,0,0,0.12)',
      fontFamily: '-apple-system, system-ui, sans-serif',
      WebkitFontSmoothing: 'antialiased'
    }
  }, /*#__PURE__*/React.createElement("div", {
    style: {
      position: 'absolute',
      top: 11,
      left: '50%',
      transform: 'translateX(-50%)',
      width: 126,
      height: 37,
      borderRadius: 24,
      background: '#000',
      zIndex: 50
    }
  }), /*#__PURE__*/React.createElement("div", {
    style: {
      position: 'absolute',
      top: 0,
      left: 0,
      right: 0,
      zIndex: 10
    }
  }, /*#__PURE__*/React.createElement(IOSStatusBar, {
    dark: dark
  })), /*#__PURE__*/React.createElement("div", {
    style: {
      height: '100%',
      display: 'flex',
      flexDirection: 'column'
    }
  }, title !== undefined && /*#__PURE__*/React.createElement(IOSNavBar, {
    title: title,
    dark: dark
  }), /*#__PURE__*/React.createElement("div", {
    style: {
      flex: 1,
      overflow: 'auto'
    }
  }, children), keyboard && /*#__PURE__*/React.createElement(IOSKeyboard, {
    dark: dark
  })), /*#__PURE__*/React.createElement("div", {
    style: {
      position: 'absolute',
      bottom: 0,
      left: 0,
      right: 0,
      zIndex: 60,
      height: 34,
      display: 'flex',
      justifyContent: 'center',
      alignItems: 'flex-end',
      paddingBottom: 8,
      pointerEvents: 'none'
    }
  }, /*#__PURE__*/React.createElement("div", {
    style: {
      width: 139,
      height: 5,
      borderRadius: 100,
      background: dark ? 'rgba(255,255,255,0.7)' : 'rgba(0,0,0,0.25)'
    }
  })));
}

// ─────────────────────────────────────────────────────────────
// Keyboard — iOS 26 liquid glass
// ─────────────────────────────────────────────────────────────
function IOSKeyboard({
  dark = false
}) {
  const glyph = dark ? 'rgba(255,255,255,0.7)' : '#595959';
  const sugg = dark ? 'rgba(255,255,255,0.6)' : '#333';
  const keyBg = dark ? 'rgba(255,255,255,0.22)' : 'rgba(255,255,255,0.85)';

  // special-key icons
  const icons = {
    shift: /*#__PURE__*/React.createElement("svg", {
      width: "19",
      height: "17",
      viewBox: "0 0 19 17"
    }, /*#__PURE__*/React.createElement("path", {
      d: "M9.5 1L1 9.5h4.5V16h8V9.5H18L9.5 1z",
      fill: glyph
    })),
    del: /*#__PURE__*/React.createElement("svg", {
      width: "23",
      height: "17",
      viewBox: "0 0 23 17"
    }, /*#__PURE__*/React.createElement("path", {
      d: "M7 1h13a2 2 0 012 2v11a2 2 0 01-2 2H7l-6-7.5L7 1z",
      fill: "none",
      stroke: glyph,
      strokeWidth: "1.6",
      strokeLinejoin: "round"
    }), /*#__PURE__*/React.createElement("path", {
      d: "M10 5l7 7M17 5l-7 7",
      stroke: glyph,
      strokeWidth: "1.6",
      strokeLinecap: "round"
    })),
    ret: /*#__PURE__*/React.createElement("svg", {
      width: "20",
      height: "14",
      viewBox: "0 0 20 14"
    }, /*#__PURE__*/React.createElement("path", {
      d: "M18 1v6H4m0 0l4-4M4 7l4 4",
      fill: "none",
      stroke: "#fff",
      strokeWidth: "1.8",
      strokeLinecap: "round",
      strokeLinejoin: "round"
    }))
  };
  const key = (content, {
    w,
    flex,
    ret,
    fs = 25,
    k
  } = {}) => /*#__PURE__*/React.createElement("div", {
    key: k,
    style: {
      height: 42,
      borderRadius: 8.5,
      flex: flex ? 1 : undefined,
      width: w,
      minWidth: 0,
      background: ret ? '#08f' : keyBg,
      boxShadow: '0 1px 0 rgba(0,0,0,0.075)',
      display: 'flex',
      alignItems: 'center',
      justifyContent: 'center',
      fontFamily: '-apple-system, "SF Compact", system-ui',
      fontSize: fs,
      fontWeight: 458,
      color: ret ? '#fff' : glyph
    }
  }, content);
  const row = (keys, pad = 0) => /*#__PURE__*/React.createElement("div", {
    style: {
      display: 'flex',
      gap: 6.5,
      justifyContent: 'center',
      padding: `0 ${pad}px`
    }
  }, keys.map(l => key(l, {
    flex: true,
    k: l
  })));
  return /*#__PURE__*/React.createElement("div", {
    style: {
      position: 'relative',
      zIndex: 15,
      borderRadius: 27,
      overflow: 'hidden',
      padding: '11px 0 2px',
      display: 'flex',
      flexDirection: 'column',
      alignItems: 'center',
      boxShadow: dark ? '0 -2px 20px rgba(0,0,0,0.09)' : '0 -1px 6px rgba(0,0,0,0.018), 0 -3px 20px rgba(0,0,0,0.012)'
    }
  }, /*#__PURE__*/React.createElement("div", {
    style: {
      position: 'absolute',
      inset: 0,
      borderRadius: 27,
      backdropFilter: 'blur(12px) saturate(180%)',
      WebkitBackdropFilter: 'blur(12px) saturate(180%)',
      background: dark ? 'rgba(120,120,128,0.14)' : 'rgba(255,255,255,0.25)'
    }
  }), /*#__PURE__*/React.createElement("div", {
    style: {
      position: 'absolute',
      inset: 0,
      borderRadius: 27,
      boxShadow: dark ? 'inset 1.5px 1.5px 1px rgba(255,255,255,0.15)' : 'inset 1.5px 1.5px 1px rgba(255,255,255,0.7), inset -1px -1px 1px rgba(255,255,255,0.4)',
      border: dark ? '0.5px solid rgba(255,255,255,0.15)' : '0.5px solid rgba(0,0,0,0.06)',
      pointerEvents: 'none'
    }
  }), /*#__PURE__*/React.createElement("div", {
    style: {
      display: 'flex',
      gap: 20,
      alignItems: 'center',
      padding: '8px 22px 13px',
      width: '100%',
      boxSizing: 'border-box',
      position: 'relative'
    }
  }, ['"The"', 'the', 'to'].map((w, i) => /*#__PURE__*/React.createElement(React.Fragment, {
    key: i
  }, i > 0 && /*#__PURE__*/React.createElement("div", {
    style: {
      width: 1,
      height: 25,
      background: '#ccc',
      opacity: 0.3
    }
  }), /*#__PURE__*/React.createElement("div", {
    style: {
      flex: 1,
      textAlign: 'center',
      fontFamily: '-apple-system, system-ui',
      fontSize: 17,
      color: sugg,
      letterSpacing: -0.43,
      lineHeight: '22px'
    }
  }, w)))), /*#__PURE__*/React.createElement("div", {
    style: {
      display: 'flex',
      flexDirection: 'column',
      gap: 13,
      padding: '0 6.5px',
      width: '100%',
      boxSizing: 'border-box',
      position: 'relative'
    }
  }, row(['q', 'w', 'e', 'r', 't', 'y', 'u', 'i', 'o', 'p']), row(['a', 's', 'd', 'f', 'g', 'h', 'j', 'k', 'l'], 20), /*#__PURE__*/React.createElement("div", {
    style: {
      display: 'flex',
      gap: 14.25,
      alignItems: 'center'
    }
  }, key(icons.shift, {
    w: 45,
    k: 'shift'
  }), /*#__PURE__*/React.createElement("div", {
    style: {
      display: 'flex',
      gap: 6.5,
      flex: 1
    }
  }, ['z', 'x', 'c', 'v', 'b', 'n', 'm'].map(l => key(l, {
    flex: true,
    k: l
  }))), key(icons.del, {
    w: 45,
    k: 'del'
  })), /*#__PURE__*/React.createElement("div", {
    style: {
      display: 'flex',
      gap: 6,
      alignItems: 'center'
    }
  }, key('ABC', {
    w: 92.25,
    fs: 18,
    k: 'abc'
  }), key('', {
    flex: true,
    k: 'space'
  }), key(icons.ret, {
    w: 92.25,
    ret: true,
    k: 'ret'
  }))), /*#__PURE__*/React.createElement("div", {
    style: {
      height: 56,
      width: '100%',
      position: 'relative'
    }
  }));
}
Object.assign(window, {
  IOSDevice,
  IOSStatusBar,
  IOSNavBar,
  IOSGlassPill,
  IOSList,
  IOSListRow,
  IOSKeyboard
});
})(); } catch (e) { __ds_ns.__errors.push({ path: "role-game/ios-frame.jsx", error: String((e && e.message) || e) }); }

// role-game/levels.jsx
try { (() => {
/* global window */
/* role-game · 12 stages from baby to professor.
   Each stage has:
     - id, name (Hebrew), eyebrow (small over-title)
     - kicker — the motivational line shown on level-up
     - difficulty — used to tune timer / question pool
     - Avatar() — a small SVG component drawn in a 240×260 viewBox

   Style: minimal geometric avatars on the lavender palette.
   All bodies share a common silhouette so the level-up transition feels
   like the same person growing up. Accessories carry the meaning.
*/

const LV = {
  ink: "#1A1530",
  // dark — face, hair, outlines
  ink2: "#3a3358",
  // soft dark
  skin: "#FBD9C2",
  // orange-soft = skin tone
  skinD: "#F37327",
  // brand orange = cheeks, nose
  hair: "#1A1530",
  body: "#A9A4EC",
  // lavender — clothes
  bodyD: "#6E68C9",
  // deeper lavender — shadows
  accent: "#F37327",
  // brand orange — accent props
  paper: "#FFFFFF",
  paperW: "#F4F2EE",
  indigo: "#3F4197"
};

/* shared face — gentle, no expression switching needed yet */
function BaseFace({
  blink = false,
  mouthW = 22
}) {
  return /*#__PURE__*/React.createElement("g", {
    className: "rg-face"
  }, blink ? /*#__PURE__*/React.createElement("g", {
    stroke: LV.ink,
    strokeWidth: "3",
    strokeLinecap: "round",
    fill: "none"
  }, /*#__PURE__*/React.createElement("path", {
    d: "M -10 0 q 8 -4 16 0"
  }), /*#__PURE__*/React.createElement("path", {
    d: "M 10 0 q 8 -4 16 0",
    transform: "translate(-4 0)"
  })) : /*#__PURE__*/React.createElement("g", {
    fill: LV.ink
  }, /*#__PURE__*/React.createElement("circle", {
    cx: "-8",
    cy: "0",
    r: "3"
  }), /*#__PURE__*/React.createElement("circle", {
    cx: "12",
    cy: "0",
    r: "3"
  })), /*#__PURE__*/React.createElement("circle", {
    cx: "-16",
    cy: "8",
    r: "3.5",
    fill: LV.skinD,
    opacity: "0.55"
  }), /*#__PURE__*/React.createElement("circle", {
    cx: "20",
    cy: "8",
    r: "3.5",
    fill: LV.skinD,
    opacity: "0.55"
  }), /*#__PURE__*/React.createElement("path", {
    d: `M ${-mouthW / 2} 14 q ${mouthW / 2} 8 ${mouthW} 0`,
    stroke: LV.ink,
    strokeWidth: "2.5",
    fill: "none",
    strokeLinecap: "round"
  }));
}

/* Background tile — soft lavender disc with brand "dot cluster" feel.
   The avatar drops on top of this. */
function AvatarBG() {
  return /*#__PURE__*/React.createElement("g", null, /*#__PURE__*/React.createElement("circle", {
    cx: "120",
    cy: "135",
    r: "110",
    fill: "#EFEDFB"
  }), /*#__PURE__*/React.createElement("circle", {
    cx: "42",
    cy: "60",
    r: "7",
    fill: LV.skinD,
    opacity: "0.18"
  }), /*#__PURE__*/React.createElement("circle", {
    cx: "206",
    cy: "50",
    r: "5",
    fill: LV.skinD,
    opacity: "0.28"
  }), /*#__PURE__*/React.createElement("circle", {
    cx: "220",
    cy: "180",
    r: "9",
    fill: LV.skinD,
    opacity: "0.18"
  }), /*#__PURE__*/React.createElement("circle", {
    cx: "32",
    cy: "200",
    r: "4",
    fill: LV.skinD,
    opacity: "0.35"
  }));
}

/* ──────────────────────────────────────────────
   STAGE 1 — תינוק (baby)
   ────────────────────────────────────────────── */
function Avatar01() {
  return /*#__PURE__*/React.createElement("svg", {
    viewBox: "0 0 240 260",
    className: "rg-avatar"
  }, /*#__PURE__*/React.createElement(AvatarBG, null), /*#__PURE__*/React.createElement("path", {
    d: "M 80 230 Q 60 160 120 130 Q 180 160 160 230 Z",
    fill: LV.body
  }), /*#__PURE__*/React.createElement("path", {
    d: "M 100 230 Q 90 190 120 175 Q 150 190 140 230 Z",
    fill: LV.bodyD,
    opacity: "0.35"
  }), /*#__PURE__*/React.createElement("circle", {
    cx: "120",
    cy: "115",
    r: "44",
    fill: LV.skin
  }), /*#__PURE__*/React.createElement("path", {
    d: "M 110 78 q 8 -10 18 -2 q -4 6 -10 6 z",
    fill: LV.hair
  }), /*#__PURE__*/React.createElement("g", {
    transform: "translate(120 115)"
  }, /*#__PURE__*/React.createElement(BaseFace, {
    mouthW: 14
  })), /*#__PURE__*/React.createElement("g", {
    transform: "translate(120 142)"
  }, /*#__PURE__*/React.createElement("ellipse", {
    cx: "0",
    cy: "0",
    rx: "10",
    ry: "6",
    fill: LV.accent
  }), /*#__PURE__*/React.createElement("circle", {
    cx: "0",
    cy: "-2",
    r: "4",
    fill: LV.paper
  })));
}

/* ──────────────────────────────────────────────
   STAGE 2 — ילד (kid, crayon in hand)
   ────────────────────────────────────────────── */
function Avatar02() {
  return /*#__PURE__*/React.createElement("svg", {
    viewBox: "0 0 240 260",
    className: "rg-avatar"
  }, /*#__PURE__*/React.createElement(AvatarBG, null), /*#__PURE__*/React.createElement("path", {
    d: "M 76 240 L 78 170 Q 80 150 100 145 L 140 145 Q 160 150 162 170 L 164 240 Z",
    fill: LV.body
  }), /*#__PURE__*/React.createElement("path", {
    d: "M 78 175 q -16 12 -6 32 q 6 4 12 -2 q -4 -14 4 -22 z",
    fill: LV.body
  }), /*#__PURE__*/React.createElement("path", {
    d: "M 162 175 q 16 12 6 32 q -6 4 -12 -2 q 4 -14 -4 -22 z",
    fill: LV.body
  }), /*#__PURE__*/React.createElement("g", {
    transform: "translate(174 200) rotate(40)"
  }, /*#__PURE__*/React.createElement("rect", {
    x: "-3",
    y: "-18",
    width: "6",
    height: "22",
    rx: "1.5",
    fill: LV.accent
  }), /*#__PURE__*/React.createElement("path", {
    d: "M -3 -18 L 0 -26 L 3 -18 Z",
    fill: LV.indigo
  })), /*#__PURE__*/React.createElement("circle", {
    cx: "120",
    cy: "115",
    r: "44",
    fill: LV.skin
  }), /*#__PURE__*/React.createElement("path", {
    d: "M 78 110 Q 78 70 120 68 Q 162 70 162 110 Q 156 86 138 80 Q 132 92 118 84 Q 110 94 96 84 Q 84 92 78 110 Z",
    fill: LV.hair
  }), /*#__PURE__*/React.createElement("g", {
    transform: "translate(120 115)"
  }, /*#__PURE__*/React.createElement(BaseFace, null)));
}

/* ──────────────────────────────────────────────
   STAGE 3 — תלמיד יסודי (elementary, backpack)
   ────────────────────────────────────────────── */
function Avatar03() {
  return /*#__PURE__*/React.createElement("svg", {
    viewBox: "0 0 240 260",
    className: "rg-avatar"
  }, /*#__PURE__*/React.createElement(AvatarBG, null), /*#__PURE__*/React.createElement("rect", {
    x: "58",
    y: "160",
    width: "40",
    height: "60",
    rx: "8",
    fill: LV.indigo
  }), /*#__PURE__*/React.createElement("rect", {
    x: "62",
    y: "174",
    width: "32",
    height: "10",
    rx: "3",
    fill: LV.accent
  }), /*#__PURE__*/React.createElement("path", {
    d: "M 80 240 L 80 168 Q 82 150 102 145 L 138 145 Q 158 150 160 168 L 160 240 Z",
    fill: LV.body
  }), /*#__PURE__*/React.createElement("path", {
    d: "M 100 145 q -10 30 -28 36",
    stroke: LV.indigo,
    strokeWidth: "6",
    fill: "none"
  }), /*#__PURE__*/React.createElement("circle", {
    cx: "120",
    cy: "113",
    r: "44",
    fill: LV.skin
  }), /*#__PURE__*/React.createElement("path", {
    d: "M 78 108 Q 80 70 120 68 Q 160 70 162 108 Q 152 84 120 82 Q 90 84 78 108 Z",
    fill: LV.hair
  }), /*#__PURE__*/React.createElement("path", {
    d: "M 160 105 q 14 4 14 24 q -10 -4 -16 -10 z",
    fill: LV.hair
  }), /*#__PURE__*/React.createElement("g", {
    transform: "translate(120 113)"
  }, /*#__PURE__*/React.createElement(BaseFace, {
    mouthW: 20
  })));
}

/* ──────────────────────────────────────────────
   STAGE 4 — נער (teen, headphones)
   ────────────────────────────────────────────── */
function Avatar04() {
  return /*#__PURE__*/React.createElement("svg", {
    viewBox: "0 0 240 260",
    className: "rg-avatar"
  }, /*#__PURE__*/React.createElement(AvatarBG, null), /*#__PURE__*/React.createElement("path", {
    d: "M 72 240 L 72 174 Q 76 150 100 144 L 140 144 Q 164 150 168 174 L 168 240 Z",
    fill: LV.body
  }), /*#__PURE__*/React.createElement("path", {
    d: "M 96 205 Q 120 220 144 205",
    stroke: LV.bodyD,
    strokeWidth: "3",
    fill: "none"
  }), /*#__PURE__*/React.createElement("circle", {
    cx: "120",
    cy: "113",
    r: "44",
    fill: LV.skin
  }), /*#__PURE__*/React.createElement("path", {
    d: "M 76 108 Q 76 64 120 64 Q 164 64 164 110 Q 158 100 150 100 L 140 110 L 132 100 L 122 112 L 110 100 L 102 110 L 92 100 Q 84 100 76 108 Z",
    fill: LV.hair
  }), /*#__PURE__*/React.createElement("g", {
    transform: "translate(120 113)"
  }, /*#__PURE__*/React.createElement(BaseFace, {
    mouthW: 18
  })), /*#__PURE__*/React.createElement("path", {
    d: "M 70 102 Q 120 60 170 102",
    stroke: LV.ink,
    strokeWidth: "6",
    fill: "none"
  }), /*#__PURE__*/React.createElement("rect", {
    x: "60",
    y: "98",
    width: "18",
    height: "26",
    rx: "6",
    fill: LV.accent
  }), /*#__PURE__*/React.createElement("rect", {
    x: "162",
    y: "98",
    width: "18",
    height: "26",
    rx: "6",
    fill: LV.accent
  }));
}

/* ──────────────────────────────────────────────
   STAGE 5 — תיכוניסט (high schooler, with phone)
   ────────────────────────────────────────────── */
function Avatar05() {
  return /*#__PURE__*/React.createElement("svg", {
    viewBox: "0 0 240 260",
    className: "rg-avatar"
  }, /*#__PURE__*/React.createElement(AvatarBG, null), /*#__PURE__*/React.createElement("path", {
    d: "M 76 240 L 76 172 Q 80 150 100 144 L 140 144 Q 160 150 164 172 L 164 240 Z",
    fill: LV.body
  }), /*#__PURE__*/React.createElement("path", {
    d: "M 158 175 q 18 6 14 32 q -2 6 -10 4 q -6 -16 -8 -22 z",
    fill: LV.body
  }), /*#__PURE__*/React.createElement("rect", {
    x: "158",
    y: "194",
    width: "22",
    height: "36",
    rx: "4",
    fill: LV.ink
  }), /*#__PURE__*/React.createElement("rect", {
    x: "161",
    y: "198",
    width: "16",
    height: "26",
    rx: "2",
    fill: LV.indigo
  }), /*#__PURE__*/React.createElement("circle", {
    cx: "120",
    cy: "113",
    r: "44",
    fill: LV.skin
  }), /*#__PURE__*/React.createElement("path", {
    d: "M 76 110 Q 70 60 120 60 Q 170 60 164 110 Q 168 130 158 142 Q 160 116 152 108 Q 130 116 110 104 Q 92 116 82 108 Q 72 116 76 130 Q 70 124 76 110 Z",
    fill: LV.hair
  }), /*#__PURE__*/React.createElement("g", {
    transform: "translate(120 113)"
  }, /*#__PURE__*/React.createElement(BaseFace, {
    mouthW: 16
  })));
}

/* ──────────────────────────────────────────────
   STAGE 6 — בוגר תיכון (high-school graduate, mortarboard)
   ────────────────────────────────────────────── */
function Avatar06() {
  return /*#__PURE__*/React.createElement("svg", {
    viewBox: "0 0 240 260",
    className: "rg-avatar"
  }, /*#__PURE__*/React.createElement(AvatarBG, null), /*#__PURE__*/React.createElement("path", {
    d: "M 70 240 L 76 170 Q 80 150 100 144 L 140 144 Q 160 150 164 170 L 170 240 Z",
    fill: LV.indigo
  }), /*#__PURE__*/React.createElement("path", {
    d: "M 100 144 L 120 180 L 140 144 Z",
    fill: LV.paper
  }), /*#__PURE__*/React.createElement("path", {
    d: "M 100 144 L 120 180 L 140 144",
    stroke: LV.body,
    strokeWidth: "6",
    fill: "none"
  }), /*#__PURE__*/React.createElement("circle", {
    cx: "120",
    cy: "113",
    r: "44",
    fill: LV.skin
  }), /*#__PURE__*/React.createElement("path", {
    d: "M 76 108 Q 80 78 120 78 Q 160 78 164 108 Q 152 96 120 94 Q 88 96 76 108 Z",
    fill: LV.hair
  }), /*#__PURE__*/React.createElement("g", {
    transform: "translate(120 113)"
  }, /*#__PURE__*/React.createElement(BaseFace, {
    mouthW: 26
  })), /*#__PURE__*/React.createElement("rect", {
    x: "78",
    y: "58",
    width: "84",
    height: "14",
    rx: "2",
    fill: LV.ink
  }), /*#__PURE__*/React.createElement("rect", {
    x: "98",
    y: "50",
    width: "44",
    height: "10",
    rx: "2",
    fill: LV.ink
  }), /*#__PURE__*/React.createElement("circle", {
    cx: "158",
    cy: "64",
    r: "3",
    fill: LV.accent
  }), /*#__PURE__*/React.createElement("path", {
    d: "M 158 67 L 168 90 L 174 86",
    stroke: LV.accent,
    strokeWidth: "3",
    fill: "none"
  }));
}

/* ──────────────────────────────────────────────
   STAGE 7 — חייל (soldier, beret + dog tag)
   ────────────────────────────────────────────── */
function Avatar07() {
  return /*#__PURE__*/React.createElement("svg", {
    viewBox: "0 0 240 260",
    className: "rg-avatar"
  }, /*#__PURE__*/React.createElement(AvatarBG, null), /*#__PURE__*/React.createElement("path", {
    d: "M 76 240 L 76 172 Q 80 150 100 144 L 140 144 Q 160 150 164 172 L 164 240 Z",
    fill: "#5d6b3b"
  }), /*#__PURE__*/React.createElement("rect", {
    x: "92",
    y: "170",
    width: "22",
    height: "14",
    rx: "2",
    fill: "#48542d"
  }), /*#__PURE__*/React.createElement("rect", {
    x: "126",
    y: "170",
    width: "22",
    height: "14",
    rx: "2",
    fill: "#48542d"
  }), /*#__PURE__*/React.createElement("line", {
    x1: "108",
    y1: "148",
    x2: "132",
    y2: "148",
    stroke: LV.ink,
    strokeWidth: "2"
  }), /*#__PURE__*/React.createElement("rect", {
    x: "116",
    y: "148",
    width: "8",
    height: "14",
    rx: "1.5",
    fill: "#c8c4cf"
  }), /*#__PURE__*/React.createElement("circle", {
    cx: "120",
    cy: "113",
    r: "42",
    fill: LV.skin
  }), /*#__PURE__*/React.createElement("path", {
    d: "M 80 108 Q 84 90 120 90 Q 156 90 160 108 Q 148 102 120 102 Q 92 102 80 108 Z",
    fill: LV.hair
  }), /*#__PURE__*/React.createElement("g", {
    transform: "translate(120 115)"
  }, /*#__PURE__*/React.createElement(BaseFace, {
    mouthW: 18
  })), /*#__PURE__*/React.createElement("path", {
    d: "M 76 92 Q 96 60 154 70 Q 168 78 158 96 Q 116 100 76 92 Z",
    fill: "#7d3a1f"
  }), /*#__PURE__*/React.createElement("circle", {
    cx: "154",
    cy: "73",
    r: "6",
    fill: LV.accent
  }), /*#__PURE__*/React.createElement("path", {
    d: "M 76 92 Q 100 86 130 86",
    stroke: "#5d2b14",
    strokeWidth: "2",
    fill: "none"
  }));
}

/* ──────────────────────────────────────────────
   STAGE 8 — אזרח אחרי הצבא (post-army, with coffee)
   ────────────────────────────────────────────── */
function Avatar08() {
  return /*#__PURE__*/React.createElement("svg", {
    viewBox: "0 0 240 260",
    className: "rg-avatar"
  }, /*#__PURE__*/React.createElement(AvatarBG, null), /*#__PURE__*/React.createElement("path", {
    d: "M 76 240 L 76 172 Q 80 150 100 144 L 140 144 Q 160 150 164 172 L 164 240 Z",
    fill: LV.body
  }), /*#__PURE__*/React.createElement("path", {
    d: "M 118 144 L 122 240",
    stroke: LV.bodyD,
    strokeWidth: "3"
  }), /*#__PURE__*/React.createElement("path", {
    d: "M 76 200 L 164 200",
    stroke: LV.bodyD,
    strokeWidth: "2"
  }), /*#__PURE__*/React.createElement("g", {
    transform: "translate(60 190)"
  }, /*#__PURE__*/React.createElement("path", {
    d: "M 0 0 L 4 24 L 22 24 L 26 0 Z",
    fill: LV.paper
  }), /*#__PURE__*/React.createElement("rect", {
    x: "2",
    y: "0",
    width: "22",
    height: "6",
    rx: "1",
    fill: LV.accent
  }), /*#__PURE__*/React.createElement("path", {
    d: "M 6 -10 q 0 8 4 10 m 4 -10 q 0 8 4 10",
    stroke: LV.bodyD,
    strokeWidth: "2",
    fill: "none"
  })), /*#__PURE__*/React.createElement("circle", {
    cx: "120",
    cy: "113",
    r: "44",
    fill: LV.skin
  }), /*#__PURE__*/React.createElement("path", {
    d: "M 92 130 Q 120 150 148 130 Q 144 138 120 142 Q 96 138 92 130 Z",
    fill: LV.ink,
    opacity: "0.35"
  }), /*#__PURE__*/React.createElement("path", {
    d: "M 76 100 Q 80 70 120 70 Q 160 70 164 100 L 162 108 L 78 108 Z",
    fill: LV.indigo
  }), /*#__PURE__*/React.createElement("rect", {
    x: "76",
    y: "104",
    width: "88",
    height: "8",
    rx: "2",
    fill: LV.indigo
  }), /*#__PURE__*/React.createElement("path", {
    d: "M 100 80 L 100 100 M 130 76 L 130 100",
    stroke: "#2A2B6E",
    strokeWidth: "2"
  }), /*#__PURE__*/React.createElement("g", {
    transform: "translate(120 115)"
  }, /*#__PURE__*/React.createElement(BaseFace, {
    mouthW: 20
  })));
}

/* ──────────────────────────────────────────────
   STAGE 09 — תלמיד מכינה (prep / mechina — notebook + pen)
   ────────────────────────────────────────────── */
function AvatarMechina() {
  return /*#__PURE__*/React.createElement("svg", {
    viewBox: "0 0 240 260",
    className: "rg-avatar"
  }, /*#__PURE__*/React.createElement(AvatarBG, null), /*#__PURE__*/React.createElement("path", {
    d: "M 76 240 L 76 172 Q 80 150 100 144 L 140 144 Q 160 150 164 172 L 164 240 Z",
    fill: LV.body
  }), /*#__PURE__*/React.createElement("path", {
    d: "M 112 150 L 110 178",
    stroke: LV.bodyD,
    strokeWidth: "3"
  }), /*#__PURE__*/React.createElement("path", {
    d: "M 128 150 L 130 178",
    stroke: LV.bodyD,
    strokeWidth: "3"
  }), /*#__PURE__*/React.createElement("rect", {
    x: "86",
    y: "196",
    width: "68",
    height: "44",
    rx: "3",
    fill: LV.paper
  }), /*#__PURE__*/React.createElement("rect", {
    x: "86",
    y: "196",
    width: "10",
    height: "44",
    fill: LV.accent
  }), /*#__PURE__*/React.createElement("line", {
    x1: "100",
    y1: "208",
    x2: "148",
    y2: "208",
    stroke: LV.ink,
    strokeWidth: "1.6",
    opacity: "0.6"
  }), /*#__PURE__*/React.createElement("line", {
    x1: "100",
    y1: "218",
    x2: "144",
    y2: "218",
    stroke: LV.ink,
    strokeWidth: "1.6",
    opacity: "0.6"
  }), /*#__PURE__*/React.createElement("line", {
    x1: "100",
    y1: "228",
    x2: "140",
    y2: "228",
    stroke: LV.ink,
    strokeWidth: "1.6",
    opacity: "0.6"
  }), /*#__PURE__*/React.createElement("circle", {
    cx: "120",
    cy: "113",
    r: "44",
    fill: LV.skin
  }), /*#__PURE__*/React.createElement("path", {
    d: "M 78 108 Q 80 70 120 68 Q 162 70 164 108 Q 152 88 132 86 Q 116 102 100 92 Q 88 92 78 108 Z",
    fill: LV.hair
  }), /*#__PURE__*/React.createElement("g", {
    transform: "translate(120 113)"
  }, /*#__PURE__*/React.createElement(BaseFace, {
    mouthW: 18
  })), /*#__PURE__*/React.createElement("g", {
    transform: "translate(76 102) rotate(-12)"
  }, /*#__PURE__*/React.createElement("rect", {
    x: "-2",
    y: "-2",
    width: "22",
    height: "5",
    rx: "1.5",
    fill: LV.indigo
  }), /*#__PURE__*/React.createElement("path", {
    d: "M 20 -2 L 26 0.5 L 20 3 Z",
    fill: LV.accent
  })));
}

/* ──────────────────────────────────────────────
   STAGE 10 — סטודנט (uni student, laptop bag + book)
   ────────────────────────────────────────────── */
function Avatar09() {
  return /*#__PURE__*/React.createElement("svg", {
    viewBox: "0 0 240 260",
    className: "rg-avatar"
  }, /*#__PURE__*/React.createElement(AvatarBG, null), /*#__PURE__*/React.createElement("path", {
    d: "M 76 240 L 76 172 Q 80 150 100 144 L 140 144 Q 160 150 164 172 L 164 240 Z",
    fill: "#d6a9a4"
  }), /*#__PURE__*/React.createElement("rect", {
    x: "88",
    y: "195",
    width: "64",
    height: "44",
    rx: "3",
    fill: LV.indigo
  }), /*#__PURE__*/React.createElement("rect", {
    x: "92",
    y: "199",
    width: "56",
    height: "36",
    rx: "2",
    fill: LV.paper
  }), /*#__PURE__*/React.createElement("line", {
    x1: "100",
    y1: "208",
    x2: "142",
    y2: "208",
    stroke: LV.ink,
    strokeWidth: "2"
  }), /*#__PURE__*/React.createElement("line", {
    x1: "100",
    y1: "216",
    x2: "138",
    y2: "216",
    stroke: LV.ink,
    strokeWidth: "2"
  }), /*#__PURE__*/React.createElement("line", {
    x1: "100",
    y1: "224",
    x2: "132",
    y2: "224",
    stroke: LV.ink,
    strokeWidth: "2"
  }), /*#__PURE__*/React.createElement("circle", {
    cx: "120",
    cy: "113",
    r: "44",
    fill: LV.skin
  }), /*#__PURE__*/React.createElement("path", {
    d: "M 76 108 Q 76 66 120 66 Q 164 66 164 108 Q 156 94 130 92 Q 100 96 92 108 Q 84 102 76 108 Z",
    fill: LV.hair
  }), /*#__PURE__*/React.createElement("g", {
    transform: "translate(120 113)"
  }, /*#__PURE__*/React.createElement(BaseFace, {
    mouthW: 16
  })), /*#__PURE__*/React.createElement("circle", {
    cx: "108",
    cy: "113",
    r: "10",
    fill: "none",
    stroke: LV.ink,
    strokeWidth: "2.5"
  }), /*#__PURE__*/React.createElement("circle", {
    cx: "134",
    cy: "113",
    r: "10",
    fill: "none",
    stroke: LV.ink,
    strokeWidth: "2.5"
  }), /*#__PURE__*/React.createElement("line", {
    x1: "118",
    y1: "113",
    x2: "124",
    y2: "113",
    stroke: LV.ink,
    strokeWidth: "2.5"
  }));
}

/* ──────────────────────────────────────────────
   STAGE 10 — בוגר תואר ראשון (BA grad — small diploma)
   ────────────────────────────────────────────── */
function Avatar10() {
  return /*#__PURE__*/React.createElement("svg", {
    viewBox: "0 0 240 260",
    className: "rg-avatar"
  }, /*#__PURE__*/React.createElement(AvatarBG, null), /*#__PURE__*/React.createElement("path", {
    d: "M 70 240 L 76 170 Q 80 150 100 144 L 140 144 Q 160 150 164 170 L 170 240 Z",
    fill: LV.ink2
  }), /*#__PURE__*/React.createElement("path", {
    d: "M 100 144 L 112 184 L 100 200 Z",
    fill: LV.indigo
  }), /*#__PURE__*/React.createElement("path", {
    d: "M 140 144 L 128 184 L 140 200 Z",
    fill: LV.indigo
  }), /*#__PURE__*/React.createElement("path", {
    d: "M 112 184 L 120 196 L 128 184 L 124 240 L 116 240 Z",
    fill: LV.paper
  }), /*#__PURE__*/React.createElement("path", {
    d: "M 116 196 L 124 196 L 122 220 L 118 220 Z",
    fill: LV.accent
  }), /*#__PURE__*/React.createElement("g", {
    transform: "translate(168 198) rotate(15)"
  }, /*#__PURE__*/React.createElement("rect", {
    x: "-8",
    y: "-4",
    width: "32",
    height: "10",
    rx: "2",
    fill: LV.paper
  }), /*#__PURE__*/React.createElement("rect", {
    x: "22",
    y: "-4",
    width: "6",
    height: "10",
    rx: "2",
    fill: LV.accent
  })), /*#__PURE__*/React.createElement("circle", {
    cx: "120",
    cy: "113",
    r: "44",
    fill: LV.skin
  }), /*#__PURE__*/React.createElement("path", {
    d: "M 78 100 Q 82 72 120 72 Q 158 72 162 100 Q 152 84 120 84 Q 88 84 78 100 Z",
    fill: LV.hair
  }), /*#__PURE__*/React.createElement("g", {
    transform: "translate(120 113)"
  }, /*#__PURE__*/React.createElement(BaseFace, {
    mouthW: 22
  })));
}

/* ──────────────────────────────────────────────
   STAGE 11 — תואר שני (MA student, glasses + stack of books)
   ────────────────────────────────────────────── */
function Avatar11() {
  return /*#__PURE__*/React.createElement("svg", {
    viewBox: "0 0 240 260",
    className: "rg-avatar"
  }, /*#__PURE__*/React.createElement(AvatarBG, null), /*#__PURE__*/React.createElement("path", {
    d: "M 76 240 L 76 172 Q 80 150 100 144 L 140 144 Q 160 150 164 172 L 164 240 Z",
    fill: LV.indigo
  }), /*#__PURE__*/React.createElement("ellipse", {
    cx: "120",
    cy: "148",
    rx: "22",
    ry: "10",
    fill: LV.indigo
  }), /*#__PURE__*/React.createElement("ellipse", {
    cx: "120",
    cy: "148",
    rx: "22",
    ry: "10",
    fill: "none",
    stroke: LV.ink,
    strokeWidth: "2",
    opacity: "0.5"
  }), /*#__PURE__*/React.createElement("rect", {
    x: "84",
    y: "210",
    width: "72",
    height: "10",
    rx: "2",
    fill: LV.accent
  }), /*#__PURE__*/React.createElement("rect", {
    x: "80",
    y: "220",
    width: "80",
    height: "10",
    rx: "2",
    fill: LV.body
  }), /*#__PURE__*/React.createElement("rect", {
    x: "88",
    y: "230",
    width: "64",
    height: "10",
    rx: "2",
    fill: "#5d6b3b"
  }), /*#__PURE__*/React.createElement("circle", {
    cx: "120",
    cy: "113",
    r: "44",
    fill: LV.skin
  }), /*#__PURE__*/React.createElement("path", {
    d: "M 78 100 Q 78 70 120 70 Q 162 70 162 100 Q 156 86 132 84 Q 110 88 92 86 Q 84 92 78 100 Z",
    fill: LV.hair
  }), /*#__PURE__*/React.createElement("g", {
    transform: "translate(120 113)"
  }, /*#__PURE__*/React.createElement(BaseFace, {
    mouthW: 18
  })), /*#__PURE__*/React.createElement("rect", {
    x: "96",
    y: "106",
    width: "20",
    height: "14",
    rx: "2",
    fill: "none",
    stroke: LV.ink,
    strokeWidth: "2.5"
  }), /*#__PURE__*/React.createElement("rect", {
    x: "124",
    y: "106",
    width: "20",
    height: "14",
    rx: "2",
    fill: "none",
    stroke: LV.ink,
    strokeWidth: "2.5"
  }), /*#__PURE__*/React.createElement("line", {
    x1: "116",
    y1: "113",
    x2: "124",
    y2: "113",
    stroke: LV.ink,
    strokeWidth: "2.5"
  }));
}

/* ──────────────────────────────────────────────
   STAGE 13 — דוקטורנט (PhD candidate, clipboard + tired eyes)
   ────────────────────────────────────────────── */
function AvatarDoctorand() {
  return /*#__PURE__*/React.createElement("svg", {
    viewBox: "0 0 240 260",
    className: "rg-avatar"
  }, /*#__PURE__*/React.createElement(AvatarBG, null), /*#__PURE__*/React.createElement("path", {
    d: "M 76 240 L 76 172 Q 80 150 100 144 L 140 144 Q 160 150 164 172 L 164 240 Z",
    fill: LV.indigo
  }), /*#__PURE__*/React.createElement("path", {
    d: "M 78 240 L 78 175 Q 84 154 102 148 L 102 240 Z",
    fill: LV.paper
  }), /*#__PURE__*/React.createElement("path", {
    d: "M 162 240 L 162 175 Q 156 154 138 148 L 138 240 Z",
    fill: LV.paper
  }), /*#__PURE__*/React.createElement("path", {
    d: "M 102 148 L 120 178 L 138 148",
    stroke: LV.ink,
    strokeWidth: "1.5",
    fill: "none",
    opacity: "0.3"
  }), /*#__PURE__*/React.createElement("g", {
    transform: "translate(170 200) rotate(8)"
  }, /*#__PURE__*/React.createElement("rect", {
    x: "-22",
    y: "-22",
    width: "32",
    height: "44",
    rx: "2",
    fill: LV.paper
  }), /*#__PURE__*/React.createElement("rect", {
    x: "-22",
    y: "-22",
    width: "32",
    height: "6",
    fill: LV.accent
  }), /*#__PURE__*/React.createElement("line", {
    x1: "-18",
    y1: "-8",
    x2: "4",
    y2: "-8",
    stroke: LV.ink,
    strokeWidth: "1.5",
    opacity: "0.55"
  }), /*#__PURE__*/React.createElement("line", {
    x1: "-18",
    y1: "0",
    x2: "6",
    y2: "0",
    stroke: LV.ink,
    strokeWidth: "1.5",
    opacity: "0.55"
  }), /*#__PURE__*/React.createElement("line", {
    x1: "-18",
    y1: "8",
    x2: "2",
    y2: "8",
    stroke: LV.ink,
    strokeWidth: "1.5",
    opacity: "0.55"
  })), /*#__PURE__*/React.createElement("circle", {
    cx: "120",
    cy: "113",
    r: "44",
    fill: LV.skin
  }), /*#__PURE__*/React.createElement("path", {
    d: "M 76 100 Q 74 64 100 64 Q 108 56 120 64 Q 132 56 140 64 Q 168 64 164 100 Q 158 78 142 86 Q 122 78 110 92 Q 92 82 76 100 Z",
    fill: LV.hair
  }), /*#__PURE__*/React.createElement("g", {
    transform: "translate(120 113)"
  }, /*#__PURE__*/React.createElement(BaseFace, {
    mouthW: 12
  })), /*#__PURE__*/React.createElement("circle", {
    cx: "108",
    cy: "113",
    r: "10",
    fill: "none",
    stroke: LV.ink,
    strokeWidth: "2.5"
  }), /*#__PURE__*/React.createElement("circle", {
    cx: "134",
    cy: "113",
    r: "10",
    fill: "none",
    stroke: LV.ink,
    strokeWidth: "2.5"
  }), /*#__PURE__*/React.createElement("line", {
    x1: "118",
    y1: "113",
    x2: "124",
    y2: "113",
    stroke: LV.ink,
    strokeWidth: "2.5"
  }));
}

/* ──────────────────────────────────────────────
   STAGE 14 — דוקטור (Doctor — graduation robe + diploma scroll)
   ────────────────────────────────────────────── */
function AvatarDoctor() {
  return /*#__PURE__*/React.createElement("svg", {
    viewBox: "0 0 240 260",
    className: "rg-avatar"
  }, /*#__PURE__*/React.createElement(AvatarBG, null), /*#__PURE__*/React.createElement("path", {
    d: "M 68 240 L 76 168 Q 80 150 100 144 L 140 144 Q 160 150 164 168 L 172 240 Z",
    fill: LV.bodyD
  }), /*#__PURE__*/React.createElement("path", {
    d: "M 100 144 L 116 240 L 124 240 L 108 144 Z",
    fill: LV.accent
  }), /*#__PURE__*/React.createElement("path", {
    d: "M 108 144 L 120 178 L 132 144 Z",
    fill: LV.paper
  }), /*#__PURE__*/React.createElement("g", {
    transform: "translate(64 198) rotate(-12)"
  }, /*#__PURE__*/React.createElement("rect", {
    x: "-4",
    y: "-22",
    width: "30",
    height: "10",
    rx: "5",
    fill: LV.paper
  }), /*#__PURE__*/React.createElement("rect", {
    x: "-4",
    y: "-22",
    width: "30",
    height: "10",
    rx: "5",
    fill: "none",
    stroke: LV.ink,
    strokeWidth: "1.5"
  }), /*#__PURE__*/React.createElement("circle", {
    cx: "24",
    cy: "-17",
    r: "4",
    fill: LV.accent
  })), /*#__PURE__*/React.createElement("circle", {
    cx: "120",
    cy: "113",
    r: "44",
    fill: LV.skin
  }), /*#__PURE__*/React.createElement("path", {
    d: "M 78 102 Q 78 68 120 68 Q 162 68 162 102 Q 152 88 120 86 Q 88 88 78 102 Z",
    fill: LV.hair
  }), /*#__PURE__*/React.createElement("path", {
    d: "M 78 102 Q 80 92 90 90 L 90 104 Z",
    fill: "#9a96a4"
  }), /*#__PURE__*/React.createElement("path", {
    d: "M 162 102 Q 160 92 150 90 L 150 104 Z",
    fill: "#9a96a4"
  }), /*#__PURE__*/React.createElement("g", {
    transform: "translate(120 113)"
  }, /*#__PURE__*/React.createElement(BaseFace, {
    mouthW: 20
  })), /*#__PURE__*/React.createElement("rect", {
    x: "80",
    y: "56",
    width: "80",
    height: "12",
    rx: "2",
    fill: LV.ink
  }), /*#__PURE__*/React.createElement("rect", {
    x: "98",
    y: "48",
    width: "44",
    height: "10",
    rx: "2",
    fill: LV.ink
  }), /*#__PURE__*/React.createElement("circle", {
    cx: "156",
    cy: "62",
    r: "3",
    fill: LV.accent
  }), /*#__PURE__*/React.createElement("path", {
    d: "M 156 65 L 166 86",
    stroke: LV.accent,
    strokeWidth: "3",
    fill: "none"
  }));
}

/* ──────────────────────────────────────────────
   STAGE 15 — פרופסור (full regalia, bow tie + mustache)
   ────────────────────────────────────────────── */
function Avatar12() {
  return /*#__PURE__*/React.createElement("svg", {
    viewBox: "0 0 240 260",
    className: "rg-avatar"
  }, /*#__PURE__*/React.createElement(AvatarBG, null), /*#__PURE__*/React.createElement("path", {
    d: "M 64 240 L 76 168 Q 80 150 100 144 L 140 144 Q 160 150 164 168 L 176 240 Z",
    fill: LV.ink
  }), /*#__PURE__*/React.createElement("path", {
    d: "M 100 144 L 116 240",
    stroke: LV.accent,
    strokeWidth: "6",
    fill: "none"
  }), /*#__PURE__*/React.createElement("path", {
    d: "M 140 144 L 124 240",
    stroke: LV.accent,
    strokeWidth: "6",
    fill: "none"
  }), /*#__PURE__*/React.createElement("path", {
    d: "M 116 144 L 124 144 L 122 200 L 118 200 Z",
    fill: LV.paper
  }), /*#__PURE__*/React.createElement("path", {
    d: "M 108 156 L 120 162 L 132 156 L 132 174 L 120 168 L 108 174 Z",
    fill: LV.accent
  }), /*#__PURE__*/React.createElement("rect", {
    x: "118",
    y: "161",
    width: "4",
    height: "8",
    fill: LV.indigo
  }), /*#__PURE__*/React.createElement("circle", {
    cx: "120",
    cy: "113",
    r: "44",
    fill: LV.skin
  }), /*#__PURE__*/React.createElement("path", {
    d: "M 76 108 Q 80 86 102 86 Q 88 96 84 110 Z",
    fill: "#9a96a4"
  }), /*#__PURE__*/React.createElement("path", {
    d: "M 164 108 Q 160 86 138 86 Q 152 96 156 110 Z",
    fill: "#9a96a4"
  }), /*#__PURE__*/React.createElement("path", {
    d: "M 88 86 Q 92 76 120 76 Q 148 76 152 86 Q 132 84 120 84 Q 108 84 88 86 Z",
    fill: LV.hair
  }), /*#__PURE__*/React.createElement("g", {
    transform: "translate(120 115)"
  }, /*#__PURE__*/React.createElement(BaseFace, {
    mouthW: 14
  })), /*#__PURE__*/React.createElement("path", {
    d: "M 102 124 Q 110 132 120 128 Q 130 132 138 124 Q 130 130 120 130 Q 110 130 102 124 Z",
    fill: LV.hair
  }), /*#__PURE__*/React.createElement("rect", {
    x: "76",
    y: "50",
    width: "88",
    height: "12",
    rx: "2",
    fill: LV.ink
  }), /*#__PURE__*/React.createElement("rect", {
    x: "96",
    y: "42",
    width: "48",
    height: "10",
    rx: "2",
    fill: LV.ink
  }), /*#__PURE__*/React.createElement("circle", {
    cx: "160",
    cy: "56",
    r: "3",
    fill: "#E0A21A"
  }), /*#__PURE__*/React.createElement("path", {
    d: "M 160 59 L 172 84",
    stroke: "#E0A21A",
    strokeWidth: "3",
    fill: "none"
  }), /*#__PURE__*/React.createElement("path", {
    d: "M 168 80 q 4 8 8 4",
    stroke: "#E0A21A",
    strokeWidth: "3",
    fill: "none"
  }));
}

/* ──────────────────────────────────────────────
   The level table
   ────────────────────────────────────────────── */
const LEVELS = [{
  id: 1,
  name: "תינוק",
  en: "Stage 01",
  eyebrow: "שלב 01 · ההתחלה",
  kicker: "מתחילים מאפס.",
  subKicker: "כל סיפור גדול מתחיל ככה.",
  Avatar: Avatar01
}, {
  id: 2,
  name: "ילד",
  en: "Stage 02",
  eyebrow: "שלב 02 · גן",
  kicker: "צבעי. שאלי. נסי.",
  subKicker: "התשובות הנכונות מסתתרות בסקרנות.",
  Avatar: Avatar02
}, {
  id: 3,
  name: "תלמיד יסודי",
  en: "Stage 03",
  eyebrow: "שלב 03 · יסודי",
  kicker: "תיק על הגב, ראש קדימה.",
  subKicker: "הזמן ללמוד איך ללמוד.",
  Avatar: Avatar03
}, {
  id: 4,
  name: "נער",
  en: "Stage 04",
  eyebrow: "שלב 04 · חט\"ב",
  kicker: "מצאתם את הקצב.",
  subKicker: "אוזניות, ריכוז, הצלחה.",
  Avatar: Avatar04
}, {
  id: 5,
  name: "תיכוניסט",
  en: "Stage 05",
  eyebrow: "שלב 05 · תיכון",
  kicker: "בגרויות נכבשות.",
  subKicker: "אחת אחת. בלי לחץ.",
  Avatar: Avatar05
}, {
  id: 6,
  name: "בוגר תיכון",
  en: "Stage 06",
  eyebrow: "שלב 06 · 12 שנה",
  kicker: "כובע באוויר!",
  subKicker: "12 שנים מאחורייך. שיא ראשון.",
  Avatar: Avatar06
}, {
  id: 7,
  name: "חייל",
  en: "Stage 07",
  eyebrow: "שלב 07 · צבא",
  kicker: "מדים, משימה, ביצוע.",
  subKicker: "הולכים על המסיחים.",
  Avatar: Avatar07
}, {
  id: 8,
  name: "אחרי הצבא",
  en: "Stage 08",
  eyebrow: "שלב 08 · השתחררתם",
  kicker: "קפה, נשימה, יציאה לדרך.",
  subKicker: "השנה הזאת מסמנת אתכם.",
  Avatar: Avatar08
}, {
  id: 9,
  name: "תלמיד מכינה",
  en: "Stage 09",
  eyebrow: "שלב 09 · מכינה",
  kicker: "שנה לסגור את הפערים.",
  subKicker: "טעם של למידה אמיתית.",
  Avatar: AvatarMechina
}, {
  id: 10,
  name: "סטודנט",
  en: "Stage 10",
  eyebrow: "שלב 10 · אוניברסיטה",
  kicker: "פסיכומטרי מאחור.",
  subKicker: "המשחק מתחיל להיות רציני.",
  Avatar: Avatar09
}, {
  id: 11,
  name: "בוגר תואר ראשון",
  en: "Stage 11",
  eyebrow: "שלב 11 · B.A.",
  kicker: "תואר ראשון בכיס.",
  subKicker: "ועוד יש לאן לטפס.",
  Avatar: Avatar10
}, {
  id: 12,
  name: "תואר שני",
  en: "Stage 12",
  eyebrow: "שלב 12 · M.A.",
  kicker: "אתם המומחים בחדר.",
  subKicker: "הזמן לחקור באמת.",
  Avatar: Avatar11
}, {
  id: 13,
  name: "דוקטורנט",
  en: "Stage 13",
  eyebrow: "שלב 13 · מחקר",
  kicker: "המחקר שלכם מתחיל.",
  subKicker: "לילות ארוכים, תגליות גדולות.",
  Avatar: AvatarDoctorand
}, {
  id: 14,
  name: "דוקטור",
  en: "Stage 14",
  eyebrow: "שלב 14 · Ph.D",
  kicker: "קוראים לכם דוקטור.",
  subKicker: "התזה עבר את הסף.",
  Avatar: AvatarDoctor
}, {
  id: 15,
  name: "פרופסור",
  en: "Stage 15",
  eyebrow: "שלב 15 · הפסגה",
  kicker: "פשוט הצלחתם.",
  subKicker: "הגעתם לפסגה. השם מתנגן: פרופ׳.",
  Avatar: Avatar12
}];
window.ROLE_LEVELS = LEVELS;
})(); } catch (e) { __ds_ns.__errors.push({ path: "role-game/levels.jsx", error: String((e && e.message) || e) }); }

// role-game/levelup-sketches.jsx
try { (() => {
/* global React, ReactDOM, ROLE_LEVELS */
const {
  useState,
  useMemo,
  useEffect,
  useRef,
  useCallback
} = React;
const LEVELS = window.ROLE_LEVELS;

/* Pick from→to pairs that show off each concept. */
const PAIRS = {
  c1: [13, 14],
  // Doctor → Professor — cinematic finale
  c2: [0, 1],
  // Baby → Kid — gentle metamorphosis
  c3: [10, 11],
  // BA → MA — diploma scroll
  c4: [3, 4],
  // Teen → HS — entering a new "place"
  c5: [5, 6],
  // HS Grad → Soldier — front-page worthy
  c6: [7, 8] // Post-army → Mechina — stamp of approval
};

/* ──────────────────────────────────────────────
   CARD SHELL — every concept renders inside this
   ────────────────────────────────────────────── */
/* Play durations vary by concept so the longer celebrations (cinematic,
   newspaper) get to breathe while the punchier ones (stamp) end on time. */
const PLAY_MS = 4500;
function ConceptCard({
  num,
  name,
  tagline,
  stagesTag,
  notes,
  children,
  registerPlay
}) {
  const [playing, setPlaying] = useState(false);
  const cardRef = useRef(null);
  const timerRef = useRef(null);
  const play = useCallback(() => {
    setPlaying(false); // reset so re-clicks restart the anim
    clearTimeout(timerRef.current);
    // double-rAF so the .playing class is removed then re-applied — restarts CSS keyframes.
    requestAnimationFrame(() => requestAnimationFrame(() => {
      setPlaying(true);
      timerRef.current = setTimeout(() => setPlaying(false), PLAY_MS);
    }));
  }, []);
  useEffect(() => () => clearTimeout(timerRef.current), []);
  useEffect(() => {
    if (registerPlay) registerPlay(num, play);
  }, [registerPlay, num, play]);
  return /*#__PURE__*/React.createElement("div", {
    className: "card"
  }, /*#__PURE__*/React.createElement("div", {
    className: "card-hd"
  }, /*#__PURE__*/React.createElement("div", {
    className: "num"
  }, String(num).padStart(2, "0")), /*#__PURE__*/React.createElement("h2", null, name, /*#__PURE__*/React.createElement("span", {
    style: {
      color: "var(--ez-orange)"
    }
  }, ".")), /*#__PURE__*/React.createElement("span", {
    className: "stages-tag"
  }, stagesTag), /*#__PURE__*/React.createElement("div", {
    className: "sub"
  }, tagline)), /*#__PURE__*/React.createElement("div", {
    className: "stage",
    ref: cardRef
  }, /*#__PURE__*/React.createElement("div", {
    className: "bg-z",
    "aria-hidden": true
  }), React.cloneElement(children, {
    playing
  })), /*#__PURE__*/React.createElement("div", {
    className: "card-ft"
  }, /*#__PURE__*/React.createElement("div", {
    className: "notes"
  }, notes), /*#__PURE__*/React.createElement("button", {
    className: "play-btn" + (playing ? " playing" : ""),
    onClick: play
  }, playing ? /*#__PURE__*/React.createElement(React.Fragment, null, /*#__PURE__*/React.createElement("span", null, "\u05DE\u05E0\u05D2\u05DF\u2026")) : /*#__PURE__*/React.createElement(React.Fragment, null, /*#__PURE__*/React.createElement("svg", {
    viewBox: "0 0 24 24",
    fill: "currentColor",
    "aria-hidden": true
  }, /*#__PURE__*/React.createElement("path", {
    d: "M8 5v14l11-7L8 5z"
  })), /*#__PURE__*/React.createElement("span", null, "\u05E0\u05D2\u05DF \u05D0\u05EA \u05D4\u05DE\u05E2\u05D1\u05E8")))));
}

/* ──────────────────────────────────────────────
   CONCEPT 01 — TITLE CARD (cinematic)
     • Bars slide in (letterbox)
     • Title letters cascade in with a stagger
     • Diagonal light sweep across the screen
     • Spark particles burst from the title center
     • Title rests with a subtle orange glow pulse
     • New avatar drifts up/down in idle
   ────────────────────────────────────────────── */
function Concept1({
  playing
}) {
  const [fromIdx, toIdx] = PAIRS.c1;
  const From = LEVELS[fromIdx].Avatar;
  const To = LEVELS[toIdx].Avatar;
  const name = LEVELS[toIdx].name;
  const dot = ".";
  // 8 sparks flying outward from title center
  const sparks = useMemo(() => Array.from({
    length: 10
  }, () => {
    const ang = Math.random() * Math.PI * 2;
    const dist = 60 + Math.random() * 110;
    return {
      dx: Math.cos(ang) * dist + "px",
      dy: Math.sin(ang) * dist + "px"
    };
  }), []);
  return /*#__PURE__*/React.createElement("div", {
    className: "c1" + (playing ? " playing" : "")
  }, /*#__PURE__*/React.createElement("div", {
    className: "bars top"
  }), /*#__PURE__*/React.createElement("div", {
    className: "bars bottom"
  }), /*#__PURE__*/React.createElement("div", {
    className: "av-from"
  }, /*#__PURE__*/React.createElement(From, null)), /*#__PURE__*/React.createElement("div", {
    className: "av-to"
  }, /*#__PURE__*/React.createElement(To, null)), /*#__PURE__*/React.createElement("div", {
    className: "eye"
  }, "stage ", String(LEVELS[toIdx].id).padStart(2, "0"), " \xB7 achievement"), /*#__PURE__*/React.createElement("div", {
    className: "title"
  }, Array.from(name).map((ch, i) => /*#__PURE__*/React.createElement("span", {
    key: i,
    className: "ch",
    style: {
      transitionDelay: 0.9 + i * 0.06 + "s"
    }
  }, ch === " " ? "\u00A0" : ch)), /*#__PURE__*/React.createElement("span", {
    className: "ch dot",
    style: {
      transitionDelay: 0.9 + name.length * 0.06 + "s"
    }
  }, dot)), /*#__PURE__*/React.createElement("div", {
    className: "sparks",
    "aria-hidden": true
  }, sparks.map((s, i) => /*#__PURE__*/React.createElement("i", {
    key: i,
    style: {
      "--dx": s.dx,
      "--dy": s.dy,
      animationDelay: 1.3 + Math.random() * 0.15 + "s"
    }
  }))), /*#__PURE__*/React.createElement("div", {
    className: "sweep"
  }));
}

/* ──────────────────────────────────────────────
   CONCEPT 02 — METAMORPHOSIS
     • Old avatar fades, burst + ring expand
     • Tiny particles fly outward (orange/lavender)
     • New avatar fades in with a gentle bob loop
   ────────────────────────────────────────────── */
function Concept2({
  playing
}) {
  const [fromIdx, toIdx] = PAIRS.c2;
  const From = LEVELS[fromIdx].Avatar;
  const To = LEVELS[toIdx].Avatar;
  const particles = useMemo(() => Array.from({
    length: 14
  }, (_, i) => {
    const ang = i / 14 * Math.PI * 2 + Math.random() * 0.3;
    const dist = 90 + Math.random() * 90;
    return {
      dx: Math.cos(ang) * dist + "px",
      dy: Math.sin(ang) * dist + "px",
      bg: i % 2 ? "var(--ez-orange)" : "var(--ez-lavender)"
    };
  }), []);
  return /*#__PURE__*/React.createElement("div", {
    className: "c2" + (playing ? " playing" : "")
  }, /*#__PURE__*/React.createElement("div", {
    className: "stack"
  }, /*#__PURE__*/React.createElement("div", {
    className: "ring"
  }), /*#__PURE__*/React.createElement("div", {
    className: "burst"
  }), /*#__PURE__*/React.createElement("div", {
    className: "av-from"
  }, /*#__PURE__*/React.createElement(From, null)), /*#__PURE__*/React.createElement("div", {
    className: "av-to"
  }, /*#__PURE__*/React.createElement(To, null))), /*#__PURE__*/React.createElement("div", {
    className: "particles",
    "aria-hidden": true
  }, particles.map((p, i) => /*#__PURE__*/React.createElement("i", {
    key: i,
    style: {
      "--dx": p.dx,
      "--dy": p.dy,
      background: p.bg
    }
  }))), /*#__PURE__*/React.createElement("div", {
    className: "labels"
  }, /*#__PURE__*/React.createElement("span", {
    className: "from-name"
  }, LEVELS[fromIdx].name), /*#__PURE__*/React.createElement("span", {
    className: "arrow"
  }, "\u203A"), /*#__PURE__*/React.createElement("span", {
    className: "to-name"
  }, LEVELS[toIdx].name, /*#__PURE__*/React.createElement("span", {
    className: "dot"
  }, "."))));
}

/* ──────────────────────────────────────────────
   CONCEPT 03 — DIPLOMA UNFURLS
     • Scroll opens with scale+fade
     • Orange seal stamps down with impact
     • Seal pulses gently after landing
     • Paper-tone petals confetti fall around the scroll
   ────────────────────────────────────────────── */
function Concept3({
  playing
}) {
  const [, toIdx] = PAIRS.c3;
  const petals = useMemo(() => Array.from({
    length: 18
  }, () => ({
    left: 5 + Math.random() * 90 + "%",
    delay: Math.random() * 1.6 + "s",
    duration: 2.2 + Math.random() * 1.4 + "s",
    bg: ["var(--ez-paper)", "var(--ez-orange-tint, #FBD9C2)", "var(--ez-lavender-tint, #D6D2F4)", "var(--ez-orange)"][Math.floor(Math.random() * 4)]
  })), []);
  return /*#__PURE__*/React.createElement("div", {
    className: "c3" + (playing ? " playing" : "")
  }, /*#__PURE__*/React.createElement("div", {
    className: "petals",
    "aria-hidden": true
  }, petals.map((p, i) => /*#__PURE__*/React.createElement("i", {
    key: i,
    style: {
      left: p.left,
      animationDelay: p.delay,
      animationDuration: p.duration,
      background: p.bg
    }
  }))), /*#__PURE__*/React.createElement("div", {
    className: "scroll-wrap"
  }, /*#__PURE__*/React.createElement("div", {
    className: "scroll"
  }, /*#__PURE__*/React.createElement("div", {
    className: "eye"
  }, "\u05EA\u05E2\u05D5\u05D3\u05EA \u05D4\u05E9\u05DC\u05D1"), /*#__PURE__*/React.createElement("div", {
    className: "title"
  }, LEVELS[toIdx].name, /*#__PURE__*/React.createElement("span", {
    className: "dot"
  }, ".")), /*#__PURE__*/React.createElement("div", {
    className: "body"
  }, "\u05E0\u05D9\u05EA\u05E0\u05EA \u05D1\u05D6\u05D0\u05EA \u05E2\u05DC \u05D4\u05E6\u05DC\u05D7\u05D4 \u05D1\u05DE\u05E2\u05D1\u05E8 ", LEVELS[toIdx].eyebrow.split("·")[0].trim(), ". ", LEVELS[toIdx].subKicker), /*#__PURE__*/React.createElement("div", {
    className: "seal"
  }, "\u05D0\u05D5\u05E9\u05E8", /*#__PURE__*/React.createElement("br", null), String(LEVELS[toIdx].id).padStart(2, "0")))));
}

/* ──────────────────────────────────────────────
   CONCEPT 04 — HIGHWAY SIGN
     • Sign drops in from above with bounce
     • Avatar walks up from below
     • Road chevrons stream forward (perspective receding)
     • Sign sways gently in idle, avatar bobs
   ────────────────────────────────────────────── */
function Concept4({
  playing
}) {
  const [, toIdx] = PAIRS.c4;
  const To = LEVELS[toIdx].Avatar;
  // 5 chevrons staggered along the road, looping continuously
  const chevrons = Array.from({
    length: 5
  });
  return /*#__PURE__*/React.createElement("div", {
    className: "c4" + (playing ? " playing" : "")
  }, /*#__PURE__*/React.createElement("div", {
    className: "chevrons",
    "aria-hidden": true
  }, chevrons.map((_, i) => /*#__PURE__*/React.createElement("i", {
    key: i,
    style: {
      animationDelay: i * 0.48 + "s"
    }
  }))), /*#__PURE__*/React.createElement("div", {
    className: "sign"
  }, /*#__PURE__*/React.createElement("div", {
    className: "eye"
  }, "\u2014 now entering \u2014"), /*#__PURE__*/React.createElement("div", {
    className: "name"
  }, LEVELS[toIdx].name, /*#__PURE__*/React.createElement("span", {
    className: "dot"
  }, ".")), /*#__PURE__*/React.createElement("div", {
    className: "stamp"
  }, "\u05E9\u05DC\u05D1 ", String(LEVELS[toIdx].id).padStart(2, "0"), " \xB7 \u05E7\u05E6\u05D1 \u05DE\u05E2\u05D5\u05DC\u05D4")), /*#__PURE__*/React.createElement("div", {
    className: "av-to"
  }, /*#__PURE__*/React.createElement(To, null)));
}

/* ──────────────────────────────────────────────
   CONCEPT 05 — FRONT PAGE
     • Paper rotates in from bottom + opacity
     • Settles with a subtle rocking idle
     • A red "EXTRA!" stamp lands on top, rotated
   ────────────────────────────────────────────── */
function Concept5({
  playing
}) {
  const [, toIdx] = PAIRS.c5;
  const To = LEVELS[toIdx].Avatar;
  return /*#__PURE__*/React.createElement("div", {
    className: "c5" + (playing ? " playing" : "")
  }, /*#__PURE__*/React.createElement("div", {
    className: "paper"
  }, /*#__PURE__*/React.createElement("div", {
    className: "masthead"
  }, /*#__PURE__*/React.createElement("span", {
    className: "name"
  }, "eazy", /*#__PURE__*/React.createElement("span", {
    className: "dot"
  }, ".")), /*#__PURE__*/React.createElement("span", {
    className: "date"
  }, "\u05D2\u05DC\u05D9\u05D5\u05DF \u05DE\u05E1\u05F3 ", String(LEVELS[toIdx].id).padStart(3, "0"), " \xB7 \u05D9\u05D5\u05DD \u05D4\u05E9\u05DC\u05D1")), /*#__PURE__*/React.createElement("div", {
    className: "kicker"
  }, LEVELS[toIdx].eyebrow), /*#__PURE__*/React.createElement("div", {
    className: "body"
  }, /*#__PURE__*/React.createElement("div", null, /*#__PURE__*/React.createElement("div", {
    className: "headline"
  }, LEVELS[toIdx].kicker.replace(/[.!]$/, ""), /*#__PURE__*/React.createElement("span", {
    className: "dot"
  }, LEVELS[toIdx].kicker.match(/[.!]$/)?.[0] || ".")), /*#__PURE__*/React.createElement("div", {
    className: "col"
  }, /*#__PURE__*/React.createElement("p", null, "\u05D4\u05E9\u05D7\u05E7\u05DF \u05E2\u05DC\u05D4 \u05D4\u05D1\u05D5\u05E7\u05E8 \u05DC\u05E9\u05DC\u05D1 ", LEVELS[toIdx].name, " \u05D0\u05D7\u05E8\u05D9 \u05E8\u05E6\u05E3 \u05E0\u05DB\u05D5\u05E0\u05D5\u05EA \u05DE\u05E8\u05E9\u05D9\u05DD."), /*#__PURE__*/React.createElement("p", null, LEVELS[toIdx].subKicker, " \u05E4\u05D9\u05E8\u05D5\u05D8 \u05DE\u05DC\u05D0 \u05D1\u05E2\u05DE\u05D5\u05D3 \u05D4\u05D1\u05D0."))), /*#__PURE__*/React.createElement("div", {
    className: "photo"
  }, /*#__PURE__*/React.createElement(To, null)))), /*#__PURE__*/React.createElement("div", {
    className: "extra-stamp"
  }, "EXTRA", /*#__PURE__*/React.createElement("span", {
    style: {
      color: "inherit"
    }
  }, "!")));
}

/* ──────────────────────────────────────────────
   CONCEPT 06 — STAMP & SEAL
   ────────────────────────────────────────────── */
function Concept6({
  playing
}) {
  const [, toIdx] = PAIRS.c6;
  // confetti positions — radial burst
  const pieces = useMemo(() => Array.from({
    length: 24
  }, (_, i) => {
    const ang = i / 24 * Math.PI * 2 + Math.random() * 0.2;
    const dist = 110 + Math.random() * 80;
    return {
      dx: Math.cos(ang) * dist + "px",
      dy: Math.sin(ang) * dist + "px",
      rz: Math.random() * 720 - 360 + "deg",
      bg: ["var(--ez-orange)", "var(--ez-lavender)", "var(--ez-indigo)", "var(--ez-orange-soft, #FBD9C2)"][i % 4],
      delay: Math.random() * 0.3 + "s"
    };
  }), []);
  return /*#__PURE__*/React.createElement("div", {
    className: "c6" + (playing ? " playing" : "")
  }, /*#__PURE__*/React.createElement("div", {
    className: "paper-bg"
  }, /*#__PURE__*/React.createElement("div", {
    className: "eye"
  }, "\u05EA\u05E2\u05D5\u05D3\u05EA \u05DE\u05E2\u05D1\u05E8"), /*#__PURE__*/React.createElement("div", {
    className: "title"
  }, LEVELS[toIdx].kicker.replace(/[.!]$/, ""), /*#__PURE__*/React.createElement("span", {
    className: "dot"
  }, LEVELS[toIdx].kicker.match(/[.!]$/)?.[0] || "."))), /*#__PURE__*/React.createElement("div", {
    className: "stamp"
  }, /*#__PURE__*/React.createElement("div", {
    className: "ring-out"
  }), /*#__PURE__*/React.createElement("div", {
    className: "ring-in"
  }), /*#__PURE__*/React.createElement("div", {
    className: "word"
  }, "\u05D0\u05D5\u05E9\u05E8", /*#__PURE__*/React.createElement("span", {
    className: "dot"
  }, "."))), /*#__PURE__*/React.createElement("div", {
    className: "confetti-burst"
  }, pieces.map((p, i) => /*#__PURE__*/React.createElement("i", {
    key: i,
    style: {
      "--dx": p.dx,
      "--dy": p.dy,
      "--rz": p.rz,
      background: p.bg,
      animationDelay: p.delay
    }
  }))), /*#__PURE__*/React.createElement("div", {
    className: "confetti-burst wave2",
    "aria-hidden": true
  }, pieces.map((p, i) => /*#__PURE__*/React.createElement("i", {
    key: i,
    style: {
      "--dx": p.dx,
      "--dy": p.dy,
      "--rz": p.rz,
      background: p.bg
    }
  }))));
}

/* ──────────────────────────────────────────────
   ROOT — render the grid + the mapping table
   ────────────────────────────────────────────── */
function App() {
  // Each concept registers its `play()` function so the toolbar
  // "Play all" button can fire them in sequence.
  const playFnsRef = useRef({});
  const registerPlay = useCallback((num, fn) => {
    playFnsRef.current[num] = fn;
  }, []);
  const playAllTimers = useRef([]);
  const [playingAll, setPlayingAll] = useState(false);
  useEffect(() => {
    const btn = document.getElementById("play-all-btn");
    const label = document.getElementById("play-all-label");
    if (!btn || !label) return;
    function clearAll() {
      playAllTimers.current.forEach(clearTimeout);
      playAllTimers.current = [];
    }
    function onClick() {
      clearAll();
      setPlayingAll(true);
      btn.classList.add("playing");
      label.textContent = "מנגן… 1/6";
      [1, 2, 3, 4, 5, 6].forEach((n, i) => {
        playAllTimers.current.push(setTimeout(() => {
          const fn = playFnsRef.current[n];
          if (fn) fn();
          label.textContent = "מנגן… " + n + "/6";
          // scroll the card into view as we go so the user actually sees it
          const cards = document.querySelectorAll(".grid > .card");
          if (cards[n - 1]) cards[n - 1].scrollIntoView({
            behavior: "smooth",
            block: "center"
          });
        }, i * (PLAY_MS - 700)));
      });
      playAllTimers.current.push(setTimeout(() => {
        setPlayingAll(false);
        btn.classList.remove("playing");
        label.textContent = "נגן את כל ה־6";
      }, 6 * (PLAY_MS - 700) + 600));
    }
    btn.addEventListener("click", onClick);
    return () => {
      btn.removeEventListener("click", onClick);
      clearAll();
    };
  }, []);
  const concepts = [{
    num: 1,
    name: "כותרת קולנועית",
    tagline: "Letterbox + שם ענק + סוויפ אור · 1.5 שניות של תהילה",
    stagesTag: "לרגעים דרמטיים",
    notes: "פסים שחורים נסגרים מלמעלה ומלמטה כמו סרט קולנוע, האווטר עולה מהאפלולית, השם נחתם במרכז. הכי מתאים לרגעי שיא: בוגר תיכון, חייל, ופרופסור.",
    Comp: Concept1
  }, {
    num: 2,
    name: "מטמורפוזה",
    tagline: "ילד הופך לבא · התפוצצות אור · חילופי דמות",
    stagesTag: "לרגעי המשך עדינים",
    notes: "האווטר הישן מתפוגג לסילואטה, גל אור מתפזר, ומבפנים בוקעת הדמות החדשה. שומר על תחושת אותו אדם שגדל. מושלם למעברים בילדות.",
    Comp: Concept2
  }, {
    num: 3,
    name: "תעודה נגללת",
    tagline: "ניר רשמי · חותמת מסתחררת · indigo + orange seal",
    stagesTag: "להישגים אקדמיים",
    notes: "תעודה רשמית בעיצוב מסמך, נפתחת מ־scale 0.4 ל־1, חותמת כתומה נחבטת בפינה תוך כדי סיבוב. הקונספט הזה גם משחק על הזהות של eazy סביב לימודים גבוהים.",
    Comp: Concept3
  }, {
    num: 4,
    name: "שלט כביש",
    tagline: "Now Entering · שם השלב כשלט תנועה כתום",
    stagesTag: "למעברים אנרגטיים",
    notes: "פרספקטיבה של כביש לילי, שלט כתום בסגנון הכבישים המהירים נחבט מלמטה למקום ועליו השם החדש. האווטר מטייל מתחתיו. מטאפורה של 'עוברים את הגבול'.",
    Comp: Concept4
  }, {
    num: 5,
    name: "כותרת ראשית",
    tagline: "עיתון מתעופף פנימה · השם החדש כתבה ראשית",
    stagesTag: "לסיפור גדול",
    notes: "ה־eazy של מחר. דף ראשון של עיתון מסתחרר פנימה, עם תאריך, ציטוט, קולומה, ותמונה בגווני אפור. מצוין למעברים שמרגישים כמו 'אירוע' — בגרות, אחרי הצבא.",
    Comp: Concept5
  }, {
    num: 6,
    name: "חותמת אישור",
    tagline: "Stamp + confetti burst רדיאלי",
    stagesTag: "לקצב משחקי",
    notes: "חותמת כתומה ענקית נחבטת על תעודה (rotate + scale impact), ובאותו רגע פיצוץ קונפטי רדיאלי בארבעה צבעי המותג. מהיר, אגרסיבי בכיף, בלי לעצור את הקצב.",
    Comp: Concept6
  }];
  return concepts.map(c => /*#__PURE__*/React.createElement(ConceptCard, {
    key: c.num,
    num: c.num,
    name: c.name,
    tagline: c.tagline,
    stagesTag: c.stagesTag,
    notes: c.notes,
    registerPlay: registerPlay
  }, /*#__PURE__*/React.createElement(c.Comp, null)));
}
ReactDOM.createRoot(document.getElementById("root")).render(/*#__PURE__*/React.createElement(App, null));

/* ──────────────────────────────────────────────
   STAGE → CONCEPT mapping table
   ────────────────────────────────────────────── */
const MAPPING = [
// levelIdx 1..14 — the transition is "X → X+1", attribute to the destination
{
  to: 1,
  concept: 2,
  why: "המעבר העדין הראשון — לא רוצים לעצור את הקצב; מטמורפוזה רכה."
}, {
  to: 2,
  concept: 2,
  why: "עדיין ילדות — אותה דמות שגדלה. שומר על המשכיות."
}, {
  to: 3,
  concept: 4,
  why: "כניסה ל'עולם הגדול' של חט\"ב — שלט כביש עם 'now entering'."
}, {
  to: 4,
  concept: 6,
  why: "תיכוניסט — חותמת אישור עם קונפטי, קצב משחקי."
}, {
  to: 5,
  concept: 1,
  why: "בוגר תיכון — רגע ההכרזה הראשון. כותרת קולנועית."
}, {
  to: 6,
  concept: 5,
  why: "חייל — אירוע. עיתון, כותרת ראשית, תמונה בגווני אפור."
}, {
  to: 7,
  concept: 4,
  why: "אחרי הצבא — שלב חדש בחיים. שלט 'now entering'."
}, {
  to: 8,
  concept: 6,
  why: "מכינה — מוטיבציוני, חותמת + קונפטי לחזק את הצעד הזה."
}, {
  to: 9,
  concept: 1,
  why: "סטודנט — רגע משמעותי. כותרת קולנועית עם שם."
}, {
  to: 10,
  concept: 3,
  why: "תואר ראשון — תעודה. מסמך רשמי שנגלל וחותמת."
}, {
  to: 11,
  concept: 3,
  why: "תואר שני — שוב תעודה אבל ב־indigo עמוק יותר. סדרה אקדמית."
}, {
  to: 12,
  concept: 6,
  why: "דוקטורנט — עוד צעד פנימי. חותמת + קונפטי כדי לחזק."
}, {
  to: 13,
  concept: 3,
  why: "דוקטור — שיא אקדמי. תעודה רשמית עם חותמת זהובה."
}, {
  to: 14,
  concept: 1,
  why: "פרופסור — הקרדיטים. הכותרת הקולנועית הסופית, full bleed."
}];
function MappingTable() {
  return /*#__PURE__*/React.createElement(React.Fragment, null, /*#__PURE__*/React.createElement("h3", null, "\u05D0\u05D9\u05DA \u05DC\u05D2\u05D5\u05D5\u05DF \u05D1\u05D9\u05DF \u05D4\u05E9\u05DC\u05D1\u05D9\u05DD", /*#__PURE__*/React.createElement("span", {
    className: "dot"
  }, ".")), /*#__PURE__*/React.createElement("p", null, "14 \u05D4\u05DE\u05E2\u05D1\u05E8\u05D9\u05DD \u05E9\u05D9\u05E9 \u05D1\u05DE\u05E9\u05D7\u05E7, \u05DE\u05E7\u05D5\u05D8\u05DC\u05D2\u05D9\u05DD \u05DC\u05E4\u05D9 \u05E7\u05D5\u05E0\u05E1\u05E4\u05D8. \u05D4\u05E8\u05E2\u05D9\u05D5\u05DF: \u05E9\u05DC\u05D0 \u05DB\u05DC \u05DE\u05E2\u05D1\u05E8 \u05D9\u05E8\u05D2\u05D9\u05E9 \u05D0\u05D5\u05EA\u05D5 \u05D3\u05D1\u05E8 \u2014 \u05D4\u05D0\u05E7\u05D3\u05DE\u05D9\u05D9\u05DD \u05DE\u05E7\u05D1\u05DC\u05D9\u05DD \u05EA\u05E2\u05D5\u05D3\u05D5\u05EA, \u05D4'\u05D0\u05D9\u05E8\u05D5\u05E2\u05D9\u05D9\u05DD' \u05DE\u05E7\u05D1\u05DC\u05D9\u05DD \u05E2\u05D9\u05EA\u05D5\u05DF \u05D0\u05D5 \u05DB\u05D5\u05EA\u05E8\u05EA \u05E7\u05D5\u05DC\u05E0\u05D5\u05E2\u05D9\u05EA, \u05D5\u05D1\u05D0\u05DE\u05E6\u05E2 \u05D9\u05E9 \u05E7\u05D5\u05E0\u05E4\u05D8\u05D9 \u05DE\u05E9\u05D7\u05E7\u05D9 \u05DB\u05D3\u05D9 \u05DC\u05E9\u05DE\u05D5\u05E8 \u05E2\u05DC \u05E7\u05E6\u05D1."), /*#__PURE__*/React.createElement("table", null, /*#__PURE__*/React.createElement("thead", null, /*#__PURE__*/React.createElement("tr", null, /*#__PURE__*/React.createElement("th", {
    style: {
      width: "24px"
    }
  }, "#"), /*#__PURE__*/React.createElement("th", null, "\u05D4\u05DE\u05E2\u05D1\u05E8"), /*#__PURE__*/React.createElement("th", null, "\u05E7\u05D5\u05E0\u05E1\u05E4\u05D8"), /*#__PURE__*/React.createElement("th", null, "\u05DC\u05DE\u05D4 \u05D6\u05D4 \u05DE\u05EA\u05D0\u05D9\u05DD"))), /*#__PURE__*/React.createElement("tbody", null, MAPPING.map(m => {
    const lv = LEVELS[m.to];
    const lvFrom = LEVELS[m.to - 1];
    return /*#__PURE__*/React.createElement("tr", {
      key: m.to
    }, /*#__PURE__*/React.createElement("td", null, /*#__PURE__*/React.createElement("span", {
      className: "stage-num"
    }, String(lv.id).padStart(2, "0"))), /*#__PURE__*/React.createElement("td", null, /*#__PURE__*/React.createElement("span", {
      className: "stage-name"
    }, lvFrom.name), /*#__PURE__*/React.createElement("span", {
      style: {
        margin: "0 8px",
        color: "var(--ez-orange)"
      }
    }, "\u203A"), /*#__PURE__*/React.createElement("span", {
      className: "stage-name"
    }, lv.name)), /*#__PURE__*/React.createElement("td", null, /*#__PURE__*/React.createElement("span", {
      className: "concept-pill c" + m.concept
    }, "\u05E7\u05D5\u05E0\u05E1\u05E4\u05D8 ", String(m.concept).padStart(2, "0"))), /*#__PURE__*/React.createElement("td", {
      className: "why"
    }, m.why));
  }))));
}
ReactDOM.createRoot(document.getElementById("map-root")).render(/*#__PURE__*/React.createElement(MappingTable, null));
})(); } catch (e) { __ds_ns.__errors.push({ path: "role-game/levelup-sketches.jsx", error: String((e && e.message) || e) }); }

// role-game/levelup-variants.jsx
try { (() => {
/* global React */
/* eazy · role-game — Level-Up Variants
   ─────────────────────────────────────────────────────────────
   Six "big-deal" level-up celebrations. Each takes the same props:
     from           — the level the player just left (LEVEL object)
     to             — the new level (LEVEL object)
     onContinue     — fired when the player taps "המשך לשלב הבא ›"

   The exported <LevelUpV2> component picks the right variant for
   the destination stage id, via STAGE_LU_MAPPING. A `forceVariant`
   prop can pin a specific concept (used by the Tweaks panel for
   testing). All six concepts use the same .rg-lu-cta button at the
   bottom so the "continue" interaction is identical across them.
*/

const {
  useState: useStateLU,
  useEffect: useEffectLU,
  useMemo: useMemoLU
} = React;

/* Pick a concept per destination stage. Designed for the 15-stage
   journey in levels.jsx — see levelup-sketches.html for the rationale.
   The destination stage id is 1-indexed (matches level.id). */
const STAGE_LU_MAPPING = {
  2: "metamorph",
  //  baby → kid
  3: "metamorph",
  //  kid → elementary
  4: "sign",
  //  elementary → teen
  5: "stamp",
  //  teen → highschool
  6: "title",
  //  highschool → grad — first big cinematic moment
  7: "frontpage",
  //  grad → soldier — event-worthy
  8: "sign",
  //  soldier → post-army
  9: "stamp",
  //  post-army → mechina
  10: "title",
  //  mechina → student
  11: "diploma",
  //  student → BA
  12: "diploma",
  //  BA → MA
  13: "stamp",
  //  MA → PhD-candidate
  14: "diploma",
  //  PhD-candidate → doctor
  15: "title" //  doctor → professor — finale cinematic
};

/* ──────────────────────────────────────────────
   Concept 01 — TITLE CARD (cinematic)
   ────────────────────────────────────────────── */
function LU_TitleCard({
  from,
  to
}) {
  const name = to.name;
  // Letter cascade — each character gets its own delayed reveal
  const chars = useMemoLU(() => Array.from(name), [name]);
  // Spark particles fly outward from title center
  const sparks = useMemoLU(() => Array.from({
    length: 12
  }, () => {
    const ang = Math.random() * Math.PI * 2;
    const dist = 70 + Math.random() * 130;
    return {
      dx: Math.cos(ang) * dist + "px",
      dy: Math.sin(ang) * dist + "px",
      delay: 1.3 + Math.random() * 0.2 + "s"
    };
  }), [to.id]);
  const From = from.Avatar,
    To = to.Avatar;
  return /*#__PURE__*/React.createElement("div", {
    className: "lu-v1 playing"
  }, /*#__PURE__*/React.createElement("div", {
    className: "bars top"
  }), /*#__PURE__*/React.createElement("div", {
    className: "bars bottom"
  }), /*#__PURE__*/React.createElement("div", {
    className: "av-from"
  }, /*#__PURE__*/React.createElement(From, null)), /*#__PURE__*/React.createElement("div", {
    className: "av-to"
  }, /*#__PURE__*/React.createElement(To, null)), /*#__PURE__*/React.createElement("div", {
    className: "eye"
  }, to.eyebrow), /*#__PURE__*/React.createElement("div", {
    className: "title"
  }, chars.map((ch, i) => /*#__PURE__*/React.createElement("span", {
    key: i,
    className: "ch",
    style: {
      transitionDelay: 0.9 + i * 0.06 + "s"
    }
  }, ch === " " ? "\u00A0" : ch)), /*#__PURE__*/React.createElement("span", {
    className: "ch dot",
    style: {
      transitionDelay: 0.9 + name.length * 0.06 + "s"
    }
  }, ".")), /*#__PURE__*/React.createElement("div", {
    className: "sub"
  }, to.subKicker), /*#__PURE__*/React.createElement("div", {
    className: "sparks",
    "aria-hidden": true
  }, sparks.map((s, i) => /*#__PURE__*/React.createElement("i", {
    key: i,
    style: {
      "--dx": s.dx,
      "--dy": s.dy,
      animationDelay: s.delay
    }
  }))), /*#__PURE__*/React.createElement("div", {
    className: "sweep"
  }));
}

/* ──────────────────────────────────────────────
   Concept 02 — METAMORPHOSIS
   ────────────────────────────────────────────── */
function LU_Metamorph({
  from,
  to
}) {
  const From = from.Avatar,
    To = to.Avatar;
  const particles = useMemoLU(() => Array.from({
    length: 14
  }, (_, i) => {
    const ang = i / 14 * Math.PI * 2 + Math.random() * 0.3;
    const dist = 90 + Math.random() * 90;
    return {
      dx: Math.cos(ang) * dist + "px",
      dy: Math.sin(ang) * dist + "px",
      bg: i % 2 ? "var(--ez-orange)" : "var(--ez-lavender)"
    };
  }), [to.id]);
  return /*#__PURE__*/React.createElement("div", {
    className: "lu-v2 playing"
  }, /*#__PURE__*/React.createElement("div", {
    className: "stack"
  }, /*#__PURE__*/React.createElement("div", {
    className: "ring"
  }), /*#__PURE__*/React.createElement("div", {
    className: "burst"
  }), /*#__PURE__*/React.createElement("div", {
    className: "av-from"
  }, /*#__PURE__*/React.createElement(From, null)), /*#__PURE__*/React.createElement("div", {
    className: "av-to"
  }, /*#__PURE__*/React.createElement(To, null))), /*#__PURE__*/React.createElement("div", {
    className: "particles",
    "aria-hidden": true
  }, particles.map((p, i) => /*#__PURE__*/React.createElement("i", {
    key: i,
    style: {
      "--dx": p.dx,
      "--dy": p.dy,
      background: p.bg
    }
  }))), /*#__PURE__*/React.createElement("div", {
    className: "labels"
  }, /*#__PURE__*/React.createElement("span", {
    className: "from-name"
  }, from.name), /*#__PURE__*/React.createElement("span", {
    className: "arrow"
  }, "\u203A"), /*#__PURE__*/React.createElement("span", {
    className: "to-name"
  }, to.name, /*#__PURE__*/React.createElement("span", {
    className: "dot"
  }, "."))), /*#__PURE__*/React.createElement("div", {
    className: "kicker"
  }, to.kicker.replace(/[.!]$/, ""), /*#__PURE__*/React.createElement("span", {
    className: "dot"
  }, to.kicker.match(/[.!]$/)?.[0] || ".")));
}

/* ──────────────────────────────────────────────
   Concept 03 — DIPLOMA UNFURLS
   ────────────────────────────────────────────── */
function LU_Diploma({
  to
}) {
  const petals = useMemoLU(() => Array.from({
    length: 22
  }, () => ({
    left: 4 + Math.random() * 92 + "%",
    delay: Math.random() * 1.8 + "s",
    duration: 2.2 + Math.random() * 1.4 + "s",
    bg: ["var(--ez-paper)", "var(--ez-orange-tint, #FBD9C2)", "var(--ez-lavender-tint, #D6D2F4)", "var(--ez-orange)"][Math.floor(Math.random() * 4)]
  })), [to.id]);
  return /*#__PURE__*/React.createElement("div", {
    className: "lu-v3 playing"
  }, /*#__PURE__*/React.createElement("div", {
    className: "petals",
    "aria-hidden": true
  }, petals.map((p, i) => /*#__PURE__*/React.createElement("i", {
    key: i,
    style: {
      left: p.left,
      animationDelay: p.delay,
      animationDuration: p.duration,
      background: p.bg
    }
  }))), /*#__PURE__*/React.createElement("div", {
    className: "scroll-wrap"
  }, /*#__PURE__*/React.createElement("div", {
    className: "scroll"
  }, /*#__PURE__*/React.createElement("div", {
    className: "eye"
  }, "\u05EA\u05E2\u05D5\u05D3\u05EA \u05D4\u05E9\u05DC\u05D1"), /*#__PURE__*/React.createElement("div", {
    className: "title"
  }, to.name, /*#__PURE__*/React.createElement("span", {
    className: "dot"
  }, ".")), /*#__PURE__*/React.createElement("div", {
    className: "body"
  }, "\u05E0\u05D9\u05EA\u05E0\u05EA \u05D1\u05D6\u05D0\u05EA \u05E2\u05DC \u05D4\u05E6\u05DC\u05D7\u05D4 \u05D1\u05DE\u05E2\u05D1\u05E8 ", to.eyebrow.split("·")[0].trim(), ". ", to.subKicker), /*#__PURE__*/React.createElement("div", {
    className: "seal"
  }, "\u05D0\u05D5\u05E9\u05E8", /*#__PURE__*/React.createElement("br", null), String(to.id).padStart(2, "0")))));
}

/* ──────────────────────────────────────────────
   Concept 04 — HIGHWAY SIGN
   ────────────────────────────────────────────── */
function LU_Sign({
  to
}) {
  const To = to.Avatar;
  return /*#__PURE__*/React.createElement("div", {
    className: "lu-v4 playing"
  }, /*#__PURE__*/React.createElement("div", {
    className: "chevrons",
    "aria-hidden": true
  }, Array.from({
    length: 5
  }).map((_, i) => /*#__PURE__*/React.createElement("i", {
    key: i,
    style: {
      animationDelay: i * 0.48 + "s"
    }
  }))), /*#__PURE__*/React.createElement("div", {
    className: "sign"
  }, /*#__PURE__*/React.createElement("div", {
    className: "eye"
  }, "\u2014 now entering \u2014"), /*#__PURE__*/React.createElement("div", {
    className: "name"
  }, to.name, /*#__PURE__*/React.createElement("span", {
    className: "dot"
  }, ".")), /*#__PURE__*/React.createElement("div", {
    className: "stamp"
  }, "\u05E9\u05DC\u05D1 ", String(to.id).padStart(2, "0"), " \xB7 ", to.kicker.replace(/[.!]$/, ""))), /*#__PURE__*/React.createElement("div", {
    className: "av-to"
  }, /*#__PURE__*/React.createElement(To, null)));
}

/* ──────────────────────────────────────────────
   Concept 05 — FRONT PAGE
   ────────────────────────────────────────────── */
function LU_FrontPage({
  to
}) {
  const To = to.Avatar;
  return /*#__PURE__*/React.createElement("div", {
    className: "lu-v5 playing"
  }, /*#__PURE__*/React.createElement("div", {
    className: "paper"
  }, /*#__PURE__*/React.createElement("div", {
    className: "masthead"
  }, /*#__PURE__*/React.createElement("span", {
    className: "name"
  }, "eazy", /*#__PURE__*/React.createElement("span", {
    className: "dot"
  }, ".")), /*#__PURE__*/React.createElement("span", {
    className: "date"
  }, "\u05D2\u05DC\u05D9\u05D5\u05DF \u05DE\u05E1\u05F3 ", String(to.id).padStart(3, "0"), " \xB7 \u05D9\u05D5\u05DD \u05D4\u05E9\u05DC\u05D1")), /*#__PURE__*/React.createElement("div", {
    className: "kicker"
  }, to.eyebrow), /*#__PURE__*/React.createElement("div", {
    className: "body"
  }, /*#__PURE__*/React.createElement("div", null, /*#__PURE__*/React.createElement("div", {
    className: "headline"
  }, to.kicker.replace(/[.!]$/, ""), /*#__PURE__*/React.createElement("span", {
    className: "dot"
  }, to.kicker.match(/[.!]$/)?.[0] || ".")), /*#__PURE__*/React.createElement("div", {
    className: "col"
  }, /*#__PURE__*/React.createElement("p", null, "\u05D4\u05E9\u05D7\u05E7\u05DF \u05E2\u05DC\u05D4 \u05D4\u05D1\u05D5\u05E7\u05E8 \u05DC\u05E9\u05DC\u05D1 ", to.name, " \u05D0\u05D7\u05E8\u05D9 \u05E8\u05E6\u05E3 \u05E0\u05DB\u05D5\u05E0\u05D5\u05EA \u05DE\u05E8\u05E9\u05D9\u05DD."), /*#__PURE__*/React.createElement("p", null, to.subKicker, " \u05E4\u05D9\u05E8\u05D5\u05D8 \u05DE\u05DC\u05D0 \u05D1\u05E2\u05DE\u05D5\u05D3 \u05D4\u05D1\u05D0."))), /*#__PURE__*/React.createElement("div", {
    className: "photo"
  }, /*#__PURE__*/React.createElement(To, null)))), /*#__PURE__*/React.createElement("div", {
    className: "extra-stamp"
  }, "EXTRA", /*#__PURE__*/React.createElement("span", null, "!")));
}

/* ──────────────────────────────────────────────
   Concept 06 — STAMP & SEAL
   ────────────────────────────────────────────── */
function LU_Stamp({
  to
}) {
  const pieces = useMemoLU(() => Array.from({
    length: 32
  }, (_, i) => {
    const ang = i / 32 * Math.PI * 2 + Math.random() * 0.2;
    const dist = 130 + Math.random() * 110;
    return {
      dx: Math.cos(ang) * dist + "px",
      dy: Math.sin(ang) * dist + "px",
      rz: Math.random() * 720 - 360 + "deg",
      bg: ["var(--ez-orange)", "var(--ez-lavender)", "var(--ez-indigo)", "var(--ez-orange-soft, #FBD9C2)"][i % 4],
      delay: Math.random() * 0.3 + "s"
    };
  }), [to.id]);
  return /*#__PURE__*/React.createElement("div", {
    className: "lu-v6 playing"
  }, /*#__PURE__*/React.createElement("div", {
    className: "paper-bg"
  }, /*#__PURE__*/React.createElement("div", {
    className: "eye"
  }, "\u05EA\u05E2\u05D5\u05D3\u05EA \u05DE\u05E2\u05D1\u05E8"), /*#__PURE__*/React.createElement("div", {
    className: "title"
  }, to.kicker.replace(/[.!]$/, ""), /*#__PURE__*/React.createElement("span", {
    className: "dot"
  }, to.kicker.match(/[.!]$/)?.[0] || ".")), /*#__PURE__*/React.createElement("div", {
    className: "sub"
  }, to.subKicker)), /*#__PURE__*/React.createElement("div", {
    className: "stamp"
  }, /*#__PURE__*/React.createElement("div", {
    className: "ring-out"
  }), /*#__PURE__*/React.createElement("div", {
    className: "ring-in"
  }), /*#__PURE__*/React.createElement("div", {
    className: "word"
  }, "\u05D0\u05D5\u05E9\u05E8", /*#__PURE__*/React.createElement("span", {
    className: "dot"
  }, "."))), /*#__PURE__*/React.createElement("div", {
    className: "confetti-burst"
  }, pieces.map((p, i) => /*#__PURE__*/React.createElement("i", {
    key: i,
    style: {
      "--dx": p.dx,
      "--dy": p.dy,
      "--rz": p.rz,
      background: p.bg,
      animationDelay: p.delay
    }
  }))), /*#__PURE__*/React.createElement("div", {
    className: "confetti-burst wave2",
    "aria-hidden": true
  }, pieces.map((p, i) => /*#__PURE__*/React.createElement("i", {
    key: i,
    style: {
      "--dx": p.dx,
      "--dy": p.dy,
      "--rz": p.rz,
      background: p.bg
    }
  }))));
}

/* ──────────────────────────────────────────────
   Dispatcher — picks the variant per destination stage
   ────────────────────────────────────────────── */
const VARIANTS = {
  title: LU_TitleCard,
  metamorph: LU_Metamorph,
  diploma: LU_Diploma,
  sign: LU_Sign,
  frontpage: LU_FrontPage,
  stamp: LU_Stamp
};
const VARIANT_LIST = ["auto", "title", "metamorph", "diploma", "sign", "frontpage", "stamp"];
function LevelUpV2({
  from,
  to,
  onContinue,
  forceVariant
}) {
  // CTA reveal — wait for the entrance animation to settle before
  // surfacing the button so the user is encouraged to enjoy the moment.
  const [ctaReady, setCtaReady] = useStateLU(false);
  useEffectLU(() => {
    setCtaReady(false);
    const t = setTimeout(() => setCtaReady(true), 1800);
    return () => clearTimeout(t);
  }, [to.id]);

  // Pick variant — explicit override > stage mapping > fallback to stamp
  let variantName = forceVariant && forceVariant !== "auto" ? forceVariant : STAGE_LU_MAPPING[to.id];
  if (!variantName || !VARIANTS[variantName]) variantName = "stamp";
  const Variant = VARIANTS[variantName];
  return /*#__PURE__*/React.createElement("div", {
    className: "rg-levelup-v2",
    "data-variant": variantName
  }, /*#__PURE__*/React.createElement(Variant, {
    from: from,
    to: to
  }), /*#__PURE__*/React.createElement("div", {
    className: "rg-lu-brand",
    "aria-hidden": true
  }, /*#__PURE__*/React.createElement("img", {
    src: "../assets/ez-icon.png",
    alt: ""
  }), /*#__PURE__*/React.createElement("span", {
    className: "brand-eazy"
  }, "eazy", /*#__PURE__*/React.createElement("span", {
    className: "dot"
  }, "."))), /*#__PURE__*/React.createElement("button", {
    className: "rg-lu-cta" + (ctaReady ? " ready" : ""),
    onClick: onContinue,
    "aria-label": "\u05D4\u05DE\u05E9\u05DA \u05DC\u05E9\u05DC\u05D1 \u05D4\u05D1\u05D0"
  }, "\u05D4\u05DE\u05E9\u05DA \u05DC\u05E9\u05DC\u05D1 \u05D4\u05D1\u05D0 ", /*#__PURE__*/React.createElement("span", {
    "aria-hidden": true
  }, "\u203A")));
}

/* Expose to the global scope so Game.jsx can pick them up without
   needing JS modules (every script-tag gets its own scope under Babel). */
Object.assign(window, {
  LevelUpV2,
  STAGE_LU_MAPPING,
  LU_VARIANT_LIST: VARIANT_LIST
});
})(); } catch (e) { __ds_ns.__errors.push({ path: "role-game/levelup-variants.jsx", error: String((e && e.message) || e) }); }

// role-game/questions.js
try { (() => {
/* global window */
/* role-game · psychometric question bank (v3 — sourced from psychometric_questions_v3.xlsx)

   150 questions across 6 categories, three difficulty tiers:
     1 = קל     (easy   — available from stage 1+)
     2 = בינוני  (medium — available from stage 2+)
     3 = קשה    (hard   — available from stage 3+ ONLY)

   The Game.jsx draw routine picks questions with
     q.difficulty <= currentLevelId
   so the difficulty rule above is enforced by level threshold.

   Each question's options[] has the CORRECT answer at index 0; the
   runtime shuffles them per draw (shuffleOptions in Game.jsx) so the
   correct slot is randomised every time the question shows.

   Schema: { id, kind: 'V'|'Q', category, difficulty: 1..3,
            prompt, options[4], correct: 0 }
*/

const QUESTIONS = [{
  id: "v001",
  kind: "V",
  category: "אנלוגיות מילוליות בפסיכומטרי",
  difficulty: 1,
  prompt: "רופא : חולה",
  options: ["מורה : תלמיד", "שוטר : כביש", "טבח : מסעדה", "זמר : מיקרופון"],
  correct: 0
}, {
  id: "v002",
  kind: "V",
  category: "אנלוגיות מילוליות בפסיכומטרי",
  difficulty: 1,
  prompt: "עט : כתיבה",
  options: ["מכחול : ציור", "ספר : ספרייה", "מפתח : דלת", "מחשב : חשמל"],
  correct: 0
}, {
  id: "v003",
  kind: "V",
  category: "אנלוגיות מילוליות בפסיכומטרי",
  difficulty: 1,
  prompt: "שורש : עץ",
  options: ["יסוד : בניין", "גלגל : רכב", "נר : אור", "חוט : חשמל"],
  correct: 0
}, {
  id: "q004",
  kind: "Q",
  category: "שורשים וחזקות",
  difficulty: 2,
  prompt: "2³ + 3² = ?",
  options: ["17", "12", "15", "19"],
  correct: 0
}, {
  id: "q005",
  kind: "Q",
  category: "שורשים וחזקות",
  difficulty: 2,
  prompt: "2⁴ × 2² = ?",
  options: ["64", "32", "16", "128"],
  correct: 0
}, {
  id: "q006",
  kind: "Q",
  category: "שאלות חזקות",
  difficulty: 3,
  prompt: "2⁵ גדול מ־",
  options: ["5²", "4³", "2⁴", "3³"],
  correct: 0
}, {
  id: "q007",
  kind: "Q",
  category: "שאלות חזקות",
  difficulty: 3,
  prompt: "(2³)³ = ?",
  options: ["512", "64", "256", "729"],
  correct: 0
}, {
  id: "v008",
  kind: "V",
  category: "מחזק / מחליש",
  difficulty: 2,
  prompt: "טענה: ריצה משפרת זיכרון. מה מחזק?",
  options: ["רצים זכרו יותר מילים", "ריצה פופולרית", "יש מרוצים", "נעליים יקרות"],
  correct: 0
}, {
  id: "q009",
  kind: "Q",
  category: "סדרות מספרים",
  difficulty: 2,
  prompt: "2,5,10,17,?",
  options: ["26", "24", "28", "30"],
  correct: 0
}, {
  id: "q010",
  kind: "Q",
  category: "אחוזים",
  difficulty: 2,
  prompt: "מחיר עלה מ־80 ל־100. בכמה אחוזים?",
  options: ["25%", "20%", "15%", "30%"],
  correct: 0
}, {
  id: "v011",
  kind: "V",
  category: "אנלוגיות מילוליות בפסיכומטרי",
  difficulty: 1,
  prompt: "רופא : חולה",
  options: ["מורה : תלמיד", "שוטר : כביש", "טבח : מסעדה", "זמר : מיקרופון"],
  correct: 0
}, {
  id: "v012",
  kind: "V",
  category: "אנלוגיות מילוליות בפסיכומטרי",
  difficulty: 1,
  prompt: "עט : כתיבה",
  options: ["מכחול : ציור", "ספר : ספרייה", "מפתח : דלת", "מחשב : חשמל"],
  correct: 0
}, {
  id: "v013",
  kind: "V",
  category: "אנלוגיות מילוליות בפסיכומטרי",
  difficulty: 1,
  prompt: "שורש : עץ",
  options: ["יסוד : בניין", "גלגל : רכב", "נר : אור", "חוט : חשמל"],
  correct: 0
}, {
  id: "q014",
  kind: "Q",
  category: "שורשים וחזקות",
  difficulty: 2,
  prompt: "2³ + 3² = ?",
  options: ["17", "12", "15", "19"],
  correct: 0
}, {
  id: "q015",
  kind: "Q",
  category: "שורשים וחזקות",
  difficulty: 2,
  prompt: "2⁴ × 2² = ?",
  options: ["64", "32", "16", "128"],
  correct: 0
}, {
  id: "q016",
  kind: "Q",
  category: "שאלות חזקות",
  difficulty: 3,
  prompt: "2⁵ גדול מ־",
  options: ["5²", "4³", "2⁴", "3³"],
  correct: 0
}, {
  id: "q017",
  kind: "Q",
  category: "שאלות חזקות",
  difficulty: 3,
  prompt: "(2³)³ = ?",
  options: ["512", "64", "256", "729"],
  correct: 0
}, {
  id: "v018",
  kind: "V",
  category: "מחזק / מחליש",
  difficulty: 2,
  prompt: "טענה: ריצה משפרת זיכרון. מה מחזק?",
  options: ["רצים זכרו יותר מילים", "ריצה פופולרית", "יש מרוצים", "נעליים יקרות"],
  correct: 0
}, {
  id: "q019",
  kind: "Q",
  category: "סדרות מספרים",
  difficulty: 2,
  prompt: "2,5,10,17,?",
  options: ["26", "24", "28", "30"],
  correct: 0
}, {
  id: "q020",
  kind: "Q",
  category: "אחוזים",
  difficulty: 2,
  prompt: "מחיר עלה מ־80 ל־100. בכמה אחוזים?",
  options: ["25%", "20%", "15%", "30%"],
  correct: 0
}, {
  id: "v021",
  kind: "V",
  category: "אנלוגיות מילוליות בפסיכומטרי",
  difficulty: 1,
  prompt: "רופא : חולה",
  options: ["מורה : תלמיד", "שוטר : כביש", "טבח : מסעדה", "זמר : מיקרופון"],
  correct: 0
}, {
  id: "v022",
  kind: "V",
  category: "אנלוגיות מילוליות בפסיכומטרי",
  difficulty: 1,
  prompt: "עט : כתיבה",
  options: ["מכחול : ציור", "ספר : ספרייה", "מפתח : דלת", "מחשב : חשמל"],
  correct: 0
}, {
  id: "v023",
  kind: "V",
  category: "אנלוגיות מילוליות בפסיכומטרי",
  difficulty: 1,
  prompt: "שורש : עץ",
  options: ["יסוד : בניין", "גלגל : רכב", "נר : אור", "חוט : חשמל"],
  correct: 0
}, {
  id: "q024",
  kind: "Q",
  category: "שורשים וחזקות",
  difficulty: 2,
  prompt: "2³ + 3² = ?",
  options: ["17", "12", "15", "19"],
  correct: 0
}, {
  id: "q025",
  kind: "Q",
  category: "שורשים וחזקות",
  difficulty: 2,
  prompt: "2⁴ × 2² = ?",
  options: ["64", "32", "16", "128"],
  correct: 0
}, {
  id: "q026",
  kind: "Q",
  category: "שאלות חזקות",
  difficulty: 3,
  prompt: "2⁵ גדול מ־",
  options: ["5²", "4³", "2⁴", "3³"],
  correct: 0
}, {
  id: "q027",
  kind: "Q",
  category: "שאלות חזקות",
  difficulty: 3,
  prompt: "(2³)³ = ?",
  options: ["512", "64", "256", "729"],
  correct: 0
}, {
  id: "v028",
  kind: "V",
  category: "מחזק / מחליש",
  difficulty: 2,
  prompt: "טענה: ריצה משפרת זיכרון. מה מחזק?",
  options: ["רצים זכרו יותר מילים", "ריצה פופולרית", "יש מרוצים", "נעליים יקרות"],
  correct: 0
}, {
  id: "q029",
  kind: "Q",
  category: "סדרות מספרים",
  difficulty: 2,
  prompt: "2,5,10,17,?",
  options: ["26", "24", "28", "30"],
  correct: 0
}, {
  id: "q030",
  kind: "Q",
  category: "אחוזים",
  difficulty: 2,
  prompt: "מחיר עלה מ־80 ל־100. בכמה אחוזים?",
  options: ["25%", "20%", "15%", "30%"],
  correct: 0
}, {
  id: "v031",
  kind: "V",
  category: "אנלוגיות מילוליות בפסיכומטרי",
  difficulty: 1,
  prompt: "רופא : חולה",
  options: ["מורה : תלמיד", "שוטר : כביש", "טבח : מסעדה", "זמר : מיקרופון"],
  correct: 0
}, {
  id: "v032",
  kind: "V",
  category: "אנלוגיות מילוליות בפסיכומטרי",
  difficulty: 1,
  prompt: "עט : כתיבה",
  options: ["מכחול : ציור", "ספר : ספרייה", "מפתח : דלת", "מחשב : חשמל"],
  correct: 0
}, {
  id: "v033",
  kind: "V",
  category: "אנלוגיות מילוליות בפסיכומטרי",
  difficulty: 1,
  prompt: "שורש : עץ",
  options: ["יסוד : בניין", "גלגל : רכב", "נר : אור", "חוט : חשמל"],
  correct: 0
}, {
  id: "q034",
  kind: "Q",
  category: "שורשים וחזקות",
  difficulty: 2,
  prompt: "2³ + 3² = ?",
  options: ["17", "12", "15", "19"],
  correct: 0
}, {
  id: "q035",
  kind: "Q",
  category: "שורשים וחזקות",
  difficulty: 2,
  prompt: "2⁴ × 2² = ?",
  options: ["64", "32", "16", "128"],
  correct: 0
}, {
  id: "q036",
  kind: "Q",
  category: "שאלות חזקות",
  difficulty: 3,
  prompt: "2⁵ גדול מ־",
  options: ["5²", "4³", "2⁴", "3³"],
  correct: 0
}, {
  id: "q037",
  kind: "Q",
  category: "שאלות חזקות",
  difficulty: 3,
  prompt: "(2³)³ = ?",
  options: ["512", "64", "256", "729"],
  correct: 0
}, {
  id: "v038",
  kind: "V",
  category: "מחזק / מחליש",
  difficulty: 2,
  prompt: "טענה: ריצה משפרת זיכרון. מה מחזק?",
  options: ["רצים זכרו יותר מילים", "ריצה פופולרית", "יש מרוצים", "נעליים יקרות"],
  correct: 0
}, {
  id: "q039",
  kind: "Q",
  category: "סדרות מספרים",
  difficulty: 2,
  prompt: "2,5,10,17,?",
  options: ["26", "24", "28", "30"],
  correct: 0
}, {
  id: "q040",
  kind: "Q",
  category: "אחוזים",
  difficulty: 2,
  prompt: "מחיר עלה מ־80 ל־100. בכמה אחוזים?",
  options: ["25%", "20%", "15%", "30%"],
  correct: 0
}, {
  id: "v041",
  kind: "V",
  category: "אנלוגיות מילוליות בפסיכומטרי",
  difficulty: 1,
  prompt: "רופא : חולה",
  options: ["מורה : תלמיד", "שוטר : כביש", "טבח : מסעדה", "זמר : מיקרופון"],
  correct: 0
}, {
  id: "v042",
  kind: "V",
  category: "אנלוגיות מילוליות בפסיכומטרי",
  difficulty: 1,
  prompt: "עט : כתיבה",
  options: ["מכחול : ציור", "ספר : ספרייה", "מפתח : דלת", "מחשב : חשמל"],
  correct: 0
}, {
  id: "v043",
  kind: "V",
  category: "אנלוגיות מילוליות בפסיכומטרי",
  difficulty: 1,
  prompt: "שורש : עץ",
  options: ["יסוד : בניין", "גלגל : רכב", "נר : אור", "חוט : חשמל"],
  correct: 0
}, {
  id: "q044",
  kind: "Q",
  category: "שורשים וחזקות",
  difficulty: 2,
  prompt: "2³ + 3² = ?",
  options: ["17", "12", "15", "19"],
  correct: 0
}, {
  id: "q045",
  kind: "Q",
  category: "שורשים וחזקות",
  difficulty: 2,
  prompt: "2⁴ × 2² = ?",
  options: ["64", "32", "16", "128"],
  correct: 0
}, {
  id: "q046",
  kind: "Q",
  category: "שאלות חזקות",
  difficulty: 3,
  prompt: "2⁵ גדול מ־",
  options: ["5²", "4³", "2⁴", "3³"],
  correct: 0
}, {
  id: "q047",
  kind: "Q",
  category: "שאלות חזקות",
  difficulty: 3,
  prompt: "(2³)³ = ?",
  options: ["512", "64", "256", "729"],
  correct: 0
}, {
  id: "v048",
  kind: "V",
  category: "מחזק / מחליש",
  difficulty: 2,
  prompt: "טענה: ריצה משפרת זיכרון. מה מחזק?",
  options: ["רצים זכרו יותר מילים", "ריצה פופולרית", "יש מרוצים", "נעליים יקרות"],
  correct: 0
}, {
  id: "q049",
  kind: "Q",
  category: "סדרות מספרים",
  difficulty: 2,
  prompt: "2,5,10,17,?",
  options: ["26", "24", "28", "30"],
  correct: 0
}, {
  id: "q050",
  kind: "Q",
  category: "אחוזים",
  difficulty: 2,
  prompt: "מחיר עלה מ־80 ל־100. בכמה אחוזים?",
  options: ["25%", "20%", "15%", "30%"],
  correct: 0
}, {
  id: "v051",
  kind: "V",
  category: "אנלוגיות מילוליות בפסיכומטרי",
  difficulty: 1,
  prompt: "רופא : חולה",
  options: ["מורה : תלמיד", "שוטר : כביש", "טבח : מסעדה", "זמר : מיקרופון"],
  correct: 0
}, {
  id: "v052",
  kind: "V",
  category: "אנלוגיות מילוליות בפסיכומטרי",
  difficulty: 1,
  prompt: "עט : כתיבה",
  options: ["מכחול : ציור", "ספר : ספרייה", "מפתח : דלת", "מחשב : חשמל"],
  correct: 0
}, {
  id: "v053",
  kind: "V",
  category: "אנלוגיות מילוליות בפסיכומטרי",
  difficulty: 1,
  prompt: "שורש : עץ",
  options: ["יסוד : בניין", "גלגל : רכב", "נר : אור", "חוט : חשמל"],
  correct: 0
}, {
  id: "q054",
  kind: "Q",
  category: "שורשים וחזקות",
  difficulty: 2,
  prompt: "2³ + 3² = ?",
  options: ["17", "12", "15", "19"],
  correct: 0
}, {
  id: "q055",
  kind: "Q",
  category: "שורשים וחזקות",
  difficulty: 2,
  prompt: "2⁴ × 2² = ?",
  options: ["64", "32", "16", "128"],
  correct: 0
}, {
  id: "q056",
  kind: "Q",
  category: "שאלות חזקות",
  difficulty: 3,
  prompt: "2⁵ גדול מ־",
  options: ["5²", "4³", "2⁴", "3³"],
  correct: 0
}, {
  id: "q057",
  kind: "Q",
  category: "שאלות חזקות",
  difficulty: 3,
  prompt: "(2³)³ = ?",
  options: ["512", "64", "256", "729"],
  correct: 0
}, {
  id: "v058",
  kind: "V",
  category: "מחזק / מחליש",
  difficulty: 2,
  prompt: "טענה: ריצה משפרת זיכרון. מה מחזק?",
  options: ["רצים זכרו יותר מילים", "ריצה פופולרית", "יש מרוצים", "נעליים יקרות"],
  correct: 0
}, {
  id: "q059",
  kind: "Q",
  category: "סדרות מספרים",
  difficulty: 2,
  prompt: "2,5,10,17,?",
  options: ["26", "24", "28", "30"],
  correct: 0
}, {
  id: "q060",
  kind: "Q",
  category: "אחוזים",
  difficulty: 2,
  prompt: "מחיר עלה מ־80 ל־100. בכמה אחוזים?",
  options: ["25%", "20%", "15%", "30%"],
  correct: 0
}, {
  id: "v061",
  kind: "V",
  category: "אנלוגיות מילוליות בפסיכומטרי",
  difficulty: 1,
  prompt: "רופא : חולה",
  options: ["מורה : תלמיד", "שוטר : כביש", "טבח : מסעדה", "זמר : מיקרופון"],
  correct: 0
}, {
  id: "v062",
  kind: "V",
  category: "אנלוגיות מילוליות בפסיכומטרי",
  difficulty: 1,
  prompt: "עט : כתיבה",
  options: ["מכחול : ציור", "ספר : ספרייה", "מפתח : דלת", "מחשב : חשמל"],
  correct: 0
}, {
  id: "v063",
  kind: "V",
  category: "אנלוגיות מילוליות בפסיכומטרי",
  difficulty: 1,
  prompt: "שורש : עץ",
  options: ["יסוד : בניין", "גלגל : רכב", "נר : אור", "חוט : חשמל"],
  correct: 0
}, {
  id: "q064",
  kind: "Q",
  category: "שורשים וחזקות",
  difficulty: 2,
  prompt: "2³ + 3² = ?",
  options: ["17", "12", "15", "19"],
  correct: 0
}, {
  id: "q065",
  kind: "Q",
  category: "שורשים וחזקות",
  difficulty: 2,
  prompt: "2⁴ × 2² = ?",
  options: ["64", "32", "16", "128"],
  correct: 0
}, {
  id: "q066",
  kind: "Q",
  category: "שאלות חזקות",
  difficulty: 3,
  prompt: "2⁵ גדול מ־",
  options: ["5²", "4³", "2⁴", "3³"],
  correct: 0
}, {
  id: "q067",
  kind: "Q",
  category: "שאלות חזקות",
  difficulty: 3,
  prompt: "(2³)³ = ?",
  options: ["512", "64", "256", "729"],
  correct: 0
}, {
  id: "v068",
  kind: "V",
  category: "מחזק / מחליש",
  difficulty: 2,
  prompt: "טענה: ריצה משפרת זיכרון. מה מחזק?",
  options: ["רצים זכרו יותר מילים", "ריצה פופולרית", "יש מרוצים", "נעליים יקרות"],
  correct: 0
}, {
  id: "q069",
  kind: "Q",
  category: "סדרות מספרים",
  difficulty: 2,
  prompt: "2,5,10,17,?",
  options: ["26", "24", "28", "30"],
  correct: 0
}, {
  id: "q070",
  kind: "Q",
  category: "אחוזים",
  difficulty: 2,
  prompt: "מחיר עלה מ־80 ל־100. בכמה אחוזים?",
  options: ["25%", "20%", "15%", "30%"],
  correct: 0
}, {
  id: "v071",
  kind: "V",
  category: "אנלוגיות מילוליות בפסיכומטרי",
  difficulty: 1,
  prompt: "רופא : חולה",
  options: ["מורה : תלמיד", "שוטר : כביש", "טבח : מסעדה", "זמר : מיקרופון"],
  correct: 0
}, {
  id: "v072",
  kind: "V",
  category: "אנלוגיות מילוליות בפסיכומטרי",
  difficulty: 1,
  prompt: "עט : כתיבה",
  options: ["מכחול : ציור", "ספר : ספרייה", "מפתח : דלת", "מחשב : חשמל"],
  correct: 0
}, {
  id: "v073",
  kind: "V",
  category: "אנלוגיות מילוליות בפסיכומטרי",
  difficulty: 1,
  prompt: "שורש : עץ",
  options: ["יסוד : בניין", "גלגל : רכב", "נר : אור", "חוט : חשמל"],
  correct: 0
}, {
  id: "q074",
  kind: "Q",
  category: "שורשים וחזקות",
  difficulty: 2,
  prompt: "2³ + 3² = ?",
  options: ["17", "12", "15", "19"],
  correct: 0
}, {
  id: "q075",
  kind: "Q",
  category: "שורשים וחזקות",
  difficulty: 2,
  prompt: "2⁴ × 2² = ?",
  options: ["64", "32", "16", "128"],
  correct: 0
}, {
  id: "q076",
  kind: "Q",
  category: "שאלות חזקות",
  difficulty: 3,
  prompt: "2⁵ גדול מ־",
  options: ["5²", "4³", "2⁴", "3³"],
  correct: 0
}, {
  id: "q077",
  kind: "Q",
  category: "שאלות חזקות",
  difficulty: 3,
  prompt: "(2³)³ = ?",
  options: ["512", "64", "256", "729"],
  correct: 0
}, {
  id: "v078",
  kind: "V",
  category: "מחזק / מחליש",
  difficulty: 2,
  prompt: "טענה: ריצה משפרת זיכרון. מה מחזק?",
  options: ["רצים זכרו יותר מילים", "ריצה פופולרית", "יש מרוצים", "נעליים יקרות"],
  correct: 0
}, {
  id: "q079",
  kind: "Q",
  category: "סדרות מספרים",
  difficulty: 2,
  prompt: "2,5,10,17,?",
  options: ["26", "24", "28", "30"],
  correct: 0
}, {
  id: "q080",
  kind: "Q",
  category: "אחוזים",
  difficulty: 2,
  prompt: "מחיר עלה מ־80 ל־100. בכמה אחוזים?",
  options: ["25%", "20%", "15%", "30%"],
  correct: 0
}, {
  id: "v081",
  kind: "V",
  category: "אנלוגיות מילוליות בפסיכומטרי",
  difficulty: 1,
  prompt: "רופא : חולה",
  options: ["מורה : תלמיד", "שוטר : כביש", "טבח : מסעדה", "זמר : מיקרופון"],
  correct: 0
}, {
  id: "v082",
  kind: "V",
  category: "אנלוגיות מילוליות בפסיכומטרי",
  difficulty: 1,
  prompt: "עט : כתיבה",
  options: ["מכחול : ציור", "ספר : ספרייה", "מפתח : דלת", "מחשב : חשמל"],
  correct: 0
}, {
  id: "v083",
  kind: "V",
  category: "אנלוגיות מילוליות בפסיכומטרי",
  difficulty: 1,
  prompt: "שורש : עץ",
  options: ["יסוד : בניין", "גלגל : רכב", "נר : אור", "חוט : חשמל"],
  correct: 0
}, {
  id: "q084",
  kind: "Q",
  category: "שורשים וחזקות",
  difficulty: 2,
  prompt: "2³ + 3² = ?",
  options: ["17", "12", "15", "19"],
  correct: 0
}, {
  id: "q085",
  kind: "Q",
  category: "שורשים וחזקות",
  difficulty: 2,
  prompt: "2⁴ × 2² = ?",
  options: ["64", "32", "16", "128"],
  correct: 0
}, {
  id: "q086",
  kind: "Q",
  category: "שאלות חזקות",
  difficulty: 3,
  prompt: "2⁵ גדול מ־",
  options: ["5²", "4³", "2⁴", "3³"],
  correct: 0
}, {
  id: "q087",
  kind: "Q",
  category: "שאלות חזקות",
  difficulty: 3,
  prompt: "(2³)³ = ?",
  options: ["512", "64", "256", "729"],
  correct: 0
}, {
  id: "v088",
  kind: "V",
  category: "מחזק / מחליש",
  difficulty: 2,
  prompt: "טענה: ריצה משפרת זיכרון. מה מחזק?",
  options: ["רצים זכרו יותר מילים", "ריצה פופולרית", "יש מרוצים", "נעליים יקרות"],
  correct: 0
}, {
  id: "q089",
  kind: "Q",
  category: "סדרות מספרים",
  difficulty: 2,
  prompt: "2,5,10,17,?",
  options: ["26", "24", "28", "30"],
  correct: 0
}, {
  id: "q090",
  kind: "Q",
  category: "אחוזים",
  difficulty: 2,
  prompt: "מחיר עלה מ־80 ל־100. בכמה אחוזים?",
  options: ["25%", "20%", "15%", "30%"],
  correct: 0
}, {
  id: "v091",
  kind: "V",
  category: "אנלוגיות מילוליות בפסיכומטרי",
  difficulty: 1,
  prompt: "רופא : חולה",
  options: ["מורה : תלמיד", "שוטר : כביש", "טבח : מסעדה", "זמר : מיקרופון"],
  correct: 0
}, {
  id: "v092",
  kind: "V",
  category: "אנלוגיות מילוליות בפסיכומטרי",
  difficulty: 1,
  prompt: "עט : כתיבה",
  options: ["מכחול : ציור", "ספר : ספרייה", "מפתח : דלת", "מחשב : חשמל"],
  correct: 0
}, {
  id: "v093",
  kind: "V",
  category: "אנלוגיות מילוליות בפסיכומטרי",
  difficulty: 1,
  prompt: "שורש : עץ",
  options: ["יסוד : בניין", "גלגל : רכב", "נר : אור", "חוט : חשמל"],
  correct: 0
}, {
  id: "q094",
  kind: "Q",
  category: "שורשים וחזקות",
  difficulty: 2,
  prompt: "2³ + 3² = ?",
  options: ["17", "12", "15", "19"],
  correct: 0
}, {
  id: "q095",
  kind: "Q",
  category: "שורשים וחזקות",
  difficulty: 2,
  prompt: "2⁴ × 2² = ?",
  options: ["64", "32", "16", "128"],
  correct: 0
}, {
  id: "q096",
  kind: "Q",
  category: "שאלות חזקות",
  difficulty: 3,
  prompt: "2⁵ גדול מ־",
  options: ["5²", "4³", "2⁴", "3³"],
  correct: 0
}, {
  id: "q097",
  kind: "Q",
  category: "שאלות חזקות",
  difficulty: 3,
  prompt: "(2³)³ = ?",
  options: ["512", "64", "256", "729"],
  correct: 0
}, {
  id: "v098",
  kind: "V",
  category: "מחזק / מחליש",
  difficulty: 2,
  prompt: "טענה: ריצה משפרת זיכרון. מה מחזק?",
  options: ["רצים זכרו יותר מילים", "ריצה פופולרית", "יש מרוצים", "נעליים יקרות"],
  correct: 0
}, {
  id: "q099",
  kind: "Q",
  category: "סדרות מספרים",
  difficulty: 2,
  prompt: "2,5,10,17,?",
  options: ["26", "24", "28", "30"],
  correct: 0
}, {
  id: "q100",
  kind: "Q",
  category: "אחוזים",
  difficulty: 2,
  prompt: "מחיר עלה מ־80 ל־100. בכמה אחוזים?",
  options: ["25%", "20%", "15%", "30%"],
  correct: 0
}, {
  id: "v101",
  kind: "V",
  category: "אנלוגיות מילוליות בפסיכומטרי",
  difficulty: 1,
  prompt: "רופא : חולה",
  options: ["מורה : תלמיד", "שוטר : כביש", "טבח : מסעדה", "זמר : מיקרופון"],
  correct: 0
}, {
  id: "v102",
  kind: "V",
  category: "אנלוגיות מילוליות בפסיכומטרי",
  difficulty: 1,
  prompt: "עט : כתיבה",
  options: ["מכחול : ציור", "ספר : ספרייה", "מפתח : דלת", "מחשב : חשמל"],
  correct: 0
}, {
  id: "v103",
  kind: "V",
  category: "אנלוגיות מילוליות בפסיכומטרי",
  difficulty: 1,
  prompt: "שורש : עץ",
  options: ["יסוד : בניין", "גלגל : רכב", "נר : אור", "חוט : חשמל"],
  correct: 0
}, {
  id: "q104",
  kind: "Q",
  category: "שורשים וחזקות",
  difficulty: 2,
  prompt: "2³ + 3² = ?",
  options: ["17", "12", "15", "19"],
  correct: 0
}, {
  id: "q105",
  kind: "Q",
  category: "שורשים וחזקות",
  difficulty: 2,
  prompt: "2⁴ × 2² = ?",
  options: ["64", "32", "16", "128"],
  correct: 0
}, {
  id: "q106",
  kind: "Q",
  category: "שאלות חזקות",
  difficulty: 3,
  prompt: "2⁵ גדול מ־",
  options: ["5²", "4³", "2⁴", "3³"],
  correct: 0
}, {
  id: "q107",
  kind: "Q",
  category: "שאלות חזקות",
  difficulty: 3,
  prompt: "(2³)³ = ?",
  options: ["512", "64", "256", "729"],
  correct: 0
}, {
  id: "v108",
  kind: "V",
  category: "מחזק / מחליש",
  difficulty: 2,
  prompt: "טענה: ריצה משפרת זיכרון. מה מחזק?",
  options: ["רצים זכרו יותר מילים", "ריצה פופולרית", "יש מרוצים", "נעליים יקרות"],
  correct: 0
}, {
  id: "q109",
  kind: "Q",
  category: "סדרות מספרים",
  difficulty: 2,
  prompt: "2,5,10,17,?",
  options: ["26", "24", "28", "30"],
  correct: 0
}, {
  id: "q110",
  kind: "Q",
  category: "אחוזים",
  difficulty: 2,
  prompt: "מחיר עלה מ־80 ל־100. בכמה אחוזים?",
  options: ["25%", "20%", "15%", "30%"],
  correct: 0
}, {
  id: "v111",
  kind: "V",
  category: "אנלוגיות מילוליות בפסיכומטרי",
  difficulty: 1,
  prompt: "רופא : חולה",
  options: ["מורה : תלמיד", "שוטר : כביש", "טבח : מסעדה", "זמר : מיקרופון"],
  correct: 0
}, {
  id: "v112",
  kind: "V",
  category: "אנלוגיות מילוליות בפסיכומטרי",
  difficulty: 1,
  prompt: "עט : כתיבה",
  options: ["מכחול : ציור", "ספר : ספרייה", "מפתח : דלת", "מחשב : חשמל"],
  correct: 0
}, {
  id: "v113",
  kind: "V",
  category: "אנלוגיות מילוליות בפסיכומטרי",
  difficulty: 1,
  prompt: "שורש : עץ",
  options: ["יסוד : בניין", "גלגל : רכב", "נר : אור", "חוט : חשמל"],
  correct: 0
}, {
  id: "q114",
  kind: "Q",
  category: "שורשים וחזקות",
  difficulty: 2,
  prompt: "2³ + 3² = ?",
  options: ["17", "12", "15", "19"],
  correct: 0
}, {
  id: "q115",
  kind: "Q",
  category: "שורשים וחזקות",
  difficulty: 2,
  prompt: "2⁴ × 2² = ?",
  options: ["64", "32", "16", "128"],
  correct: 0
}, {
  id: "q116",
  kind: "Q",
  category: "שאלות חזקות",
  difficulty: 3,
  prompt: "2⁵ גדול מ־",
  options: ["5²", "4³", "2⁴", "3³"],
  correct: 0
}, {
  id: "q117",
  kind: "Q",
  category: "שאלות חזקות",
  difficulty: 3,
  prompt: "(2³)³ = ?",
  options: ["512", "64", "256", "729"],
  correct: 0
}, {
  id: "v118",
  kind: "V",
  category: "מחזק / מחליש",
  difficulty: 2,
  prompt: "טענה: ריצה משפרת זיכרון. מה מחזק?",
  options: ["רצים זכרו יותר מילים", "ריצה פופולרית", "יש מרוצים", "נעליים יקרות"],
  correct: 0
}, {
  id: "q119",
  kind: "Q",
  category: "סדרות מספרים",
  difficulty: 2,
  prompt: "2,5,10,17,?",
  options: ["26", "24", "28", "30"],
  correct: 0
}, {
  id: "q120",
  kind: "Q",
  category: "אחוזים",
  difficulty: 2,
  prompt: "מחיר עלה מ־80 ל־100. בכמה אחוזים?",
  options: ["25%", "20%", "15%", "30%"],
  correct: 0
}, {
  id: "v121",
  kind: "V",
  category: "אנלוגיות מילוליות בפסיכומטרי",
  difficulty: 1,
  prompt: "רופא : חולה",
  options: ["מורה : תלמיד", "שוטר : כביש", "טבח : מסעדה", "זמר : מיקרופון"],
  correct: 0
}, {
  id: "v122",
  kind: "V",
  category: "אנלוגיות מילוליות בפסיכומטרי",
  difficulty: 1,
  prompt: "עט : כתיבה",
  options: ["מכחול : ציור", "ספר : ספרייה", "מפתח : דלת", "מחשב : חשמל"],
  correct: 0
}, {
  id: "v123",
  kind: "V",
  category: "אנלוגיות מילוליות בפסיכומטרי",
  difficulty: 1,
  prompt: "שורש : עץ",
  options: ["יסוד : בניין", "גלגל : רכב", "נר : אור", "חוט : חשמל"],
  correct: 0
}, {
  id: "q124",
  kind: "Q",
  category: "שורשים וחזקות",
  difficulty: 2,
  prompt: "2³ + 3² = ?",
  options: ["17", "12", "15", "19"],
  correct: 0
}, {
  id: "q125",
  kind: "Q",
  category: "שורשים וחזקות",
  difficulty: 2,
  prompt: "2⁴ × 2² = ?",
  options: ["64", "32", "16", "128"],
  correct: 0
}, {
  id: "q126",
  kind: "Q",
  category: "שאלות חזקות",
  difficulty: 3,
  prompt: "2⁵ גדול מ־",
  options: ["5²", "4³", "2⁴", "3³"],
  correct: 0
}, {
  id: "q127",
  kind: "Q",
  category: "שאלות חזקות",
  difficulty: 3,
  prompt: "(2³)³ = ?",
  options: ["512", "64", "256", "729"],
  correct: 0
}, {
  id: "v128",
  kind: "V",
  category: "מחזק / מחליש",
  difficulty: 2,
  prompt: "טענה: ריצה משפרת זיכרון. מה מחזק?",
  options: ["רצים זכרו יותר מילים", "ריצה פופולרית", "יש מרוצים", "נעליים יקרות"],
  correct: 0
}, {
  id: "q129",
  kind: "Q",
  category: "סדרות מספרים",
  difficulty: 2,
  prompt: "2,5,10,17,?",
  options: ["26", "24", "28", "30"],
  correct: 0
}, {
  id: "q130",
  kind: "Q",
  category: "אחוזים",
  difficulty: 2,
  prompt: "מחיר עלה מ־80 ל־100. בכמה אחוזים?",
  options: ["25%", "20%", "15%", "30%"],
  correct: 0
}, {
  id: "v131",
  kind: "V",
  category: "אנלוגיות מילוליות בפסיכומטרי",
  difficulty: 1,
  prompt: "רופא : חולה",
  options: ["מורה : תלמיד", "שוטר : כביש", "טבח : מסעדה", "זמר : מיקרופון"],
  correct: 0
}, {
  id: "v132",
  kind: "V",
  category: "אנלוגיות מילוליות בפסיכומטרי",
  difficulty: 1,
  prompt: "עט : כתיבה",
  options: ["מכחול : ציור", "ספר : ספרייה", "מפתח : דלת", "מחשב : חשמל"],
  correct: 0
}, {
  id: "v133",
  kind: "V",
  category: "אנלוגיות מילוליות בפסיכומטרי",
  difficulty: 1,
  prompt: "שורש : עץ",
  options: ["יסוד : בניין", "גלגל : רכב", "נר : אור", "חוט : חשמל"],
  correct: 0
}, {
  id: "q134",
  kind: "Q",
  category: "שורשים וחזקות",
  difficulty: 2,
  prompt: "2³ + 3² = ?",
  options: ["17", "12", "15", "19"],
  correct: 0
}, {
  id: "q135",
  kind: "Q",
  category: "שורשים וחזקות",
  difficulty: 2,
  prompt: "2⁴ × 2² = ?",
  options: ["64", "32", "16", "128"],
  correct: 0
}, {
  id: "q136",
  kind: "Q",
  category: "שאלות חזקות",
  difficulty: 3,
  prompt: "2⁵ גדול מ־",
  options: ["5²", "4³", "2⁴", "3³"],
  correct: 0
}, {
  id: "q137",
  kind: "Q",
  category: "שאלות חזקות",
  difficulty: 3,
  prompt: "(2³)³ = ?",
  options: ["512", "64", "256", "729"],
  correct: 0
}, {
  id: "v138",
  kind: "V",
  category: "מחזק / מחליש",
  difficulty: 2,
  prompt: "טענה: ריצה משפרת זיכרון. מה מחזק?",
  options: ["רצים זכרו יותר מילים", "ריצה פופולרית", "יש מרוצים", "נעליים יקרות"],
  correct: 0
}, {
  id: "q139",
  kind: "Q",
  category: "סדרות מספרים",
  difficulty: 2,
  prompt: "2,5,10,17,?",
  options: ["26", "24", "28", "30"],
  correct: 0
}, {
  id: "q140",
  kind: "Q",
  category: "אחוזים",
  difficulty: 2,
  prompt: "מחיר עלה מ־80 ל־100. בכמה אחוזים?",
  options: ["25%", "20%", "15%", "30%"],
  correct: 0
}, {
  id: "v141",
  kind: "V",
  category: "אנלוגיות מילוליות בפסיכומטרי",
  difficulty: 1,
  prompt: "רופא : חולה",
  options: ["מורה : תלמיד", "שוטר : כביש", "טבח : מסעדה", "זמר : מיקרופון"],
  correct: 0
}, {
  id: "v142",
  kind: "V",
  category: "אנלוגיות מילוליות בפסיכומטרי",
  difficulty: 1,
  prompt: "עט : כתיבה",
  options: ["מכחול : ציור", "ספר : ספרייה", "מפתח : דלת", "מחשב : חשמל"],
  correct: 0
}, {
  id: "v143",
  kind: "V",
  category: "אנלוגיות מילוליות בפסיכומטרי",
  difficulty: 1,
  prompt: "שורש : עץ",
  options: ["יסוד : בניין", "גלגל : רכב", "נר : אור", "חוט : חשמל"],
  correct: 0
}, {
  id: "q144",
  kind: "Q",
  category: "שורשים וחזקות",
  difficulty: 2,
  prompt: "2³ + 3² = ?",
  options: ["17", "12", "15", "19"],
  correct: 0
}, {
  id: "q145",
  kind: "Q",
  category: "שורשים וחזקות",
  difficulty: 2,
  prompt: "2⁴ × 2² = ?",
  options: ["64", "32", "16", "128"],
  correct: 0
}, {
  id: "q146",
  kind: "Q",
  category: "שאלות חזקות",
  difficulty: 3,
  prompt: "2⁵ גדול מ־",
  options: ["5²", "4³", "2⁴", "3³"],
  correct: 0
}, {
  id: "q147",
  kind: "Q",
  category: "שאלות חזקות",
  difficulty: 3,
  prompt: "(2³)³ = ?",
  options: ["512", "64", "256", "729"],
  correct: 0
}, {
  id: "v148",
  kind: "V",
  category: "מחזק / מחליש",
  difficulty: 2,
  prompt: "טענה: ריצה משפרת זיכרון. מה מחזק?",
  options: ["רצים זכרו יותר מילים", "ריצה פופולרית", "יש מרוצים", "נעליים יקרות"],
  correct: 0
}, {
  id: "q149",
  kind: "Q",
  category: "סדרות מספרים",
  difficulty: 2,
  prompt: "2,5,10,17,?",
  options: ["26", "24", "28", "30"],
  correct: 0
}, {
  id: "q150",
  kind: "Q",
  category: "אחוזים",
  difficulty: 2,
  prompt: "מחיר עלה מ־80 ל־100. בכמה אחוזים?",
  options: ["25%", "20%", "15%", "30%"],
  correct: 0
}];
if (typeof window !== "undefined") window.ROLE_QUESTIONS = QUESTIONS;
})(); } catch (e) { __ds_ns.__errors.push({ path: "role-game/questions.js", error: String((e && e.message) || e) }); }

// role-game/tweaks-panel.jsx
try { (() => {
// tweaks-panel.jsx
// Reusable Tweaks shell + form-control helpers.
//
// Owns the host protocol (listens for __activate_edit_mode / __deactivate_edit_mode,
// posts __edit_mode_available / __edit_mode_set_keys / __edit_mode_dismissed) so
// individual prototypes don't re-roll it. Ships a consistent set of controls so you
// don't hand-draw <input type="range">, segmented radios, steppers, etc.
//
// Usage (in an HTML file that loads React + Babel):
//
//   const TWEAK_DEFAULTS = /*EDITMODE-BEGIN*/{
//     "primaryColor": "#D97757",
//     "palette": ["#D97757", "#29261b", "#f6f4ef"],
//     "fontSize": 16,
//     "density": "regular",
//     "dark": false
//   }/*EDITMODE-END*/;
//
//   function App() {
//     const [t, setTweak] = useTweaks(TWEAK_DEFAULTS);
//     return (
//       <div style={{ fontSize: t.fontSize, color: t.primaryColor }}>
//         Hello
//         <TweaksPanel>
//           <TweakSection label="Typography" />
//           <TweakSlider label="Font size" value={t.fontSize} min={10} max={32} unit="px"
//                        onChange={(v) => setTweak('fontSize', v)} />
//           <TweakRadio  label="Density" value={t.density}
//                        options={['compact', 'regular', 'comfy']}
//                        onChange={(v) => setTweak('density', v)} />
//           <TweakSection label="Theme" />
//           <TweakColor  label="Primary" value={t.primaryColor}
//                        options={['#D97757', '#2A6FDB', '#1F8A5B', '#7A5AE0']}
//                        onChange={(v) => setTweak('primaryColor', v)} />
//           <TweakColor  label="Palette" value={t.palette}
//                        options={[['#D97757', '#29261b', '#f6f4ef'],
//                                  ['#475569', '#0f172a', '#f1f5f9']]}
//                        onChange={(v) => setTweak('palette', v)} />
//           <TweakToggle label="Dark mode" value={t.dark}
//                        onChange={(v) => setTweak('dark', v)} />
//         </TweaksPanel>
//       </div>
//     );
//   }
//
// ─────────────────────────────────────────────────────────────────────────────

const __TWEAKS_STYLE = `
  .twk-panel{position:fixed;right:16px;bottom:16px;z-index:2147483646;width:280px;
    max-height:calc(100vh - 32px);display:flex;flex-direction:column;
    transform:scale(var(--dc-inv-zoom,1));transform-origin:bottom right;
    background:rgba(250,249,247,.78);color:#29261b;
    -webkit-backdrop-filter:blur(24px) saturate(160%);backdrop-filter:blur(24px) saturate(160%);
    border:.5px solid rgba(255,255,255,.6);border-radius:14px;
    box-shadow:0 1px 0 rgba(255,255,255,.5) inset,0 12px 40px rgba(0,0,0,.18);
    font:11.5px/1.4 ui-sans-serif,system-ui,-apple-system,sans-serif;overflow:hidden}
  .twk-hd{display:flex;align-items:center;justify-content:space-between;
    padding:10px 8px 10px 14px;cursor:move;user-select:none}
  .twk-hd b{font-size:12px;font-weight:600;letter-spacing:.01em}
  .twk-x{appearance:none;border:0;background:transparent;color:rgba(41,38,27,.55);
    width:22px;height:22px;border-radius:6px;cursor:default;font-size:13px;line-height:1}
  .twk-x:hover{background:rgba(0,0,0,.06);color:#29261b}
  .twk-body{padding:2px 14px 14px;display:flex;flex-direction:column;gap:10px;
    overflow-y:auto;overflow-x:hidden;min-height:0;
    scrollbar-width:thin;scrollbar-color:rgba(0,0,0,.15) transparent}
  .twk-body::-webkit-scrollbar{width:8px}
  .twk-body::-webkit-scrollbar-track{background:transparent;margin:2px}
  .twk-body::-webkit-scrollbar-thumb{background:rgba(0,0,0,.15);border-radius:4px;
    border:2px solid transparent;background-clip:content-box}
  .twk-body::-webkit-scrollbar-thumb:hover{background:rgba(0,0,0,.25);
    border:2px solid transparent;background-clip:content-box}
  .twk-row{display:flex;flex-direction:column;gap:5px}
  .twk-row-h{flex-direction:row;align-items:center;justify-content:space-between;gap:10px}
  .twk-lbl{display:flex;justify-content:space-between;align-items:baseline;
    color:rgba(41,38,27,.72)}
  .twk-lbl>span:first-child{font-weight:500}
  .twk-val{color:rgba(41,38,27,.5);font-variant-numeric:tabular-nums}

  .twk-sect{font-size:10px;font-weight:600;letter-spacing:.06em;text-transform:uppercase;
    color:rgba(41,38,27,.45);padding:10px 0 0}
  .twk-sect:first-child{padding-top:0}

  .twk-field{appearance:none;width:100%;height:26px;padding:0 8px;
    border:.5px solid rgba(0,0,0,.1);border-radius:7px;
    background:rgba(255,255,255,.6);color:inherit;font:inherit;outline:none}
  .twk-field:focus{border-color:rgba(0,0,0,.25);background:rgba(255,255,255,.85)}
  select.twk-field{padding-right:22px;
    background-image:url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='10' height='6' viewBox='0 0 10 6'><path fill='rgba(0,0,0,.5)' d='M0 0h10L5 6z'/></svg>");
    background-repeat:no-repeat;background-position:right 8px center}

  .twk-slider{appearance:none;-webkit-appearance:none;width:100%;height:4px;margin:6px 0;
    border-radius:999px;background:rgba(0,0,0,.12);outline:none}
  .twk-slider::-webkit-slider-thumb{-webkit-appearance:none;appearance:none;
    width:14px;height:14px;border-radius:50%;background:#fff;
    border:.5px solid rgba(0,0,0,.12);box-shadow:0 1px 3px rgba(0,0,0,.2);cursor:default}
  .twk-slider::-moz-range-thumb{width:14px;height:14px;border-radius:50%;
    background:#fff;border:.5px solid rgba(0,0,0,.12);box-shadow:0 1px 3px rgba(0,0,0,.2);cursor:default}

  .twk-seg{position:relative;display:flex;padding:2px;border-radius:8px;
    background:rgba(0,0,0,.06);user-select:none}
  .twk-seg-thumb{position:absolute;top:2px;bottom:2px;border-radius:6px;
    background:rgba(255,255,255,.9);box-shadow:0 1px 2px rgba(0,0,0,.12);
    transition:left .15s cubic-bezier(.3,.7,.4,1),width .15s}
  .twk-seg.dragging .twk-seg-thumb{transition:none}
  .twk-seg button{appearance:none;position:relative;z-index:1;flex:1;border:0;
    background:transparent;color:inherit;font:inherit;font-weight:500;min-height:22px;
    border-radius:6px;cursor:default;padding:4px 6px;line-height:1.2;
    overflow-wrap:anywhere}

  .twk-toggle{position:relative;width:32px;height:18px;border:0;border-radius:999px;
    background:rgba(0,0,0,.15);transition:background .15s;cursor:default;padding:0}
  .twk-toggle[data-on="1"]{background:#34c759}
  .twk-toggle i{position:absolute;top:2px;left:2px;width:14px;height:14px;border-radius:50%;
    background:#fff;box-shadow:0 1px 2px rgba(0,0,0,.25);transition:transform .15s}
  .twk-toggle[data-on="1"] i{transform:translateX(14px)}

  .twk-num{display:flex;align-items:center;height:26px;padding:0 0 0 8px;
    border:.5px solid rgba(0,0,0,.1);border-radius:7px;background:rgba(255,255,255,.6)}
  .twk-num-lbl{font-weight:500;color:rgba(41,38,27,.6);cursor:ew-resize;
    user-select:none;padding-right:8px}
  .twk-num input{flex:1;min-width:0;height:100%;border:0;background:transparent;
    font:inherit;font-variant-numeric:tabular-nums;text-align:right;padding:0 8px 0 0;
    outline:none;color:inherit;-moz-appearance:textfield}
  .twk-num input::-webkit-inner-spin-button,.twk-num input::-webkit-outer-spin-button{
    -webkit-appearance:none;margin:0}
  .twk-num-unit{padding-right:8px;color:rgba(41,38,27,.45)}

  .twk-btn{appearance:none;height:26px;padding:0 12px;border:0;border-radius:7px;
    background:rgba(0,0,0,.78);color:#fff;font:inherit;font-weight:500;cursor:default}
  .twk-btn:hover{background:rgba(0,0,0,.88)}
  .twk-btn.secondary{background:rgba(0,0,0,.06);color:inherit}
  .twk-btn.secondary:hover{background:rgba(0,0,0,.1)}

  .twk-swatch{appearance:none;-webkit-appearance:none;width:56px;height:22px;
    border:.5px solid rgba(0,0,0,.1);border-radius:6px;padding:0;cursor:default;
    background:transparent;flex-shrink:0}
  .twk-swatch::-webkit-color-swatch-wrapper{padding:0}
  .twk-swatch::-webkit-color-swatch{border:0;border-radius:5.5px}
  .twk-swatch::-moz-color-swatch{border:0;border-radius:5.5px}

  .twk-chips{display:flex;gap:6px}
  .twk-chip{position:relative;appearance:none;flex:1;min-width:0;height:46px;
    padding:0;border:0;border-radius:6px;overflow:hidden;cursor:default;
    box-shadow:0 0 0 .5px rgba(0,0,0,.12),0 1px 2px rgba(0,0,0,.06);
    transition:transform .12s cubic-bezier(.3,.7,.4,1),box-shadow .12s}
  .twk-chip:hover{transform:translateY(-1px);
    box-shadow:0 0 0 .5px rgba(0,0,0,.18),0 4px 10px rgba(0,0,0,.12)}
  .twk-chip[data-on="1"]{box-shadow:0 0 0 1.5px rgba(0,0,0,.85),
    0 2px 6px rgba(0,0,0,.15)}
  .twk-chip>span{position:absolute;top:0;bottom:0;right:0;width:34%;
    display:flex;flex-direction:column;box-shadow:-1px 0 0 rgba(0,0,0,.1)}
  .twk-chip>span>i{flex:1;box-shadow:0 -1px 0 rgba(0,0,0,.1)}
  .twk-chip>span>i:first-child{box-shadow:none}
  .twk-chip svg{position:absolute;top:6px;left:6px;width:13px;height:13px;
    filter:drop-shadow(0 1px 1px rgba(0,0,0,.3))}
`;

// ── useTweaks ───────────────────────────────────────────────────────────────
// Single source of truth for tweak values. setTweak persists via the host
// (__edit_mode_set_keys → host rewrites the EDITMODE block on disk).
function useTweaks(defaults) {
  const [values, setValues] = React.useState(defaults);
  // Accepts either setTweak('key', value) or setTweak({ key: value, ... }) so a
  // useState-style call doesn't write a "[object Object]" key into the persisted
  // JSON block.
  const setTweak = React.useCallback((keyOrEdits, val) => {
    const edits = typeof keyOrEdits === 'object' && keyOrEdits !== null ? keyOrEdits : {
      [keyOrEdits]: val
    };
    setValues(prev => ({
      ...prev,
      ...edits
    }));
    window.parent.postMessage({
      type: '__edit_mode_set_keys',
      edits
    }, '*');
    // Same-window signal so in-page listeners (deck-stage rail thumbnails)
    // can react — the parent message only reaches the host, not peers.
    window.dispatchEvent(new CustomEvent('tweakchange', {
      detail: edits
    }));
  }, []);
  return [values, setTweak];
}

// ── TweaksPanel ─────────────────────────────────────────────────────────────
// Floating shell. Registers the protocol listener BEFORE announcing
// availability — if the announce ran first, the host's activate could land
// before our handler exists and the toolbar toggle would silently no-op.
// The close button posts __edit_mode_dismissed so the host's toolbar toggle
// flips off in lockstep; the host echoes __deactivate_edit_mode back which
// is what actually hides the panel.
function TweaksPanel({
  title = 'Tweaks',
  noDeckControls = false,
  children
}) {
  const [open, setOpen] = React.useState(false);
  const dragRef = React.useRef(null);
  // Auto-inject a rail toggle when a <deck-stage> is on the page. The
  // toggle drives the deck's per-viewer _railVisible via window message;
  // state is mirrored from the same localStorage key the deck reads so
  // the control reflects reality across reloads. The mechanism is the
  // message — authors who want custom placement can post it directly
  // and pass noDeckControls to suppress this one.
  const hasDeckStage = React.useMemo(() => typeof document !== 'undefined' && !!document.querySelector('deck-stage'), []);
  // Hide the toggle until the host has actually enabled the rail (the
  // __omelette_rail_enabled window message, posted only when the
  // omelette_deck_rail_enabled flag is on for this user). The initial read
  // covers TweaksPanel mounting after the message already arrived; the
  // listener covers the common case of mounting first.
  const [railEnabled, setRailEnabled] = React.useState(() => hasDeckStage && !!document.querySelector('deck-stage')?._railEnabled);
  React.useEffect(() => {
    if (!hasDeckStage || railEnabled) return undefined;
    const onMsg = e => {
      if (e.data && e.data.type === '__omelette_rail_enabled') setRailEnabled(true);
    };
    window.addEventListener('message', onMsg);
    return () => window.removeEventListener('message', onMsg);
  }, [hasDeckStage, railEnabled]);
  const [railVisible, setRailVisible] = React.useState(() => {
    try {
      return localStorage.getItem('deck-stage.railVisible') !== '0';
    } catch (e) {
      return true;
    }
  });
  const toggleRail = on => {
    setRailVisible(on);
    window.postMessage({
      type: '__deck_rail_visible',
      on
    }, '*');
  };
  const offsetRef = React.useRef({
    x: 16,
    y: 16
  });
  const PAD = 16;
  const clampToViewport = React.useCallback(() => {
    const panel = dragRef.current;
    if (!panel) return;
    const w = panel.offsetWidth,
      h = panel.offsetHeight;
    const maxRight = Math.max(PAD, window.innerWidth - w - PAD);
    const maxBottom = Math.max(PAD, window.innerHeight - h - PAD);
    offsetRef.current = {
      x: Math.min(maxRight, Math.max(PAD, offsetRef.current.x)),
      y: Math.min(maxBottom, Math.max(PAD, offsetRef.current.y))
    };
    panel.style.right = offsetRef.current.x + 'px';
    panel.style.bottom = offsetRef.current.y + 'px';
  }, []);
  React.useEffect(() => {
    if (!open) return;
    clampToViewport();
    if (typeof ResizeObserver === 'undefined') {
      window.addEventListener('resize', clampToViewport);
      return () => window.removeEventListener('resize', clampToViewport);
    }
    const ro = new ResizeObserver(clampToViewport);
    ro.observe(document.documentElement);
    return () => ro.disconnect();
  }, [open, clampToViewport]);
  React.useEffect(() => {
    const onMsg = e => {
      const t = e?.data?.type;
      if (t === '__activate_edit_mode') setOpen(true);else if (t === '__deactivate_edit_mode') setOpen(false);
    };
    window.addEventListener('message', onMsg);
    window.parent.postMessage({
      type: '__edit_mode_available'
    }, '*');
    return () => window.removeEventListener('message', onMsg);
  }, []);
  const dismiss = () => {
    setOpen(false);
    window.parent.postMessage({
      type: '__edit_mode_dismissed'
    }, '*');
  };
  const onDragStart = e => {
    const panel = dragRef.current;
    if (!panel) return;
    const r = panel.getBoundingClientRect();
    const sx = e.clientX,
      sy = e.clientY;
    const startRight = window.innerWidth - r.right;
    const startBottom = window.innerHeight - r.bottom;
    const move = ev => {
      offsetRef.current = {
        x: startRight - (ev.clientX - sx),
        y: startBottom - (ev.clientY - sy)
      };
      clampToViewport();
    };
    const up = () => {
      window.removeEventListener('mousemove', move);
      window.removeEventListener('mouseup', up);
    };
    window.addEventListener('mousemove', move);
    window.addEventListener('mouseup', up);
  };
  if (!open) return null;
  return /*#__PURE__*/React.createElement(React.Fragment, null, /*#__PURE__*/React.createElement("style", null, __TWEAKS_STYLE), /*#__PURE__*/React.createElement("div", {
    ref: dragRef,
    className: "twk-panel",
    "data-noncommentable": "",
    style: {
      right: offsetRef.current.x,
      bottom: offsetRef.current.y
    }
  }, /*#__PURE__*/React.createElement("div", {
    className: "twk-hd",
    onMouseDown: onDragStart
  }, /*#__PURE__*/React.createElement("b", null, title), /*#__PURE__*/React.createElement("button", {
    className: "twk-x",
    "aria-label": "Close tweaks",
    onMouseDown: e => e.stopPropagation(),
    onClick: dismiss
  }, "\u2715")), /*#__PURE__*/React.createElement("div", {
    className: "twk-body"
  }, children, hasDeckStage && railEnabled && !noDeckControls && /*#__PURE__*/React.createElement(TweakSection, {
    label: "Deck"
  }, /*#__PURE__*/React.createElement(TweakToggle, {
    label: "Thumbnail rail",
    value: railVisible,
    onChange: toggleRail
  })))));
}

// ── Layout helpers ──────────────────────────────────────────────────────────

function TweakSection({
  label,
  children
}) {
  return /*#__PURE__*/React.createElement(React.Fragment, null, /*#__PURE__*/React.createElement("div", {
    className: "twk-sect"
  }, label), children);
}
function TweakRow({
  label,
  value,
  children,
  inline = false
}) {
  return /*#__PURE__*/React.createElement("div", {
    className: inline ? 'twk-row twk-row-h' : 'twk-row'
  }, /*#__PURE__*/React.createElement("div", {
    className: "twk-lbl"
  }, /*#__PURE__*/React.createElement("span", null, label), value != null && /*#__PURE__*/React.createElement("span", {
    className: "twk-val"
  }, value)), children);
}

// ── Controls ────────────────────────────────────────────────────────────────

function TweakSlider({
  label,
  value,
  min = 0,
  max = 100,
  step = 1,
  unit = '',
  onChange
}) {
  return /*#__PURE__*/React.createElement(TweakRow, {
    label: label,
    value: `${value}${unit}`
  }, /*#__PURE__*/React.createElement("input", {
    type: "range",
    className: "twk-slider",
    min: min,
    max: max,
    step: step,
    value: value,
    onChange: e => onChange(Number(e.target.value))
  }));
}
function TweakToggle({
  label,
  value,
  onChange
}) {
  return /*#__PURE__*/React.createElement("div", {
    className: "twk-row twk-row-h"
  }, /*#__PURE__*/React.createElement("div", {
    className: "twk-lbl"
  }, /*#__PURE__*/React.createElement("span", null, label)), /*#__PURE__*/React.createElement("button", {
    type: "button",
    className: "twk-toggle",
    "data-on": value ? '1' : '0',
    role: "switch",
    "aria-checked": !!value,
    onClick: () => onChange(!value)
  }, /*#__PURE__*/React.createElement("i", null)));
}
function TweakRadio({
  label,
  value,
  options,
  onChange
}) {
  const trackRef = React.useRef(null);
  const [dragging, setDragging] = React.useState(false);
  // The active value is read by pointer-move handlers attached for the lifetime
  // of a drag — ref it so a stale closure doesn't fire onChange for every move.
  const valueRef = React.useRef(value);
  valueRef.current = value;

  // Segments wrap mid-word once per-segment width runs out. The track is
  // ~248px (280 panel − 28 body pad − 4 seg pad), each button loses 12px
  // to its own padding, and 11.5px system-ui averages ~6.3px/char — so 2
  // options fit ~16 chars each, 3 fit ~10. Past that (or >3 options), fall
  // back to a dropdown rather than wrap.
  const labelLen = o => String(typeof o === 'object' ? o.label : o).length;
  const maxLen = options.reduce((m, o) => Math.max(m, labelLen(o)), 0);
  const fitsAsSegments = maxLen <= ({
    2: 16,
    3: 10
  }[options.length] ?? 0);
  if (!fitsAsSegments) {
    // <select> emits strings — map back to the original option value so the
    // fallback stays type-preserving (numbers, booleans) like the segment path.
    const resolve = s => {
      const m = options.find(o => String(typeof o === 'object' ? o.value : o) === s);
      return m === undefined ? s : typeof m === 'object' ? m.value : m;
    };
    return /*#__PURE__*/React.createElement(TweakSelect, {
      label: label,
      value: value,
      options: options,
      onChange: s => onChange(resolve(s))
    });
  }
  const opts = options.map(o => typeof o === 'object' ? o : {
    value: o,
    label: o
  });
  const idx = Math.max(0, opts.findIndex(o => o.value === value));
  const n = opts.length;
  const segAt = clientX => {
    const r = trackRef.current.getBoundingClientRect();
    const inner = r.width - 4;
    const i = Math.floor((clientX - r.left - 2) / inner * n);
    return opts[Math.max(0, Math.min(n - 1, i))].value;
  };
  const onPointerDown = e => {
    setDragging(true);
    const v0 = segAt(e.clientX);
    if (v0 !== valueRef.current) onChange(v0);
    const move = ev => {
      if (!trackRef.current) return;
      const v = segAt(ev.clientX);
      if (v !== valueRef.current) onChange(v);
    };
    const up = () => {
      setDragging(false);
      window.removeEventListener('pointermove', move);
      window.removeEventListener('pointerup', up);
    };
    window.addEventListener('pointermove', move);
    window.addEventListener('pointerup', up);
  };
  return /*#__PURE__*/React.createElement(TweakRow, {
    label: label
  }, /*#__PURE__*/React.createElement("div", {
    ref: trackRef,
    role: "radiogroup",
    onPointerDown: onPointerDown,
    className: dragging ? 'twk-seg dragging' : 'twk-seg'
  }, /*#__PURE__*/React.createElement("div", {
    className: "twk-seg-thumb",
    style: {
      left: `calc(2px + ${idx} * (100% - 4px) / ${n})`,
      width: `calc((100% - 4px) / ${n})`
    }
  }), opts.map(o => /*#__PURE__*/React.createElement("button", {
    key: o.value,
    type: "button",
    role: "radio",
    "aria-checked": o.value === value
  }, o.label))));
}
function TweakSelect({
  label,
  value,
  options,
  onChange
}) {
  return /*#__PURE__*/React.createElement(TweakRow, {
    label: label
  }, /*#__PURE__*/React.createElement("select", {
    className: "twk-field",
    value: value,
    onChange: e => onChange(e.target.value)
  }, options.map(o => {
    const v = typeof o === 'object' ? o.value : o;
    const l = typeof o === 'object' ? o.label : o;
    return /*#__PURE__*/React.createElement("option", {
      key: v,
      value: v
    }, l);
  })));
}
function TweakText({
  label,
  value,
  placeholder,
  onChange
}) {
  return /*#__PURE__*/React.createElement(TweakRow, {
    label: label
  }, /*#__PURE__*/React.createElement("input", {
    className: "twk-field",
    type: "text",
    value: value,
    placeholder: placeholder,
    onChange: e => onChange(e.target.value)
  }));
}
function TweakNumber({
  label,
  value,
  min,
  max,
  step = 1,
  unit = '',
  onChange
}) {
  const clamp = n => {
    if (min != null && n < min) return min;
    if (max != null && n > max) return max;
    return n;
  };
  const startRef = React.useRef({
    x: 0,
    val: 0
  });
  const onScrubStart = e => {
    e.preventDefault();
    startRef.current = {
      x: e.clientX,
      val: value
    };
    const decimals = (String(step).split('.')[1] || '').length;
    const move = ev => {
      const dx = ev.clientX - startRef.current.x;
      const raw = startRef.current.val + dx * step;
      const snapped = Math.round(raw / step) * step;
      onChange(clamp(Number(snapped.toFixed(decimals))));
    };
    const up = () => {
      window.removeEventListener('pointermove', move);
      window.removeEventListener('pointerup', up);
    };
    window.addEventListener('pointermove', move);
    window.addEventListener('pointerup', up);
  };
  return /*#__PURE__*/React.createElement("div", {
    className: "twk-num"
  }, /*#__PURE__*/React.createElement("span", {
    className: "twk-num-lbl",
    onPointerDown: onScrubStart
  }, label), /*#__PURE__*/React.createElement("input", {
    type: "number",
    value: value,
    min: min,
    max: max,
    step: step,
    onChange: e => onChange(clamp(Number(e.target.value)))
  }), unit && /*#__PURE__*/React.createElement("span", {
    className: "twk-num-unit"
  }, unit));
}

// Relative-luminance contrast pick — checkmarks drawn over a swatch need to
// read on both #111 and #fafafa without per-option configuration. Hex input
// only (#rgb / #rrggbb); named or rgb()/hsl() colors fall through to "light".
function __twkIsLight(hex) {
  const h = String(hex).replace('#', '');
  const x = h.length === 3 ? h.replace(/./g, c => c + c) : h.padEnd(6, '0');
  const n = parseInt(x.slice(0, 6), 16);
  if (Number.isNaN(n)) return true;
  const r = n >> 16 & 255,
    g = n >> 8 & 255,
    b = n & 255;
  return r * 299 + g * 587 + b * 114 > 148000;
}
const __TwkCheck = ({
  light
}) => /*#__PURE__*/React.createElement("svg", {
  viewBox: "0 0 14 14",
  "aria-hidden": "true"
}, /*#__PURE__*/React.createElement("path", {
  d: "M3 7.2 5.8 10 11 4.2",
  fill: "none",
  strokeWidth: "2.2",
  strokeLinecap: "round",
  strokeLinejoin: "round",
  stroke: light ? 'rgba(0,0,0,.78)' : '#fff'
}));

// TweakColor — curated color/palette picker. Each option is either a single
// hex string or an array of 1-5 hex strings; the card adapts — a lone color
// renders solid, a palette renders colors[0] as the hero (left ~2/3) with the
// rest stacked in a sharp column on the right. onChange emits the
// option in the shape it was passed (string stays string, array stays array).
// Without options it falls back to the native color input for back-compat.
function TweakColor({
  label,
  value,
  options,
  onChange
}) {
  if (!options || !options.length) {
    return /*#__PURE__*/React.createElement("div", {
      className: "twk-row twk-row-h"
    }, /*#__PURE__*/React.createElement("div", {
      className: "twk-lbl"
    }, /*#__PURE__*/React.createElement("span", null, label)), /*#__PURE__*/React.createElement("input", {
      type: "color",
      className: "twk-swatch",
      value: value,
      onChange: e => onChange(e.target.value)
    }));
  }
  // Native <input type=color> emits lowercase hex per the HTML spec, so
  // compare case-insensitively. String() guards JSON.stringify(undefined),
  // which returns the primitive undefined (no .toLowerCase).
  const key = o => String(JSON.stringify(o)).toLowerCase();
  const cur = key(value);
  return /*#__PURE__*/React.createElement(TweakRow, {
    label: label
  }, /*#__PURE__*/React.createElement("div", {
    className: "twk-chips",
    role: "radiogroup"
  }, options.map((o, i) => {
    const colors = Array.isArray(o) ? o : [o];
    const [hero, ...rest] = colors;
    const sup = rest.slice(0, 4);
    const on = key(o) === cur;
    return /*#__PURE__*/React.createElement("button", {
      key: i,
      type: "button",
      className: "twk-chip",
      role: "radio",
      "aria-checked": on,
      "data-on": on ? '1' : '0',
      "aria-label": colors.join(', '),
      title: colors.join(' · '),
      style: {
        background: hero
      },
      onClick: () => onChange(o)
    }, sup.length > 0 && /*#__PURE__*/React.createElement("span", null, sup.map((c, j) => /*#__PURE__*/React.createElement("i", {
      key: j,
      style: {
        background: c
      }
    }))), on && /*#__PURE__*/React.createElement(__TwkCheck, {
      light: __twkIsLight(hero)
    }));
  })));
}
function TweakButton({
  label,
  onClick,
  secondary = false
}) {
  return /*#__PURE__*/React.createElement("button", {
    type: "button",
    className: secondary ? 'twk-btn secondary' : 'twk-btn',
    onClick: onClick
  }, label);
}
Object.assign(window, {
  useTweaks,
  TweaksPanel,
  TweakSection,
  TweakRow,
  TweakSlider,
  TweakToggle,
  TweakRadio,
  TweakSelect,
  TweakText,
  TweakNumber,
  TweakColor,
  TweakButton
});
})(); } catch (e) { __ds_ns.__errors.push({ path: "role-game/tweaks-panel.jsx", error: String((e && e.message) || e) }); }

// tetri-psychometry-export/tetri-game.jsx
try { (() => {
/* global React */
const {
  useState,
  useEffect,
  useRef,
  useCallback,
  useMemo,
  useLayoutEffect
} = React;
// icon source: resolves to an inlined data-URI in the single-file build, or the
// relative path in the folder/server build (works on http:// and file://).
const EZ_ICON = typeof document !== 'undefined' && document.getElementById('ez-icon-src') && document.getElementById('ez-icon-src').src || 'ez-icon.png';

/* ════════════════ sound (WebAudio FX) ════════════════ */
const MUTED_KEY = "tx-muted-v1";
const REVIEW_KEY = "tx-review-v1";
const Sound = {
  ctx: null,
  muted: false,
  init() {
    if (!this.ctx) {
      try {
        this.ctx = new (window.AudioContext || window.webkitAudioContext)();
      } catch (e) {}
    }
    if (this.ctx && this.ctx.state === 'suspended') this.ctx.resume();
  },
  setMuted(m) {
    this.muted = !!m;
    try {
      localStorage.setItem(MUTED_KEY, m ? '1' : '0');
    } catch (e) {}
  },
  beep(f, d, type = 'sine', g = 0.15, delay = 0) {
    if (this.muted || !this.ctx) return;
    const t = this.ctx.currentTime + delay,
      o = this.ctx.createOscillator(),
      gn = this.ctx.createGain();
    o.type = type;
    o.frequency.value = f;
    gn.gain.setValueAtTime(g, t);
    gn.gain.exponentialRampToValueAtTime(0.001, t + d);
    o.connect(gn);
    gn.connect(this.ctx.destination);
    o.start(t);
    o.stop(t + d);
  },
  play(name) {
    if (this.muted) return;
    this.init();
    switch (name) {
      case 'move':
        this.beep(420, 0.04, 'square', 0.06);
        break;
      case 'drop':
        this.beep(180, 0.08, 'sawtooth', 0.12);
        this.beep(120, 0.1, 'square', 0.1, 0.03);
        break;
      case 'hit':
        this.beep(523, 0.1, 'square', 0.16);
        this.beep(784, 0.12, 'square', 0.14, 0.08);
        this.beep(1047, 0.22, 'triangle', 0.16, 0.16);
        break;
      case 'miss':
        this.beep(330, 0.14, 'square', 0.2);
        this.beep(196, 0.3, 'sawtooth', 0.2, 0.12);
        this.beep(130, 0.4, 'triangle', 0.18, 0.34);
        break;
      case 'fifty':
        this.beep(880, 0.1, 'sine', 0.15);
        this.beep(1320, 0.18, 'sine', 0.16, 0.1);
        break;
      case 'levelup':
        this.beep(523, 0.1, 'triangle', 0.18);
        this.beep(659, 0.1, 'triangle', 0.18, 0.1);
        this.beep(784, 0.1, 'triangle', 0.18, 0.2);
        this.beep(1047, 0.32, 'sine', 0.2, 0.3);
        break;
      case 'streak':
        this.beep(880, 0.08, 'sine', 0.13);
        this.beep(1320, 0.1, 'sine', 0.14, 0.08);
        this.beep(1760, 0.2, 'sine', 0.14, 0.16);
        break;
      case 'gameover':
        this.beep(440, 0.2, 'sine', 0.15);
        this.beep(330, 0.24, 'sine', 0.15, 0.2);
        this.beep(220, 0.5, 'sine', 0.18, 0.45);
        break;
    }
  }
};
try {
  Sound.muted = localStorage.getItem(MUTED_KEY) === '1';
} catch (e) {}

/* ════════════════ review list (persisted per-browser) ════════════════ */
function getReview() {
  try {
    return JSON.parse(localStorage.getItem(REVIEW_KEY) || '[]');
  } catch (e) {
    return [];
  }
}
function addReview(words) {
  const cur = getReview();
  const seen = new Set(cur.map(w => String(w.en).toLowerCase()));
  for (const w of words || []) {
    if (!w || !w.en) continue;
    const k = String(w.en).toLowerCase();
    if (!seen.has(k)) {
      seen.add(k);
      cur.push({
        en: w.en,
        he: w.he
      });
    }
  }
  try {
    localStorage.setItem(REVIEW_KEY, JSON.stringify(cur));
  } catch (e) {}
  return cur;
}
function clearReview() {
  try {
    localStorage.removeItem(REVIEW_KEY);
  } catch (e) {}
}

/* ════════════════ dictionary helpers ════════════════ */
function shuffle(a) {
  const x = [...a];
  for (let i = x.length - 1; i > 0; i--) {
    const j = Math.random() * (i + 1) | 0;
    [x[i], x[j]] = [x[j], x[i]];
  }
  return x;
}
function normMeaning(s) {
  return String(s || '').toLowerCase().replace(/[\/,،]/g, ' ').replace(/\s+/g, ' ').replace(/[״"׳'.…]/g, '').trim();
}
function buildQuestion(correct, fullDict, idx) {
  const ck = normMeaning(correct.he);
  const cen = String(correct.en).toLowerCase();
  const pool = fullDict.map(e => ({
    e,
    key: normMeaning(e.he)
  })).filter(({
    e,
    key
  }) => String(e.en).toLowerCase() !== cen && key !== ck);
  const picked = [];
  const seen = new Set([ck]);
  for (const {
    e,
    key
  } of shuffle(pool)) {
    if (seen.has(key)) continue;
    seen.add(key);
    picked.push(e);
    if (picked.length === 3) break;
  }
  while (picked.length < 3) {
    const f = shuffle(pool).filter(p => !picked.includes(p.e));
    if (!f.length) break;
    picked.push(f[0].e);
  }
  const options = shuffle([correct.he, ...picked.map(d => d.he)]);
  return {
    en: String(correct.en),
    he: correct.he,
    options,
    dictIdx: idx
  };
}

/* ════════════════ icons ════════════════ */
const Ico = {
  sound: () => /*#__PURE__*/React.createElement("svg", {
    viewBox: "0 0 24 24",
    fill: "currentColor"
  }, /*#__PURE__*/React.createElement("path", {
    d: "M3 10v4a1 1 0 0 0 1 1h3l4 3.5a1 1 0 0 0 1.6-.8V6.3a1 1 0 0 0-1.6-.8L7 9H4a1 1 0 0 0-1 1Z"
  }), /*#__PURE__*/React.createElement("path", {
    d: "M16 8.5a4 4 0 0 1 0 7",
    fill: "none",
    stroke: "currentColor",
    strokeWidth: "2",
    strokeLinecap: "round"
  })),
  mute: () => /*#__PURE__*/React.createElement("svg", {
    viewBox: "0 0 24 24",
    fill: "none",
    stroke: "currentColor",
    strokeWidth: "2.2",
    strokeLinecap: "round",
    strokeLinejoin: "round"
  }, /*#__PURE__*/React.createElement("path", {
    d: "M3 10v4a1 1 0 0 0 1 1h3l4 3.5a1 1 0 0 0 1.6-.8V6.3a1 1 0 0 0-1.6-.8L7 9H4a1 1 0 0 0-1 1Z",
    fill: "currentColor",
    stroke: "none"
  }), /*#__PURE__*/React.createElement("path", {
    d: "M16 9l5 5M21 9l-5 5"
  })),
  expand: () => /*#__PURE__*/React.createElement("svg", {
    viewBox: "0 0 24 24",
    fill: "none",
    stroke: "currentColor",
    strokeWidth: "2.4",
    strokeLinecap: "round",
    strokeLinejoin: "round"
  }, /*#__PURE__*/React.createElement("path", {
    d: "M4 9V4h5M20 9V4h-5M4 15v5h5M20 15v5h-5"
  })),
  home: () => /*#__PURE__*/React.createElement("svg", {
    viewBox: "0 0 24 24",
    fill: "none",
    stroke: "currentColor",
    strokeWidth: "2.2",
    strokeLinecap: "round",
    strokeLinejoin: "round"
  }, /*#__PURE__*/React.createElement("path", {
    d: "M3 11l9-8 9 8"
  }), /*#__PURE__*/React.createElement("path", {
    d: "M5 10v10h14V10"
  }), /*#__PURE__*/React.createElement("path", {
    d: "M10 20v-6h4v6"
  })),
  trophy: () => /*#__PURE__*/React.createElement("svg", {
    viewBox: "0 0 24 24",
    fill: "none",
    stroke: "currentColor",
    strokeWidth: "2.2",
    strokeLinecap: "round",
    strokeLinejoin: "round"
  }, /*#__PURE__*/React.createElement("path", {
    d: "M8 21h8M12 17v4M7 4h10v5a5 5 0 0 1-10 0V4z"
  }), /*#__PURE__*/React.createElement("path", {
    d: "M7 6H4v2a3 3 0 0 0 3 3M17 6h3v2a3 3 0 0 1-3 3"
  })),
  left: () => /*#__PURE__*/React.createElement("svg", {
    viewBox: "0 0 24 24",
    fill: "currentColor"
  }, /*#__PURE__*/React.createElement("path", {
    d: "M15 5 L7 12 L15 19 Z"
  })),
  right: () => /*#__PURE__*/React.createElement("svg", {
    viewBox: "0 0 24 24",
    fill: "currentColor"
  }, /*#__PURE__*/React.createElement("path", {
    d: "M9 5 L17 12 L9 19 Z"
  })),
  down: () => /*#__PURE__*/React.createElement("svg", {
    viewBox: "0 0 24 24",
    fill: "currentColor"
  }, /*#__PURE__*/React.createElement("path", {
    d: "M5 9 L12 17 L19 9 Z"
  })),
  play: () => /*#__PURE__*/React.createElement("svg", {
    viewBox: "0 0 24 24",
    fill: "currentColor"
  }, /*#__PURE__*/React.createElement("path", {
    d: "M7 5 L19 12 L7 19 Z"
  })),
  go: () => /*#__PURE__*/React.createElement("svg", {
    viewBox: "0 0 24 24",
    fill: "none",
    stroke: "currentColor",
    strokeWidth: "2.6",
    strokeLinecap: "round",
    strokeLinejoin: "round"
  }, /*#__PURE__*/React.createElement("path", {
    d: "M19 12H5"
  }), /*#__PURE__*/React.createElement("path", {
    d: "M12 5l-7 7 7 7"
  })),
  share: () => /*#__PURE__*/React.createElement("svg", {
    viewBox: "0 0 24 24",
    fill: "none",
    stroke: "currentColor",
    strokeWidth: "2.2",
    strokeLinecap: "round",
    strokeLinejoin: "round"
  }, /*#__PURE__*/React.createElement("circle", {
    cx: "18",
    cy: "5",
    r: "3"
  }), /*#__PURE__*/React.createElement("circle", {
    cx: "6",
    cy: "12",
    r: "3"
  }), /*#__PURE__*/React.createElement("circle", {
    cx: "18",
    cy: "19",
    r: "3"
  }), /*#__PURE__*/React.createElement("path", {
    d: "M8.6 13.5l6.8 4M15.4 6.5l-6.8 4"
  })),
  print: () => /*#__PURE__*/React.createElement("svg", {
    viewBox: "0 0 24 24",
    fill: "none",
    stroke: "currentColor",
    strokeWidth: "2.2",
    strokeLinecap: "round",
    strokeLinejoin: "round"
  }, /*#__PURE__*/React.createElement("path", {
    d: "M6 9V3h12v6"
  }), /*#__PURE__*/React.createElement("path", {
    d: "M6 18H4a1 1 0 0 1-1-1v-5a1 1 0 0 1 1-1h16a1 1 0 0 1 1 1v5a1 1 0 0 1-1 1h-2"
  }), /*#__PURE__*/React.createElement("rect", {
    x: "6",
    y: "14",
    width: "12",
    height: "7",
    rx: "1"
  })),
  gift: () => /*#__PURE__*/React.createElement("svg", {
    viewBox: "0 0 24 24",
    fill: "none",
    stroke: "currentColor",
    strokeWidth: "2.1",
    strokeLinecap: "round",
    strokeLinejoin: "round"
  }, /*#__PURE__*/React.createElement("path", {
    d: "M20 12v8a1 1 0 0 1-1 1H5a1 1 0 0 1-1-1v-8"
  }), /*#__PURE__*/React.createElement("path", {
    d: "M2 8h20v4H2z"
  }), /*#__PURE__*/React.createElement("path", {
    d: "M12 8v13M12 8S10.5 4 8 4a2 2 0 0 0 0 4M12 8s1.5-4 4-4a2 2 0 0 1 0 4"
  })),
  mail: () => /*#__PURE__*/React.createElement("svg", {
    viewBox: "0 0 24 24",
    fill: "none",
    stroke: "currentColor",
    strokeWidth: "2.2",
    strokeLinecap: "round",
    strokeLinejoin: "round"
  }, /*#__PURE__*/React.createElement("rect", {
    x: "3",
    y: "5",
    width: "18",
    height: "14",
    rx: "2.5"
  }), /*#__PURE__*/React.createElement("path", {
    d: "M3.5 7l8.5 6 8.5-6"
  })),
  refresh: () => /*#__PURE__*/React.createElement("svg", {
    viewBox: "0 0 24 24",
    fill: "none",
    stroke: "currentColor",
    strokeWidth: "2.3",
    strokeLinecap: "round",
    strokeLinejoin: "round"
  }, /*#__PURE__*/React.createElement("path", {
    d: "M3 12a9 9 0 0 1 15.5-6.3L21 8"
  }), /*#__PURE__*/React.createElement("path", {
    d: "M21 3v5h-5"
  }), /*#__PURE__*/React.createElement("path", {
    d: "M21 12a9 9 0 0 1-15.5 6.3L3 16"
  }), /*#__PURE__*/React.createElement("path", {
    d: "M3 21v-5h5"
  })),
  hand: () => /*#__PURE__*/React.createElement("svg", {
    viewBox: "0 0 40 58",
    fill: "none"
  }, /*#__PURE__*/React.createElement("ellipse", {
    cx: "20",
    cy: "55",
    rx: "11",
    ry: "3.5",
    fill: "#000",
    opacity: ".16"
  }), /*#__PURE__*/React.createElement("path", {
    d: "M12.5 51 V17 a7.5 7.5 0 0 1 15 0 v29 a5 5 0 0 1-5 5 h-5 a5 5 0 0 1-5-5 z",
    fill: "#F7CBA6",
    stroke: "#00000018",
    strokeWidth: "1.5"
  }), /*#__PURE__*/React.createElement("path", {
    d: "M12.5 40 q7.5 4 15 0",
    stroke: "#E0A87E",
    strokeWidth: "1.4",
    strokeLinecap: "round",
    fill: "none"
  }), /*#__PURE__*/React.createElement("ellipse", {
    cx: "20",
    cy: "14.5",
    rx: "5.5",
    ry: "4.2",
    fill: "#fff",
    opacity: ".5"
  }))
};
function Heart({
  lost
}) {
  return /*#__PURE__*/React.createElement("svg", {
    viewBox: "0 0 24 24",
    className: lost ? 'lost' : ''
  }, /*#__PURE__*/React.createElement("path", {
    fill: "#F33F3F",
    d: "M12 21s-7.5-4.7-9.6-9.5C.9 7.7 3.5 4 7.2 4c2 0 3.6 1 4.8 2.6C13.2 5 14.8 4 16.8 4c3.7 0 6.3 3.7 4.8 7.5C19.5 16.3 12 21 12 21z"
  }));
}
const TET_COLORS = ['#F2C230', '#E0519B', '#7E5BC2', '#3FA76C', '#5BB8E8', '#3F6BD6', '#D6463A', '#F37327', '#A9A4EC'];
function randColor(seed) {
  return TET_COLORS[Math.floor((Math.sin(seed * 99.13) * 0.5 + 0.5) * TET_COLORS.length) % TET_COLORS.length];
}

/* decorative tetris-block wall — memoised so it never re-renders mid-game */
const Wall = React.memo(function Wall({
  side,
  n
}) {
  const cells = useMemo(() => Array.from({
    length: n * 2
  }, (_, i) => randColor(i + (side === 'left' ? 7 : 31))), [side, n]);
  return /*#__PURE__*/React.createElement("div", {
    className: 'gm-wall ' + side,
    "aria-hidden": true
  }, cells.map((c, i) => /*#__PURE__*/React.createElement("div", {
    key: i,
    className: "gm-brick",
    style: {
      background: c
    }
  })));
});

/* ════════════════ Intro: home screen → (first time) animated explainer ════════════════ */
/* A stage that shows a mini game board and drives one tutorial beat with an animated finger. */
function ExStage({
  phase
}) {
  const bins = ['חמדנות', 'פחד', 'שפע', 'כעס']; // 0 = correct meaning of GREED
  const CORRECT = 0,
    WRONG = 2;
  const [ltoggle, setLtoggle] = useState(false); // move-scene: which arrow the finger presses
  useEffect(() => {
    if (phase !== 'move') return;
    const t = setInterval(() => setLtoggle(v => !v), 1050);
    return () => clearInterval(t);
  }, [phase]);

  // tower height per phase
  const tower = phase === 'mistake' ? ['#5BB8E8', '#E0519B', '#F2C230', '#7E5BC2', '#3FA76C'] : phase === 'correct' ? ['#5BB8E8', '#E0519B', '#F2C230'] : ['#5BB8E8', '#E0519B'];
  const towerCol = WRONG;
  const tileIdx = phase === 'move' ? ltoggle ? 0 : 3 : phase === 'correct' ? CORRECT : phase === 'mistake' ? WRONG : 1;
  const tileState = phase === 'correct' ? 'right' : phase === 'mistake' ? 'wrong' : 'live';
  const handPos = phase === 'move' ? ltoggle ? 'l' : 'r' : 'd';
  return /*#__PURE__*/React.createElement("div", {
    className: 'ex-stage ' + phase
  }, /*#__PURE__*/React.createElement("div", {
    className: "ex-lane"
  }, /*#__PURE__*/React.createElement("div", {
    className: 'ex-danger' + (phase === 'mistake' ? ' hot' : '')
  }), /*#__PURE__*/React.createElement("div", {
    className: 'ex-tile ' + tileState,
    key: phase,
    style: {
      left: `${tileIdx * 25 + 12.5}%`
    }
  }, /*#__PURE__*/React.createElement("span", {
    className: "w"
  }, "GREED"), phase === 'correct' && /*#__PURE__*/React.createElement("span", {
    className: "badge good"
  }, "\u2713"), phase === 'mistake' && /*#__PURE__*/React.createElement("span", {
    className: "badge bad"
  }, "\u2717")), phase === 'speed' && /*#__PURE__*/React.createElement("div", {
    className: "ex-score-pop"
  }, "+320"), phase === 'correct' && /*#__PURE__*/React.createElement("div", {
    className: "ex-burst",
    style: {
      left: `calc(${towerCol * 25}% + 12.5%)`
    }
  }, [0, 1, 2, 3, 4, 5].map(i => /*#__PURE__*/React.createElement("span", {
    key: i,
    className: 'p p' + i
  }))), /*#__PURE__*/React.createElement("div", {
    className: "ex-pile",
    style: {
      left: `calc(${towerCol * 25}% + 5px)`
    }
  }, tower.map((c, i) => /*#__PURE__*/React.createElement("div", {
    key: phase + '-' + i,
    className: 'ex-brick' + (phase === 'mistake' && i === tower.length - 1 ? ' top new' : '') + (phase === 'correct' && i === tower.length - 1 ? ' shatter' : ''),
    style: {
      background: c
    }
  }))), /*#__PURE__*/React.createElement("div", {
    className: "ex-bins"
  }, bins.map((b, i) => {
    let cls = 'ex-bin';
    if (phase === 'correct' && i === CORRECT) cls += ' hit';else if (phase === 'mistake' && i === WRONG) cls += ' miss';else if (i === tileIdx) cls += ' target';
    return /*#__PURE__*/React.createElement("div", {
      key: i,
      className: cls
    }, b);
  }))), /*#__PURE__*/React.createElement("div", {
    className: "ex-ctrl"
  }, /*#__PURE__*/React.createElement("span", {
    className: 'ex-arrow l' + (handPos === 'l' ? ' hit' : '')
  }, /*#__PURE__*/React.createElement(Ico.left, null)), /*#__PURE__*/React.createElement("span", {
    className: 'ex-arrow d' + (handPos === 'd' ? ' hit' : '') + (phase === 'speed' ? ' fast' : '')
  }, /*#__PURE__*/React.createElement(Ico.down, null)), /*#__PURE__*/React.createElement("span", {
    className: 'ex-arrow r' + (handPos === 'r' ? ' hit' : '')
  }, /*#__PURE__*/React.createElement(Ico.right, null)), /*#__PURE__*/React.createElement("div", {
    className: 'ex-hand pos-' + handPos + (phase === 'speed' ? ' rapid' : '')
  }, /*#__PURE__*/React.createElement(Ico.hand, null))));
}

/* summary beat — the post-game reward, shown as a mini end-card */
function ExSummary() {
  const rows = [['GREED', 'חמדנות'], ['VANISH', 'להיעלם'], ['SOLEMN', 'רציני']];
  return /*#__PURE__*/React.createElement("div", {
    className: "ex-summary"
  }, /*#__PURE__*/React.createElement("div", {
    className: "ex-sum-title"
  }, "\u05D4\u05DE\u05D9\u05DC\u05D9\u05DD \u05E9\u05DC\u05D0 \u05D9\u05D3\u05E2\u05EA", /*#__PURE__*/React.createElement("span", {
    className: "dot"
  }, ".")), /*#__PURE__*/React.createElement("div", {
    className: "ex-sum-list"
  }, rows.map((r, i) => /*#__PURE__*/React.createElement("div", {
    key: i,
    className: "ex-sum-row",
    style: {
      animationDelay: i * 0.15 + 's'
    }
  }, /*#__PURE__*/React.createElement("span", {
    className: "en"
  }, r[0]), /*#__PURE__*/React.createElement("span", {
    className: "he"
  }, r[1])))), /*#__PURE__*/React.createElement("div", {
    className: "ex-sum-actions"
  }, /*#__PURE__*/React.createElement("span", {
    className: "ex-sum-btn share"
  }, /*#__PURE__*/React.createElement(Ico.share, null), "\u05E9\u05D9\u05EA\u05D5\u05E3"), /*#__PURE__*/React.createElement("span", {
    className: "ex-sum-btn again"
  }, /*#__PURE__*/React.createElement(Ico.refresh, null), "\u05E1\u05D9\u05D1\u05D5\u05D1 \u05E2\u05DC \u05D0\u05DC\u05D5")));
}
const EX_STEPS = [{
  key: 'move',
  title: 'מזיזים ובוחרים',
  cap: 'החליקו את המילה עם ◄ ► עד לפירוש הנכון בעברית'
}, {
  key: 'speed',
  title: 'מאיצים וצוברים',
  cap: 'כל לחיצה על ▼ מפילה מהר יותר — ומזניקה את הניקוד'
}, {
  key: 'correct',
  title: 'פירוש נכון = ניפוץ',
  cap: 'נחיתה על הפירוש הנכון מנפצת לבנה מהמגדל'
}, {
  key: 'mistake',
  title: 'טעות = המגדל גדל',
  cap: 'טעות משאירה לבנה. כשהמגדל מגיע לקו האדום — נפסלים'
}, {
  key: 'summary',
  title: 'המילים שלא ידעת',
  cap: 'בסוף מקבלים את רשימת המילים — לשיתוף, או לסיבוב נוסף שמתמקד בהן'
}];
function Explainer({
  onNext,
  muted,
  toggleMute,
  toggleFs
}) {
  const [step, setStep] = useState(0);
  const [paused, setPaused] = useState(false);
  const last = EX_STEPS.length - 1;
  useEffect(() => {
    if (paused) return;
    const t = setTimeout(() => setStep(s => (s + 1) % EX_STEPS.length), step === last ? 5200 : 4200);
    return () => clearTimeout(t);
  }, [step, paused, last]);
  const go = i => {
    setPaused(true);
    setStep((i + EX_STEPS.length) % EX_STEPS.length);
  };
  const cur = EX_STEPS[step];
  return /*#__PURE__*/React.createElement("div", {
    className: "gm-app"
  }, /*#__PURE__*/React.createElement("div", {
    className: "gm-frame"
  }, /*#__PURE__*/React.createElement("div", {
    className: "gm-intro gm-explainer"
  }, /*#__PURE__*/React.createElement("div", {
    className: "gm-intro-actions"
  }, /*#__PURE__*/React.createElement("button", {
    className: "gm-round-btn",
    onClick: toggleFs,
    title: "\u05DE\u05E1\u05DA \u05DE\u05DC\u05D0"
  }, /*#__PURE__*/React.createElement(Ico.expand, null)), /*#__PURE__*/React.createElement("button", {
    className: "gm-round-btn fifty",
    onClick: toggleMute,
    title: "\u05E1\u05D0\u05D5\u05E0\u05D3"
  }, muted ? /*#__PURE__*/React.createElement(Ico.mute, null) : /*#__PURE__*/React.createElement(Ico.sound, null))), /*#__PURE__*/React.createElement("button", {
    className: "gm-intro-skip",
    onClick: onNext
  }, /*#__PURE__*/React.createElement("span", null, "\u05D3\u05DC\u05D2"), /*#__PURE__*/React.createElement(Ico.go, null)), /*#__PURE__*/React.createElement("div", {
    className: "gm-intro-brand ex-brand"
  }, /*#__PURE__*/React.createElement("img", {
    src: EZ_ICON,
    alt: ""
  }), /*#__PURE__*/React.createElement("span", {
    className: "brand-eazy"
  }, "eazy")), /*#__PURE__*/React.createElement("div", {
    className: "ex-visual",
    key: step
  }, cur.key === 'summary' ? /*#__PURE__*/React.createElement(ExSummary, null) : /*#__PURE__*/React.createElement(ExStage, {
    phase: cur.key
  })), /*#__PURE__*/React.createElement("div", {
    className: "ex-textblock"
  }, /*#__PURE__*/React.createElement("div", {
    className: "ex-step-n"
  }, step + 1, /*#__PURE__*/React.createElement("span", {
    className: "tot"
  }, " / ", EX_STEPS.length)), /*#__PURE__*/React.createElement("div", {
    className: "ex-head"
  }, cur.title), /*#__PURE__*/React.createElement("div", {
    className: "ex-caption"
  }, cur.cap)), /*#__PURE__*/React.createElement("div", {
    className: "ex-dots"
  }, EX_STEPS.map((_, i) => /*#__PURE__*/React.createElement("button", {
    key: i,
    className: 'ex-dot' + (i === step ? ' on' : ''),
    onClick: () => go(i),
    "aria-label": 'שלב ' + (i + 1)
  }))), /*#__PURE__*/React.createElement("div", {
    className: "ex-nav"
  }, /*#__PURE__*/React.createElement("button", {
    className: "ex-nav-btn ghost",
    onClick: () => go(step - 1)
  }, /*#__PURE__*/React.createElement(Ico.right, null)), step === last ? /*#__PURE__*/React.createElement("button", {
    className: "gm-start ex-start",
    onClick: onNext
  }, /*#__PURE__*/React.createElement("span", null, "\u05DE\u05EA\u05D7\u05D9\u05DC\u05D9\u05DD \u05DC\u05E9\u05D7\u05E7"), /*#__PURE__*/React.createElement(Ico.go, null)) : /*#__PURE__*/React.createElement("button", {
    className: "gm-start ex-start",
    onClick: () => go(step + 1)
  }, /*#__PURE__*/React.createElement("span", null, "\u05D4\u05D1\u05D0"), /*#__PURE__*/React.createElement(Ico.left, null)), /*#__PURE__*/React.createElement("button", {
    className: "ex-nav-btn ghost",
    onClick: () => go(step + 1)
  }, /*#__PURE__*/React.createElement(Ico.left, null))))));
}
function MainIntro({
  onStart,
  muted,
  toggleMute,
  toggleFs
}) {
  const rain = useMemo(() => Array.from({
    length: 14
  }, (_, i) => ({
    left: (i * 7.3 + i % 3 * 4) % 96,
    size: 18 + i % 4 * 8,
    dur: 6 + i % 5 * 1.6,
    delay: -(i * 0.9),
    color: randColor(i + 3)
  })), []);
  return /*#__PURE__*/React.createElement("div", {
    className: "gm-app"
  }, /*#__PURE__*/React.createElement("div", {
    className: "gm-frame"
  }, /*#__PURE__*/React.createElement("div", {
    className: "gm-intro"
  }, /*#__PURE__*/React.createElement("div", {
    className: "gm-intro-rain",
    "aria-hidden": true
  }, rain.map((r, i) => /*#__PURE__*/React.createElement("div", {
    key: i,
    className: "tb",
    style: {
      left: r.left + '%',
      width: r.size,
      height: r.size,
      background: r.color,
      animationDuration: r.dur + 's',
      animationDelay: r.delay + 's'
    }
  }))), /*#__PURE__*/React.createElement("div", {
    className: "gm-intro-actions"
  }, /*#__PURE__*/React.createElement("button", {
    className: "gm-round-btn",
    onClick: toggleFs,
    title: "\u05DE\u05E1\u05DA \u05DE\u05DC\u05D0"
  }, /*#__PURE__*/React.createElement(Ico.expand, null)), /*#__PURE__*/React.createElement("button", {
    className: "gm-round-btn fifty",
    onClick: toggleMute,
    title: "\u05E1\u05D0\u05D5\u05E0\u05D3"
  }, muted ? /*#__PURE__*/React.createElement(Ico.mute, null) : /*#__PURE__*/React.createElement(Ico.sound, null))), /*#__PURE__*/React.createElement("button", {
    className: "gm-intro-home",
    title: "\u05DC\u05D0\u05EA\u05E8 ezway",
    onClick: () => {
      try {
        window.top.location.href = 'https://www.ezway.co.il';
      } catch (e) {
        window.open('https://www.ezway.co.il', '_blank');
      }
    }
  }, /*#__PURE__*/React.createElement(Ico.home, null)), /*#__PURE__*/React.createElement("div", {
    className: "gm-intro-inner"
  }, /*#__PURE__*/React.createElement("div", {
    className: "gm-intro-brand"
  }, /*#__PURE__*/React.createElement("img", {
    src: EZ_ICON,
    alt: ""
  }), /*#__PURE__*/React.createElement("span", {
    className: "brand-eazy"
  }, "eazy")), /*#__PURE__*/React.createElement("h1", {
    className: "gm-intro-title"
  }, "\u05D8\u05D8\u05E8\u05D9 \u05DE\u05D9\u05DC\u05D9\u05DD", /*#__PURE__*/React.createElement("span", {
    className: "dot"
  }, "."), /*#__PURE__*/React.createElement("span", {
    className: "en"
  }, "\u05D0\u05E0\u05D2\u05DC\u05D9\u05EA \u05D4\u05D9\u05D0 ", /*#__PURE__*/React.createElement("span", {
    className: "brand-eazy"
  }, "eazy"))), /*#__PURE__*/React.createElement("p", {
    className: "gm-intro-lead"
  }, "\u05DE\u05D9\u05DC\u05D4 \u05D1\u05D0\u05E0\u05D2\u05DC\u05D9\u05EA \u05E0\u05D5\u05E4\u05DC\u05EA \u05DE\u05DC\u05DE\u05E2\u05DC\u05D4. ", /*#__PURE__*/React.createElement("br", {
    className: "m-br"
  }), "\u05D4\u05D6\u05D9\u05D6\u05D5 \u05D0\u05D5\u05EA\u05D4 \u05D0\u05DC \u05D4\u05E4\u05D9\u05E8\u05D5\u05E9 \u05D4\u05E0\u05DB\u05D5\u05DF \u05D1\u05E2\u05D1\u05E8\u05D9\u05EA ", /*#__PURE__*/React.createElement("br", {
    className: "m-br"
  }), "\u05DC\u05E4\u05E0\u05D9 \u05E9\u05D4\u05D9\u05D0 \u05E0\u05D5\u05D7\u05EA\u05EA."), /*#__PURE__*/React.createElement("div", {
    className: "gm-intro-bonus"
  }, /*#__PURE__*/React.createElement("div", {
    className: "gift"
  }, /*#__PURE__*/React.createElement(Ico.gift, null)), /*#__PURE__*/React.createElement("div", {
    className: "bt"
  }, /*#__PURE__*/React.createElement("div", {
    className: "bh"
  }, "\u05D1\u05D5\u05E0\u05D5\u05E1 \u05D1\u05E1\u05D5\u05E3 \u05DB\u05DC \u05DE\u05E9\u05D7\u05E7", /*#__PURE__*/React.createElement("span", {
    className: "dot"
  }, ".")), /*#__PURE__*/React.createElement("div", {
    className: "bs"
  }, "\u05DC\u05E9\u05EA\u05E3, \u05DC\u05D4\u05D3\u05E4\u05D9\u05E1 \u05D0\u05D5 \u05DC\u05E9\u05D7\u05E7 \u05E9\u05D5\u05D1 \u2014 \u05D1\u05D3\u05D2\u05E9 \u05E2\u05DC \u05D4\u05DE\u05D9\u05DC\u05D9\u05DD \u05E9\u05E2\u05D3\u05D9\u05D9\u05DF \u05DC\u05D0 \u05D9\u05D3\u05E2\u05EA.")))), /*#__PURE__*/React.createElement("button", {
    className: "gm-start",
    onClick: onStart
  }, /*#__PURE__*/React.createElement("span", null, "\u05D9\u05D5\u05E6\u05D0\u05D9\u05DD \u05DC\u05D3\u05E8\u05DA"), /*#__PURE__*/React.createElement(Ico.go, null)))));
}
function IntroScreen({
  onStart,
  muted,
  toggleMute,
  toggleFs
}) {
  const [stage, setStage] = useState('home');
  const EXPLAINER_KEY = 'tx-explainer-seen-v1';
  const seen = () => {
    try {
      return localStorage.getItem(EXPLAINER_KEY) === '1';
    } catch (e) {
      return false;
    }
  };
  const begin = () => {
    if (seen()) onStart();else setStage('explainer');
  };
  const finishExplainer = () => {
    try {
      localStorage.setItem(EXPLAINER_KEY, '1');
    } catch (e) {}
    onStart();
  };
  if (stage === 'explainer') return /*#__PURE__*/React.createElement(Explainer, {
    onNext: finishExplainer,
    muted: muted,
    toggleMute: toggleMute,
    toggleFs: toggleFs
  });
  return /*#__PURE__*/React.createElement(MainIntro, {
    onStart: begin,
    muted: muted,
    toggleMute: toggleMute,
    toggleFs: toggleFs
  });
}

/* ════════════════ End screen ════════════════ */
function EndScreen({
  score,
  missedWords,
  onRestart,
  onReviewRound
}) {
  const [note, setNote] = useState(null);
  // merge this round's mistakes into the persistent (per-browser) review list, once.
  const [review, setReview] = useState(() => addReview(missedWords));
  const roundCount = missedWords.length;
  const buildText = () => {
    const lines = review.map(w => `${String(w.en).toUpperCase()} — ${w.he}`).join('\n');
    return `TETRI PSYCHOMETRY · רשימת המילים לחזרה\n\n${lines}\n\nמשחק אנגלית מבית eazy · ezway.co.il`;
  };
  const onShare = async () => {
    const text = buildText();
    try {
      if (navigator.share) {
        await navigator.share({
          title: 'TETRI PSYCHOMETRY',
          text
        });
        return;
      }
    } catch (e) {
      if (e && e.name === 'AbortError') return;
    }
    try {
      await navigator.clipboard.writeText(text);
      setNote('הרשימה הועתקה — אפשר להדביק בכל מקום.');
      setTimeout(() => setNote(null), 2500);
    } catch (e) {
      setNote('לא ניתן לשתף בדפדפן הזה.');
      setTimeout(() => setNote(null), 2500);
    }
  };
  const onPrint = () => {
    try {
      window.print();
    } catch (e) {}
  };
  const onClear = () => {
    clearReview();
    setReview([]);
    setNote('רשימת החזרה נוקתה.');
    setTimeout(() => setNote(null), 2200);
  };
  const today = new Date().toLocaleDateString('he-IL');
  return /*#__PURE__*/React.createElement("div", {
    className: "gm-app"
  }, /*#__PURE__*/React.createElement("div", {
    className: "gm-frame"
  }, /*#__PURE__*/React.createElement("div", {
    className: "gm-end"
  }, /*#__PURE__*/React.createElement("div", {
    className: "gm-end-head"
  }, /*#__PURE__*/React.createElement("button", {
    className: "gm-end-home",
    title: "\u05D0\u05EA\u05E8 eazy",
    onClick: () => {
      try {
        window.top.location.href = 'https://www.ezway.co.il';
      } catch (e) {
        window.open('https://www.ezway.co.il', '_top');
      }
    }
  }, /*#__PURE__*/React.createElement(Ico.home, null)), /*#__PURE__*/React.createElement("div", {
    className: "gm-end-brand"
  }, /*#__PURE__*/React.createElement("img", {
    src: EZ_ICON,
    alt: ""
  }), /*#__PURE__*/React.createElement("span", {
    className: "brand-eazy"
  }, "eazy", /*#__PURE__*/React.createElement("span", {
    style: {
      color: 'var(--tx-orange)'
    }
  }, ".")))), /*#__PURE__*/React.createElement("div", {
    className: "gm-end-top"
  }, /*#__PURE__*/React.createElement("div", {
    className: "gm-end-title"
  }, "\u05E1\u05D5\u05E3 \u05E1\u05D9\u05D1\u05D5\u05D1", /*#__PURE__*/React.createElement("span", {
    className: "dot"
  }, ".")), /*#__PURE__*/React.createElement("div", {
    className: "gm-end-scorechip"
  }, /*#__PURE__*/React.createElement("span", {
    className: "lbl"
  }, "\u05E0\u05D9\u05E7\u05D5\u05D3"), /*#__PURE__*/React.createElement("span", {
    className: "num"
  }, score))), /*#__PURE__*/React.createElement("div", {
    className: "gm-end-listwrap"
  }, review.length > 0 ? /*#__PURE__*/React.createElement(React.Fragment, null, /*#__PURE__*/React.createElement("div", {
    className: "gm-end-eye"
  }, "\u05E8\u05E9\u05D9\u05DE\u05EA \u05D4\u05DE\u05D9\u05DC\u05D9\u05DD \u05DC\u05D7\u05D6\u05E8\u05D4", /*#__PURE__*/React.createElement("span", {
    className: "cnt"
  }, review.length)), /*#__PURE__*/React.createElement("div", {
    className: "gm-end-sub"
  }, roundCount > 0 ? `${roundCount} נוספו בסיבוב הזה · ` : '', "\u05E0\u05E9\u05DE\u05E8 \u05D1\u05D3\u05E4\u05D3\u05E4\u05DF \u05D4\u05D6\u05D4 \u05D5\u05DE\u05EA\u05E2\u05D3\u05DB\u05DF \u05D1\u05DB\u05DC \u05E1\u05D9\u05D1\u05D5\u05D1"), /*#__PURE__*/React.createElement("div", {
    className: "gm-end-list"
  }, review.map((w, i) => /*#__PURE__*/React.createElement("div", {
    key: i,
    className: "gm-end-row"
  }, /*#__PURE__*/React.createElement("span", {
    className: "gm-end-en"
  }, String(w.en).toUpperCase()), /*#__PURE__*/React.createElement("span", {
    className: "gm-end-he"
  }, w.he))))) : /*#__PURE__*/React.createElement("div", {
    className: "gm-end-nomiss"
  }, /*#__PURE__*/React.createElement("span", {
    className: "hi"
  }, "\u05DE\u05D5\u05E9\u05DC\u05DD", /*#__PURE__*/React.createElement("span", {
    style: {
      color: 'var(--tx-orange)'
    }
  }, "!")), /*#__PURE__*/React.createElement("span", {
    className: "lo"
  }, "\u05D0\u05D9\u05DF \u05DE\u05D9\u05DC\u05D9\u05DD \u05DC\u05D7\u05D6\u05E8\u05D4."))), review.length > 0 && /*#__PURE__*/React.createElement(React.Fragment, null, /*#__PURE__*/React.createElement("div", {
    className: "gm-end-actions"
  }, /*#__PURE__*/React.createElement("button", {
    className: "gm-end-tool",
    onClick: onShare
  }, /*#__PURE__*/React.createElement(Ico.share, null), /*#__PURE__*/React.createElement("span", null, "\u05E9\u05D9\u05EA\u05D5\u05E3")), /*#__PURE__*/React.createElement("button", {
    className: "gm-end-tool",
    onClick: onPrint
  }, /*#__PURE__*/React.createElement(Ico.print, null), /*#__PURE__*/React.createElement("span", null, "\u05E9\u05DE\u05D9\u05E8\u05D4 / \u05D4\u05D3\u05E4\u05E1\u05D4"))), /*#__PURE__*/React.createElement("button", {
    className: "gm-end-clear",
    onClick: onClear
  }, "\u05E0\u05D9\u05E7\u05D5\u05D9 \u05E8\u05E9\u05D9\u05DE\u05EA \u05D4\u05D7\u05D6\u05E8\u05D4")), note && /*#__PURE__*/React.createElement("div", {
    className: "gm-end-note"
  }, note), /*#__PURE__*/React.createElement("div", {
    className: "gm-end-cta-row"
  }, review.length > 0 && /*#__PURE__*/React.createElement("button", {
    className: "gm-end-cta review",
    onClick: onReviewRound
  }, /*#__PURE__*/React.createElement("span", null, "\u05E1\u05D9\u05D1\u05D5\u05D1 \u05D8\u05E2\u05D5\u05D9\u05D5\u05EA"), /*#__PURE__*/React.createElement("span", {
    className: "badge"
  }, review.length)), /*#__PURE__*/React.createElement("button", {
    className: "gm-end-cta",
    onClick: onRestart
  }, /*#__PURE__*/React.createElement(Ico.go, null), /*#__PURE__*/React.createElement("span", null, "\u05E1\u05D9\u05D1\u05D5\u05D1 \u05D7\u05D3\u05E9"))), /*#__PURE__*/React.createElement("div", {
    className: "gm-print",
    "aria-hidden": true
  }, /*#__PURE__*/React.createElement("div", {
    className: "p-head"
  }, /*#__PURE__*/React.createElement("div", {
    className: "p-brand"
  }, /*#__PURE__*/React.createElement("img", {
    src: EZ_ICON,
    alt: "eazy"
  }), /*#__PURE__*/React.createElement("span", null, "eazy")), /*#__PURE__*/React.createElement("div", {
    className: "p-meta"
  }, "TETRI PSYCHOMETRY \xB7 ", today)), /*#__PURE__*/React.createElement("h1", {
    className: "p-title"
  }, "\u05E8\u05E9\u05D9\u05DE\u05EA \u05D4\u05DE\u05D9\u05DC\u05D9\u05DD \u05DC\u05D7\u05D6\u05E8\u05D4"), /*#__PURE__*/React.createElement("div", {
    className: "p-score"
  }, review.length, " \u05DE\u05D9\u05DC\u05D9\u05DD"), /*#__PURE__*/React.createElement("table", {
    className: "p-table"
  }, /*#__PURE__*/React.createElement("tbody", null, review.map((w, i) => /*#__PURE__*/React.createElement("tr", {
    key: i
  }, /*#__PURE__*/React.createElement("td", {
    className: "p-num"
  }, i + 1), /*#__PURE__*/React.createElement("td", {
    className: "p-en"
  }, String(w.en).toUpperCase()), /*#__PURE__*/React.createElement("td", {
    className: "p-he"
  }, w.he))))), /*#__PURE__*/React.createElement("div", {
    className: "p-foot"
  }, "\u05DE\u05E9\u05D7\u05E7 \u05D0\u05E0\u05D2\u05DC\u05D9\u05EA \u05E4\u05E1\u05D9\u05DB\u05D5\u05DE\u05D8\u05E8\u05D9 \u05DE\u05D1\u05D9\u05EA eazy \xB7 ezway.co.il")))));
}

/* ════════════════ Main game ════════════════ */
const COLS = 4;
const ROWS = 9; // playable rows above the bins; overflow past the top = game over
const MAXSTACK = ROWS - 1; // a column this tall reaches the start height
function TetriGame() {
  const [started, setStarted] = useState(false);
  const [dict, setDict] = useState(null);
  const [used, setUsed] = useState([]);
  const [missed, setMissed] = useState([]);
  const [question, setQuestion] = useState(null);
  const [stacks, setStacks] = useState(() => [[], [], [], []]); // junk bricks left by mistakes
  const [score, setScore] = useState(0);
  const [streak, setStreak] = useState(0);
  const [col, setCol] = useState(1);
  const [phase, setPhase] = useState('falling'); // falling | resolving | over
  const [binFx, setBinFx] = useState({}); // {idx:'hit'|'miss'|'reveal'}
  const [pieceFx, setPieceFx] = useState(''); // ''|'correct'|'wrong'
  const [dimmed, setDimmed] = useState(() => new Set());
  const [fiftyUsed, setFiftyUsed] = useState(false);
  const [toast, setToast] = useState(null);
  const [missBanner, setMissBanner] = useState(null); // {en,he} shown briefly on a mistake
  const [gate, setGate] = useState(null); // pausing modal: {kind:'level',sub} | {kind:'audio'}
  const [correctCount, setCorrectCount] = useState(0);
  const [audioEnabled, setAudioEnabled] = useState(false);
  const [pool, setPool] = useState(null); // correct-word pool: full dict, or the mistakes list
  const [muted, setMuted] = useState(Sound.muted);
  const pieceRef = useRef(null);
  const rafRef = useRef(0);
  const sim = useRef({
    fall: 0,
    col: 1,
    locked: true,
    soft: false,
    startT: 0
  });
  const stacksRef = useRef([[], [], [], []]);
  const pausedRef = useRef(false);
  const audioPromptedRef = useRef(false);
  const spokenForRef = useRef(null);
  const lastBonusRef = useRef(0);
  const prevLevelRef = useRef(0);
  useEffect(() => {
    pausedRef.current = !!gate;
  }, [gate]);
  const setStacksBoth = useCallback(updater => {
    setStacks(prev => {
      const next = updater(prev);
      stacksRef.current = next;
      return next;
    });
  }, []);
  const level = Math.floor(used.length / 8);
  const fallDur = Math.max(2.3, 6.5 - level * 0.4); // seconds top→bottom, gradually faster
  const basePts = 200 + level * 80;

  /* ── load dictionary ── */
  useEffect(() => {
    if (window.GAME_DICTIONARY && window.GAME_DICTIONARY.length >= 4) {
      setDict(window.GAME_DICTIONARY);
      setPool(p => p || window.GAME_DICTIONARY);
    }
  }, []);

  /* ── draw a question whenever needed ── */
  useEffect(() => {
    if (!dict || !started || phase === 'over') return;
    if (question) return;
    const src = pool && pool.length > 0 ? pool : dict;
    const avail = src.map((_, i) => i).filter(i => !used.includes(i));
    if (avail.length === 0) {
      setUsed([]);
      return;
    }
    const idx = avail[Math.random() * avail.length | 0];
    const q = buildQuestion(src[idx], dict, idx);
    setQuestion(q);
    // spawn over the SHORTEST column so a tall pile never instant-locks the new word
    const lens = stacksRef.current.map(s => s.length);
    const minLen = Math.min(...lens);
    const cands = [0, 1, 2, 3].filter(c => lens[c] === minLen);
    const startCol = cands[Math.random() * cands.length | 0];
    setCol(startCol);
    setDimmed(new Set());
    setPieceFx('');
    setBinFx({});
    setMissBanner(null);
    spokenForRef.current = null;
    sim.current = {
      fall: 0,
      col: startCol,
      locked: false,
      soft: false,
      startT: performance.now()
    };
    setPhase('falling');
  }, [dict, started, question, used, phase, pool]);

  /* ── level-up → pause + wait for the player ── */
  useEffect(() => {
    if (level > prevLevelRef.current && used.length > 0) {
      prevLevelRef.current = level;
      Sound.play('levelup');
      setGate(g => g ? g : {
        kind: 'level',
        sub: `המהירות עולה בהדרגה · +${basePts} לכל תשובה נכונה`
      });
    } else {
      prevLevelRef.current = Math.max(prevLevelRef.current, level);
    }
  }, [level, used.length, basePts]);

  /* ── after 6 correct answers, offer word audio (one-time) ── */
  useEffect(() => {
    if (correctCount >= 6 && !audioPromptedRef.current) {
      audioPromptedRef.current = true;
      setGate({
        kind: 'audio'
      });
    }
  }, [correctCount]);

  /* ── speak the English word via the browser (content audio, not SFX) ── */
  const speakWord = useCallback(text => {
    if (!text) return;
    try {
      const s = window.speechSynthesis;
      if (!s) return;
      s.cancel();
      const u = new SpeechSynthesisUtterance(String(text));
      u.lang = 'en-US';
      u.rate = 0.85;
      u.pitch = 1;
      u.volume = 1;
      const voices = s.getVoices ? s.getVoices() : [];
      const en = voices.find(v => /^en[-_]/i.test(v.lang)) || voices.find(v => /english/i.test(v.name));
      if (en) u.voice = en;
      s.speak(u);
    } catch (e) {}
  }, []);

  /* auto-speak each new word ONCE per turn, once audio is enabled */
  useEffect(() => {
    if (!audioEnabled || muted || !started || phase === 'over' || gate || !question?.en) return;
    if (spokenForRef.current === question.dictIdx) return;
    const t = setTimeout(() => {
      speakWord(question.en);
      spokenForRef.current = question.dictIdx;
    }, 320);
    return () => clearTimeout(t);
  }, [audioEnabled, muted, started, phase, gate, question?.en, question?.dictIdx, speakWord]);

  /* ── falling loop (rAF, drives the piece DOM directly) ── */
  useEffect(() => {
    if (!started || !question || phase !== 'falling') return;
    let last = performance.now();
    const tick = now => {
      const dt = Math.min(0.05, (now - last) / 1000);
      last = now;
      const s = sim.current;
      if (!s.locked && !pausedRef.current) {
        const v = 1 / fallDur * (s.soft ? 5 : 1);
        s.fall = Math.min(1, s.fall + v * dt);
        const stackLen = stacksRef.current[s.col].length;
        const rest = Math.max(0, (ROWS - 1 - stackLen) / (ROWS - 1)); // floor for this column
        const shown = Math.min(s.fall, rest);
        if (pieceRef.current) pieceRef.current.style.setProperty('--fall', shown.toFixed(4));
        if (s.fall >= rest) {
          s.fall = rest;
          s.locked = true;
          resolveAt(s.col);
          return;
        }
      }
      rafRef.current = requestAnimationFrame(tick);
    };
    rafRef.current = requestAnimationFrame(tick);
    return () => cancelAnimationFrame(rafRef.current);
  }, [started, question, phase, fallDur]);
  const move = useCallback(dir => {
    if (phase !== 'falling' || sim.current.locked || pausedRef.current) return;
    setCol(prev => {
      let c = Math.max(0, Math.min(3, prev + dir));
      while (dimmed.has(c) && c >= 0 && c <= 3) {
        c += dir;
      }
      if (c < 0 || c > 3 || dimmed.has(c)) {
        const allow = [0, 1, 2, 3].filter(x => !dimmed.has(x));
        c = allow.length ? allow.reduce((b, x) => Math.abs(x - prev) < Math.abs(b - prev) ? x : b, allow[0]) : prev;
      }
      // can't slide UNDER a pile taller than the piece's current height (Tetris collision)
      const restTarget = (ROWS - 1 - stacksRef.current[c].length) / (ROWS - 1);
      if (restTarget < sim.current.fall - 0.001) return prev;
      if (c !== prev) {
        sim.current.col = c;
        Sound.play('move');
      }
      return c;
    });
  }, [phase, dimmed]);
  const softDrop = useCallback(() => {
    if (phase !== 'falling' || sim.current.locked || pausedRef.current) return;
    sim.current.soft = true; // hold = keep accelerating
    sim.current.fall = Math.min(0.999, sim.current.fall + 0.05); // each tap nudges it down
    if (pieceRef.current) {
      const rest = (ROWS - 1 - stacksRef.current[sim.current.col].length) / (ROWS - 1);
      pieceRef.current.style.setProperty('--fall', Math.min(sim.current.fall, rest).toFixed(4));
    }
    Sound.play('move');
  }, [phase]);
  const softRelease = useCallback(() => {
    if (sim.current) sim.current.soft = false;
  }, []);

  /* ── resolve a landing ── */
  const resolveAt = useCallback(c => {
    setPhase('resolving');
    const q = question;
    if (!q) return;
    const correctCol = q.options.indexOf(q.he);
    const correct = c === correctCol;
    if (pieceRef.current) pieceRef.current.style.setProperty('--col', c);
    if (correct) {
      const elapsed = (performance.now() - sim.current.startT) / 1000;
      const speedMult = Math.max(1, Math.min(2, 2 - elapsed / Math.max(1, fallDur)));
      const ns = streak + 1;
      const now = Date.now();
      const cooldown = now - lastBonusRef.current >= 4 * 60 * 1000;
      let comboMult = 1,
        comboBonus = 0,
        comboLabel = null;
      if (ns >= 5 && ns % 5 === 0 && cooldown) {
        if (ns >= 20) {
          comboMult = 3;
          comboLabel = `רצף ${ns} ✦ ×3`;
        } else if (ns >= 10) {
          comboMult = 2;
          comboLabel = `רצף ${ns} ✦ ×2`;
        } else {
          comboBonus = 400;
          comboLabel = `רצף ${ns} ✦ +400`;
        }
        lastBonusRef.current = now;
      }
      const pts = Math.round(basePts * speedMult * comboMult) + comboBonus;
      setScore(s => s + pts);
      setStreak(ns);
      setCorrectCount(n => n + 1);
      setPieceFx('correct');
      setBinFx({
        [c]: 'hit'
      });
      // relief: a correct answer clears one brick off the tallest pile
      setStacksBoth(prev => {
        let ti = -1,
          max = 0;
        prev.forEach((s, i) => {
          if (s.length > max) {
            max = s.length;
            ti = i;
          }
        });
        if (ti < 0) return prev;
        const n = prev.map(a => a.slice());
        n[ti].pop();
        return n;
      });
      Sound.play(comboLabel ? 'streak' : 'hit');
      setToast(comboLabel ? {
        kind: 'streak',
        text: `${comboLabel} · +${pts}`
      } : {
        kind: 'win',
        text: `${speedMult >= 1.6 ? 'מהיר! ' : ''}+${pts}`
      });
      setTimeout(() => setToast(null), 1700);
      setTimeout(() => advance(q.dictIdx), 900);
    } else {
      setStreak(0);
      setPieceFx('wrong');
      setBinFx({
        [c]: 'miss',
        [correctCol]: 'reveal'
      });
      setMissed(m => m.some(w => String(w.en).toLowerCase() === String(q.en).toLowerCase()) ? m : [...m, {
        en: q.en,
        he: q.he
      }]);
      // show the correct word + meaning at the top, noting it returns in the summary
      setMissBanner({
        en: String(q.en).toUpperCase(),
        he: q.he
      });
      // a mistake leaves a brick behind in that column — Tetris-style.
      // compute overflow SYNCHRONOUSLY from the ref (the state updater runs later).
      const over = stacksRef.current[c].length + 1 >= MAXSTACK;
      setStacksBoth(prev => {
        const n = prev.map(a => a.slice());
        n[c] = [...n[c], randColor(Date.now() + c * 7)];
        return n;
      });
      Sound.play(over ? 'gameover' : 'miss');
      if (over) {
        setTimeout(() => setPhase('over'), 1700);
      } else {
        setTimeout(() => advance(q.dictIdx), 2000);
      }
    }
  }, [question, streak, basePts, fallDur, setStacksBoth]);
  const advance = useCallback(dictIdx => {
    setUsed(u => [...u, dictIdx]);
    setQuestion(null); // triggers next draw
  }, []);

  /* ── 50/50 ── */
  const useFifty = useCallback(() => {
    if (fiftyUsed || phase !== 'falling' || !question) return;
    const correctCol = question.options.indexOf(question.he);
    const wrongs = [0, 1, 2, 3].filter(i => i !== correctCol);
    setDimmed(new Set(shuffle(wrongs).slice(0, 2)));
    setFiftyUsed(true);
    Sound.play('fifty');
  }, [fiftyUsed, phase, question]);

  /* ── keyboard ── */
  useEffect(() => {
    const onKey = e => {
      if (!started) return;
      if (e.key === 'ArrowLeft') {
        e.preventDefault();
        move(-1);
      } else if (e.key === 'ArrowRight') {
        e.preventDefault();
        move(1);
      } else if (e.key === 'ArrowDown' || e.key === ' ') {
        e.preventDefault();
        softDrop();
      }
    };
    const onUp = e => {
      if (e.key === 'ArrowDown' || e.key === ' ') softRelease();
    };
    window.addEventListener('keydown', onKey);
    window.addEventListener('keyup', onUp);
    return () => {
      window.removeEventListener('keydown', onKey);
      window.removeEventListener('keyup', onUp);
    };
  }, [started, move, softDrop, softRelease]);
  const toggleMute = useCallback(() => {
    const n = !Sound.muted;
    Sound.setMuted(n);
    setMuted(n);
    if (n) {
      try {
        window.speechSynthesis?.cancel();
      } catch (e) {}
    }
  }, []);
  const toggleFs = useCallback(() => {
    try {
      const t = window.frameElement ? window.frameElement : document.documentElement;
      const d = window.frameElement ? window.parent.document : document;
      const fs = d.fullscreenElement || d.webkitFullscreenElement;
      if (!fs) {
        const r = t.requestFullscreen || t.webkitRequestFullscreen;
        if (r) {
          const p = r.call(t);
          if (p && p.then) p.then(() => {
            try {
              screen.orientation?.lock?.('portrait').catch(() => {});
            } catch (e) {}
          }).catch(() => {});
        }
      } else {
        const x = d.exitFullscreen || d.webkitExitFullscreen;
        if (x) x.call(d);
      }
    } catch (e) {}
  }, []);
  const start = useCallback(() => {
    Sound.init();
    setStarted(true);
    // prime SpeechSynthesis on the user gesture so later auto-speaks are allowed (iOS)
    try {
      const s = window.speechSynthesis;
      if (s) {
        const p = new SpeechSynthesisUtterance(' ');
        p.volume = 0;
        s.speak(p);
        s.getVoices?.();
      }
    } catch (e) {}
  }, []);
  const resetRound = useCallback(nextPool => {
    setPool(nextPool);
    setUsed([]);
    setMissed([]);
    setScore(0);
    setStreak(0);
    setCorrectCount(0);
    setStacks([[], [], [], []]);
    stacksRef.current = [[], [], [], []];
    setQuestion(null);
    setPhase('falling');
    setFiftyUsed(false);
    setDimmed(new Set());
    setGate(null);
    setAudioEnabled(false);
    audioPromptedRef.current = false;
    prevLevelRef.current = 0;
    lastBonusRef.current = 0;
  }, []);
  const restart = useCallback(() => {
    resetRound(dict);
  }, [resetRound, dict]);
  const goHome = useCallback(() => {
    resetRound(dict);
    setStarted(false);
  }, [resetRound, dict]);
  const reviewRound = useCallback(() => {
    const words = getReview();
    if (words.length < 1) return;
    resetRound(words);
  }, [resetRound]);

  /* ════════ render ════════ */
  if (!started) return /*#__PURE__*/React.createElement(IntroScreen, {
    onStart: start,
    muted: muted,
    toggleMute: toggleMute,
    toggleFs: toggleFs
  });
  if (phase === 'over') {
    return /*#__PURE__*/React.createElement(EndScreen, {
      score: score,
      missedWords: missed,
      onRestart: restart,
      onReviewRound: reviewRound
    });
  }
  if (!dict || !question) {
    return /*#__PURE__*/React.createElement("div", {
      className: "gm-app"
    }, /*#__PURE__*/React.createElement("div", {
      className: "gm-frame",
      style: {
        alignItems: 'center',
        justifyContent: 'center'
      }
    }, /*#__PURE__*/React.createElement("div", {
      style: {
        color: '#fff',
        fontFamily: 'var(--font-body)'
      }
    }, "\u05D8\u05D5\u05E2\u05DF\u2026")));
  }
  const correctCol = question.options.indexOf(question.he);
  return /*#__PURE__*/React.createElement("div", {
    className: "gm-app"
  }, /*#__PURE__*/React.createElement("div", {
    className: "gm-frame"
  }, /*#__PURE__*/React.createElement("div", {
    className: "gm-top"
  }, /*#__PURE__*/React.createElement("div", {
    className: "gm-top-group"
  }, /*#__PURE__*/React.createElement("button", {
    className: "gm-round-btn",
    onClick: toggleMute,
    title: "\u05E1\u05D0\u05D5\u05E0\u05D3"
  }, muted ? /*#__PURE__*/React.createElement(Ico.mute, null) : /*#__PURE__*/React.createElement(Ico.sound, null)), /*#__PURE__*/React.createElement("button", {
    className: 'gm-round-btn fifty' + (fiftyUsed ? ' used' : ''),
    onClick: useFifty,
    title: "50/50",
    disabled: fiftyUsed
  }, /*#__PURE__*/React.createElement("span", {
    className: "ft"
  }, "50", /*#__PURE__*/React.createElement("br", null), "50"))), /*#__PURE__*/React.createElement("div", {
    className: "gm-level-chip"
  }, /*#__PURE__*/React.createElement("span", {
    className: "lv"
  }, "\u05E9\u05DC\u05D1 ", /*#__PURE__*/React.createElement("b", null, level + 1))), /*#__PURE__*/React.createElement("div", {
    className: "gm-top-group"
  }, /*#__PURE__*/React.createElement("button", {
    className: "gm-round-btn mail",
    title: "\u05E6\u05E8\u05D5 \u05E7\u05E9\u05E8",
    onClick: () => {
      try {
        window.top.location.href = 'https://www.ezway.co.il/contact/';
      } catch (e) {
        window.open('https://www.ezway.co.il/contact/', '_blank');
      }
    }
  }, /*#__PURE__*/React.createElement(Ico.mail, null)), /*#__PURE__*/React.createElement("button", {
    className: "gm-round-btn",
    onClick: toggleFs,
    title: "\u05DE\u05E1\u05DA \u05DE\u05DC\u05D0"
  }, /*#__PURE__*/React.createElement(Ico.expand, null)))), /*#__PURE__*/React.createElement("div", {
    className: "gm-well"
  }, /*#__PURE__*/React.createElement(Wall, {
    side: "left",
    n: 14
  }), /*#__PURE__*/React.createElement(Wall, {
    side: "right",
    n: 14
  }), /*#__PURE__*/React.createElement("div", {
    className: "gm-field"
  }, /*#__PURE__*/React.createElement("div", {
    className: "gm-dangerline"
  }), stacks.map((colBricks, c) => colBricks.map((color, k) => /*#__PURE__*/React.createElement("div", {
    key: c + '-' + k,
    className: 'gm-stackbrick' + (k >= MAXSTACK - 2 ? ' danger' : ''),
    style: {
      '--col': c,
      '--k': k,
      background: color
    }
  }))), /*#__PURE__*/React.createElement("div", {
    className: "gm-ghost",
    style: {
      '--col': col
    }
  }), /*#__PURE__*/React.createElement("div", {
    ref: pieceRef,
    className: 'gm-piece ' + pieceFx + (question.en.length > 11 ? ' twoline' : ''),
    style: {
      '--col': col,
      '--cx': col * 25 + 12.5 + '%',
      '--fall': 0
    }
  }, question.en.toUpperCase()), /*#__PURE__*/React.createElement("div", {
    className: "gm-bins"
  }, question.options.map((opt, i) => {
    let cls = 'gm-bin';
    if (binFx[i]) cls += ' ' + binFx[i];
    if (dimmed.has(i)) cls += ' dim';else if (phase === 'falling' && i === col) cls += ' target';
    return /*#__PURE__*/React.createElement("div", {
      key: i,
      className: cls
    }, opt);
  }))), toast && /*#__PURE__*/React.createElement("div", {
    className: 'gm-toast ' + toast.kind
  }, toast.text), missBanner && /*#__PURE__*/React.createElement("div", {
    className: "gm-missbanner"
  }, /*#__PURE__*/React.createElement("div", {
    className: "mb-word"
  }, /*#__PURE__*/React.createElement("span", {
    className: "en"
  }, missBanner.en), /*#__PURE__*/React.createElement("span", {
    className: "sep"
  }, "="), /*#__PURE__*/React.createElement("span", {
    className: "he"
  }, missBanner.he)), /*#__PURE__*/React.createElement("div", {
    className: "mb-note"
  }, "\u05D4\u05DE\u05D9\u05DC\u05D4 \u05EA\u05D5\u05E4\u05D9\u05E2 \u05D1\u05E1\u05D9\u05DB\u05D5\u05DD \u05D1\u05E1\u05D5\u05E3 \u05D4\u05DE\u05E9\u05D7\u05E7")), gate && /*#__PURE__*/React.createElement("div", {
    className: "gm-levelup"
  }, gate.kind === 'level' ? /*#__PURE__*/React.createElement(React.Fragment, null, /*#__PURE__*/React.createElement("div", {
    className: "gm-levelup-title"
  }, "\u05E2\u05DC\u05D9\u05EA \u05E9\u05DC\u05D1", /*#__PURE__*/React.createElement("span", {
    className: "dot"
  }, "!")), /*#__PURE__*/React.createElement("div", {
    className: "gm-levelup-sub"
  }, gate.sub), /*#__PURE__*/React.createElement("div", {
    className: "gm-levelup-btnrow"
  }, /*#__PURE__*/React.createElement("button", {
    className: "gm-levelup-cta",
    onClick: () => setGate(null)
  }, "\u05DE\u05DE\u05E9\u05D9\u05DB\u05D9\u05DD", /*#__PURE__*/React.createElement("span", {
    className: "dot"
  }, ".")))) : /*#__PURE__*/React.createElement(React.Fragment, null, /*#__PURE__*/React.createElement("div", {
    className: "gm-levelup-title"
  }, "\u05DC\u05E9\u05DE\u05D5\u05E2 \u05D0\u05EA \u05D4\u05DE\u05D9\u05DC\u05D4", /*#__PURE__*/React.createElement("span", {
    className: "dot"
  }, "?")), /*#__PURE__*/React.createElement("div", {
    className: "gm-levelup-sub"
  }, "\u05EA\u05E8\u05E6\u05D5 \u05E9\u05DE\u05E2\u05DB\u05E9\u05D9\u05D5 \u05E0\u05E9\u05DE\u05D9\u05E2 \u05D0\u05D9\u05DA \u05DB\u05DC \u05DE\u05D9\u05DC\u05D4 \u05E0\u05E9\u05DE\u05E2\u05EA \u05D1\u05D0\u05E0\u05D2\u05DC\u05D9\u05EA?"), /*#__PURE__*/React.createElement("div", {
    className: "gm-levelup-btnrow"
  }, /*#__PURE__*/React.createElement("button", {
    className: "gm-levelup-cta",
    onClick: () => {
      setAudioEnabled(true);
      if (Sound.muted) {
        Sound.setMuted(false);
        setMuted(false);
      }
      setGate(null);
    }
  }, "\u05DB\u05DF, \u05DC\u05D4\u05E9\u05DE\u05D9\u05E2"), /*#__PURE__*/React.createElement("button", {
    className: "gm-levelup-cta secondary",
    onClick: () => {
      setAudioEnabled(false);
      setGate(null);
    }
  }, "\u05DC\u05D0, \u05EA\u05D5\u05D3\u05D4")), /*#__PURE__*/React.createElement("div", {
    className: "gm-levelup-note"
  }, "\u05EA\u05DE\u05D9\u05D3 \u05D0\u05E4\u05E9\u05E8 \u05DC\u05DB\u05D1\u05D5\u05EA \u05D1\u05E2\u05D6\u05E8\u05EA \u05DB\u05E4\u05EA\u05D5\u05E8 \u05D4\u05E1\u05D0\u05D5\u05E0\u05D3")))), /*#__PURE__*/React.createElement("div", {
    className: "gm-controls"
  }, /*#__PURE__*/React.createElement("div", {
    className: "gm-meta"
  }, /*#__PURE__*/React.createElement("button", {
    className: "gm-logo",
    onClick: goHome,
    title: "\u05DC\u05DE\u05E1\u05DA \u05D4\u05D1\u05D9\u05EA \u05E9\u05DC \u05D4\u05DE\u05E9\u05D7\u05E7"
  }, /*#__PURE__*/React.createElement("img", {
    src: EZ_ICON,
    alt: ""
  }), /*#__PURE__*/React.createElement("span", {
    className: "brand-eazy"
  }, "eazy", /*#__PURE__*/React.createElement("span", {
    className: "dot"
  }, "."))), /*#__PURE__*/React.createElement("div", {
    className: "gm-score"
  }, /*#__PURE__*/React.createElement("span", {
    className: "lbl"
  }, "\u05E0\u05D9\u05E7\u05D5\u05D3"), /*#__PURE__*/React.createElement("span", {
    className: "num"
  }, score))), /*#__PURE__*/React.createElement("div", {
    className: "gm-pad"
  }, /*#__PURE__*/React.createElement("button", {
    className: "gm-arcade",
    "aria-label": "\u05E9\u05DE\u05D0\u05DC\u05D4",
    onClick: () => move(-1)
  }, /*#__PURE__*/React.createElement(Ico.left, null)), /*#__PURE__*/React.createElement("button", {
    className: "gm-arcade down",
    "aria-label": "\u05D4\u05D0\u05E6\u05D4",
    onPointerDown: softDrop,
    onPointerUp: softRelease,
    onPointerLeave: softRelease
  }, /*#__PURE__*/React.createElement(Ico.down, null)), /*#__PURE__*/React.createElement("button", {
    className: "gm-arcade",
    "aria-label": "\u05D9\u05DE\u05D9\u05E0\u05D4",
    onClick: () => move(1)
  }, /*#__PURE__*/React.createElement(Ico.right, null))))));
}
window.Game = TetriGame;
})(); } catch (e) { __ds_ns.__errors.push({ path: "tetri-psychometry-export/tetri-game.jsx", error: String((e && e.message) || e) }); }

// tetri-psychometry-export/words.js
try { (() => {
/* eazy · משחק תותח־מילים — מילון המשחק
   ─────────────────────────────────────────────────────────────
   זהו הדטה־בייס של המשחק. לכל שורה:
     en — המילה באנגלית
     he — הפירוש בעברית
   המשחק יטען את הרשימה הזו אוטומטית בכל מכשיר, ללא צורך בהעלאה.

   להוסיף/לערוך מילים — פשוט ערוך את הקובץ הזה ושמור.
   מספר הערכים הנוכחי: 637
*/
window.GAME_DICTIONARY = [{
  en: "a fortnight ago",
  he: "לפני שבועיים"
}, {
  en: "abduct",
  he: "לחטוף"
}, {
  en: "abolish",
  he: "לבטל"
}, {
  en: "accelerate",
  he: "להאיץ"
}, {
  en: "accent",
  he: "מבטא"
}, {
  en: "access",
  he: "גישה"
}, {
  en: "acclaim",
  he: "הכרה / הוקרה"
}, {
  en: "ache",
  he: "כאב / לכאוב"
}, {
  en: "activity",
  he: "פעילות"
}, {
  en: "acute",
  he: "חריף"
}, {
  en: "admiration",
  he: "הערצה"
}, {
  en: "admission process",
  he: "תהליך ההרשמה"
}, {
  en: "advertisement",
  he: "פרסומת"
}, {
  en: "adviser",
  he: "יועץ"
}, {
  en: "affirmative action",
  he: "העדפה מתקנת"
}, {
  en: "ague",
  he: "צמרמורת / קדחת"
}, {
  en: "aid",
  he: "עזרה"
}, {
  en: "ailment",
  he: "מחלה"
}, {
  en: "aimed at",
  he: "המכוון אל..."
}, {
  en: "alert",
  he: "כוננות"
}, {
  en: "allegation",
  he: "האשמה"
}, {
  en: "allegedly",
  he: "לכאורה"
}, {
  en: "ally",
  he: "בעל ברית"
}, {
  en: "along with",
  he: "לצד"
}, {
  en: "along side",
  he: "לצד / ליד"
}, {
  en: "ambassador",
  he: "שגריר"
}, {
  en: "ambiguous",
  he: "מעורפל"
}, {
  en: "ambition",
  he: "שאיפה"
}, {
  en: "ambitious",
  he: "שאפתן"
}, {
  en: "amnesia",
  he: "שכחה / נשייה"
}, {
  en: "ample",
  he: "הרבה / שפע"
}, {
  en: "analyze",
  he: "לנתח"
}, {
  en: "animosity",
  he: "עוינות"
}, {
  en: "annihilation",
  he: "השמדה מוחלטת"
}, {
  en: "anniversary",
  he: "יום השנה"
}, {
  en: "annoyance",
  he: "מטרד"
}, {
  en: "annulment",
  he: "ביטול נישואין"
}, {
  en: "anonymous",
  he: "אלמוני"
}, {
  en: "anthem",
  he: "המנון"
}, {
  en: "anticipation",
  he: "ציפייה"
}, {
  en: "anxious",
  he: "עצבני / מודאג"
}, {
  en: "any given moment",
  he: "כל רגע נתון"
}, {
  en: "apology",
  he: "התנצלות"
}, {
  en: "appear",
  he: "מופיע"
}, {
  en: "appliance",
  he: "כלי/מתקן"
}, {
  en: "application",
  he: "בקשה לקבלה"
}, {
  en: "approve",
  he: "לאשר"
}, {
  en: "arena",
  he: "זירה / מגרש"
}, {
  en: "argument",
  he: "ויכוח / טיעון"
}, {
  en: "arrogance",
  he: "שחצנות"
}, {
  en: "assessment",
  he: "הערכה"
}, {
  en: "associate",
  he: "עמית / שותף"
}, {
  en: "assumption",
  he: "הנחה"
}, {
  en: "astonishment",
  he: "תדהמה"
}, {
  en: "attack",
  he: "התקפה"
}, {
  en: "attendance",
  he: "נוכחות"
}, {
  en: "attention",
  he: "תשומת לב"
}, {
  en: "attribution",
  he: "ייחוס / תכונה"
}, {
  en: "awe-inspiring",
  he: "מעורר השתאות"
}, {
  en: "bark",
  he: "לנבוח"
}, {
  en: "barrier",
  he: "מחסום, סייג"
}, {
  en: "beforehand",
  he: "מראש"
}, {
  en: "bench",
  he: "ספסל"
}, {
  en: "beneficial",
  he: "מועיל / מיטיב"
}, {
  en: "beneficiary",
  he: "המוטב / הנהנה"
}, {
  en: "benefit",
  he: "להרוויח"
}, {
  en: "benign",
  he: "שפיר"
}, {
  en: "bequeath",
  he: "להוריש"
}, {
  en: "bereavement",
  he: "אבל / שכול"
}, {
  en: "bigotry",
  he: "גזענות"
}, {
  en: "birth",
  he: "לידה / ללדת"
}, {
  en: "blink",
  he: "מצמוץ"
}, {
  en: "blizzard",
  he: "סופה / סערה"
}, {
  en: "block",
  he: "לחסום"
}, {
  en: "board",
  he: "מועצה / לוח"
}, {
  en: "boldly",
  he: "באופן נועז"
}, {
  en: "bone-marrow",
  he: "מוח עצם"
}, {
  en: "border",
  he: "גבול / גבולי"
}, {
  en: "boredom",
  he: "שעמום"
}, {
  en: "boundless",
  he: "חסר גבולות"
}, {
  en: "brash",
  he: "פזיז / נמהר"
}, {
  en: "breast",
  he: "שד / חזה"
}, {
  en: "briefing",
  he: "תדריך"
}, {
  en: "brisk",
  he: "בחטף / במהרה"
}, {
  en: "broadcast",
  he: "לשדר / שידור"
}, {
  en: "broker",
  he: "מתווך / סוכן"
}, {
  en: "budget",
  he: "תקציב"
}, {
  en: "bulks",
  he: "כמויות גדולות"
}, {
  en: "buried",
  he: "קבור"
}, {
  en: "campaign",
  he: "מסע בחירות"
}, {
  en: "canal",
  he: "תעלה"
}, {
  en: "cancel",
  he: "לבטל"
}, {
  en: "candidate",
  he: "מועמד"
}, {
  en: "capsized",
  he: "מתהפך / מתבטל"
}, {
  en: "captions",
  he: "כתוביות"
}, {
  en: "capture",
  he: "ללכוד / לשבות"
}, {
  en: "careful consideration",
  he: "מחשבה מרובה"
}, {
  en: "cargo",
  he: "מטען"
}, {
  en: "cell",
  he: "תא"
}, {
  en: "cemeteries",
  he: "בתי קברות"
}, {
  en: "centric",
  he: "מרכזי"
}, {
  en: "chairman",
  he: "יו\"ר"
}, {
  en: "challenge",
  he: "אתגר"
}, {
  en: "charity",
  he: "צדקה"
}, {
  en: "charming",
  he: "מקסים"
}, {
  en: "chauvinistic",
  he: "שוביניסטי"
}, {
  en: "chronic illness",
  he: "מחלה כרונית"
}, {
  en: "circulated",
  he: "סבב / נפוץ"
}, {
  en: "civil",
  he: "אזרחי"
}, {
  en: "clarify",
  he: "להבהיר / לחדד"
}, {
  en: "clash",
  he: "עימות"
}, {
  en: "classified material",
  he: "חומר מסווג"
}, {
  en: "classify",
  he: "לסווג / למיין"
}, {
  en: "classified",
  he: "מסווג"
}, {
  en: "cloning",
  he: "לשכפל"
}, {
  en: "coach",
  he: "מאמן"
}, {
  en: "coating",
  he: "ציפוי"
}, {
  en: "coercion",
  he: "כפייה"
}, {
  en: "cognition",
  he: "תפישה"
}, {
  en: "colleague",
  he: "עמית"
}, {
  en: "collision",
  he: "התנגשות"
}, {
  en: "come to a halt",
  he: "לעצור / לחדול"
}, {
  en: "come to light",
  he: "נודע / הופיע"
}, {
  en: "comet",
  he: "כוכב שביט"
}, {
  en: "comfort",
  he: "הטבה / נוחיות"
}, {
  en: "commitment",
  he: "מחויבות"
}, {
  en: "committed to",
  he: "מסור ל..."
}, {
  en: "committee",
  he: "ועדה"
}, {
  en: "companion",
  he: "בן זוג / שותף"
}, {
  en: "compel",
  he: "לאלץ / לכפות"
}, {
  en: "complaint",
  he: "תלונה"
}, {
  en: "comprehensive",
  he: "מקיף וכוללני"
}, {
  en: "compromise",
  he: "להתפשר / לסכן"
}, {
  en: "compulsive",
  he: "כפייתי"
}, {
  en: "concentration",
  he: "ריכוז"
}, {
  en: "conditioning",
  he: "התניה"
}, {
  en: "confess",
  he: "להתוודות"
}, {
  en: "confronted",
  he: "מעומת למול"
}, {
  en: "connection",
  he: "קשר"
}, {
  en: "conniving",
  he: "תככן וחתרן"
}, {
  en: "conquest",
  he: "כיבוש"
}, {
  en: "consecutive",
  he: "רציף / רצוף"
}, {
  en: "considering",
  he: "בהתחשב"
}, {
  en: "consortium",
  he: "תאגיד"
}, {
  en: "construct",
  he: "לבנות"
}, {
  en: "continent",
  he: "יבשת"
}, {
  en: "continuity",
  he: "המשכיות"
}, {
  en: "continuously",
  he: "מתמשך"
}, {
  en: "contradiction",
  he: "סתירה"
}, {
  en: "contrary to",
  he: "בניגוד ל..."
}, {
  en: "conviction",
  he: "הרשעה / שכנוע"
}, {
  en: "convince",
  he: "לשכנע"
}, {
  en: "copyrights",
  he: "זכויות יוצרים"
}, {
  en: "coral",
  he: "אלמוג"
}, {
  en: "correspondent",
  he: "מתכתב / כתב"
}, {
  en: "co-star",
  he: "כוכב משנה"
}, {
  en: "counterfeit",
  he: "מזויף"
}, {
  en: "county judge",
  he: "שופט מחוזי"
}, {
  en: "courage",
  he: "אומץ"
}, {
  en: "court ruling",
  he: "פסיקת ביהמ\"ש"
}, {
  en: "cover story",
  he: "סיפור שער"
}, {
  en: "covert operation",
  he: "מבצע חשאי"
}, {
  en: "covertly",
  he: "בחשאיות"
}, {
  en: "covet",
  he: "לחמוד"
}, {
  en: "creativity",
  he: "יצירתיות"
}, {
  en: "credential",
  he: "מסמך / אישור"
}, {
  en: "credible",
  he: "מהימן / אמין"
}, {
  en: "crime prevention",
  he: "מניעת פשע"
}, {
  en: "crops",
  he: "יבולים"
}, {
  en: "crusade",
  he: "מסע צלב"
}, {
  en: "cumbersome",
  he: "מסורבל"
}, {
  en: "curse",
  he: "קללה"
}, {
  en: "debased",
  he: "פוגע / מעליב"
}, {
  en: "debut",
  he: "סרט ביכורים"
}, {
  en: "deceitfulness",
  he: "מרמה והונאה"
}, {
  en: "decentralized",
  he: "דה-צנטרליסטי"
}, {
  en: "decisive",
  he: "החלטי / מכריע"
}, {
  en: "debrief",
  he: "לתחקר"
}, {
  en: "decipher",
  he: "לפענח"
}, {
  en: "deduction",
  he: "דדוקציה"
}, {
  en: "defeat",
  he: "מפלה"
}, {
  en: "defect",
  he: "פגם / \"דפקט\""
}, {
  en: "defendant",
  he: "הנאשם"
}, {
  en: "defended",
  he: "הגן על..."
}, {
  en: "deform",
  he: "לעוות צורה"
}, {
  en: "defrost",
  he: "להפשיר"
}, {
  en: "denounce",
  he: "לגנות"
}, {
  en: "density",
  he: "צפיפות"
}, {
  en: "deny",
  he: "להכחיש"
}, {
  en: "depict",
  he: "לתאר"
}, {
  en: "deportation",
  he: "גירוש"
}, {
  en: "depression",
  he: "שפל"
}, {
  en: "descendant",
  he: "צאצא"
}, {
  en: "desirable",
  he: "נחשק"
}, {
  en: "deterrence",
  he: "הרתעה"
}, {
  en: "detest",
  he: "לתעב / לשנוא"
}, {
  en: "devastatingly",
  he: "באופן הרסני"
}, {
  en: "diminutive",
  he: "מקטין / זעיר"
}, {
  en: "disarray",
  he: "תוהו ובוהו"
}, {
  en: "discipline",
  he: "משמעת"
}, {
  en: "disclose",
  he: "לחשוף / לגלות"
}, {
  en: "disclosure",
  he: "חשיפה"
}, {
  en: "discount",
  he: "הנחה"
}, {
  en: "discovery",
  he: "תגלית"
}, {
  en: "disgusted",
  he: "נגעל"
}, {
  en: "disqualify",
  he: "לפסול"
}, {
  en: "disrupt",
  he: "להפריע"
}, {
  en: "distinguish",
  he: "להבחין"
}, {
  en: "distribute",
  he: "לחלק / להפיץ"
}, {
  en: "district",
  he: "מחוז / אזור"
}, {
  en: "disturbance",
  he: "הפרעה"
}, {
  en: "diver",
  he: "צוללן"
}, {
  en: "divulge",
  he: "לחשוף"
}, {
  en: "documentation",
  he: "תיעוד"
}, {
  en: "dodge",
  he: "להתחמק"
}, {
  en: "domain",
  he: "תחום"
}, {
  en: "dominated",
  he: "נשלט"
}, {
  en: "dormant",
  he: "רדום"
}, {
  en: "dosage",
  he: "מינון"
}, {
  en: "dot",
  he: "נקודה"
}, {
  en: "draw back",
  he: "לסגת / להירתע"
}, {
  en: "eager",
  he: "להוט"
}, {
  en: "earnest",
  he: "רציני"
}, {
  en: "echo",
  he: "הד"
}, {
  en: "editor",
  he: "עורך"
}, {
  en: "editorial",
  he: "מאמר מערכת"
}, {
  en: "educate",
  he: "לחנך"
}, {
  en: "efficient",
  he: "יעיל"
}, {
  en: "effort",
  he: "מאמץ / ניסיון"
}, {
  en: "elderly",
  he: "קשיש"
}, {
  en: "embezzle",
  he: "למעול / מעילה"
}, {
  en: "embrace",
  he: "לחבק"
}, {
  en: "emigrate",
  he: "להגר / לרדת"
}, {
  en: "employee",
  he: "עובד שכיר"
}, {
  en: "enclosure",
  he: "סגירת שטח"
}, {
  en: "encouragement",
  he: "עידוד"
}, {
  en: "endeavor",
  he: "מאמץ"
}, {
  en: "endorsement",
  he: "תמיכה / חסות"
}, {
  en: "enhance",
  he: "להרחיב"
}, {
  en: "enrollment",
  he: "הרשמה"
}, {
  en: "enthusiasm",
  he: "התלהבות"
}, {
  en: "eruption",
  he: "התפרצות"
}, {
  en: "espionage",
  he: "ריגול"
}, {
  en: "establishment",
  he: "מוסד / ממסד"
}, {
  en: "ethical",
  he: "אתי / מוסרי"
}, {
  en: "evaluation",
  he: "הערכה"
}, {
  en: "eventful",
  he: "מלא אירועים"
}, {
  en: "evolution",
  he: "אבולוציה"
}, {
  en: "excessive",
  he: "מוגזם"
}, {
  en: "excuse",
  he: "תירוץ"
}, {
  en: "expose",
  he: "לחשוף"
}, {
  en: "extend",
  he: "להאריך"
}, {
  en: "extensive",
  he: "מקיף"
}, {
  en: "extinction",
  he: "הכחדה"
}, {
  en: "facial features",
  he: "תווי פנים"
}, {
  en: "factor",
  he: "גורם"
}, {
  en: "faculty",
  he: "פקולטה"
}, {
  en: "fancy",
  he: "מהודר"
}, {
  en: "fan",
  he: "אוהד / מניפה"
}, {
  en: "favor",
  he: "טובה / העדפה"
}, {
  en: "feminine",
  he: "נשי"
}, {
  en: "ferocious",
  he: "פראי / אכזר"
}, {
  en: "ferociously",
  he: "באכזריות"
}, {
  en: "fertility",
  he: "פוריות"
}, {
  en: "feud",
  he: "משטמה"
}, {
  en: "fidelity",
  he: "נאמנות"
}, {
  en: "first aid",
  he: "עזרה ראשונה"
}, {
  en: "fixture",
  he: "משהו קבוע"
}, {
  en: "flat",
  he: "שטוח / דירה"
}, {
  en: "flaw",
  he: "חסרון / פגם"
}, {
  en: "flexibility",
  he: "גמישות"
}, {
  en: "foe",
  he: "אויב"
}, {
  en: "forge",
  he: "לזייף"
}, {
  en: "forming",
  he: "מייסדים"
}, {
  en: "fortify",
  he: "לבצר / לחזק"
}, {
  en: "foster",
  he: "לטפח / לאמץ"
}, {
  en: "found",
  he: "לייסד / להקים"
}, {
  en: "fraud",
  he: "הונאה / מרמה"
}, {
  en: "frown",
  he: "להזעיף פנים"
}, {
  en: "fruitful",
  he: "פורה"
}, {
  en: "frustrated",
  he: "מתוסכל"
}, {
  en: "function",
  he: "תפקוד"
}, {
  en: "fundamental",
  he: "בסיסי / יסודי"
}, {
  en: "furious",
  he: "זועם / \"רותח\""
}, {
  en: "gag order",
  he: "צו איסור פרסום"
}, {
  en: "gap",
  he: "פער"
}, {
  en: "genetic information",
  he: "מידע גנטי"
}, {
  en: "genuine",
  he: "מקורי / אמיתי"
}, {
  en: "get under way",
  he: "לצאת לדרך"
}, {
  en: "giant",
  he: "ענק"
}, {
  en: "glance",
  he: "מבט חטוף"
}, {
  en: "glimpse",
  he: "הצצה רגעית"
}, {
  en: "global economy",
  he: "כלכלה עולמית"
}, {
  en: "gown",
  he: "שמלה / חלוק"
}, {
  en: "graduate degree",
  he: "תואר אקדמאי"
}, {
  en: "greed",
  he: "תאוות בצע"
}, {
  en: "grief",
  he: "יגון"
}, {
  en: "guarded",
  he: "שמור"
}, {
  en: "guidance",
  he: "הנחיה"
}, {
  en: "gulf",
  he: "מפרץ"
}, {
  en: "halt",
  he: "לעצור / לחדול"
}, {
  en: "handcuffs",
  he: "אזיקים"
}, {
  en: "handy",
  he: "יעיל"
}, {
  en: "harbor",
  he: "נמל"
}, {
  en: "hearing",
  he: "שימוע / שומע"
}, {
  en: "heir",
  he: "יורש"
}, {
  en: "hint",
  he: "רמז"
}, {
  en: "holocaust survivor",
  he: "ניצול שואה"
}, {
  en: "honorable",
  he: "מכובד"
}, {
  en: "hopefulness",
  he: "מלא תקווה"
}, {
  en: "hostage",
  he: "בן ערובה"
}, {
  en: "hostile",
  he: "עוין"
}, {
  en: "hostility",
  he: "עוינות"
}, {
  en: "humidity",
  he: "לחות"
}, {
  en: "humiliation",
  he: "השפלה / בושה"
}, {
  en: "identical",
  he: "זהה"
}, {
  en: "identity",
  he: "זהות"
}, {
  en: "ignoring",
  he: "להתעלם"
}, {
  en: "ill-fated",
  he: "מסתיים בכי רע"
}, {
  en: "image",
  he: "תמונה / דמות"
}, {
  en: "imaginable",
  he: "ניתן לדמיון"
}, {
  en: "immunity",
  he: "חסינות"
}, {
  en: "impede",
  he: "להאט / להפריע"
}, {
  en: "implant",
  he: "לשתול"
}, {
  en: "imply",
  he: "לרמוז"
}, {
  en: "imprison",
  he: "לכלוא / לאסור"
}, {
  en: "improbable",
  he: "בלתי סביר"
}, {
  en: "in accordance",
  he: "בהתאם ל..."
}, {
  en: "in contradiction",
  he: "בסתירה"
}, {
  en: "incapable",
  he: "לא מסוגל"
}, {
  en: "incautious",
  he: "בלתי זהיר"
}, {
  en: "incentive",
  he: "תמריץ"
}, {
  en: "incident",
  he: "תקרית"
}, {
  en: "inclination",
  he: "נטייה ל..."
}, {
  en: "in common",
  he: "במשותף"
}, {
  en: "incompatible",
  he: "בלתי מתאים"
}, {
  en: "incompetence",
  he: "חוסר יכולת"
}, {
  en: "inconceivable",
  he: "בלתי נתפש"
}, {
  en: "indication",
  he: "אינדיקציה"
}, {
  en: "indicator",
  he: "אינדיקטור"
}, {
  en: "indictment",
  he: "כתב אישום"
}, {
  en: "infant",
  he: "תינוק קטן"
}, {
  en: "infectious",
  he: "מדבק"
}, {
  en: "infer",
  he: "להסיק / להבין"
}, {
  en: "infinitesimal",
  he: "מזערי"
}, {
  en: "inherent",
  he: "טבוע"
}, {
  en: "inheritance",
  he: "ירושה"
}, {
  en: "initial",
  he: "ראשוני"
}, {
  en: "initiate",
  he: "ליזום"
}, {
  en: "insanity",
  he: "שיגעון"
}, {
  en: "insect",
  he: "חרק"
}, {
  en: "inspiration",
  he: "השראה"
}, {
  en: "institution",
  he: "מוסד"
}, {
  en: "insufferable",
  he: "בלתי נסבל"
}, {
  en: "insufficient",
  he: "בלתי מספק"
}, {
  en: "insurance evaluators",
  he: "שמאי ביטוח"
}, {
  en: "insurance policy",
  he: "פוליסת ביטוח"
}, {
  en: "insure",
  he: "להבטיח"
}, {
  en: "integrity",
  he: "יושר / אמינות"
}, {
  en: "intelligence officer",
  he: "קצין מודיעין"
}, {
  en: "intended effect",
  he: "אפקט מיועד"
}, {
  en: "intent",
  he: "כוונה"
}, {
  en: "interaction",
  he: "אינטראקציה"
}, {
  en: "interrogation",
  he: "חקירה"
}, {
  en: "investigation",
  he: "חקירה (בלשית)"
}, {
  en: "investor",
  he: "משקיע"
}, {
  en: "invincible",
  he: "בלתי מנוצח"
}, {
  en: "invisible",
  he: "בלתי נראה"
}, {
  en: "invitation",
  he: "הזמנה"
}, {
  en: "isolate",
  he: "לבודד / לנתק"
}, {
  en: "isolationism",
  he: "בדלנות"
}, {
  en: "issue a declaration",
  he: "לפרסם הצהרה"
}, {
  en: "journey",
  he: "מסע"
}, {
  en: "judgment",
  he: "יכולת שיפוט"
}, {
  en: "jump-start",
  he: "להתניע"
}, {
  en: "justify",
  he: "להצדיק"
}, {
  en: "kidnapping",
  he: "חטיפה"
}, {
  en: "lab",
  he: "מעבדה"
}, {
  en: "lap",
  he: "הקפה / ירך"
}, {
  en: "launch",
  he: "להשיק / לשגר"
}, {
  en: "lavishly",
  he: "בהידור"
}, {
  en: "lawyer",
  he: "עורך דין"
}, {
  en: "layoffs",
  he: "פיטורין"
}, {
  en: "lecture",
  he: "הרצאה"
}, {
  en: "legacy",
  he: "מורשת"
}, {
  en: "lethal",
  he: "קטלני"
}, {
  en: "likeness",
  he: "דמיון"
}, {
  en: "limitation",
  he: "מגבלה"
}, {
  en: "line of research",
  he: "קו מחקרי"
}, {
  en: "link",
  he: "קשר"
}, {
  en: "loathe",
  he: "מתעב"
}, {
  en: "makes sense",
  he: "נשמע הגיוני"
}, {
  en: "malfunction",
  he: "תקלה"
}, {
  en: "management position",
  he: "תפקיד ניהולי"
}, {
  en: "mandatory",
  he: "חובה"
}, {
  en: "manner",
  he: "אופן"
}, {
  en: "marginal element",
  he: "גורם שולי"
}, {
  en: "markedly",
  he: "באופן ניכר"
}, {
  en: "masculine",
  he: "גברי"
}, {
  en: "massacre",
  he: "טבח"
}, {
  en: "meager",
  he: "זעום"
}, {
  en: "meaningless",
  he: "חסר משמעות"
}, {
  en: "means of deterrence",
  he: "אמצעי הרתעה"
}, {
  en: "mediator",
  he: "מתווך"
}, {
  en: "mediocre",
  he: "בינוני"
}, {
  en: "meek",
  he: "חלש / קלוש"
}, {
  en: "meet these goals",
  he: "לעמוד ביעדים"
}, {
  en: "mental",
  he: "נפשי / מנטאלי"
}, {
  en: "merger",
  he: "איחוד / מיזוג"
}, {
  en: "meticulous",
  he: "קפדני ודקדקני"
}, {
  en: "middleman",
  he: "מתווך"
}, {
  en: "mild",
  he: "מתון"
}, {
  en: "minister",
  he: "שר"
}, {
  en: "minute",
  he: "זעיר / דקה"
}, {
  en: "miracle",
  he: "נס"
}, {
  en: "misconception",
  he: "תפישה שגויה"
}, {
  en: "misinterpret",
  he: "לפרש לא נכון"
}, {
  en: "missionary",
  he: "מיסיונר"
}, {
  en: "moral question",
  he: "שאלה מוסרית"
}, {
  en: "mortal danger",
  he: "סכנת חיים"
}, {
  en: "motion",
  he: "תנועה"
}, {
  en: "motive",
  he: "מניע"
}, {
  en: "mutual",
  he: "הדדי"
}, {
  en: "mysteriousness",
  he: "מסתוריות"
}, {
  en: "mystical",
  he: "מיסטי"
}, {
  en: "mystify",
  he: "לערפל"
}, {
  en: "naive",
  he: "נאיבי / תמים"
}, {
  en: "narcissist",
  he: "נרקיסיסט"
}, {
  en: "navigate",
  he: "לנווט"
}, {
  en: "nerve cell",
  he: "תא עצב"
}, {
  en: "neutral",
  he: "נייטראלי"
}, {
  en: "next of kin",
  he: "קרוב משפחה"
}, {
  en: "nightmare",
  he: "סיוט"
}, {
  en: "novel",
  he: "חדשני"
}, {
  en: "novelist",
  he: "סופר"
}, {
  en: "obligation",
  he: "התחייבות"
}, {
  en: "offspring",
  he: "צאצא"
}, {
  en: "ongoing",
  he: "מתמשך"
}, {
  en: "oppose",
  he: "להתנגד ל..."
}, {
  en: "opposite",
  he: "הפוך"
}, {
  en: "oppression",
  he: "דיכוי"
}, {
  en: "oral",
  he: "בעל פה"
}, {
  en: "orbit",
  he: "מסלול היקפי"
}, {
  en: "originates from",
  he: "נובע מ..."
}, {
  en: "outcome",
  he: "תוצאה"
}, {
  en: "overshadow",
  he: "להאפיל"
}, {
  en: "overt",
  he: "גלוי, פומבי"
}, {
  en: "overwhelmed",
  he: "המום"
}, {
  en: "pamper",
  he: "לפנק"
}, {
  en: "parade",
  he: "מצעד / להצעיד"
}, {
  en: "paralyze",
  he: "לשתק"
}, {
  en: "participant",
  he: "משתתף"
}, {
  en: "particle",
  he: "חלקיק"
}, {
  en: "pave",
  he: "לסלול"
}, {
  en: "peacefulness",
  he: "שקט ושלווה"
}, {
  en: "penetration",
  he: "חדירה"
}, {
  en: "percent",
  he: "אחוז"
}, {
  en: "perception",
  he: "תפישה"
}, {
  en: "persist",
  he: "להתמיד"
}, {
  en: "personnel",
  he: "כוח אדם"
}, {
  en: "persuasion",
  he: "שכנוע"
}, {
  en: "phase",
  he: "שלב"
}, {
  en: "pipeline",
  he: "צינור"
}, {
  en: "plagiarism",
  he: "גניבה ספרותית"
}, {
  en: "plain",
  he: "פשוט / ברור"
}, {
  en: "plaintiff",
  he: "תובע / מאשים"
}, {
  en: "planet",
  he: "כוכב לכת"
}, {
  en: "plea",
  he: "טענה"
}, {
  en: "pledge",
  he: "התחייבות"
}, {
  en: "plenty",
  he: "שפע"
}, {
  en: "point out",
  he: "לציין"
}, {
  en: "pollute",
  he: "לזהם"
}, {
  en: "popular belief",
  he: "אמונה מקובלת"
}, {
  en: "port",
  he: "נמל"
}, {
  en: "precaution",
  he: "אמצעי זהירות"
}, {
  en: "precious",
  he: "יקר"
}, {
  en: "precisely",
  he: "בדיוק"
}, {
  en: "preclude",
  he: "להוציא מהכלל"
}, {
  en: "preference",
  he: "העדפה"
}, {
  en: "premise",
  he: "הנחת יסוד"
}, {
  en: "preparation",
  he: "הכנה"
}, {
  en: "preserved bodies",
  he: "גופות משומרות"
}, {
  en: "prestigious",
  he: "יוקרתי"
}, {
  en: "probable successor",
  he: "יורש אפשרי"
}, {
  en: "probation",
  he: "תקופת מבחן"
}, {
  en: "probe",
  he: "סקירה מעמיקה"
}, {
  en: "profit",
  he: "להרוויח"
}, {
  en: "projected",
  he: "צפוי / מתוכנן"
}, {
  en: "prolonged",
  he: "מוארך / ממושך"
}, {
  en: "prominent",
  he: "בולט"
}, {
  en: "promotion",
  he: "קידום"
}, {
  en: "pronunciation",
  he: "היגוי / מבטא"
}, {
  en: "prophecy",
  he: "נבואה"
}, {
  en: "proponent",
  he: "תומך"
}, {
  en: "proposal",
  he: "הצעה"
}, {
  en: "prosperity",
  he: "שגשוג ורווחה"
}, {
  en: "protest",
  he: "מחאה / הפגנה"
}, {
  en: "punishment",
  he: "עונש / ענישה"
}, {
  en: "purify",
  he: "לטהר"
}, {
  en: "purloined material",
  he: "חומר \"מושאל\""
}, {
  en: "purposeful",
  he: "מלא כוונה"
}, {
  en: "pursuit",
  he: "מרדף"
}, {
  en: "puzzled",
  he: "תמוה"
}, {
  en: "qualified",
  he: "מתאים / מוסמך"
}, {
  en: "quarter",
  he: "רבע"
}, {
  en: "quiz",
  he: "בוחן / חידון"
}, {
  en: "racism",
  he: "גזענות"
}, {
  en: "racist",
  he: "גזען"
}, {
  en: "radiation",
  he: "קרינה"
}, {
  en: "reaction",
  he: "תגובה"
}, {
  en: "reasonable",
  he: "סביר / הגיוני"
}, {
  en: "reassembled",
  he: "מורכב מחדש"
}, {
  en: "rebuttal",
  he: "הפרכה"
}, {
  en: "recipe",
  he: "מתכון"
}, {
  en: "rectify",
  he: "לתקן"
}, {
  en: "refuel",
  he: "לתדלק מחדש"
}, {
  en: "regardless",
  he: "ללא קשר"
}, {
  en: "regime",
  he: "משטר"
}, {
  en: "regiment",
  he: "גדוד"
}, {
  en: "region",
  he: "אזור / תחום"
}, {
  en: "reinforce",
  he: "לתגבר / לחזק"
}, {
  en: "reluctance",
  he: "חוסר רצון"
}, {
  en: "remarkable",
  he: "ראוי לציון"
}, {
  en: "remorse",
  he: "חרטה / צער"
}, {
  en: "reprehensible",
  he: "ראוי לגינוי"
}, {
  en: "reptile",
  he: "זוחל"
}, {
  en: "requester",
  he: "המבקש"
}, {
  en: "residency",
  he: "מקום מגורים"
}, {
  en: "respiration",
  he: "נשימה"
}, {
  en: "restoration",
  he: "שחזור"
}, {
  en: "restore",
  he: "לשחזר"
}, {
  en: "retirement",
  he: "פרישה"
}, {
  en: "reveal",
  he: "לחשוף / לגלות"
}, {
  en: "review",
  he: "לבדוק שנית"
}, {
  en: "revive",
  he: "להחיות"
}, {
  en: "revolutionize",
  he: "לחולל מהפיכה"
}, {
  en: "role",
  he: "תפקיד"
}, {
  en: "root",
  he: "שורש"
}, {
  en: "routine",
  he: "רוטינה / שגרה"
}, {
  en: "rural",
  he: "כפרי"
}, {
  en: "sacred",
  he: "קדוש"
}, {
  en: "satellite",
  he: "לוויין"
}, {
  en: "scatter",
  he: "לפזר / להתפזר"
}, {
  en: "scenario",
  he: "תרחיש"
}, {
  en: "schooling",
  he: "חינוך"
}, {
  en: "scroll",
  he: "מגילה"
}, {
  en: "self-preservation",
  he: "שימור עצמי"
}, {
  en: "self-restraint",
  he: "שליטה עצמית"
}, {
  en: "semi",
  he: "למחצה"
}, {
  en: "seminar",
  he: "סמינר"
}, {
  en: "sensible",
  he: "הגיוני"
}, {
  en: "sensuous",
  he: "חושני"
}, {
  en: "serenity",
  he: "שלווה"
}, {
  en: "server",
  he: "שרת מחשב"
}, {
  en: "session",
  he: "פגישה /סדנא"
}, {
  en: "shortage",
  he: "מחסור"
}, {
  en: "similarly",
  he: "באופן דומה"
}, {
  en: "simulate",
  he: "לדמות"
}, {
  en: "site",
  he: "אתר"
}, {
  en: "skinny",
  he: "רזה מאוד"
}, {
  en: "sleepiness",
  he: "ישנוניות"
}, {
  en: "slim",
  he: "רזה / קלוש"
}, {
  en: "slips of the tongue",
  he: "מעידות בלשון"
}, {
  en: "sober",
  he: "פיכח"
}, {
  en: "software patches",
  he: "טלאי תוכנה"
}, {
  en: "sought after",
  he: "מחפשים אחריו"
}, {
  en: "specialist",
  he: "מומחה"
}, {
  en: "specialize",
  he: "מתמחה ב..."
}, {
  en: "spectator",
  he: "צופה"
}, {
  en: "spokesperson",
  he: "דובר"
}, {
  en: "spokeswoman",
  he: "דוברת"
}, {
  en: "sporadic",
  he: "בלתי סדיר"
}, {
  en: "spot",
  he: "נקודה"
}, {
  en: "squeeze",
  he: "ללחוץ / למחוץ"
}, {
  en: "stage",
  he: "שלב"
}, {
  en: "stakes",
  he: "סיכונים"
}, {
  en: "stand",
  he: "לעמוד / יציע"
}, {
  en: "startling",
  he: "מפתיע / מדהים"
}, {
  en: "stems from",
  he: "נובע מ..."
}, {
  en: "stock",
  he: "מניה בורסאית"
}, {
  en: "stomach",
  he: "קיבה / בטן"
}, {
  en: "storm",
  he: "סופה / סערה"
}, {
  en: "straight-forward",
  he: "ישיר"
}, {
  en: "strict",
  he: "נוקשה / קפדני"
}, {
  en: "suburban",
  he: "פרברי"
}, {
  en: "superstition",
  he: "אמונה טפלה"
}, {
  en: "supervision",
  he: "פיקוח"
}, {
  en: "surface variance",
  he: "משתנה חיצוני"
}, {
  en: "surrogate mother",
  he: "אם פונדקאית"
}, {
  en: "suspended",
  he: "מושעה / מושהה"
}, {
  en: "tantalizing",
  he: "מרגש / מרעיד"
}, {
  en: "tempt fate",
  he: "להתגרות בגורל"
}, {
  en: "testify",
  he: "להעיד"
}, {
  en: "testimony",
  he: "עדות"
}, {
  en: "therapy",
  he: "תרפיה / טיפול"
}, {
  en: "tide",
  he: "גאות ושפל"
}, {
  en: "timeliness",
  he: "דייקנות"
}, {
  en: "tool",
  he: "כלי"
}, {
  en: "topic",
  he: "הנושא"
}, {
  en: "topple",
  he: "למוטט"
}, {
  en: "tournament",
  he: "טורניר"
}, {
  en: "trade-offs",
  he: "החלפות"
}, {
  en: "traditional",
  he: "מסורתי"
}, {
  en: "traitorous",
  he: "בוגדני"
}, {
  en: "tranquility",
  he: "שלווה"
}, {
  en: "transaction",
  he: "עסקה"
}, {
  en: "transfer",
  he: "להעביר"
}, {
  en: "translucent",
  he: "מעט שקוף"
}, {
  en: "transparent",
  he: "שקוף / ברור"
}, {
  en: "tremendous",
  he: "עצום"
}, {
  en: "trend",
  he: "אופנה"
}, {
  en: "trial and error",
  he: "ניסוי וטעייה"
}, {
  en: "truthfully",
  he: "בכנות"
}, {
  en: "unbearable",
  he: "בלתי נסבל"
}, {
  en: "under dispute",
  he: "נתון במחלוקת"
}, {
  en: "undeterred",
  he: "לא נרתע מ..."
}, {
  en: "unravel",
  he: "לחשוף"
}, {
  en: "unstable",
  he: "בלתי יציב"
}, {
  en: "usable",
  he: "ניתן לשימוש"
}, {
  en: "vacancy",
  he: "מקום פנוי"
}, {
  en: "varies",
  he: "משתנה"
}, {
  en: "vast majority",
  he: "הרוב המוחלט"
}, {
  en: "veil",
  he: "הינומה"
}, {
  en: "violate",
  he: "להפר"
}, {
  en: "voyage",
  he: "מסע"
}, {
  en: "wage",
  he: "שכר / משכורת"
}, {
  en: "want of understanding",
  he: "העדר הבנה"
}, {
  en: "waver",
  he: "לוותר"
}, {
  en: "will",
  he: "רצון / צוואה"
}, {
  en: "willingness",
  he: "מוכנות"
}, {
  en: "wiped out",
  he: "למחוק"
}, {
  en: "work ethic",
  he: "מוסר עבודה"
}, {
  en: "worship",
  he: "לסגוד ל..."
}, {
  en: "wrapped up",
  he: "עטוף"
}, {
  en: "wrist",
  he: "פרק יד"
}, {
  en: "yearn",
  he: "להשתוקק"
}, {
  en: "youth",
  he: "נעורים"
}];
})(); } catch (e) { __ds_ns.__errors.push({ path: "tetri-psychometry-export/words.js", error: String((e && e.message) || e) }); }

// tetri-psychometry/TetriGame.jsx
try { (() => {
/* global React */
const {
  useState,
  useEffect,
  useRef,
  useCallback,
  useMemo,
  useLayoutEffect
} = React;
// icon source: resolves to an inlined data-URI in the single-file build, or the
// relative path in the folder/server build (works on http:// and file://).
const EZ_ICON = typeof document !== 'undefined' && document.getElementById('ez-icon-src') && document.getElementById('ez-icon-src').src || 'ez-icon.png';

/* ════════════════ sound (WebAudio FX) ════════════════ */
const MUTED_KEY = "tx-muted-v1";
const REVIEW_KEY = "tx-review-v1";
const Sound = {
  ctx: null,
  muted: false,
  init() {
    if (!this.ctx) {
      try {
        this.ctx = new (window.AudioContext || window.webkitAudioContext)();
      } catch (e) {}
    }
    if (this.ctx && this.ctx.state === 'suspended') this.ctx.resume();
  },
  setMuted(m) {
    this.muted = !!m;
    try {
      localStorage.setItem(MUTED_KEY, m ? '1' : '0');
    } catch (e) {}
  },
  beep(f, d, type = 'sine', g = 0.15, delay = 0) {
    if (this.muted || !this.ctx) return;
    const t = this.ctx.currentTime + delay,
      o = this.ctx.createOscillator(),
      gn = this.ctx.createGain();
    o.type = type;
    o.frequency.value = f;
    gn.gain.setValueAtTime(g, t);
    gn.gain.exponentialRampToValueAtTime(0.001, t + d);
    o.connect(gn);
    gn.connect(this.ctx.destination);
    o.start(t);
    o.stop(t + d);
  },
  play(name) {
    if (this.muted) return;
    this.init();
    switch (name) {
      case 'move':
        this.beep(420, 0.04, 'square', 0.06);
        break;
      case 'drop':
        this.beep(180, 0.08, 'sawtooth', 0.12);
        this.beep(120, 0.1, 'square', 0.1, 0.03);
        break;
      case 'hit':
        this.beep(523, 0.1, 'square', 0.16);
        this.beep(784, 0.12, 'square', 0.14, 0.08);
        this.beep(1047, 0.22, 'triangle', 0.16, 0.16);
        break;
      case 'miss':
        this.beep(330, 0.14, 'square', 0.2);
        this.beep(196, 0.3, 'sawtooth', 0.2, 0.12);
        this.beep(130, 0.4, 'triangle', 0.18, 0.34);
        break;
      case 'fifty':
        this.beep(880, 0.1, 'sine', 0.15);
        this.beep(1320, 0.18, 'sine', 0.16, 0.1);
        break;
      case 'levelup':
        this.beep(523, 0.1, 'triangle', 0.18);
        this.beep(659, 0.1, 'triangle', 0.18, 0.1);
        this.beep(784, 0.1, 'triangle', 0.18, 0.2);
        this.beep(1047, 0.32, 'sine', 0.2, 0.3);
        break;
      case 'streak':
        this.beep(880, 0.08, 'sine', 0.13);
        this.beep(1320, 0.1, 'sine', 0.14, 0.08);
        this.beep(1760, 0.2, 'sine', 0.14, 0.16);
        break;
      case 'gameover':
        this.beep(440, 0.2, 'sine', 0.15);
        this.beep(330, 0.24, 'sine', 0.15, 0.2);
        this.beep(220, 0.5, 'sine', 0.18, 0.45);
        break;
    }
  }
};
try {
  Sound.muted = localStorage.getItem(MUTED_KEY) === '1';
} catch (e) {}

/* ════════════════ review list (persisted per-browser) ════════════════ */
function getReview() {
  try {
    return JSON.parse(localStorage.getItem(REVIEW_KEY) || '[]');
  } catch (e) {
    return [];
  }
}
function addReview(words) {
  const cur = getReview();
  const seen = new Set(cur.map(w => String(w.en).toLowerCase()));
  for (const w of words || []) {
    if (!w || !w.en) continue;
    const k = String(w.en).toLowerCase();
    if (!seen.has(k)) {
      seen.add(k);
      cur.push({
        en: w.en,
        he: w.he
      });
    }
  }
  try {
    localStorage.setItem(REVIEW_KEY, JSON.stringify(cur));
  } catch (e) {}
  return cur;
}
function clearReview() {
  try {
    localStorage.removeItem(REVIEW_KEY);
  } catch (e) {}
}

/* ════════════════ dictionary helpers ════════════════ */
function shuffle(a) {
  const x = [...a];
  for (let i = x.length - 1; i > 0; i--) {
    const j = Math.random() * (i + 1) | 0;
    [x[i], x[j]] = [x[j], x[i]];
  }
  return x;
}
function normMeaning(s) {
  return String(s || '').toLowerCase().replace(/[\/,،]/g, ' ').replace(/\s+/g, ' ').replace(/[״"׳'.…]/g, '').trim();
}
function buildQuestion(correct, fullDict, idx) {
  const ck = normMeaning(correct.he);
  const cen = String(correct.en).toLowerCase();
  const pool = fullDict.map(e => ({
    e,
    key: normMeaning(e.he)
  })).filter(({
    e,
    key
  }) => String(e.en).toLowerCase() !== cen && key !== ck);
  const picked = [];
  const seen = new Set([ck]);
  for (const {
    e,
    key
  } of shuffle(pool)) {
    if (seen.has(key)) continue;
    seen.add(key);
    picked.push(e);
    if (picked.length === 3) break;
  }
  while (picked.length < 3) {
    const f = shuffle(pool).filter(p => !picked.includes(p.e));
    if (!f.length) break;
    picked.push(f[0].e);
  }
  const options = shuffle([correct.he, ...picked.map(d => d.he)]);
  return {
    en: String(correct.en),
    he: correct.he,
    options,
    dictIdx: idx
  };
}

/* ════════════════ icons ════════════════ */
const Ico = {
  sound: () => /*#__PURE__*/React.createElement("svg", {
    viewBox: "0 0 24 24",
    fill: "currentColor"
  }, /*#__PURE__*/React.createElement("path", {
    d: "M3 10v4a1 1 0 0 0 1 1h3l4 3.5a1 1 0 0 0 1.6-.8V6.3a1 1 0 0 0-1.6-.8L7 9H4a1 1 0 0 0-1 1Z"
  }), /*#__PURE__*/React.createElement("path", {
    d: "M16 8.5a4 4 0 0 1 0 7",
    fill: "none",
    stroke: "currentColor",
    strokeWidth: "2",
    strokeLinecap: "round"
  })),
  mute: () => /*#__PURE__*/React.createElement("svg", {
    viewBox: "0 0 24 24",
    fill: "none",
    stroke: "currentColor",
    strokeWidth: "2.2",
    strokeLinecap: "round",
    strokeLinejoin: "round"
  }, /*#__PURE__*/React.createElement("path", {
    d: "M3 10v4a1 1 0 0 0 1 1h3l4 3.5a1 1 0 0 0 1.6-.8V6.3a1 1 0 0 0-1.6-.8L7 9H4a1 1 0 0 0-1 1Z",
    fill: "currentColor",
    stroke: "none"
  }), /*#__PURE__*/React.createElement("path", {
    d: "M16 9l5 5M21 9l-5 5"
  })),
  expand: () => /*#__PURE__*/React.createElement("svg", {
    viewBox: "0 0 24 24",
    fill: "none",
    stroke: "currentColor",
    strokeWidth: "2.4",
    strokeLinecap: "round",
    strokeLinejoin: "round"
  }, /*#__PURE__*/React.createElement("path", {
    d: "M4 9V4h5M20 9V4h-5M4 15v5h5M20 15v5h-5"
  })),
  home: () => /*#__PURE__*/React.createElement("svg", {
    viewBox: "0 0 24 24",
    fill: "none",
    stroke: "currentColor",
    strokeWidth: "2.2",
    strokeLinecap: "round",
    strokeLinejoin: "round"
  }, /*#__PURE__*/React.createElement("path", {
    d: "M3 11l9-8 9 8"
  }), /*#__PURE__*/React.createElement("path", {
    d: "M5 10v10h14V10"
  }), /*#__PURE__*/React.createElement("path", {
    d: "M10 20v-6h4v6"
  })),
  trophy: () => /*#__PURE__*/React.createElement("svg", {
    viewBox: "0 0 24 24",
    fill: "none",
    stroke: "currentColor",
    strokeWidth: "2.2",
    strokeLinecap: "round",
    strokeLinejoin: "round"
  }, /*#__PURE__*/React.createElement("path", {
    d: "M8 21h8M12 17v4M7 4h10v5a5 5 0 0 1-10 0V4z"
  }), /*#__PURE__*/React.createElement("path", {
    d: "M7 6H4v2a3 3 0 0 0 3 3M17 6h3v2a3 3 0 0 1-3 3"
  })),
  left: () => /*#__PURE__*/React.createElement("svg", {
    viewBox: "0 0 24 24",
    fill: "currentColor"
  }, /*#__PURE__*/React.createElement("path", {
    d: "M15 5 L7 12 L15 19 Z"
  })),
  right: () => /*#__PURE__*/React.createElement("svg", {
    viewBox: "0 0 24 24",
    fill: "currentColor"
  }, /*#__PURE__*/React.createElement("path", {
    d: "M9 5 L17 12 L9 19 Z"
  })),
  down: () => /*#__PURE__*/React.createElement("svg", {
    viewBox: "0 0 24 24",
    fill: "currentColor"
  }, /*#__PURE__*/React.createElement("path", {
    d: "M5 9 L12 17 L19 9 Z"
  })),
  play: () => /*#__PURE__*/React.createElement("svg", {
    viewBox: "0 0 24 24",
    fill: "currentColor"
  }, /*#__PURE__*/React.createElement("path", {
    d: "M7 5 L19 12 L7 19 Z"
  })),
  go: () => /*#__PURE__*/React.createElement("svg", {
    viewBox: "0 0 24 24",
    fill: "none",
    stroke: "currentColor",
    strokeWidth: "2.6",
    strokeLinecap: "round",
    strokeLinejoin: "round"
  }, /*#__PURE__*/React.createElement("path", {
    d: "M19 12H5"
  }), /*#__PURE__*/React.createElement("path", {
    d: "M12 5l-7 7 7 7"
  })),
  share: () => /*#__PURE__*/React.createElement("svg", {
    viewBox: "0 0 24 24",
    fill: "none",
    stroke: "currentColor",
    strokeWidth: "2.2",
    strokeLinecap: "round",
    strokeLinejoin: "round"
  }, /*#__PURE__*/React.createElement("circle", {
    cx: "18",
    cy: "5",
    r: "3"
  }), /*#__PURE__*/React.createElement("circle", {
    cx: "6",
    cy: "12",
    r: "3"
  }), /*#__PURE__*/React.createElement("circle", {
    cx: "18",
    cy: "19",
    r: "3"
  }), /*#__PURE__*/React.createElement("path", {
    d: "M8.6 13.5l6.8 4M15.4 6.5l-6.8 4"
  })),
  print: () => /*#__PURE__*/React.createElement("svg", {
    viewBox: "0 0 24 24",
    fill: "none",
    stroke: "currentColor",
    strokeWidth: "2.2",
    strokeLinecap: "round",
    strokeLinejoin: "round"
  }, /*#__PURE__*/React.createElement("path", {
    d: "M6 9V3h12v6"
  }), /*#__PURE__*/React.createElement("path", {
    d: "M6 18H4a1 1 0 0 1-1-1v-5a1 1 0 0 1 1-1h16a1 1 0 0 1 1 1v5a1 1 0 0 1-1 1h-2"
  }), /*#__PURE__*/React.createElement("rect", {
    x: "6",
    y: "14",
    width: "12",
    height: "7",
    rx: "1"
  })),
  gift: () => /*#__PURE__*/React.createElement("svg", {
    viewBox: "0 0 24 24",
    fill: "none",
    stroke: "currentColor",
    strokeWidth: "2.1",
    strokeLinecap: "round",
    strokeLinejoin: "round"
  }, /*#__PURE__*/React.createElement("path", {
    d: "M20 12v8a1 1 0 0 1-1 1H5a1 1 0 0 1-1-1v-8"
  }), /*#__PURE__*/React.createElement("path", {
    d: "M2 8h20v4H2z"
  }), /*#__PURE__*/React.createElement("path", {
    d: "M12 8v13M12 8S10.5 4 8 4a2 2 0 0 0 0 4M12 8s1.5-4 4-4a2 2 0 0 1 0 4"
  })),
  mail: () => /*#__PURE__*/React.createElement("svg", {
    viewBox: "0 0 24 24",
    fill: "none",
    stroke: "currentColor",
    strokeWidth: "2.2",
    strokeLinecap: "round",
    strokeLinejoin: "round"
  }, /*#__PURE__*/React.createElement("rect", {
    x: "3",
    y: "5",
    width: "18",
    height: "14",
    rx: "2.5"
  }), /*#__PURE__*/React.createElement("path", {
    d: "M3.5 7l8.5 6 8.5-6"
  })),
  refresh: () => /*#__PURE__*/React.createElement("svg", {
    viewBox: "0 0 24 24",
    fill: "none",
    stroke: "currentColor",
    strokeWidth: "2.3",
    strokeLinecap: "round",
    strokeLinejoin: "round"
  }, /*#__PURE__*/React.createElement("path", {
    d: "M3 12a9 9 0 0 1 15.5-6.3L21 8"
  }), /*#__PURE__*/React.createElement("path", {
    d: "M21 3v5h-5"
  }), /*#__PURE__*/React.createElement("path", {
    d: "M21 12a9 9 0 0 1-15.5 6.3L3 16"
  }), /*#__PURE__*/React.createElement("path", {
    d: "M3 21v-5h5"
  })),
  hand: () => /*#__PURE__*/React.createElement("svg", {
    viewBox: "0 0 40 58",
    fill: "none"
  }, /*#__PURE__*/React.createElement("ellipse", {
    cx: "20",
    cy: "55",
    rx: "11",
    ry: "3.5",
    fill: "#000",
    opacity: ".16"
  }), /*#__PURE__*/React.createElement("path", {
    d: "M12.5 51 V17 a7.5 7.5 0 0 1 15 0 v29 a5 5 0 0 1-5 5 h-5 a5 5 0 0 1-5-5 z",
    fill: "#F7CBA6",
    stroke: "#00000018",
    strokeWidth: "1.5"
  }), /*#__PURE__*/React.createElement("path", {
    d: "M12.5 40 q7.5 4 15 0",
    stroke: "#E0A87E",
    strokeWidth: "1.4",
    strokeLinecap: "round",
    fill: "none"
  }), /*#__PURE__*/React.createElement("ellipse", {
    cx: "20",
    cy: "14.5",
    rx: "5.5",
    ry: "4.2",
    fill: "#fff",
    opacity: ".5"
  })),
  rowclear: () => /*#__PURE__*/React.createElement("svg", {
    viewBox: "0 0 24 24",
    fill: "none",
    stroke: "currentColor",
    strokeWidth: "2",
    strokeLinecap: "round",
    strokeLinejoin: "round"
  }, /*#__PURE__*/React.createElement("rect", {
    x: "3",
    y: "10",
    width: "18",
    height: "4.5",
    rx: "1",
    fill: "currentColor",
    stroke: "none"
  }), /*#__PURE__*/React.createElement("path", {
    d: "M6 6.5 6.8 8M12 5.5V7M18 6.5 17.2 8",
    opacity: ".9"
  }), /*#__PURE__*/React.createElement("path", {
    d: "M6 18 6.8 16.4M12 18.6V17M18 18 17.2 16.4",
    opacity: ".9"
  })),
  readaloud: () => /*#__PURE__*/React.createElement("svg", {
    viewBox: "0 0 24 24",
    fill: "none",
    stroke: "currentColor",
    strokeWidth: "2",
    strokeLinecap: "round",
    strokeLinejoin: "round"
  }, /*#__PURE__*/React.createElement("path", {
    d: "M4 15V9h3l4-3.5v13L7 15H4z",
    fill: "currentColor",
    stroke: "none"
  }), /*#__PURE__*/React.createElement("path", {
    d: "M15 9.5a3.2 3.2 0 0 1 0 5"
  }), /*#__PURE__*/React.createElement("path", {
    d: "M17.5 7a6 6 0 0 1 0 10"
  })),
  readoff: () => /*#__PURE__*/React.createElement("svg", {
    viewBox: "0 0 24 24",
    fill: "none",
    stroke: "currentColor",
    strokeWidth: "2",
    strokeLinecap: "round",
    strokeLinejoin: "round"
  }, /*#__PURE__*/React.createElement("path", {
    d: "M4 15V9h3l4-3.5v13L7 15H4z",
    fill: "currentColor",
    stroke: "none"
  }), /*#__PURE__*/React.createElement("path", {
    d: "M15.5 9.5l5 5M20.5 9.5l-5 5"
  }))
};
function Heart({
  lost
}) {
  return /*#__PURE__*/React.createElement("svg", {
    viewBox: "0 0 24 24",
    className: lost ? 'lost' : ''
  }, /*#__PURE__*/React.createElement("path", {
    fill: "#F33F3F",
    d: "M12 21s-7.5-4.7-9.6-9.5C.9 7.7 3.5 4 7.2 4c2 0 3.6 1 4.8 2.6C13.2 5 14.8 4 16.8 4c3.7 0 6.3 3.7 4.8 7.5C19.5 16.3 12 21 12 21z"
  }));
}
const TET_COLORS = ['#F2C230', '#E0519B', '#7E5BC2', '#3FA76C', '#5BB8E8', '#3F6BD6', '#D6463A', '#F37327', '#A9A4EC'];
/* per-level well themes — kick in from level 3, cycling. levels 1–2 use the default dark well. */
const LEVEL_THEMES = [{
  top: '#2A2547',
  bot: '#14102A',
  glow: 'rgba(243,115,39,.28)'
},
// orange
{
  top: '#1C2E4A',
  bot: '#0E1626',
  glow: 'rgba(91,184,232,.30)'
},
// cyan
{
  top: '#2C1E44',
  bot: '#160E28',
  glow: 'rgba(158,111,232,.30)'
},
// purple
{
  top: '#12332B',
  bot: '#0A1C18',
  glow: 'rgba(63,167,108,.30)'
},
// green
{
  top: '#3A2038',
  bot: '#1E0F1E',
  glow: 'rgba(224,81,155,.30)'
} // pink
];
function randColor(seed) {
  return TET_COLORS[Math.floor((Math.sin(seed * 99.13) * 0.5 + 0.5) * TET_COLORS.length) % TET_COLORS.length];
}

/* decorative tetris-block wall — memoised so it never re-renders mid-game */
const Wall = React.memo(function Wall({
  side,
  n
}) {
  const cells = useMemo(() => Array.from({
    length: n * 2
  }, (_, i) => randColor(i + (side === 'left' ? 7 : 31))), [side, n]);
  return /*#__PURE__*/React.createElement("div", {
    className: 'gm-wall ' + side,
    "aria-hidden": true
  }, cells.map((c, i) => /*#__PURE__*/React.createElement("div", {
    key: i,
    className: "gm-brick",
    style: {
      background: c
    }
  })));
});

/* ════════════════ Intro: home screen → (first time) animated explainer ════════════════ */
/* A stage that shows a mini game board and drives one tutorial beat with an animated finger. */
function ExStage({
  phase
}) {
  const bins = ['חמדנות', 'פחד', 'שפע', 'כעס']; // 0 = correct meaning of GREED
  const CORRECT = 0,
    WRONG = 2;
  const [ltoggle, setLtoggle] = useState(false); // move-scene: which arrow the finger presses
  useEffect(() => {
    if (phase !== 'move') return;
    const t = setInterval(() => setLtoggle(v => !v), 1050);
    return () => clearInterval(t);
  }, [phase]);

  // tower height per phase
  const tower = phase === 'mistake' ? ['#5BB8E8', '#E0519B', '#F2C230', '#7E5BC2', '#3FA76C'] : phase === 'correct' ? ['#5BB8E8', '#E0519B', '#F2C230'] : ['#5BB8E8', '#E0519B'];
  const towerCol = WRONG;
  const tileIdx = phase === 'move' ? ltoggle ? 0 : 3 : phase === 'correct' ? CORRECT : phase === 'mistake' ? WRONG : 1;
  const tileState = phase === 'correct' ? 'right' : phase === 'mistake' ? 'wrong' : 'live';
  const handPos = phase === 'move' ? ltoggle ? 'l' : 'r' : 'd';
  return /*#__PURE__*/React.createElement("div", {
    className: 'ex-stage ' + phase
  }, /*#__PURE__*/React.createElement("div", {
    className: "ex-lane"
  }, /*#__PURE__*/React.createElement("div", {
    className: 'ex-danger' + (phase === 'mistake' ? ' hot' : '')
  }), /*#__PURE__*/React.createElement("div", {
    className: 'ex-tile ' + tileState,
    key: phase,
    style: {
      left: `${tileIdx * 25 + 12.5}%`
    }
  }, /*#__PURE__*/React.createElement("span", {
    className: "w"
  }, "GREED"), phase === 'correct' && /*#__PURE__*/React.createElement("span", {
    className: "badge good"
  }, "\u2713"), phase === 'mistake' && /*#__PURE__*/React.createElement("span", {
    className: "badge bad"
  }, "\u2717")), phase === 'speed' && /*#__PURE__*/React.createElement("div", {
    className: "ex-score-pop"
  }, "+320"), phase === 'correct' && /*#__PURE__*/React.createElement("div", {
    className: "ex-burst",
    style: {
      left: `calc(${towerCol * 25}% + 12.5%)`
    }
  }, [0, 1, 2, 3, 4, 5].map(i => /*#__PURE__*/React.createElement("span", {
    key: i,
    className: 'p p' + i
  }))), /*#__PURE__*/React.createElement("div", {
    className: "ex-pile",
    style: {
      left: `calc(${towerCol * 25}% + 5px)`
    }
  }, tower.map((c, i) => /*#__PURE__*/React.createElement("div", {
    key: phase + '-' + i,
    className: 'ex-brick' + (phase === 'mistake' && i === tower.length - 1 ? ' top new' : '') + (phase === 'correct' && i === tower.length - 1 ? ' shatter' : ''),
    style: {
      background: c
    }
  }))), /*#__PURE__*/React.createElement("div", {
    className: "ex-bins"
  }, bins.map((b, i) => {
    let cls = 'ex-bin';
    if (phase === 'correct' && i === CORRECT) cls += ' hit';else if (phase === 'mistake' && i === WRONG) cls += ' miss';else if (i === tileIdx) cls += ' target';
    return /*#__PURE__*/React.createElement("div", {
      key: i,
      className: cls
    }, b);
  }))), /*#__PURE__*/React.createElement("div", {
    className: "ex-ctrl"
  }, /*#__PURE__*/React.createElement("span", {
    className: 'ex-arrow l' + (handPos === 'l' ? ' hit' : '')
  }, /*#__PURE__*/React.createElement(Ico.left, null)), /*#__PURE__*/React.createElement("span", {
    className: 'ex-arrow d' + (handPos === 'd' ? ' hit' : '') + (phase === 'speed' ? ' fast' : '')
  }, /*#__PURE__*/React.createElement(Ico.down, null)), /*#__PURE__*/React.createElement("span", {
    className: 'ex-arrow r' + (handPos === 'r' ? ' hit' : '')
  }, /*#__PURE__*/React.createElement(Ico.right, null)), /*#__PURE__*/React.createElement("div", {
    className: 'ex-hand pos-' + handPos + (phase === 'speed' ? ' rapid' : '')
  }, /*#__PURE__*/React.createElement(Ico.hand, null))));
}

/* summary beat — the post-game reward, shown as a mini end-card */
function ExSummary() {
  const rows = [['GREED', 'חמדנות'], ['VANISH', 'להיעלם'], ['SOLEMN', 'רציני']];
  return /*#__PURE__*/React.createElement("div", {
    className: "ex-summary"
  }, /*#__PURE__*/React.createElement("div", {
    className: "ex-sum-title"
  }, "\u05D4\u05DE\u05D9\u05DC\u05D9\u05DD \u05E9\u05DC\u05D0 \u05D9\u05D3\u05E2\u05EA", /*#__PURE__*/React.createElement("span", {
    className: "dot"
  }, ".")), /*#__PURE__*/React.createElement("div", {
    className: "ex-sum-list"
  }, rows.map((r, i) => /*#__PURE__*/React.createElement("div", {
    key: i,
    className: "ex-sum-row",
    style: {
      animationDelay: i * 0.15 + 's'
    }
  }, /*#__PURE__*/React.createElement("span", {
    className: "en"
  }, r[0]), /*#__PURE__*/React.createElement("span", {
    className: "he"
  }, r[1])))), /*#__PURE__*/React.createElement("div", {
    className: "ex-sum-actions"
  }, /*#__PURE__*/React.createElement("span", {
    className: "ex-sum-btn share"
  }, /*#__PURE__*/React.createElement(Ico.share, null), "\u05E9\u05D9\u05EA\u05D5\u05E3"), /*#__PURE__*/React.createElement("span", {
    className: "ex-sum-btn again"
  }, /*#__PURE__*/React.createElement(Ico.refresh, null), "\u05E1\u05D9\u05D1\u05D5\u05D1 \u05E2\u05DC \u05D0\u05DC\u05D5")));
}

/* perks & challenges beat — the final tutorial screen */
function ExPerks() {
  const perks = [{
    ic: 'sound',
    t: 'השמעת מילים',
    s: 'לשמוע איך הוגים כל מילה'
  }, {
    ic: 'fifty',
    t: '50 · 50',
    s: 'להסתיר שני פירושים שגויים'
  }, {
    ic: 'rowclear',
    t: 'ניפוץ שורה',
    s: 'נפתח אחרי 50·50 ועוד שלב',
    badge: 'חדש'
  }];
  return /*#__PURE__*/React.createElement("div", {
    className: "ex-perks"
  }, /*#__PURE__*/React.createElement("div", {
    className: "ex-perks-gift"
  }, /*#__PURE__*/React.createElement(Ico.gift, null)), /*#__PURE__*/React.createElement("div", {
    className: "ex-perks-list"
  }, perks.map((p, i) => /*#__PURE__*/React.createElement("div", {
    key: i,
    className: "ex-perk",
    style: {
      animationDelay: i * 0.12 + 's'
    }
  }, /*#__PURE__*/React.createElement("span", {
    className: 'ex-perk-ic ' + p.ic
  }, p.ic === 'fifty' ? /*#__PURE__*/React.createElement("span", {
    className: "fifty-txt"
  }, "50", /*#__PURE__*/React.createElement("br", null), "50") : Ico[p.ic]()), /*#__PURE__*/React.createElement("span", {
    className: "ex-perk-tx"
  }, /*#__PURE__*/React.createElement("span", {
    className: "t"
  }, p.t, p.badge && /*#__PURE__*/React.createElement("span", {
    className: "nw"
  }, p.badge)), /*#__PURE__*/React.createElement("span", {
    className: "s"
  }, p.s))))));
}
const EX_STEPS = [{
  key: 'move',
  title: 'מזיזים ובוחרים',
  cap: 'החליקו את המילה עם ◄ ► עד לפירוש הנכון בעברית'
}, {
  key: 'speed',
  title: 'מאיצים וצוברים',
  cap: 'כל לחיצה על ▼ מפילה מהר יותר — ומזניקה את הניקוד'
}, {
  key: 'correct',
  title: 'פירוש נכון = ניפוץ',
  cap: 'נחיתה על הפירוש הנכון מנפצת לבנה מהמגדל'
}, {
  key: 'mistake',
  title: 'טעות = המגדל גדל',
  cap: 'טעות משאירה לבנה. כשהמגדל מגיע לקו האדום — נפסלים'
}, {
  key: 'summary',
  title: 'המילים שלא ידעת',
  cap: 'בסוף מקבלים את רשימת המילים — לשיתוף, או לסיבוב נוסף שמתמקד בהן'
}, {
  key: 'perks',
  title: "צ'ופרים ואתגרים",
  cap: 'ככל שתתקדמו תקבלו יכולות חדשות — והקצב שבו צריך לענות מואץ'
}];
function Explainer({
  onNext,
  muted,
  toggleMute,
  toggleFs
}) {
  const [step, setStep] = useState(0);
  const [paused, setPaused] = useState(false);
  const last = EX_STEPS.length - 1;
  useEffect(() => {
    if (paused) return;
    const t = setTimeout(() => setStep(s => (s + 1) % EX_STEPS.length), step === last ? 5200 : 4200);
    return () => clearTimeout(t);
  }, [step, paused, last]);
  const go = i => {
    setPaused(true);
    setStep((i + EX_STEPS.length) % EX_STEPS.length);
  };
  const cur = EX_STEPS[step];
  return /*#__PURE__*/React.createElement("div", {
    className: "gm-app"
  }, /*#__PURE__*/React.createElement("div", {
    className: "gm-frame"
  }, /*#__PURE__*/React.createElement("div", {
    className: "gm-intro gm-explainer"
  }, /*#__PURE__*/React.createElement("div", {
    className: "gm-intro-actions"
  }, /*#__PURE__*/React.createElement("button", {
    className: "gm-round-btn",
    onClick: toggleFs,
    title: "\u05DE\u05E1\u05DA \u05DE\u05DC\u05D0"
  }, /*#__PURE__*/React.createElement(Ico.expand, null)), /*#__PURE__*/React.createElement("button", {
    className: "gm-round-btn fifty",
    onClick: toggleMute,
    title: "\u05E1\u05D0\u05D5\u05E0\u05D3"
  }, muted ? /*#__PURE__*/React.createElement(Ico.mute, null) : /*#__PURE__*/React.createElement(Ico.sound, null))), /*#__PURE__*/React.createElement("button", {
    className: "gm-intro-skip",
    onClick: onNext
  }, /*#__PURE__*/React.createElement("span", null, "\u05D3\u05DC\u05D2"), /*#__PURE__*/React.createElement(Ico.go, null)), /*#__PURE__*/React.createElement("div", {
    className: "gm-intro-brand ex-brand"
  }, /*#__PURE__*/React.createElement("img", {
    src: EZ_ICON,
    alt: ""
  }), /*#__PURE__*/React.createElement("span", {
    className: "brand-eazy"
  }, "eazy")), /*#__PURE__*/React.createElement("div", {
    className: "ex-visual",
    key: step
  }, cur.key === 'summary' ? /*#__PURE__*/React.createElement(ExSummary, null) : cur.key === 'perks' ? /*#__PURE__*/React.createElement(ExPerks, null) : /*#__PURE__*/React.createElement(ExStage, {
    phase: cur.key
  })), /*#__PURE__*/React.createElement("div", {
    className: "ex-textblock"
  }, /*#__PURE__*/React.createElement("div", {
    className: "ex-step-n"
  }, step + 1, /*#__PURE__*/React.createElement("span", {
    className: "tot"
  }, " / ", EX_STEPS.length)), /*#__PURE__*/React.createElement("div", {
    className: "ex-head"
  }, cur.title), /*#__PURE__*/React.createElement("div", {
    className: "ex-caption"
  }, cur.cap)), /*#__PURE__*/React.createElement("div", {
    className: "ex-dots"
  }, EX_STEPS.map((_, i) => /*#__PURE__*/React.createElement("button", {
    key: i,
    className: 'ex-dot' + (i === step ? ' on' : ''),
    onClick: () => go(i),
    "aria-label": 'שלב ' + (i + 1)
  }))), /*#__PURE__*/React.createElement("div", {
    className: "ex-nav"
  }, /*#__PURE__*/React.createElement("button", {
    className: "ex-nav-btn ghost",
    onClick: () => go(step - 1)
  }, /*#__PURE__*/React.createElement(Ico.right, null)), step === last ? /*#__PURE__*/React.createElement("button", {
    className: "gm-start ex-start",
    onClick: onNext
  }, /*#__PURE__*/React.createElement("span", null, "\u05DE\u05EA\u05D7\u05D9\u05DC\u05D9\u05DD \u05DC\u05E9\u05D7\u05E7"), /*#__PURE__*/React.createElement(Ico.go, null)) : /*#__PURE__*/React.createElement("button", {
    className: "gm-start ex-start",
    onClick: () => go(step + 1)
  }, /*#__PURE__*/React.createElement("span", null, "\u05D4\u05D1\u05D0"), /*#__PURE__*/React.createElement(Ico.left, null)), /*#__PURE__*/React.createElement("button", {
    className: "ex-nav-btn ghost",
    onClick: () => go(step + 1)
  }, /*#__PURE__*/React.createElement(Ico.left, null))))));
}
function MainIntro({
  onStart,
  muted,
  toggleMute,
  toggleFs
}) {
  const rain = useMemo(() => Array.from({
    length: 14
  }, (_, i) => ({
    left: (i * 7.3 + i % 3 * 4) % 96,
    size: 18 + i % 4 * 8,
    dur: 6 + i % 5 * 1.6,
    delay: -(i * 0.9),
    color: randColor(i + 3)
  })), []);
  return /*#__PURE__*/React.createElement("div", {
    className: "gm-app"
  }, /*#__PURE__*/React.createElement("div", {
    className: "gm-frame"
  }, /*#__PURE__*/React.createElement("div", {
    className: "gm-intro"
  }, /*#__PURE__*/React.createElement("div", {
    className: "gm-intro-rain",
    "aria-hidden": true
  }, rain.map((r, i) => /*#__PURE__*/React.createElement("div", {
    key: i,
    className: "tb",
    style: {
      left: r.left + '%',
      width: r.size,
      height: r.size,
      background: r.color,
      animationDuration: r.dur + 's',
      animationDelay: r.delay + 's'
    }
  }))), /*#__PURE__*/React.createElement("div", {
    className: "gm-intro-actions"
  }, /*#__PURE__*/React.createElement("button", {
    className: "gm-round-btn",
    onClick: toggleFs,
    title: "\u05DE\u05E1\u05DA \u05DE\u05DC\u05D0"
  }, /*#__PURE__*/React.createElement(Ico.expand, null)), /*#__PURE__*/React.createElement("button", {
    className: "gm-round-btn fifty",
    onClick: toggleMute,
    title: "\u05E1\u05D0\u05D5\u05E0\u05D3"
  }, muted ? /*#__PURE__*/React.createElement(Ico.mute, null) : /*#__PURE__*/React.createElement(Ico.sound, null))), /*#__PURE__*/React.createElement("button", {
    className: "gm-intro-home",
    title: "\u05DC\u05D0\u05EA\u05E8 ezway",
    onClick: () => {
      try {
        window.top.location.href = 'https://www.ezway.co.il';
      } catch (e) {
        window.open('https://www.ezway.co.il', '_blank');
      }
    }
  }, /*#__PURE__*/React.createElement(Ico.home, null)), /*#__PURE__*/React.createElement("div", {
    className: "gm-intro-inner"
  }, /*#__PURE__*/React.createElement("div", {
    className: "gm-intro-brand"
  }, /*#__PURE__*/React.createElement("img", {
    src: EZ_ICON,
    alt: ""
  }), /*#__PURE__*/React.createElement("span", {
    className: "brand-eazy"
  }, "eazy")), /*#__PURE__*/React.createElement("h1", {
    className: "gm-intro-title"
  }, "\u05D8\u05D8\u05E8\u05D9 \u05DE\u05D9\u05DC\u05D9\u05DD", /*#__PURE__*/React.createElement("span", {
    className: "dot"
  }, "."), /*#__PURE__*/React.createElement("span", {
    className: "en"
  }, "\u05D0\u05E0\u05D2\u05DC\u05D9\u05EA \u05D4\u05D9\u05D0 ", /*#__PURE__*/React.createElement("span", {
    className: "brand-eazy"
  }, "eazy"))), /*#__PURE__*/React.createElement("p", {
    className: "gm-intro-lead"
  }, "\u05DE\u05D9\u05DC\u05D4 \u05D1\u05D0\u05E0\u05D2\u05DC\u05D9\u05EA \u05E0\u05D5\u05E4\u05DC\u05EA \u05DE\u05DC\u05DE\u05E2\u05DC\u05D4. ", /*#__PURE__*/React.createElement("br", {
    className: "m-br"
  }), "\u05D4\u05D6\u05D9\u05D6\u05D5 \u05D0\u05D5\u05EA\u05D4 \u05D0\u05DC \u05D4\u05E4\u05D9\u05E8\u05D5\u05E9 \u05D4\u05E0\u05DB\u05D5\u05DF \u05D1\u05E2\u05D1\u05E8\u05D9\u05EA ", /*#__PURE__*/React.createElement("br", {
    className: "m-br"
  }), "\u05DC\u05E4\u05E0\u05D9 \u05E9\u05D4\u05D9\u05D0 \u05E0\u05D5\u05D7\u05EA\u05EA."), /*#__PURE__*/React.createElement("div", {
    className: "gm-intro-bonus"
  }, /*#__PURE__*/React.createElement("div", {
    className: "gift"
  }, /*#__PURE__*/React.createElement(Ico.gift, null)), /*#__PURE__*/React.createElement("div", {
    className: "bt"
  }, /*#__PURE__*/React.createElement("div", {
    className: "bh"
  }, "\u05D1\u05D5\u05E0\u05D5\u05E1 \u05D1\u05E1\u05D5\u05E3 \u05DB\u05DC \u05DE\u05E9\u05D7\u05E7", /*#__PURE__*/React.createElement("span", {
    className: "dot"
  }, ".")), /*#__PURE__*/React.createElement("div", {
    className: "bs"
  }, "\u05DC\u05E9\u05EA\u05E3, \u05DC\u05D4\u05D3\u05E4\u05D9\u05E1 \u05D0\u05D5 \u05DC\u05E9\u05D7\u05E7 \u05E9\u05D5\u05D1 \u2014 \u05D1\u05D3\u05D2\u05E9 \u05E2\u05DC \u05D4\u05DE\u05D9\u05DC\u05D9\u05DD \u05E9\u05E2\u05D3\u05D9\u05D9\u05DF \u05DC\u05D0 \u05D9\u05D3\u05E2\u05EA.")))), /*#__PURE__*/React.createElement("button", {
    className: "gm-start",
    onClick: onStart
  }, /*#__PURE__*/React.createElement("span", null, "\u05D9\u05D5\u05E6\u05D0\u05D9\u05DD \u05DC\u05D3\u05E8\u05DA"), /*#__PURE__*/React.createElement(Ico.go, null)))));
}
function IntroScreen({
  onStart,
  muted,
  toggleMute,
  toggleFs
}) {
  const [stage, setStage] = useState('home');
  const EXPLAINER_KEY = 'tx-explainer-seen-v1';
  const seen = () => {
    try {
      return localStorage.getItem(EXPLAINER_KEY) === '1';
    } catch (e) {
      return false;
    }
  };
  const begin = () => {
    if (seen()) onStart();else setStage('explainer');
  };
  const finishExplainer = () => {
    try {
      localStorage.setItem(EXPLAINER_KEY, '1');
    } catch (e) {}
    onStart();
  };
  if (stage === 'explainer') return /*#__PURE__*/React.createElement(Explainer, {
    onNext: finishExplainer,
    muted: muted,
    toggleMute: toggleMute,
    toggleFs: toggleFs
  });
  return /*#__PURE__*/React.createElement(MainIntro, {
    onStart: begin,
    muted: muted,
    toggleMute: toggleMute,
    toggleFs: toggleFs
  });
}

/* ════════════════ End screen ════════════════ */
function EndScreen({
  score,
  missedWords,
  onRestart,
  onReviewRound
}) {
  const [note, setNote] = useState(null);
  // merge this round's mistakes into the persistent (per-browser) review list, once.
  const [review, setReview] = useState(() => addReview(missedWords));
  const roundCount = missedWords.length;
  const buildText = () => {
    const lines = review.map(w => `${String(w.en).toUpperCase()} — ${w.he}`).join('\n');
    return `TETRI PSYCHOMETRY · רשימת המילים לחזרה\n\n${lines}\n\nמשחק אנגלית מבית eazy · ezway.co.il`;
  };
  const onShare = async () => {
    const text = buildText();
    try {
      if (navigator.share) {
        await navigator.share({
          title: 'TETRI PSYCHOMETRY',
          text
        });
        return;
      }
    } catch (e) {
      if (e && e.name === 'AbortError') return;
    }
    try {
      await navigator.clipboard.writeText(text);
      setNote('הרשימה הועתקה — אפשר להדביק בכל מקום.');
      setTimeout(() => setNote(null), 2500);
    } catch (e) {
      setNote('לא ניתן לשתף בדפדפן הזה.');
      setTimeout(() => setNote(null), 2500);
    }
  };
  const onPrint = () => {
    try {
      window.print();
    } catch (e) {}
  };
  const onClear = () => {
    clearReview();
    setReview([]);
    setNote('רשימת החזרה נוקתה.');
    setTimeout(() => setNote(null), 2200);
  };
  const today = new Date().toLocaleDateString('he-IL');
  return /*#__PURE__*/React.createElement("div", {
    className: "gm-app"
  }, /*#__PURE__*/React.createElement("div", {
    className: "gm-frame"
  }, /*#__PURE__*/React.createElement("div", {
    className: "gm-end"
  }, /*#__PURE__*/React.createElement("div", {
    className: "gm-end-head"
  }, /*#__PURE__*/React.createElement("button", {
    className: "gm-end-home",
    title: "\u05D0\u05EA\u05E8 eazy",
    onClick: () => {
      try {
        window.top.location.href = 'https://www.ezway.co.il';
      } catch (e) {
        window.open('https://www.ezway.co.il', '_top');
      }
    }
  }, /*#__PURE__*/React.createElement(Ico.home, null)), /*#__PURE__*/React.createElement("div", {
    className: "gm-end-brand"
  }, /*#__PURE__*/React.createElement("img", {
    src: EZ_ICON,
    alt: ""
  }), /*#__PURE__*/React.createElement("span", {
    className: "brand-eazy"
  }, "eazy", /*#__PURE__*/React.createElement("span", {
    style: {
      color: 'var(--tx-orange)'
    }
  }, ".")))), /*#__PURE__*/React.createElement("div", {
    className: "gm-end-top"
  }, /*#__PURE__*/React.createElement("div", {
    className: "gm-end-title"
  }, "\u05E1\u05D5\u05E3 \u05E1\u05D9\u05D1\u05D5\u05D1", /*#__PURE__*/React.createElement("span", {
    className: "dot"
  }, ".")), /*#__PURE__*/React.createElement("div", {
    className: "gm-end-scorechip"
  }, /*#__PURE__*/React.createElement("span", {
    className: "lbl"
  }, "\u05E0\u05D9\u05E7\u05D5\u05D3"), /*#__PURE__*/React.createElement("span", {
    className: "num"
  }, score))), /*#__PURE__*/React.createElement("div", {
    className: "gm-end-listwrap"
  }, review.length > 0 ? /*#__PURE__*/React.createElement(React.Fragment, null, /*#__PURE__*/React.createElement("div", {
    className: "gm-end-eye"
  }, "\u05E8\u05E9\u05D9\u05DE\u05EA \u05D4\u05DE\u05D9\u05DC\u05D9\u05DD \u05DC\u05D7\u05D6\u05E8\u05D4", /*#__PURE__*/React.createElement("span", {
    className: "cnt"
  }, review.length)), /*#__PURE__*/React.createElement("div", {
    className: "gm-end-sub"
  }, roundCount > 0 ? `${roundCount} נוספו בסיבוב הזה · ` : '', "\u05E0\u05E9\u05DE\u05E8 \u05D1\u05D3\u05E4\u05D3\u05E4\u05DF \u05D4\u05D6\u05D4 \u05D5\u05DE\u05EA\u05E2\u05D3\u05DB\u05DF \u05D1\u05DB\u05DC \u05E1\u05D9\u05D1\u05D5\u05D1"), /*#__PURE__*/React.createElement("div", {
    className: "gm-end-list"
  }, review.map((w, i) => /*#__PURE__*/React.createElement("div", {
    key: i,
    className: "gm-end-row"
  }, /*#__PURE__*/React.createElement("span", {
    className: "gm-end-en"
  }, String(w.en).toUpperCase()), /*#__PURE__*/React.createElement("span", {
    className: "gm-end-he"
  }, w.he))))) : /*#__PURE__*/React.createElement("div", {
    className: "gm-end-nomiss"
  }, /*#__PURE__*/React.createElement("span", {
    className: "hi"
  }, "\u05DE\u05D5\u05E9\u05DC\u05DD", /*#__PURE__*/React.createElement("span", {
    style: {
      color: 'var(--tx-orange)'
    }
  }, "!")), /*#__PURE__*/React.createElement("span", {
    className: "lo"
  }, "\u05D0\u05D9\u05DF \u05DE\u05D9\u05DC\u05D9\u05DD \u05DC\u05D7\u05D6\u05E8\u05D4."))), review.length > 0 && /*#__PURE__*/React.createElement(React.Fragment, null, /*#__PURE__*/React.createElement("div", {
    className: "gm-end-actions"
  }, /*#__PURE__*/React.createElement("button", {
    className: "gm-end-tool",
    onClick: onShare
  }, /*#__PURE__*/React.createElement(Ico.share, null), /*#__PURE__*/React.createElement("span", null, "\u05E9\u05D9\u05EA\u05D5\u05E3")), /*#__PURE__*/React.createElement("button", {
    className: "gm-end-tool",
    onClick: onPrint
  }, /*#__PURE__*/React.createElement(Ico.print, null), /*#__PURE__*/React.createElement("span", null, "\u05E9\u05DE\u05D9\u05E8\u05D4 / \u05D4\u05D3\u05E4\u05E1\u05D4"))), /*#__PURE__*/React.createElement("button", {
    className: "gm-end-clear",
    onClick: onClear
  }, "\u05E0\u05D9\u05E7\u05D5\u05D9 \u05E8\u05E9\u05D9\u05DE\u05EA \u05D4\u05D7\u05D6\u05E8\u05D4")), note && /*#__PURE__*/React.createElement("div", {
    className: "gm-end-note"
  }, note), /*#__PURE__*/React.createElement("div", {
    className: "gm-end-cta-row"
  }, review.length > 0 && /*#__PURE__*/React.createElement("button", {
    className: "gm-end-cta review",
    onClick: onReviewRound
  }, /*#__PURE__*/React.createElement("span", null, "\u05E1\u05D9\u05D1\u05D5\u05D1 \u05D8\u05E2\u05D5\u05D9\u05D5\u05EA"), /*#__PURE__*/React.createElement("span", {
    className: "badge"
  }, review.length)), /*#__PURE__*/React.createElement("button", {
    className: "gm-end-cta",
    onClick: onRestart
  }, /*#__PURE__*/React.createElement(Ico.go, null), /*#__PURE__*/React.createElement("span", null, "\u05E1\u05D9\u05D1\u05D5\u05D1 \u05D7\u05D3\u05E9"))), /*#__PURE__*/React.createElement("div", {
    className: "gm-print",
    "aria-hidden": true
  }, /*#__PURE__*/React.createElement("div", {
    className: "p-head"
  }, /*#__PURE__*/React.createElement("div", {
    className: "p-brand"
  }, /*#__PURE__*/React.createElement("img", {
    src: EZ_ICON,
    alt: "eazy"
  }), /*#__PURE__*/React.createElement("span", null, "eazy")), /*#__PURE__*/React.createElement("div", {
    className: "p-meta"
  }, "TETRI PSYCHOMETRY \xB7 ", today)), /*#__PURE__*/React.createElement("h1", {
    className: "p-title"
  }, "\u05E8\u05E9\u05D9\u05DE\u05EA \u05D4\u05DE\u05D9\u05DC\u05D9\u05DD \u05DC\u05D7\u05D6\u05E8\u05D4"), /*#__PURE__*/React.createElement("div", {
    className: "p-score"
  }, review.length, " \u05DE\u05D9\u05DC\u05D9\u05DD"), /*#__PURE__*/React.createElement("table", {
    className: "p-table"
  }, /*#__PURE__*/React.createElement("tbody", null, review.map((w, i) => /*#__PURE__*/React.createElement("tr", {
    key: i
  }, /*#__PURE__*/React.createElement("td", {
    className: "p-num"
  }, i + 1), /*#__PURE__*/React.createElement("td", {
    className: "p-en"
  }, String(w.en).toUpperCase()), /*#__PURE__*/React.createElement("td", {
    className: "p-he"
  }, w.he))))), /*#__PURE__*/React.createElement("div", {
    className: "p-foot"
  }, "\u05DE\u05E9\u05D7\u05E7 \u05D0\u05E0\u05D2\u05DC\u05D9\u05EA \u05E4\u05E1\u05D9\u05DB\u05D5\u05DE\u05D8\u05E8\u05D9 \u05DE\u05D1\u05D9\u05EA eazy \xB7 ezway.co.il")))));
}

/* ════════════════ Main game ════════════════ */
const COLS = 4;
const ROWS = 9; // playable rows above the bins; overflow past the top = game over
const MAXSTACK = ROWS - 1; // a column this tall reaches the start height
function TetriGame() {
  const [started, setStarted] = useState(false);
  const [dict, setDict] = useState(null);
  const [used, setUsed] = useState([]);
  const [missed, setMissed] = useState([]);
  const [question, setQuestion] = useState(null);
  const [stacks, setStacks] = useState(() => [[], [], [], []]); // junk bricks left by mistakes
  const [score, setScore] = useState(0);
  const [streak, setStreak] = useState(0);
  const [col, setCol] = useState(1);
  const [phase, setPhase] = useState('falling'); // falling | resolving | over
  const [binFx, setBinFx] = useState({}); // {idx:'hit'|'miss'|'reveal'}
  const [pieceFx, setPieceFx] = useState(''); // ''|'correct'|'wrong'
  const [dimmed, setDimmed] = useState(() => new Set());
  const [fiftyUsed, setFiftyUsed] = useState(false);
  const [rowClearUsed, setRowClearUsed] = useState(false);
  const [toast, setToast] = useState(null);
  const [missBanner, setMissBanner] = useState(null); // {en,he} shown briefly on a mistake (flow mode)
  const [studyCard, setStudyCard] = useState(null); // {en,he,dictIdx} — study mode: waits for "next"
  const mistakeCountRef = useRef(0);
  const studyModeRef = useRef(null); // null | 'flow' | 'study'
  const [gate, setGate] = useState(null); // pausing modal: {kind:'level',sub} | {kind:'audio'}
  const [correctCount, setCorrectCount] = useState(0);
  const [audioEnabled, setAudioEnabled] = useState(false);
  const [audioOffered, setAudioOffered] = useState(false); // once accepted, show a dedicated word-reading toggle
  const [pool, setPool] = useState(null); // correct-word pool: full dict, or the mistakes list
  const [muted, setMuted] = useState(Sound.muted);
  const pieceRef = useRef(null);
  const rafRef = useRef(0);
  const sim = useRef({
    fall: 0,
    col: 1,
    locked: true,
    soft: false,
    startT: 0
  });
  const stacksRef = useRef([[], [], [], []]);
  const pausedRef = useRef(false);
  const audioPromptedRef = useRef(false);
  const spokenForRef = useRef(null);
  const lastBonusRef = useRef(0);
  const prevLevelRef = useRef(1);
  useEffect(() => {
    pausedRef.current = !!gate;
  }, [gate]);
  const setStacksBoth = useCallback(updater => {
    setStacks(prev => {
      const next = updater(prev);
      stacksRef.current = next;
      return next;
    });
  }, []);
  const level = correctCount < 15 ? 1 : 2 + Math.floor((correctCount - 15) / 20);
  const speedMult = Math.pow(1.02, level - 1); // pace +2% each level
  const fallDur = Math.max(2.0, 6.2 / speedMult); // seconds top→bottom
  const basePts = 200 + (level - 1) * 80;
  const fiftyUnlocked = correctCount >= 15; // unlocked at 15 correct
  const rowClearUnlocked = correctCount >= 35; // unlocked at 35 correct
  // well theme: default (dark) for levels 1–2, then cycle the approved tints from level 3
  const wellStyle = level >= 3 ? (t => ({
    '--well-top': t.top,
    '--well-bot': t.bot,
    '--well-glow': t.glow,
    '--well-wm': 0.16
  }))(LEVEL_THEMES[(level - 3) % LEVEL_THEMES.length]) : undefined;

  /* ── load dictionary ── */
  useEffect(() => {
    if (window.GAME_DICTIONARY && window.GAME_DICTIONARY.length >= 4) {
      setDict(window.GAME_DICTIONARY);
      setPool(p => p || window.GAME_DICTIONARY);
    }
  }, []);

  /* ── draw a question whenever needed ── */
  useEffect(() => {
    if (!dict || !started || phase === 'over') return;
    if (question) return;
    const src = pool && pool.length > 0 ? pool : dict;
    const avail = src.map((_, i) => i).filter(i => !used.includes(i));
    if (avail.length === 0) {
      setUsed([]);
      return;
    }
    const idx = avail[Math.random() * avail.length | 0];
    const q = buildQuestion(src[idx], dict, idx);
    setQuestion(q);
    // always spawn from the second column from the right (index 2, field is LTR)
    const startCol = 2;
    setCol(startCol);
    setDimmed(new Set());
    setPieceFx('');
    setBinFx({});
    setMissBanner(null);
    spokenForRef.current = null;
    sim.current = {
      fall: 0,
      shown: 0,
      col: startCol,
      locked: false,
      soft: false,
      startT: performance.now()
    };
    setPhase('falling');
  }, [dict, started, question, used, phase, pool]);

  /* ── level-up → confetti celebration + refresh power-ups ── */
  const COMPLIMENTS = ['כל הכבוד!', 'מדהים!', 'אלוף/ה!', 'ממשיכים חזק!', 'מרשים ביותר!', 'וואו, איזה קצב!'];
  useEffect(() => {
    if (level > prevLevelRef.current) {
      prevLevelRef.current = level;
      Sound.play('levelup');
      // refresh the power-ups on every level-up
      setFiftyUsed(false);
      setRowClearUsed(false);
      const compliment = COMPLIMENTS[(level - 2) % COMPLIMENTS.length] || 'כל הכבוד!';
      let unlock = null;
      if (level === 2) unlock = {
        ic: 'fifty',
        t: 'נפתח לך גלגל הצלה 50 · 50'
      };else if (level === 3) unlock = {
        ic: 'rowclear',
        t: 'נפתח לך ניפוץ שורה'
      };
      const sub = `הקצב עולה ב-2% · +${basePts} לכל תשובה נכונה`;
      setGate(g => g ? g : {
        kind: 'level',
        level,
        compliment,
        unlock,
        sub
      });
    } else {
      prevLevelRef.current = Math.max(prevLevelRef.current, level);
    }
  }, [level, basePts]);

  /* ── after 5 correct answers, offer word audio (one-time) ── */
  useEffect(() => {
    if (correctCount >= 5 && !audioPromptedRef.current) {
      audioPromptedRef.current = true;
      setGate(g => g ? g : {
        kind: 'audio'
      });
    }
  }, [correctCount]);

  /* ── speak the English word via the browser (content audio, not SFX) ── */
  const speakWord = useCallback(text => {
    if (!text) return;
    try {
      const s = window.speechSynthesis;
      if (!s) return;
      s.cancel();
      const u = new SpeechSynthesisUtterance(String(text));
      u.lang = 'en-US';
      u.rate = 0.85;
      u.pitch = 1;
      u.volume = 1;
      const voices = s.getVoices ? s.getVoices() : [];
      const en = voices.find(v => /^en[-_]/i.test(v.lang)) || voices.find(v => /english/i.test(v.name));
      if (en) u.voice = en;
      s.speak(u);
    } catch (e) {}
  }, []);

  /* auto-speak each new word ONCE per turn — controlled ONLY by the word-reading toggle,
     independent of the SFX mute button */
  useEffect(() => {
    if (!audioEnabled || !started || phase === 'over' || gate || !question?.en) return;
    if (spokenForRef.current === question.dictIdx) return;
    const t = setTimeout(() => {
      speakWord(question.en);
      spokenForRef.current = question.dictIdx;
    }, 320);
    return () => clearTimeout(t);
  }, [audioEnabled, started, phase, gate, question?.en, question?.dictIdx, speakWord]);

  /* ── falling loop (rAF, drives the piece DOM directly) ── */
  useEffect(() => {
    if (!started || !question || phase !== 'falling') return;
    let last = performance.now();
    const tick = now => {
      const dt = Math.min(0.05, (now - last) / 1000);
      last = now;
      const s = sim.current;
      if (!s.locked && !pausedRef.current) {
        const v = 1 / fallDur * (s.soft ? 5 : 1);
        s.fall = Math.min(1, s.fall + v * dt);
        const stackLen = stacksRef.current[s.col].length;
        const rest = Math.max(0, (ROWS - 1 - stackLen) / (ROWS - 1)); // floor for this column
        const shown = Math.min(s.fall, rest);
        s.shown = shown;
        if (pieceRef.current) pieceRef.current.style.setProperty('--fall', shown.toFixed(4));
        if (s.fall >= rest) {
          s.fall = rest;
          s.shown = rest;
          s.locked = true;
          resolveAt(s.col);
          return;
        }
      }
      rafRef.current = requestAnimationFrame(tick);
    };
    rafRef.current = requestAnimationFrame(tick);
    return () => cancelAnimationFrame(rafRef.current);
  }, [started, question, phase, fallDur]);
  const move = useCallback(dir => {
    if (phase !== 'falling' || sim.current.locked || pausedRef.current) return;
    setCol(prev => {
      let c = Math.max(0, Math.min(3, prev + dir));
      while (dimmed.has(c) && c >= 0 && c <= 3) {
        c += dir;
      }
      if (c < 0 || c > 3 || dimmed.has(c)) {
        const allow = [0, 1, 2, 3].filter(x => !dimmed.has(x));
        c = allow.length ? allow.reduce((b, x) => Math.abs(x - prev) < Math.abs(b - prev) ? x : b, allow[0]) : prev;
      }
      // can't slide UNDER a pile taller than the piece's current height (Tetris collision)
      const restTarget = (ROWS - 1 - stacksRef.current[c].length) / (ROWS - 1);
      if (restTarget < sim.current.fall - 0.001) return prev;
      if (c !== prev) {
        sim.current.col = c;
        Sound.play('move');
      }
      return c;
    });
  }, [phase, dimmed]);
  const softDrop = useCallback(() => {
    if (phase !== 'falling' || sim.current.locked || pausedRef.current) return;
    sim.current.soft = true; // hold = keep accelerating
    sim.current.fall = Math.min(0.999, sim.current.fall + 0.05); // each tap nudges it down
    if (pieceRef.current) {
      const rest = (ROWS - 1 - stacksRef.current[sim.current.col].length) / (ROWS - 1);
      const shown = Math.min(sim.current.fall, rest);
      sim.current.shown = shown;
      pieceRef.current.style.setProperty('--fall', shown.toFixed(4));
    }
    Sound.play('move');
  }, [phase]);
  const softRelease = useCallback(() => {
    if (sim.current) sim.current.soft = false;
  }, []);

  /* ── resolve a landing ── */
  const resolveAt = useCallback(c => {
    setPhase('resolving');
    const q = question;
    if (!q) return;
    const correctCol = q.options.indexOf(q.he);
    const correct = c === correctCol;
    if (pieceRef.current) pieceRef.current.style.setProperty('--col', c);
    if (correct) {
      const elapsed = (performance.now() - sim.current.startT) / 1000;
      const speedMult = Math.max(1, Math.min(2, 2 - elapsed / Math.max(1, fallDur)));
      const ns = streak + 1;
      const now = Date.now();
      const cooldown = now - lastBonusRef.current >= 4 * 60 * 1000;
      let comboMult = 1,
        comboBonus = 0,
        comboLabel = null;
      if (ns >= 5 && ns % 5 === 0 && cooldown) {
        if (ns >= 20) {
          comboMult = 3;
          comboLabel = `רצף ${ns} ✦ ×3`;
        } else if (ns >= 10) {
          comboMult = 2;
          comboLabel = `רצף ${ns} ✦ ×2`;
        } else {
          comboBonus = 400;
          comboLabel = `רצף ${ns} ✦ +400`;
        }
        lastBonusRef.current = now;
      }
      const pts = Math.round(basePts * speedMult * comboMult) + comboBonus;
      setScore(s => s + pts);
      setStreak(ns);
      setCorrectCount(n => n + 1);
      setPieceFx('correct');
      setBinFx({
        [c]: 'hit'
      });
      // relief: a correct answer clears one brick off the tallest pile
      setStacksBoth(prev => {
        let ti = -1,
          max = 0;
        prev.forEach((s, i) => {
          if (s.length > max) {
            max = s.length;
            ti = i;
          }
        });
        if (ti < 0) return prev;
        const n = prev.map(a => a.slice());
        n[ti].pop();
        return n;
      });
      Sound.play(comboLabel ? 'streak' : 'hit');
      setToast(comboLabel ? {
        kind: 'streak',
        text: `${comboLabel} · +${pts}`
      } : {
        kind: 'win',
        text: `${speedMult >= 1.6 ? 'מהיר! ' : ''}+${pts}`
      });
      setTimeout(() => setToast(null), 1700);
      setTimeout(() => advance(q.dictIdx), 900);
    } else {
      setStreak(0);
      setPieceFx('wrong');
      setBinFx({
        [c]: 'miss',
        [correctCol]: 'reveal'
      });
      setMissed(m => m.some(w => String(w.en).toLowerCase() === String(q.en).toLowerCase()) ? m : [...m, {
        en: q.en,
        he: q.he
      }]);
      // a mistake leaves a brick behind in that column — Tetris-style.
      // compute overflow SYNCHRONOUSLY from the ref (the state updater runs later).
      const over = stacksRef.current[c].length + 1 >= MAXSTACK;
      setStacksBoth(prev => {
        const n = prev.map(a => a.slice());
        n[c] = [...n[c], randColor(Date.now() + c * 7)];
        return n;
      });
      Sound.play(over ? 'gameover' : 'miss');
      if (over) {
        setTimeout(() => setPhase('over'), 1700);
        return;
      }
      const isFirstMiss = mistakeCountRef.current === 0;
      mistakeCountRef.current++;
      if (isFirstMiss) {
        // first mistake ever → let the player choose how to handle mistakes from now on
        setGate({
          kind: 'firstmiss',
          en: String(q.en).toUpperCase(),
          he: q.he,
          dictIdx: q.dictIdx
        });
      } else if (studyModeRef.current === 'study') {
        // study mode → hold on the word until the player taps "next"
        setStudyCard({
          en: String(q.en).toUpperCase(),
          he: q.he,
          dictIdx: q.dictIdx
        });
      } else {
        // flow mode → brief banner, auto-advance
        setMissBanner({
          en: String(q.en).toUpperCase(),
          he: q.he
        });
        setTimeout(() => advance(q.dictIdx), 2000);
      }
    }
  }, [question, streak, basePts, fallDur, setStacksBoth]);
  const advance = useCallback(dictIdx => {
    setUsed(u => [...u, dictIdx]);
    setQuestion(null); // triggers next draw
  }, []);

  /* ── 50/50 ── */
  const useFifty = useCallback(() => {
    if (fiftyUsed || !fiftyUnlocked || phase !== 'falling' || !question) return;
    const correctCol = question.options.indexOf(question.he);
    const wrongs = [0, 1, 2, 3].filter(i => i !== correctCol);
    setDimmed(new Set(shuffle(wrongs).slice(0, 2)));
    setFiftyUsed(true);
    Sound.play('fifty');
  }, [fiftyUsed, fiftyUnlocked, phase, question]);

  /* ── ניפוץ שורה: clear the bottom row — removes one brick from every stacked column ── */
  const useRowClear = useCallback(() => {
    if (rowClearUsed || !rowClearUnlocked || phase !== 'falling') return;
    const any = stacksRef.current.some(s => s.length > 0);
    if (!any) return;
    setStacksBoth(prev => prev.map(col => col.slice(0, Math.max(0, col.length - 1))));
    setRowClearUsed(true);
    Sound.play('hit');
    setToast({
      kind: 'streak',
      text: 'ניפוץ שורה ✦ המגדל התקצר'
    });
    setTimeout(() => setToast(null), 1500);
  }, [rowClearUsed, rowClearUnlocked, phase, setStacksBoth]);

  /* ── keyboard ── */
  useEffect(() => {
    const onKey = e => {
      if (!started) return;
      if (e.key === 'ArrowLeft') {
        e.preventDefault();
        move(-1);
      } else if (e.key === 'ArrowRight') {
        e.preventDefault();
        move(1);
      } else if (e.key === 'ArrowDown' || e.key === ' ') {
        e.preventDefault();
        softDrop();
      }
    };
    const onUp = e => {
      if (e.key === 'ArrowDown' || e.key === ' ') softRelease();
    };
    window.addEventListener('keydown', onKey);
    window.addEventListener('keyup', onUp);
    return () => {
      window.removeEventListener('keydown', onKey);
      window.removeEventListener('keyup', onUp);
    };
  }, [started, move, softDrop, softRelease]);
  const toggleMute = useCallback(() => {
    const n = !Sound.muted;
    Sound.setMuted(n);
    setMuted(n);
  }, []);
  const toggleRead = useCallback(() => {
    setAudioEnabled(v => {
      const n = !v;
      if (!n) {
        try {
          window.speechSynthesis?.cancel();
        } catch (e) {}
      }
      return n;
    });
  }, []);
  const toggleFs = useCallback(() => {
    try {
      const t = window.frameElement ? window.frameElement : document.documentElement;
      const d = window.frameElement ? window.parent.document : document;
      const fs = d.fullscreenElement || d.webkitFullscreenElement;
      if (!fs) {
        const r = t.requestFullscreen || t.webkitRequestFullscreen;
        if (r) {
          const p = r.call(t);
          if (p && p.then) p.then(() => {
            try {
              screen.orientation?.lock?.('portrait').catch(() => {});
            } catch (e) {}
          }).catch(() => {});
        }
      } else {
        const x = d.exitFullscreen || d.webkitExitFullscreen;
        if (x) x.call(d);
      }
    } catch (e) {}
  }, []);
  const start = useCallback(() => {
    Sound.init();
    setStarted(true);
    // prime SpeechSynthesis on the user gesture so later auto-speaks are allowed (iOS)
    try {
      const s = window.speechSynthesis;
      if (s) {
        const p = new SpeechSynthesisUtterance(' ');
        p.volume = 0;
        s.speak(p);
        s.getVoices?.();
      }
    } catch (e) {}
  }, []);
  const resetRound = useCallback(nextPool => {
    setPool(nextPool);
    setUsed([]);
    setMissed([]);
    setScore(0);
    setStreak(0);
    setCorrectCount(0);
    setStacks([[], [], [], []]);
    stacksRef.current = [[], [], [], []];
    setQuestion(null);
    setPhase('falling');
    setFiftyUsed(false);
    setDimmed(new Set());
    setGate(null);
    setAudioEnabled(false);
    setAudioOffered(false);
    audioPromptedRef.current = false;
    setRowClearUsed(false);
    setStudyCard(null);
    setMissBanner(null);
    mistakeCountRef.current = 0;
    studyModeRef.current = null;
    prevLevelRef.current = 1;
    lastBonusRef.current = 0;
  }, []);
  const restart = useCallback(() => {
    resetRound(dict);
  }, [resetRound, dict]);
  const goHome = useCallback(() => {
    resetRound(dict);
    setStarted(false);
  }, [resetRound, dict]);
  const reviewRound = useCallback(() => {
    const words = getReview();
    if (words.length < 1) return;
    resetRound(words);
  }, [resetRound]);

  /* ════════ render ════════ */
  if (!started) return /*#__PURE__*/React.createElement(IntroScreen, {
    onStart: start,
    muted: muted,
    toggleMute: toggleMute,
    toggleFs: toggleFs
  });
  if (phase === 'over') {
    return /*#__PURE__*/React.createElement(EndScreen, {
      score: score,
      missedWords: missed,
      onRestart: restart,
      onReviewRound: reviewRound
    });
  }
  if (!dict || !question) {
    return /*#__PURE__*/React.createElement("div", {
      className: "gm-app"
    }, /*#__PURE__*/React.createElement("div", {
      className: "gm-frame",
      style: {
        alignItems: 'center',
        justifyContent: 'center'
      }
    }, /*#__PURE__*/React.createElement("div", {
      style: {
        color: '#fff',
        fontFamily: 'var(--font-body)'
      }
    }, "\u05D8\u05D5\u05E2\u05DF\u2026")));
  }
  const correctCol = question.options.indexOf(question.he);
  return /*#__PURE__*/React.createElement("div", {
    className: "gm-app"
  }, /*#__PURE__*/React.createElement("div", {
    className: "gm-frame"
  }, /*#__PURE__*/React.createElement("div", {
    className: "gm-top"
  }, /*#__PURE__*/React.createElement("div", {
    className: "gm-top-group"
  }, /*#__PURE__*/React.createElement("button", {
    className: "gm-round-btn",
    onClick: toggleMute,
    title: "\u05E1\u05D0\u05D5\u05E0\u05D3"
  }, muted ? /*#__PURE__*/React.createElement(Ico.mute, null) : /*#__PURE__*/React.createElement(Ico.sound, null)), audioOffered && /*#__PURE__*/React.createElement("button", {
    className: 'gm-round-btn read' + (audioEnabled ? '' : ' off'),
    onClick: toggleRead,
    title: "\u05D4\u05E7\u05E8\u05D0\u05EA \u05DE\u05D9\u05DC\u05D9\u05DD"
  }, audioEnabled ? /*#__PURE__*/React.createElement(Ico.readaloud, null) : /*#__PURE__*/React.createElement(Ico.readoff, null)), fiftyUnlocked && /*#__PURE__*/React.createElement("button", {
    className: 'gm-round-btn fifty' + (fiftyUsed ? ' used' : ''),
    onClick: useFifty,
    title: "50/50",
    disabled: fiftyUsed
  }, /*#__PURE__*/React.createElement("span", {
    className: "ft"
  }, "50", /*#__PURE__*/React.createElement("br", null), "50")), rowClearUnlocked && /*#__PURE__*/React.createElement("button", {
    className: 'gm-round-btn rowclear' + (rowClearUsed ? ' used' : ''),
    onClick: useRowClear,
    title: "\u05E0\u05D9\u05E4\u05D5\u05E5 \u05E9\u05D5\u05E8\u05D4",
    disabled: rowClearUsed
  }, /*#__PURE__*/React.createElement(Ico.rowclear, null))), /*#__PURE__*/React.createElement("div", {
    className: "gm-level-chip"
  }, /*#__PURE__*/React.createElement("span", {
    className: "lv"
  }, "\u05E9\u05DC\u05D1 ", /*#__PURE__*/React.createElement("b", null, level))), /*#__PURE__*/React.createElement("div", {
    className: "gm-top-group"
  }, /*#__PURE__*/React.createElement("button", {
    className: "gm-round-btn mail",
    title: "\u05E6\u05E8\u05D5 \u05E7\u05E9\u05E8",
    onClick: () => {
      try {
        window.top.location.href = 'https://www.ezway.co.il/contact/';
      } catch (e) {
        window.open('https://www.ezway.co.il/contact/', '_blank');
      }
    }
  }, /*#__PURE__*/React.createElement(Ico.mail, null)), /*#__PURE__*/React.createElement("button", {
    className: "gm-round-btn",
    onClick: toggleFs,
    title: "\u05DE\u05E1\u05DA \u05DE\u05DC\u05D0"
  }, /*#__PURE__*/React.createElement(Ico.expand, null)))), /*#__PURE__*/React.createElement("div", {
    className: "gm-well",
    style: wellStyle
  }, /*#__PURE__*/React.createElement(Wall, {
    side: "left",
    n: 14
  }), /*#__PURE__*/React.createElement(Wall, {
    side: "right",
    n: 14
  }), /*#__PURE__*/React.createElement("div", {
    className: "gm-field"
  }, /*#__PURE__*/React.createElement("div", {
    className: "gm-dangerline"
  }), stacks.map((colBricks, c) => colBricks.map((color, k) => /*#__PURE__*/React.createElement("div", {
    key: c + '-' + k,
    className: 'gm-stackbrick' + (k >= MAXSTACK - 2 ? ' danger' : ''),
    style: {
      '--col': c,
      '--k': k,
      background: color
    }
  }))), /*#__PURE__*/React.createElement("div", {
    className: "gm-ghost",
    style: {
      '--col': col
    }
  }), /*#__PURE__*/React.createElement("div", {
    ref: pieceRef,
    className: 'gm-piece ' + pieceFx + (question.en.length > 11 ? ' twoline' : ''),
    style: {
      '--col': col,
      '--cx': col * 25 + 12.5 + '%',
      '--fall': sim.current.shown || 0
    }
  }, question.en.toUpperCase()), /*#__PURE__*/React.createElement("div", {
    className: "gm-bins"
  }, question.options.map((opt, i) => {
    let cls = 'gm-bin';
    if (binFx[i]) cls += ' ' + binFx[i];
    if (dimmed.has(i)) cls += ' dim';else if (phase === 'falling' && i === col) cls += ' target';
    return /*#__PURE__*/React.createElement("div", {
      key: i,
      className: cls
    }, opt);
  }))), toast && /*#__PURE__*/React.createElement("div", {
    className: 'gm-toast ' + toast.kind
  }, toast.text), missBanner && /*#__PURE__*/React.createElement("div", {
    className: "gm-missbanner"
  }, /*#__PURE__*/React.createElement("div", {
    className: "mb-word"
  }, /*#__PURE__*/React.createElement("span", {
    className: "en"
  }, missBanner.en), /*#__PURE__*/React.createElement("span", {
    className: "sep"
  }, "="), /*#__PURE__*/React.createElement("span", {
    className: "he"
  }, missBanner.he)), /*#__PURE__*/React.createElement("div", {
    className: "mb-note"
  }, "\u05D4\u05DE\u05D9\u05DC\u05D4 \u05EA\u05D5\u05E4\u05D9\u05E2 \u05D1\u05E1\u05D9\u05DB\u05D5\u05DD \u05D1\u05E1\u05D5\u05E3 \u05D4\u05DE\u05E9\u05D7\u05E7")), gate && /*#__PURE__*/React.createElement("div", {
    className: "gm-levelup"
  }, gate.kind === 'level' ? /*#__PURE__*/React.createElement(React.Fragment, null, /*#__PURE__*/React.createElement("div", {
    className: "gm-confetti",
    "aria-hidden": true
  }, Array.from({
    length: 28
  }).map((_, i) => /*#__PURE__*/React.createElement("span", {
    key: i,
    className: "cf",
    style: {
      left: (i * 3.4 + i % 5 * 2) % 100 + '%',
      background: TET_COLORS[i % TET_COLORS.length],
      animationDelay: -(i % 9) * 0.13 + 's',
      animationDuration: 2.4 + i % 4 * 0.5 + 's',
      transform: `rotate(${i * 40}deg)`
    }
  }))), /*#__PURE__*/React.createElement("div", {
    className: "gm-levelup-eyebrow"
  }, gate.compliment), /*#__PURE__*/React.createElement("div", {
    className: "gm-levelup-title"
  }, "\u05E9\u05DC\u05D1 ", gate.level, /*#__PURE__*/React.createElement("span", {
    className: "dot"
  }, "!")), gate.unlock && /*#__PURE__*/React.createElement("div", {
    className: 'gm-levelup-unlock ' + gate.unlock.ic
  }, /*#__PURE__*/React.createElement("span", {
    className: "ul-ic"
  }, gate.unlock.ic === 'fifty' ? /*#__PURE__*/React.createElement("span", {
    className: "fifty-txt"
  }, "50", /*#__PURE__*/React.createElement("br", null), "50") : Ico.rowclear()), /*#__PURE__*/React.createElement("span", {
    className: "ul-t"
  }, gate.unlock.t)), /*#__PURE__*/React.createElement("div", {
    className: "gm-levelup-sub"
  }, gate.sub), /*#__PURE__*/React.createElement("div", {
    className: "gm-levelup-btnrow"
  }, /*#__PURE__*/React.createElement("button", {
    className: "gm-levelup-cta",
    onClick: () => setGate(null)
  }, "\u05DE\u05DE\u05E9\u05D9\u05DB\u05D9\u05DD", /*#__PURE__*/React.createElement("span", {
    className: "dot"
  }, ".")))) : gate.kind === 'firstmiss' ? /*#__PURE__*/React.createElement(React.Fragment, null, /*#__PURE__*/React.createElement("div", {
    className: "gm-levelup-title"
  }, "\u05DE\u05D4 \u05D4\u05D4\u05E2\u05D3\u05E4\u05D4 \u05E9\u05DC\u05DA \u05DB\u05E9\u05D8\u05E2\u05D9\u05EA", /*#__PURE__*/React.createElement("span", {
    className: "dot"
  }, "?")), /*#__PURE__*/React.createElement("div", {
    className: "gm-missreveal"
  }, /*#__PURE__*/React.createElement("span", {
    className: "en"
  }, gate.en), /*#__PURE__*/React.createElement("span", {
    className: "sep"
  }, "="), /*#__PURE__*/React.createElement("span", {
    className: "he"
  }, gate.he)), /*#__PURE__*/React.createElement("div", {
    className: "gm-levelup-sub"
  }, "\u05D1\u05DB\u05DC \u05D8\u05E2\u05D5\u05EA \u05DC\u05E2\u05E6\u05D5\u05E8 \u05DC\u05D4\u05EA\u05E2\u05DE\u05E7 \u05D1\u05DE\u05D9\u05DC\u05D4 \u05D5\u05D0\u05D7\u05E8\u05D9 \u05D6\u05D4 \u05DC\u05DC\u05D7\u05D5\u05E5 \u05D4\u05D1\u05D0, \u05D0\u05D5 \u05E9\u05DE\u05E1\u05E4\u05D9\u05E7 \u05DC\u05DA \u05D4\u05E6\u05E6\u05D4 \u05D6\u05E8\u05D9\u05D6\u05D4 \u05D1\u05EA\u05E9\u05D5\u05D1\u05D4 \u05D4\u05E0\u05DB\u05D5\u05E0\u05D4 \u05D5\u05D4\u05DE\u05E9\u05DA \u05D0\u05D5\u05D8\u05D5\u05DE\u05D8\u05D9 \u05DC\u05E9\u05D0\u05DC\u05D4 \u05D4\u05D1\u05D0\u05D4? \u05D1\u05DB\u05DC \u05DE\u05E7\u05E8\u05D4 \u05DB\u05DC \u05D4\u05E9\u05D2\u05D9\u05D0\u05D5\u05EA \u05DE\u05E8\u05D5\u05DB\u05D6\u05D5\u05EA \u05D1\u05E1\u05D5\u05E3 \u05D4\u05DE\u05E9\u05D7\u05E7 \u05DC\u05E6\u05E4\u05D9\u05D4/\u05E9\u05D9\u05EA\u05D5\u05E3/\u05E1\u05D9\u05D1\u05D5\u05D1 \u05DE\u05E8\u05D5\u05DB\u05D6"), /*#__PURE__*/React.createElement("div", {
    className: "gm-levelup-btnrow col"
  }, /*#__PURE__*/React.createElement("button", {
    className: "gm-levelup-cta purple",
    onClick: () => {
      studyModeRef.current = 'study';
      setStudyCard({
        en: gate.en,
        he: gate.he,
        dictIdx: gate.dictIdx
      });
      setGate(null);
    }
  }, "\u05DC\u05E2\u05E6\u05D5\u05E8 \u05DC\u05D4\u05EA\u05E2\u05DE\u05E7"), /*#__PURE__*/React.createElement("button", {
    className: "gm-levelup-cta green",
    onClick: () => {
      studyModeRef.current = 'flow';
      const d = gate.dictIdx;
      setGate(null);
      advance(d);
    }
  }, "\u05DC\u05D4\u05DE\u05E9\u05D9\u05DA \u05D0\u05D5\u05D8\u05D5\u05DE\u05D8\u05D9\u05EA"))) : /*#__PURE__*/React.createElement(React.Fragment, null, /*#__PURE__*/React.createElement("div", {
    className: "gm-levelup-title"
  }, "\u05DC\u05E9\u05DE\u05D5\u05E2 \u05D0\u05EA \u05D4\u05DE\u05D9\u05DC\u05D4", /*#__PURE__*/React.createElement("span", {
    className: "dot"
  }, "?")), /*#__PURE__*/React.createElement("div", {
    className: "gm-levelup-sub"
  }, "\u05EA\u05E8\u05E6\u05D5 \u05E9\u05DE\u05E2\u05DB\u05E9\u05D9\u05D5 \u05E0\u05E9\u05DE\u05D9\u05E2 \u05D0\u05D9\u05DA \u05DB\u05DC \u05DE\u05D9\u05DC\u05D4 \u05E0\u05E9\u05DE\u05E2\u05EA \u05D1\u05D0\u05E0\u05D2\u05DC\u05D9\u05EA?"), /*#__PURE__*/React.createElement("div", {
    className: "gm-levelup-btnrow"
  }, /*#__PURE__*/React.createElement("button", {
    className: "gm-levelup-cta",
    onClick: () => {
      setAudioEnabled(true);
      setAudioOffered(true);
      setGate(null);
    }
  }, "\u05DB\u05DF, \u05DC\u05D4\u05E9\u05DE\u05D9\u05E2"), /*#__PURE__*/React.createElement("button", {
    className: "gm-levelup-cta secondary",
    onClick: () => {
      setAudioEnabled(false);
      setAudioOffered(true);
      setGate(null);
    }
  }, "\u05DC\u05D0, \u05EA\u05D5\u05D3\u05D4")), /*#__PURE__*/React.createElement("div", {
    className: "gm-levelup-note"
  }, "\u05D0\u05E4\u05E9\u05E8 \u05DC\u05D4\u05D3\u05DC\u05D9\u05E7 \u05D5\u05DC\u05DB\u05D1\u05D5\u05EA \u05D1\u05DB\u05DC \u05E8\u05D2\u05E2 \u05E2\u05DD \u05DB\u05E4\u05EA\u05D5\u05E8 \u05D4\u05D4\u05E7\u05E8\u05D0\u05D4"))), studyCard && /*#__PURE__*/React.createElement("div", {
    className: "gm-levelup study"
  }, /*#__PURE__*/React.createElement("div", {
    className: "gm-study-eyebrow"
  }, "\u05DB\u05D3\u05D0\u05D9 \u05DC\u05D6\u05DB\u05D5\u05E8", /*#__PURE__*/React.createElement("span", {
    className: "dot"
  }, ".")), /*#__PURE__*/React.createElement("div", {
    className: "gm-missreveal big"
  }, /*#__PURE__*/React.createElement("span", {
    className: "en"
  }, studyCard.en), /*#__PURE__*/React.createElement("span", {
    className: "sep"
  }, "="), /*#__PURE__*/React.createElement("span", {
    className: "he"
  }, studyCard.he)), audioEnabled && /*#__PURE__*/React.createElement("button", {
    className: "gm-study-say",
    onClick: () => speakWord(studyCard.en)
  }, /*#__PURE__*/React.createElement(Ico.readaloud, null), /*#__PURE__*/React.createElement("span", null, "\u05DC\u05D4\u05E9\u05DE\u05D9\u05E2 \u05E9\u05D5\u05D1")), /*#__PURE__*/React.createElement("div", {
    className: "gm-levelup-sub"
  }, "\u05D4\u05DE\u05D9\u05DC\u05D4 \u05EA\u05D7\u05DB\u05D4 \u05DC\u05DB\u05DD \u05D2\u05DD \u05D1\u05E1\u05D9\u05DB\u05D5\u05DD \u05D1\u05E1\u05D5\u05E3 \u05D4\u05DE\u05E9\u05D7\u05E7."), /*#__PURE__*/React.createElement("div", {
    className: "gm-levelup-btnrow"
  }, /*#__PURE__*/React.createElement("button", {
    className: "gm-levelup-cta",
    onClick: () => {
      const d = studyCard.dictIdx;
      setStudyCard(null);
      advance(d);
    }
  }, "\u05D4\u05D1\u05D0", /*#__PURE__*/React.createElement("span", {
    className: "dot"
  }, "."))))), /*#__PURE__*/React.createElement("div", {
    className: "gm-controls"
  }, /*#__PURE__*/React.createElement("div", {
    className: "gm-meta"
  }, /*#__PURE__*/React.createElement("button", {
    className: "gm-logo",
    onClick: goHome,
    title: "\u05DC\u05DE\u05E1\u05DA \u05D4\u05D1\u05D9\u05EA \u05E9\u05DC \u05D4\u05DE\u05E9\u05D7\u05E7"
  }, /*#__PURE__*/React.createElement("img", {
    src: EZ_ICON,
    alt: ""
  }), /*#__PURE__*/React.createElement("span", {
    className: "brand-eazy"
  }, "eazy", /*#__PURE__*/React.createElement("span", {
    className: "dot"
  }, "."))), /*#__PURE__*/React.createElement("div", {
    className: "gm-score"
  }, /*#__PURE__*/React.createElement("span", {
    className: "lbl"
  }, "\u05E0\u05D9\u05E7\u05D5\u05D3"), /*#__PURE__*/React.createElement("span", {
    className: "num"
  }, score))), /*#__PURE__*/React.createElement("div", {
    className: "gm-pad"
  }, /*#__PURE__*/React.createElement("button", {
    className: "gm-arcade",
    "aria-label": "\u05E9\u05DE\u05D0\u05DC\u05D4",
    onClick: () => move(-1)
  }, /*#__PURE__*/React.createElement(Ico.left, null)), /*#__PURE__*/React.createElement("button", {
    className: "gm-arcade down",
    "aria-label": "\u05D4\u05D0\u05E6\u05D4",
    onPointerDown: softDrop,
    onPointerUp: softRelease,
    onPointerLeave: softRelease
  }, /*#__PURE__*/React.createElement(Ico.down, null)), /*#__PURE__*/React.createElement("button", {
    className: "gm-arcade",
    "aria-label": "\u05D9\u05DE\u05D9\u05E0\u05D4",
    onClick: () => move(1)
  }, /*#__PURE__*/React.createElement(Ico.right, null))))));
}
window.Game = TetriGame;
})(); } catch (e) { __ds_ns.__errors.push({ path: "tetri-psychometry/TetriGame.jsx", error: String((e && e.message) || e) }); }

// tetri-psychometry/words.js
try { (() => {
/* eazy · משחק תותח־מילים — מילון המשחק
   ─────────────────────────────────────────────────────────────
   זהו הדטה־בייס של המשחק. לכל שורה:
     en — המילה באנגלית
     he — הפירוש בעברית
   המשחק יטען את הרשימה הזו אוטומטית בכל מכשיר, ללא צורך בהעלאה.

   להוסיף/לערוך מילים — פשוט ערוך את הקובץ הזה ושמור.
   מספר הערכים הנוכחי: 637
*/
window.GAME_DICTIONARY = [{
  en: "a fortnight ago",
  he: "לפני שבועיים"
}, {
  en: "abduct",
  he: "לחטוף"
}, {
  en: "abolish",
  he: "לבטל"
}, {
  en: "accelerate",
  he: "להאיץ"
}, {
  en: "accent",
  he: "מבטא"
}, {
  en: "access",
  he: "גישה"
}, {
  en: "acclaim",
  he: "הכרה / הוקרה"
}, {
  en: "ache",
  he: "כאב / לכאוב"
}, {
  en: "activity",
  he: "פעילות"
}, {
  en: "acute",
  he: "חריף"
}, {
  en: "admiration",
  he: "הערצה"
}, {
  en: "admission process",
  he: "תהליך ההרשמה"
}, {
  en: "advertisement",
  he: "פרסומת"
}, {
  en: "adviser",
  he: "יועץ"
}, {
  en: "affirmative action",
  he: "העדפה מתקנת"
}, {
  en: "ague",
  he: "צמרמורת / קדחת"
}, {
  en: "aid",
  he: "עזרה"
}, {
  en: "ailment",
  he: "מחלה"
}, {
  en: "aimed at",
  he: "המכוון אל..."
}, {
  en: "alert",
  he: "כוננות"
}, {
  en: "allegation",
  he: "האשמה"
}, {
  en: "allegedly",
  he: "לכאורה"
}, {
  en: "ally",
  he: "בעל ברית"
}, {
  en: "along with",
  he: "לצד"
}, {
  en: "along side",
  he: "לצד / ליד"
}, {
  en: "ambassador",
  he: "שגריר"
}, {
  en: "ambiguous",
  he: "מעורפל"
}, {
  en: "ambition",
  he: "שאיפה"
}, {
  en: "ambitious",
  he: "שאפתן"
}, {
  en: "amnesia",
  he: "שכחה / נשייה"
}, {
  en: "ample",
  he: "הרבה / שפע"
}, {
  en: "analyze",
  he: "לנתח"
}, {
  en: "animosity",
  he: "עוינות"
}, {
  en: "annihilation",
  he: "השמדה מוחלטת"
}, {
  en: "anniversary",
  he: "יום השנה"
}, {
  en: "annoyance",
  he: "מטרד"
}, {
  en: "annulment",
  he: "ביטול נישואין"
}, {
  en: "anonymous",
  he: "אלמוני"
}, {
  en: "anthem",
  he: "המנון"
}, {
  en: "anticipation",
  he: "ציפייה"
}, {
  en: "anxious",
  he: "עצבני / מודאג"
}, {
  en: "any given moment",
  he: "כל רגע נתון"
}, {
  en: "apology",
  he: "התנצלות"
}, {
  en: "appear",
  he: "מופיע"
}, {
  en: "appliance",
  he: "כלי/מתקן"
}, {
  en: "application",
  he: "בקשה לקבלה"
}, {
  en: "approve",
  he: "לאשר"
}, {
  en: "arena",
  he: "זירה / מגרש"
}, {
  en: "argument",
  he: "ויכוח / טיעון"
}, {
  en: "arrogance",
  he: "שחצנות"
}, {
  en: "assessment",
  he: "הערכה"
}, {
  en: "associate",
  he: "עמית / שותף"
}, {
  en: "assumption",
  he: "הנחה"
}, {
  en: "astonishment",
  he: "תדהמה"
}, {
  en: "attack",
  he: "התקפה"
}, {
  en: "attendance",
  he: "נוכחות"
}, {
  en: "attention",
  he: "תשומת לב"
}, {
  en: "attribution",
  he: "ייחוס / תכונה"
}, {
  en: "awe-inspiring",
  he: "מעורר השתאות"
}, {
  en: "bark",
  he: "לנבוח"
}, {
  en: "barrier",
  he: "מחסום, סייג"
}, {
  en: "beforehand",
  he: "מראש"
}, {
  en: "bench",
  he: "ספסל"
}, {
  en: "beneficial",
  he: "מועיל / מיטיב"
}, {
  en: "beneficiary",
  he: "המוטב / הנהנה"
}, {
  en: "benefit",
  he: "להרוויח"
}, {
  en: "benign",
  he: "שפיר"
}, {
  en: "bequeath",
  he: "להוריש"
}, {
  en: "bereavement",
  he: "אבל / שכול"
}, {
  en: "bigotry",
  he: "גזענות"
}, {
  en: "birth",
  he: "לידה / ללדת"
}, {
  en: "blink",
  he: "מצמוץ"
}, {
  en: "blizzard",
  he: "סופה / סערה"
}, {
  en: "block",
  he: "לחסום"
}, {
  en: "board",
  he: "מועצה / לוח"
}, {
  en: "boldly",
  he: "באופן נועז"
}, {
  en: "bone-marrow",
  he: "מוח עצם"
}, {
  en: "border",
  he: "גבול / גבולי"
}, {
  en: "boredom",
  he: "שעמום"
}, {
  en: "boundless",
  he: "חסר גבולות"
}, {
  en: "brash",
  he: "פזיז / נמהר"
}, {
  en: "breast",
  he: "שד / חזה"
}, {
  en: "briefing",
  he: "תדריך"
}, {
  en: "brisk",
  he: "בחטף / במהרה"
}, {
  en: "broadcast",
  he: "לשדר / שידור"
}, {
  en: "broker",
  he: "מתווך / סוכן"
}, {
  en: "budget",
  he: "תקציב"
}, {
  en: "bulks",
  he: "כמויות גדולות"
}, {
  en: "buried",
  he: "קבור"
}, {
  en: "campaign",
  he: "מסע בחירות"
}, {
  en: "canal",
  he: "תעלה"
}, {
  en: "cancel",
  he: "לבטל"
}, {
  en: "candidate",
  he: "מועמד"
}, {
  en: "capsized",
  he: "מתהפך / מתבטל"
}, {
  en: "captions",
  he: "כתוביות"
}, {
  en: "capture",
  he: "ללכוד / לשבות"
}, {
  en: "careful consideration",
  he: "מחשבה מרובה"
}, {
  en: "cargo",
  he: "מטען"
}, {
  en: "cell",
  he: "תא"
}, {
  en: "cemeteries",
  he: "בתי קברות"
}, {
  en: "centric",
  he: "מרכזי"
}, {
  en: "chairman",
  he: "יו\"ר"
}, {
  en: "challenge",
  he: "אתגר"
}, {
  en: "charity",
  he: "צדקה"
}, {
  en: "charming",
  he: "מקסים"
}, {
  en: "chauvinistic",
  he: "שוביניסטי"
}, {
  en: "chronic illness",
  he: "מחלה כרונית"
}, {
  en: "circulated",
  he: "סבב / נפוץ"
}, {
  en: "civil",
  he: "אזרחי"
}, {
  en: "clarify",
  he: "להבהיר / לחדד"
}, {
  en: "clash",
  he: "עימות"
}, {
  en: "classified material",
  he: "חומר מסווג"
}, {
  en: "classify",
  he: "לסווג / למיין"
}, {
  en: "classified",
  he: "מסווג"
}, {
  en: "cloning",
  he: "לשכפל"
}, {
  en: "coach",
  he: "מאמן"
}, {
  en: "coating",
  he: "ציפוי"
}, {
  en: "coercion",
  he: "כפייה"
}, {
  en: "cognition",
  he: "תפישה"
}, {
  en: "colleague",
  he: "עמית"
}, {
  en: "collision",
  he: "התנגשות"
}, {
  en: "come to a halt",
  he: "לעצור / לחדול"
}, {
  en: "come to light",
  he: "נודע / הופיע"
}, {
  en: "comet",
  he: "כוכב שביט"
}, {
  en: "comfort",
  he: "הטבה / נוחיות"
}, {
  en: "commitment",
  he: "מחויבות"
}, {
  en: "committed to",
  he: "מסור ל..."
}, {
  en: "committee",
  he: "ועדה"
}, {
  en: "companion",
  he: "בן זוג / שותף"
}, {
  en: "compel",
  he: "לאלץ / לכפות"
}, {
  en: "complaint",
  he: "תלונה"
}, {
  en: "comprehensive",
  he: "מקיף וכוללני"
}, {
  en: "compromise",
  he: "להתפשר / לסכן"
}, {
  en: "compulsive",
  he: "כפייתי"
}, {
  en: "concentration",
  he: "ריכוז"
}, {
  en: "conditioning",
  he: "התניה"
}, {
  en: "confess",
  he: "להתוודות"
}, {
  en: "confronted",
  he: "מעומת למול"
}, {
  en: "connection",
  he: "קשר"
}, {
  en: "conniving",
  he: "תככן וחתרן"
}, {
  en: "conquest",
  he: "כיבוש"
}, {
  en: "consecutive",
  he: "רציף / רצוף"
}, {
  en: "considering",
  he: "בהתחשב"
}, {
  en: "consortium",
  he: "תאגיד"
}, {
  en: "construct",
  he: "לבנות"
}, {
  en: "continent",
  he: "יבשת"
}, {
  en: "continuity",
  he: "המשכיות"
}, {
  en: "continuously",
  he: "מתמשך"
}, {
  en: "contradiction",
  he: "סתירה"
}, {
  en: "contrary to",
  he: "בניגוד ל..."
}, {
  en: "conviction",
  he: "הרשעה / שכנוע"
}, {
  en: "convince",
  he: "לשכנע"
}, {
  en: "copyrights",
  he: "זכויות יוצרים"
}, {
  en: "coral",
  he: "אלמוג"
}, {
  en: "correspondent",
  he: "מתכתב / כתב"
}, {
  en: "co-star",
  he: "כוכב משנה"
}, {
  en: "counterfeit",
  he: "מזויף"
}, {
  en: "county judge",
  he: "שופט מחוזי"
}, {
  en: "courage",
  he: "אומץ"
}, {
  en: "court ruling",
  he: "פסיקת ביהמ\"ש"
}, {
  en: "cover story",
  he: "סיפור שער"
}, {
  en: "covert operation",
  he: "מבצע חשאי"
}, {
  en: "covertly",
  he: "בחשאיות"
}, {
  en: "covet",
  he: "לחמוד"
}, {
  en: "creativity",
  he: "יצירתיות"
}, {
  en: "credential",
  he: "מסמך / אישור"
}, {
  en: "credible",
  he: "מהימן / אמין"
}, {
  en: "crime prevention",
  he: "מניעת פשע"
}, {
  en: "crops",
  he: "יבולים"
}, {
  en: "crusade",
  he: "מסע צלב"
}, {
  en: "cumbersome",
  he: "מסורבל"
}, {
  en: "curse",
  he: "קללה"
}, {
  en: "debased",
  he: "פוגע / מעליב"
}, {
  en: "debut",
  he: "סרט ביכורים"
}, {
  en: "deceitfulness",
  he: "מרמה והונאה"
}, {
  en: "decentralized",
  he: "דה-צנטרליסטי"
}, {
  en: "decisive",
  he: "החלטי / מכריע"
}, {
  en: "debrief",
  he: "לתחקר"
}, {
  en: "decipher",
  he: "לפענח"
}, {
  en: "deduction",
  he: "דדוקציה"
}, {
  en: "defeat",
  he: "מפלה"
}, {
  en: "defect",
  he: "פגם / \"דפקט\""
}, {
  en: "defendant",
  he: "הנאשם"
}, {
  en: "defended",
  he: "הגן על..."
}, {
  en: "deform",
  he: "לעוות צורה"
}, {
  en: "defrost",
  he: "להפשיר"
}, {
  en: "denounce",
  he: "לגנות"
}, {
  en: "density",
  he: "צפיפות"
}, {
  en: "deny",
  he: "להכחיש"
}, {
  en: "depict",
  he: "לתאר"
}, {
  en: "deportation",
  he: "גירוש"
}, {
  en: "depression",
  he: "שפל"
}, {
  en: "descendant",
  he: "צאצא"
}, {
  en: "desirable",
  he: "נחשק"
}, {
  en: "deterrence",
  he: "הרתעה"
}, {
  en: "detest",
  he: "לתעב / לשנוא"
}, {
  en: "devastatingly",
  he: "באופן הרסני"
}, {
  en: "diminutive",
  he: "מקטין / זעיר"
}, {
  en: "disarray",
  he: "תוהו ובוהו"
}, {
  en: "discipline",
  he: "משמעת"
}, {
  en: "disclose",
  he: "לחשוף / לגלות"
}, {
  en: "disclosure",
  he: "חשיפה"
}, {
  en: "discount",
  he: "הנחה"
}, {
  en: "discovery",
  he: "תגלית"
}, {
  en: "disgusted",
  he: "נגעל"
}, {
  en: "disqualify",
  he: "לפסול"
}, {
  en: "disrupt",
  he: "להפריע"
}, {
  en: "distinguish",
  he: "להבחין"
}, {
  en: "distribute",
  he: "לחלק / להפיץ"
}, {
  en: "district",
  he: "מחוז / אזור"
}, {
  en: "disturbance",
  he: "הפרעה"
}, {
  en: "diver",
  he: "צוללן"
}, {
  en: "divulge",
  he: "לחשוף"
}, {
  en: "documentation",
  he: "תיעוד"
}, {
  en: "dodge",
  he: "להתחמק"
}, {
  en: "domain",
  he: "תחום"
}, {
  en: "dominated",
  he: "נשלט"
}, {
  en: "dormant",
  he: "רדום"
}, {
  en: "dosage",
  he: "מינון"
}, {
  en: "dot",
  he: "נקודה"
}, {
  en: "draw back",
  he: "לסגת / להירתע"
}, {
  en: "eager",
  he: "להוט"
}, {
  en: "earnest",
  he: "רציני"
}, {
  en: "echo",
  he: "הד"
}, {
  en: "editor",
  he: "עורך"
}, {
  en: "editorial",
  he: "מאמר מערכת"
}, {
  en: "educate",
  he: "לחנך"
}, {
  en: "efficient",
  he: "יעיל"
}, {
  en: "effort",
  he: "מאמץ / ניסיון"
}, {
  en: "elderly",
  he: "קשיש"
}, {
  en: "embezzle",
  he: "למעול / מעילה"
}, {
  en: "embrace",
  he: "לחבק"
}, {
  en: "emigrate",
  he: "להגר / לרדת"
}, {
  en: "employee",
  he: "עובד שכיר"
}, {
  en: "enclosure",
  he: "סגירת שטח"
}, {
  en: "encouragement",
  he: "עידוד"
}, {
  en: "endeavor",
  he: "מאמץ"
}, {
  en: "endorsement",
  he: "תמיכה / חסות"
}, {
  en: "enhance",
  he: "להרחיב"
}, {
  en: "enrollment",
  he: "הרשמה"
}, {
  en: "enthusiasm",
  he: "התלהבות"
}, {
  en: "eruption",
  he: "התפרצות"
}, {
  en: "espionage",
  he: "ריגול"
}, {
  en: "establishment",
  he: "מוסד / ממסד"
}, {
  en: "ethical",
  he: "אתי / מוסרי"
}, {
  en: "evaluation",
  he: "הערכה"
}, {
  en: "eventful",
  he: "מלא אירועים"
}, {
  en: "evolution",
  he: "אבולוציה"
}, {
  en: "excessive",
  he: "מוגזם"
}, {
  en: "excuse",
  he: "תירוץ"
}, {
  en: "expose",
  he: "לחשוף"
}, {
  en: "extend",
  he: "להאריך"
}, {
  en: "extensive",
  he: "מקיף"
}, {
  en: "extinction",
  he: "הכחדה"
}, {
  en: "facial features",
  he: "תווי פנים"
}, {
  en: "factor",
  he: "גורם"
}, {
  en: "faculty",
  he: "פקולטה"
}, {
  en: "fancy",
  he: "מהודר"
}, {
  en: "fan",
  he: "אוהד / מניפה"
}, {
  en: "favor",
  he: "טובה / העדפה"
}, {
  en: "feminine",
  he: "נשי"
}, {
  en: "ferocious",
  he: "פראי / אכזר"
}, {
  en: "ferociously",
  he: "באכזריות"
}, {
  en: "fertility",
  he: "פוריות"
}, {
  en: "feud",
  he: "משטמה"
}, {
  en: "fidelity",
  he: "נאמנות"
}, {
  en: "first aid",
  he: "עזרה ראשונה"
}, {
  en: "fixture",
  he: "משהו קבוע"
}, {
  en: "flat",
  he: "שטוח / דירה"
}, {
  en: "flaw",
  he: "חסרון / פגם"
}, {
  en: "flexibility",
  he: "גמישות"
}, {
  en: "foe",
  he: "אויב"
}, {
  en: "forge",
  he: "לזייף"
}, {
  en: "forming",
  he: "מייסדים"
}, {
  en: "fortify",
  he: "לבצר / לחזק"
}, {
  en: "foster",
  he: "לטפח / לאמץ"
}, {
  en: "found",
  he: "לייסד / להקים"
}, {
  en: "fraud",
  he: "הונאה / מרמה"
}, {
  en: "frown",
  he: "להזעיף פנים"
}, {
  en: "fruitful",
  he: "פורה"
}, {
  en: "frustrated",
  he: "מתוסכל"
}, {
  en: "function",
  he: "תפקוד"
}, {
  en: "fundamental",
  he: "בסיסי / יסודי"
}, {
  en: "furious",
  he: "זועם / \"רותח\""
}, {
  en: "gag order",
  he: "צו איסור פרסום"
}, {
  en: "gap",
  he: "פער"
}, {
  en: "genetic information",
  he: "מידע גנטי"
}, {
  en: "genuine",
  he: "מקורי / אמיתי"
}, {
  en: "get under way",
  he: "לצאת לדרך"
}, {
  en: "giant",
  he: "ענק"
}, {
  en: "glance",
  he: "מבט חטוף"
}, {
  en: "glimpse",
  he: "הצצה רגעית"
}, {
  en: "global economy",
  he: "כלכלה עולמית"
}, {
  en: "gown",
  he: "שמלה / חלוק"
}, {
  en: "graduate degree",
  he: "תואר אקדמאי"
}, {
  en: "greed",
  he: "תאוות בצע"
}, {
  en: "grief",
  he: "יגון"
}, {
  en: "guarded",
  he: "שמור"
}, {
  en: "guidance",
  he: "הנחיה"
}, {
  en: "gulf",
  he: "מפרץ"
}, {
  en: "halt",
  he: "לעצור / לחדול"
}, {
  en: "handcuffs",
  he: "אזיקים"
}, {
  en: "handy",
  he: "יעיל"
}, {
  en: "harbor",
  he: "נמל"
}, {
  en: "hearing",
  he: "שימוע / שומע"
}, {
  en: "heir",
  he: "יורש"
}, {
  en: "hint",
  he: "רמז"
}, {
  en: "holocaust survivor",
  he: "ניצול שואה"
}, {
  en: "honorable",
  he: "מכובד"
}, {
  en: "hopefulness",
  he: "מלא תקווה"
}, {
  en: "hostage",
  he: "בן ערובה"
}, {
  en: "hostile",
  he: "עוין"
}, {
  en: "hostility",
  he: "עוינות"
}, {
  en: "humidity",
  he: "לחות"
}, {
  en: "humiliation",
  he: "השפלה / בושה"
}, {
  en: "identical",
  he: "זהה"
}, {
  en: "identity",
  he: "זהות"
}, {
  en: "ignoring",
  he: "להתעלם"
}, {
  en: "ill-fated",
  he: "מסתיים בכי רע"
}, {
  en: "image",
  he: "תמונה / דמות"
}, {
  en: "imaginable",
  he: "ניתן לדמיון"
}, {
  en: "immunity",
  he: "חסינות"
}, {
  en: "impede",
  he: "להאט / להפריע"
}, {
  en: "implant",
  he: "לשתול"
}, {
  en: "imply",
  he: "לרמוז"
}, {
  en: "imprison",
  he: "לכלוא / לאסור"
}, {
  en: "improbable",
  he: "בלתי סביר"
}, {
  en: "in accordance",
  he: "בהתאם ל..."
}, {
  en: "in contradiction",
  he: "בסתירה"
}, {
  en: "incapable",
  he: "לא מסוגל"
}, {
  en: "incautious",
  he: "בלתי זהיר"
}, {
  en: "incentive",
  he: "תמריץ"
}, {
  en: "incident",
  he: "תקרית"
}, {
  en: "inclination",
  he: "נטייה ל..."
}, {
  en: "in common",
  he: "במשותף"
}, {
  en: "incompatible",
  he: "בלתי מתאים"
}, {
  en: "incompetence",
  he: "חוסר יכולת"
}, {
  en: "inconceivable",
  he: "בלתי נתפש"
}, {
  en: "indication",
  he: "אינדיקציה"
}, {
  en: "indicator",
  he: "אינדיקטור"
}, {
  en: "indictment",
  he: "כתב אישום"
}, {
  en: "infant",
  he: "תינוק קטן"
}, {
  en: "infectious",
  he: "מדבק"
}, {
  en: "infer",
  he: "להסיק / להבין"
}, {
  en: "infinitesimal",
  he: "מזערי"
}, {
  en: "inherent",
  he: "טבוע"
}, {
  en: "inheritance",
  he: "ירושה"
}, {
  en: "initial",
  he: "ראשוני"
}, {
  en: "initiate",
  he: "ליזום"
}, {
  en: "insanity",
  he: "שיגעון"
}, {
  en: "insect",
  he: "חרק"
}, {
  en: "inspiration",
  he: "השראה"
}, {
  en: "institution",
  he: "מוסד"
}, {
  en: "insufferable",
  he: "בלתי נסבל"
}, {
  en: "insufficient",
  he: "בלתי מספק"
}, {
  en: "insurance evaluators",
  he: "שמאי ביטוח"
}, {
  en: "insurance policy",
  he: "פוליסת ביטוח"
}, {
  en: "insure",
  he: "להבטיח"
}, {
  en: "integrity",
  he: "יושר / אמינות"
}, {
  en: "intelligence officer",
  he: "קצין מודיעין"
}, {
  en: "intended effect",
  he: "אפקט מיועד"
}, {
  en: "intent",
  he: "כוונה"
}, {
  en: "interaction",
  he: "אינטראקציה"
}, {
  en: "interrogation",
  he: "חקירה"
}, {
  en: "investigation",
  he: "חקירה (בלשית)"
}, {
  en: "investor",
  he: "משקיע"
}, {
  en: "invincible",
  he: "בלתי מנוצח"
}, {
  en: "invisible",
  he: "בלתי נראה"
}, {
  en: "invitation",
  he: "הזמנה"
}, {
  en: "isolate",
  he: "לבודד / לנתק"
}, {
  en: "isolationism",
  he: "בדלנות"
}, {
  en: "issue a declaration",
  he: "לפרסם הצהרה"
}, {
  en: "journey",
  he: "מסע"
}, {
  en: "judgment",
  he: "יכולת שיפוט"
}, {
  en: "jump-start",
  he: "להתניע"
}, {
  en: "justify",
  he: "להצדיק"
}, {
  en: "kidnapping",
  he: "חטיפה"
}, {
  en: "lab",
  he: "מעבדה"
}, {
  en: "lap",
  he: "הקפה / ירך"
}, {
  en: "launch",
  he: "להשיק / לשגר"
}, {
  en: "lavishly",
  he: "בהידור"
}, {
  en: "lawyer",
  he: "עורך דין"
}, {
  en: "layoffs",
  he: "פיטורין"
}, {
  en: "lecture",
  he: "הרצאה"
}, {
  en: "legacy",
  he: "מורשת"
}, {
  en: "lethal",
  he: "קטלני"
}, {
  en: "likeness",
  he: "דמיון"
}, {
  en: "limitation",
  he: "מגבלה"
}, {
  en: "line of research",
  he: "קו מחקרי"
}, {
  en: "link",
  he: "קשר"
}, {
  en: "loathe",
  he: "מתעב"
}, {
  en: "makes sense",
  he: "נשמע הגיוני"
}, {
  en: "malfunction",
  he: "תקלה"
}, {
  en: "management position",
  he: "תפקיד ניהולי"
}, {
  en: "mandatory",
  he: "חובה"
}, {
  en: "manner",
  he: "אופן"
}, {
  en: "marginal element",
  he: "גורם שולי"
}, {
  en: "markedly",
  he: "באופן ניכר"
}, {
  en: "masculine",
  he: "גברי"
}, {
  en: "massacre",
  he: "טבח"
}, {
  en: "meager",
  he: "זעום"
}, {
  en: "meaningless",
  he: "חסר משמעות"
}, {
  en: "means of deterrence",
  he: "אמצעי הרתעה"
}, {
  en: "mediator",
  he: "מתווך"
}, {
  en: "mediocre",
  he: "בינוני"
}, {
  en: "meek",
  he: "חלש / קלוש"
}, {
  en: "meet these goals",
  he: "לעמוד ביעדים"
}, {
  en: "mental",
  he: "נפשי / מנטאלי"
}, {
  en: "merger",
  he: "איחוד / מיזוג"
}, {
  en: "meticulous",
  he: "קפדני ודקדקני"
}, {
  en: "middleman",
  he: "מתווך"
}, {
  en: "mild",
  he: "מתון"
}, {
  en: "minister",
  he: "שר"
}, {
  en: "minute",
  he: "זעיר / דקה"
}, {
  en: "miracle",
  he: "נס"
}, {
  en: "misconception",
  he: "תפישה שגויה"
}, {
  en: "misinterpret",
  he: "לפרש לא נכון"
}, {
  en: "missionary",
  he: "מיסיונר"
}, {
  en: "moral question",
  he: "שאלה מוסרית"
}, {
  en: "mortal danger",
  he: "סכנת חיים"
}, {
  en: "motion",
  he: "תנועה"
}, {
  en: "motive",
  he: "מניע"
}, {
  en: "mutual",
  he: "הדדי"
}, {
  en: "mysteriousness",
  he: "מסתוריות"
}, {
  en: "mystical",
  he: "מיסטי"
}, {
  en: "mystify",
  he: "לערפל"
}, {
  en: "naive",
  he: "נאיבי / תמים"
}, {
  en: "narcissist",
  he: "נרקיסיסט"
}, {
  en: "navigate",
  he: "לנווט"
}, {
  en: "nerve cell",
  he: "תא עצב"
}, {
  en: "neutral",
  he: "נייטראלי"
}, {
  en: "next of kin",
  he: "קרוב משפחה"
}, {
  en: "nightmare",
  he: "סיוט"
}, {
  en: "novel",
  he: "חדשני"
}, {
  en: "novelist",
  he: "סופר"
}, {
  en: "obligation",
  he: "התחייבות"
}, {
  en: "offspring",
  he: "צאצא"
}, {
  en: "ongoing",
  he: "מתמשך"
}, {
  en: "oppose",
  he: "להתנגד ל..."
}, {
  en: "opposite",
  he: "הפוך"
}, {
  en: "oppression",
  he: "דיכוי"
}, {
  en: "oral",
  he: "בעל פה"
}, {
  en: "orbit",
  he: "מסלול היקפי"
}, {
  en: "originates from",
  he: "נובע מ..."
}, {
  en: "outcome",
  he: "תוצאה"
}, {
  en: "overshadow",
  he: "להאפיל"
}, {
  en: "overt",
  he: "גלוי, פומבי"
}, {
  en: "overwhelmed",
  he: "המום"
}, {
  en: "pamper",
  he: "לפנק"
}, {
  en: "parade",
  he: "מצעד / להצעיד"
}, {
  en: "paralyze",
  he: "לשתק"
}, {
  en: "participant",
  he: "משתתף"
}, {
  en: "particle",
  he: "חלקיק"
}, {
  en: "pave",
  he: "לסלול"
}, {
  en: "peacefulness",
  he: "שקט ושלווה"
}, {
  en: "penetration",
  he: "חדירה"
}, {
  en: "percent",
  he: "אחוז"
}, {
  en: "perception",
  he: "תפישה"
}, {
  en: "persist",
  he: "להתמיד"
}, {
  en: "personnel",
  he: "כוח אדם"
}, {
  en: "persuasion",
  he: "שכנוע"
}, {
  en: "phase",
  he: "שלב"
}, {
  en: "pipeline",
  he: "צינור"
}, {
  en: "plagiarism",
  he: "גניבה ספרותית"
}, {
  en: "plain",
  he: "פשוט / ברור"
}, {
  en: "plaintiff",
  he: "תובע / מאשים"
}, {
  en: "planet",
  he: "כוכב לכת"
}, {
  en: "plea",
  he: "טענה"
}, {
  en: "pledge",
  he: "התחייבות"
}, {
  en: "plenty",
  he: "שפע"
}, {
  en: "point out",
  he: "לציין"
}, {
  en: "pollute",
  he: "לזהם"
}, {
  en: "popular belief",
  he: "אמונה מקובלת"
}, {
  en: "port",
  he: "נמל"
}, {
  en: "precaution",
  he: "אמצעי זהירות"
}, {
  en: "precious",
  he: "יקר"
}, {
  en: "precisely",
  he: "בדיוק"
}, {
  en: "preclude",
  he: "להוציא מהכלל"
}, {
  en: "preference",
  he: "העדפה"
}, {
  en: "premise",
  he: "הנחת יסוד"
}, {
  en: "preparation",
  he: "הכנה"
}, {
  en: "preserved bodies",
  he: "גופות משומרות"
}, {
  en: "prestigious",
  he: "יוקרתי"
}, {
  en: "probable successor",
  he: "יורש אפשרי"
}, {
  en: "probation",
  he: "תקופת מבחן"
}, {
  en: "probe",
  he: "סקירה מעמיקה"
}, {
  en: "profit",
  he: "להרוויח"
}, {
  en: "projected",
  he: "צפוי / מתוכנן"
}, {
  en: "prolonged",
  he: "מוארך / ממושך"
}, {
  en: "prominent",
  he: "בולט"
}, {
  en: "promotion",
  he: "קידום"
}, {
  en: "pronunciation",
  he: "היגוי / מבטא"
}, {
  en: "prophecy",
  he: "נבואה"
}, {
  en: "proponent",
  he: "תומך"
}, {
  en: "proposal",
  he: "הצעה"
}, {
  en: "prosperity",
  he: "שגשוג ורווחה"
}, {
  en: "protest",
  he: "מחאה / הפגנה"
}, {
  en: "punishment",
  he: "עונש / ענישה"
}, {
  en: "purify",
  he: "לטהר"
}, {
  en: "purloined material",
  he: "חומר \"מושאל\""
}, {
  en: "purposeful",
  he: "מלא כוונה"
}, {
  en: "pursuit",
  he: "מרדף"
}, {
  en: "puzzled",
  he: "תמוה"
}, {
  en: "qualified",
  he: "מתאים / מוסמך"
}, {
  en: "quarter",
  he: "רבע"
}, {
  en: "quiz",
  he: "בוחן / חידון"
}, {
  en: "racism",
  he: "גזענות"
}, {
  en: "racist",
  he: "גזען"
}, {
  en: "radiation",
  he: "קרינה"
}, {
  en: "reaction",
  he: "תגובה"
}, {
  en: "reasonable",
  he: "סביר / הגיוני"
}, {
  en: "reassembled",
  he: "מורכב מחדש"
}, {
  en: "rebuttal",
  he: "הפרכה"
}, {
  en: "recipe",
  he: "מתכון"
}, {
  en: "rectify",
  he: "לתקן"
}, {
  en: "refuel",
  he: "לתדלק מחדש"
}, {
  en: "regardless",
  he: "ללא קשר"
}, {
  en: "regime",
  he: "משטר"
}, {
  en: "regiment",
  he: "גדוד"
}, {
  en: "region",
  he: "אזור / תחום"
}, {
  en: "reinforce",
  he: "לתגבר / לחזק"
}, {
  en: "reluctance",
  he: "חוסר רצון"
}, {
  en: "remarkable",
  he: "ראוי לציון"
}, {
  en: "remorse",
  he: "חרטה / צער"
}, {
  en: "reprehensible",
  he: "ראוי לגינוי"
}, {
  en: "reptile",
  he: "זוחל"
}, {
  en: "requester",
  he: "המבקש"
}, {
  en: "residency",
  he: "מקום מגורים"
}, {
  en: "respiration",
  he: "נשימה"
}, {
  en: "restoration",
  he: "שחזור"
}, {
  en: "restore",
  he: "לשחזר"
}, {
  en: "retirement",
  he: "פרישה"
}, {
  en: "reveal",
  he: "לחשוף / לגלות"
}, {
  en: "review",
  he: "לבדוק שנית"
}, {
  en: "revive",
  he: "להחיות"
}, {
  en: "revolutionize",
  he: "לחולל מהפיכה"
}, {
  en: "role",
  he: "תפקיד"
}, {
  en: "root",
  he: "שורש"
}, {
  en: "routine",
  he: "רוטינה / שגרה"
}, {
  en: "rural",
  he: "כפרי"
}, {
  en: "sacred",
  he: "קדוש"
}, {
  en: "satellite",
  he: "לוויין"
}, {
  en: "scatter",
  he: "לפזר / להתפזר"
}, {
  en: "scenario",
  he: "תרחיש"
}, {
  en: "schooling",
  he: "חינוך"
}, {
  en: "scroll",
  he: "מגילה"
}, {
  en: "self-preservation",
  he: "שימור עצמי"
}, {
  en: "self-restraint",
  he: "שליטה עצמית"
}, {
  en: "semi",
  he: "למחצה"
}, {
  en: "seminar",
  he: "סמינר"
}, {
  en: "sensible",
  he: "הגיוני"
}, {
  en: "sensuous",
  he: "חושני"
}, {
  en: "serenity",
  he: "שלווה"
}, {
  en: "server",
  he: "שרת מחשב"
}, {
  en: "session",
  he: "פגישה /סדנא"
}, {
  en: "shortage",
  he: "מחסור"
}, {
  en: "similarly",
  he: "באופן דומה"
}, {
  en: "simulate",
  he: "לדמות"
}, {
  en: "site",
  he: "אתר"
}, {
  en: "skinny",
  he: "רזה מאוד"
}, {
  en: "sleepiness",
  he: "ישנוניות"
}, {
  en: "slim",
  he: "רזה / קלוש"
}, {
  en: "slips of the tongue",
  he: "מעידות בלשון"
}, {
  en: "sober",
  he: "פיכח"
}, {
  en: "software patches",
  he: "טלאי תוכנה"
}, {
  en: "sought after",
  he: "מחפשים אחריו"
}, {
  en: "specialist",
  he: "מומחה"
}, {
  en: "specialize",
  he: "מתמחה ב..."
}, {
  en: "spectator",
  he: "צופה"
}, {
  en: "spokesperson",
  he: "דובר"
}, {
  en: "spokeswoman",
  he: "דוברת"
}, {
  en: "sporadic",
  he: "בלתי סדיר"
}, {
  en: "spot",
  he: "נקודה"
}, {
  en: "squeeze",
  he: "ללחוץ / למחוץ"
}, {
  en: "stage",
  he: "שלב"
}, {
  en: "stakes",
  he: "סיכונים"
}, {
  en: "stand",
  he: "לעמוד / יציע"
}, {
  en: "startling",
  he: "מפתיע / מדהים"
}, {
  en: "stems from",
  he: "נובע מ..."
}, {
  en: "stock",
  he: "מניה בורסאית"
}, {
  en: "stomach",
  he: "קיבה / בטן"
}, {
  en: "storm",
  he: "סופה / סערה"
}, {
  en: "straight-forward",
  he: "ישיר"
}, {
  en: "strict",
  he: "נוקשה / קפדני"
}, {
  en: "suburban",
  he: "פרברי"
}, {
  en: "superstition",
  he: "אמונה טפלה"
}, {
  en: "supervision",
  he: "פיקוח"
}, {
  en: "surface variance",
  he: "משתנה חיצוני"
}, {
  en: "surrogate mother",
  he: "אם פונדקאית"
}, {
  en: "suspended",
  he: "מושעה / מושהה"
}, {
  en: "tantalizing",
  he: "מרגש / מרעיד"
}, {
  en: "tempt fate",
  he: "להתגרות בגורל"
}, {
  en: "testify",
  he: "להעיד"
}, {
  en: "testimony",
  he: "עדות"
}, {
  en: "therapy",
  he: "תרפיה / טיפול"
}, {
  en: "tide",
  he: "גאות ושפל"
}, {
  en: "timeliness",
  he: "דייקנות"
}, {
  en: "tool",
  he: "כלי"
}, {
  en: "topic",
  he: "הנושא"
}, {
  en: "topple",
  he: "למוטט"
}, {
  en: "tournament",
  he: "טורניר"
}, {
  en: "trade-offs",
  he: "החלפות"
}, {
  en: "traditional",
  he: "מסורתי"
}, {
  en: "traitorous",
  he: "בוגדני"
}, {
  en: "tranquility",
  he: "שלווה"
}, {
  en: "transaction",
  he: "עסקה"
}, {
  en: "transfer",
  he: "להעביר"
}, {
  en: "translucent",
  he: "מעט שקוף"
}, {
  en: "transparent",
  he: "שקוף / ברור"
}, {
  en: "tremendous",
  he: "עצום"
}, {
  en: "trend",
  he: "אופנה"
}, {
  en: "trial and error",
  he: "ניסוי וטעייה"
}, {
  en: "truthfully",
  he: "בכנות"
}, {
  en: "unbearable",
  he: "בלתי נסבל"
}, {
  en: "under dispute",
  he: "נתון במחלוקת"
}, {
  en: "undeterred",
  he: "לא נרתע מ..."
}, {
  en: "unravel",
  he: "לחשוף"
}, {
  en: "unstable",
  he: "בלתי יציב"
}, {
  en: "usable",
  he: "ניתן לשימוש"
}, {
  en: "vacancy",
  he: "מקום פנוי"
}, {
  en: "varies",
  he: "משתנה"
}, {
  en: "vast majority",
  he: "הרוב המוחלט"
}, {
  en: "veil",
  he: "הינומה"
}, {
  en: "violate",
  he: "להפר"
}, {
  en: "voyage",
  he: "מסע"
}, {
  en: "wage",
  he: "שכר / משכורת"
}, {
  en: "want of understanding",
  he: "העדר הבנה"
}, {
  en: "waver",
  he: "לוותר"
}, {
  en: "will",
  he: "רצון / צוואה"
}, {
  en: "willingness",
  he: "מוכנות"
}, {
  en: "wiped out",
  he: "למחוק"
}, {
  en: "work ethic",
  he: "מוסר עבודה"
}, {
  en: "worship",
  he: "לסגוד ל..."
}, {
  en: "wrapped up",
  he: "עטוף"
}, {
  en: "wrist",
  he: "פרק יד"
}, {
  en: "yearn",
  he: "להשתוקק"
}, {
  en: "youth",
  he: "נעורים"
}];
})(); } catch (e) { __ds_ns.__errors.push({ path: "tetri-psychometry/words.js", error: String((e && e.message) || e) }); }

// tetri-vocab/VocabGame.jsx
try { (() => {
/* global React */
const {
  useState,
  useEffect,
  useRef,
  useCallback,
  useMemo,
  useLayoutEffect
} = React;
// icon source: resolves to an inlined data-URI in the single-file build, or the
// relative path in the folder/server build (works on http:// and file://).
const EZ_ICON = typeof document !== 'undefined' && document.getElementById('ez-icon-src') && document.getElementById('ez-icon-src').src || 'ez-icon.png';

/* ════════════════ sound (WebAudio FX) ════════════════ */
const MUTED_KEY = "tx-muted-v1";
const REVIEW_KEY = "tx-review-v1";
const Sound = {
  ctx: null,
  muted: false,
  init() {
    if (!this.ctx) {
      try {
        this.ctx = new (window.AudioContext || window.webkitAudioContext)();
      } catch (e) {}
    }
    if (this.ctx && this.ctx.state === 'suspended') this.ctx.resume();
  },
  setMuted(m) {
    this.muted = !!m;
    try {
      localStorage.setItem(MUTED_KEY, m ? '1' : '0');
    } catch (e) {}
  },
  beep(f, d, type = 'sine', g = 0.15, delay = 0) {
    if (this.muted || !this.ctx) return;
    const t = this.ctx.currentTime + delay,
      o = this.ctx.createOscillator(),
      gn = this.ctx.createGain();
    o.type = type;
    o.frequency.value = f;
    gn.gain.setValueAtTime(g, t);
    gn.gain.exponentialRampToValueAtTime(0.001, t + d);
    o.connect(gn);
    gn.connect(this.ctx.destination);
    o.start(t);
    o.stop(t + d);
  },
  play(name) {
    if (this.muted) return;
    this.init();
    switch (name) {
      case 'move':
        this.beep(420, 0.04, 'square', 0.06);
        break;
      case 'drop':
        this.beep(180, 0.08, 'sawtooth', 0.12);
        this.beep(120, 0.1, 'square', 0.1, 0.03);
        break;
      case 'hit':
        this.beep(523, 0.1, 'square', 0.16);
        this.beep(784, 0.12, 'square', 0.14, 0.08);
        this.beep(1047, 0.22, 'triangle', 0.16, 0.16);
        break;
      case 'miss':
        this.beep(330, 0.14, 'square', 0.2);
        this.beep(196, 0.3, 'sawtooth', 0.2, 0.12);
        this.beep(130, 0.4, 'triangle', 0.18, 0.34);
        break;
      case 'fifty':
        this.beep(880, 0.1, 'sine', 0.15);
        this.beep(1320, 0.18, 'sine', 0.16, 0.1);
        break;
      case 'levelup':
        this.beep(523, 0.1, 'triangle', 0.18);
        this.beep(659, 0.1, 'triangle', 0.18, 0.1);
        this.beep(784, 0.1, 'triangle', 0.18, 0.2);
        this.beep(1047, 0.32, 'sine', 0.2, 0.3);
        break;
      case 'streak':
        this.beep(880, 0.08, 'sine', 0.13);
        this.beep(1320, 0.1, 'sine', 0.14, 0.08);
        this.beep(1760, 0.2, 'sine', 0.14, 0.16);
        break;
      case 'gameover':
        this.beep(440, 0.2, 'sine', 0.15);
        this.beep(330, 0.24, 'sine', 0.15, 0.2);
        this.beep(220, 0.5, 'sine', 0.18, 0.45);
        break;
    }
  }
};
try {
  Sound.muted = localStorage.getItem(MUTED_KEY) === '1';
} catch (e) {}

/* ════════════════ review list (persisted per-browser) ════════════════ */
function getReview() {
  try {
    return JSON.parse(localStorage.getItem(REVIEW_KEY) || '[]');
  } catch (e) {
    return [];
  }
}
function addReview(words) {
  const cur = getReview();
  const seen = new Set(cur.map(w => String(w.en).toLowerCase()));
  // add newest mistakes to the FRONT so the most recent appear on top
  for (const w of words || []) {
    if (!w || !w.en) continue;
    const k = String(w.en).toLowerCase();
    if (!seen.has(k)) {
      seen.add(k);
      cur.unshift({
        en: w.en,
        he: w.he
      });
    }
  }
  try {
    localStorage.setItem(REVIEW_KEY, JSON.stringify(cur));
  } catch (e) {}
  return cur;
}
function clearReview() {
  try {
    localStorage.removeItem(REVIEW_KEY);
  } catch (e) {}
}

/* ════════════════ dictionary helpers ════════════════ */
function shuffle(a) {
  const x = [...a];
  for (let i = x.length - 1; i > 0; i--) {
    const j = Math.random() * (i + 1) | 0;
    [x[i], x[j]] = [x[j], x[i]];
  }
  return x;
}
/* deterministic RNG (mulberry32) — same opening quiz for every player */
function mulberry32(seed) {
  let t = seed >>> 0;
  return function () {
    t += 0x6D2B79F5;
    let r = Math.imul(t ^ t >>> 15, 1 | t);
    r ^= r + Math.imul(r ^ r >>> 7, 61 | r);
    return ((r ^ r >>> 14) >>> 0) / 4294967296;
  };
}
function seededShuffle(a, seed) {
  const x = [...a];
  const rnd = mulberry32(seed);
  for (let i = x.length - 1; i > 0; i--) {
    const j = rnd() * (i + 1) | 0;
    [x[i], x[j]] = [x[j], x[i]];
  }
  return x;
}
function normMeaning(s) {
  return String(s || '').toLowerCase().replace(/[\/,،]/g, ' ').replace(/\s+/g, ' ').replace(/[״"׳'.…]/g, '').trim();
}

/* load the Hebrew word bank into the internal shape {en:word, he:meaning, cat, d} */
function loadBank() {
  const src = window.VOCAB_WORDS || [];
  return src.filter(x => x && x.w && x.m).map(x => ({
    en: String(x.w),
    he: String(x.m),
    cat: x.cat || '',
    d: x.d || 1,
    mis: (x.mis || []).map(String)
  }));
}
/* build the fixed opening quiz: 10 academic-idiom questions, uniform for all players */
const QUIZ_CAT = 'c6'; // ביטויים לחיבור
const QUIZ_SECONDS = 100; // time limit for the opening quiz
function buildQuiz(bank) {
  const manual = window.VOCAB_QUIZ;
  if (Array.isArray(manual) && manual.length) {
    const byWord = new Map(bank.map(e => [e.en, e]));
    const picked = manual.map(w => byWord.get(String(w))).filter(Boolean);
    if (picked.length) return picked;
  }
  // deterministic set of 10 from the academic-idioms category (uniform for everyone)
  const SEED = 20260702;
  let src = bank.filter(e => e.cat === QUIZ_CAT);
  if (src.length < 4) src = bank; // fallback if that category is missing
  return seededShuffle(src, SEED).slice(0, 10);
}
function buildQuestion(correct, fullDict, idx) {
  const ck = normMeaning(correct.he);
  const cen = String(correct.en).toLowerCase();
  // prefer the hand-picked distractors from the bank
  let picked = [];
  if (Array.isArray(correct.mis) && correct.mis.length) {
    const seen = new Set([ck]);
    for (const d of correct.mis) {
      const key = normMeaning(d);
      if (!d || seen.has(key)) continue;
      seen.add(key);
      picked.push({
        he: d
      });
      if (picked.length === 3) break;
    }
  }
  // fallback / top-up: distractors from the same category, then the whole bank
  if (picked.length < 3) {
    const seen = new Set([ck, ...picked.map(p => normMeaning(p.he))]);
    const sameCat = fullDict.filter(e => e.cat === correct.cat && String(e.en).toLowerCase() !== cen);
    const rest = fullDict.filter(e => String(e.en).toLowerCase() !== cen);
    for (const e of [...shuffle(sameCat), ...shuffle(rest)]) {
      const key = normMeaning(e.he);
      if (seen.has(key)) continue;
      seen.add(key);
      picked.push({
        he: e.he
      });
      if (picked.length === 3) break;
    }
  }
  const options = shuffle([correct.he, ...picked.map(d => d.he)]);
  return {
    en: String(correct.en),
    he: correct.he,
    options,
    dictIdx: idx
  };
}

/* ════════════════ icons ════════════════ */
const Ico = {
  sound: () => /*#__PURE__*/React.createElement("svg", {
    viewBox: "0 0 24 24",
    fill: "currentColor"
  }, /*#__PURE__*/React.createElement("path", {
    d: "M3 10v4a1 1 0 0 0 1 1h3l4 3.5a1 1 0 0 0 1.6-.8V6.3a1 1 0 0 0-1.6-.8L7 9H4a1 1 0 0 0-1 1Z"
  }), /*#__PURE__*/React.createElement("path", {
    d: "M16 8.5a4 4 0 0 1 0 7",
    fill: "none",
    stroke: "currentColor",
    strokeWidth: "2",
    strokeLinecap: "round"
  })),
  mute: () => /*#__PURE__*/React.createElement("svg", {
    viewBox: "0 0 24 24",
    fill: "none",
    stroke: "currentColor",
    strokeWidth: "2.2",
    strokeLinecap: "round",
    strokeLinejoin: "round"
  }, /*#__PURE__*/React.createElement("path", {
    d: "M3 10v4a1 1 0 0 0 1 1h3l4 3.5a1 1 0 0 0 1.6-.8V6.3a1 1 0 0 0-1.6-.8L7 9H4a1 1 0 0 0-1 1Z",
    fill: "currentColor",
    stroke: "none"
  }), /*#__PURE__*/React.createElement("path", {
    d: "M16 9l5 5M21 9l-5 5"
  })),
  expand: () => /*#__PURE__*/React.createElement("svg", {
    viewBox: "0 0 24 24",
    fill: "none",
    stroke: "currentColor",
    strokeWidth: "2.4",
    strokeLinecap: "round",
    strokeLinejoin: "round"
  }, /*#__PURE__*/React.createElement("path", {
    d: "M4 9V4h5M20 9V4h-5M4 15v5h5M20 15v5h-5"
  })),
  home: () => /*#__PURE__*/React.createElement("svg", {
    viewBox: "0 0 24 24",
    fill: "none",
    stroke: "currentColor",
    strokeWidth: "2.2",
    strokeLinecap: "round",
    strokeLinejoin: "round"
  }, /*#__PURE__*/React.createElement("path", {
    d: "M3 11l9-8 9 8"
  }), /*#__PURE__*/React.createElement("path", {
    d: "M5 10v10h14V10"
  }), /*#__PURE__*/React.createElement("path", {
    d: "M10 20v-6h4v6"
  })),
  trophy: () => /*#__PURE__*/React.createElement("svg", {
    viewBox: "0 0 24 24",
    fill: "none",
    stroke: "currentColor",
    strokeWidth: "2.2",
    strokeLinecap: "round",
    strokeLinejoin: "round"
  }, /*#__PURE__*/React.createElement("path", {
    d: "M8 21h8M12 17v4M7 4h10v5a5 5 0 0 1-10 0V4z"
  }), /*#__PURE__*/React.createElement("path", {
    d: "M7 6H4v2a3 3 0 0 0 3 3M17 6h3v2a3 3 0 0 1-3 3"
  })),
  left: () => /*#__PURE__*/React.createElement("svg", {
    viewBox: "0 0 24 24",
    fill: "currentColor"
  }, /*#__PURE__*/React.createElement("path", {
    d: "M15 5 L7 12 L15 19 Z"
  })),
  right: () => /*#__PURE__*/React.createElement("svg", {
    viewBox: "0 0 24 24",
    fill: "currentColor"
  }, /*#__PURE__*/React.createElement("path", {
    d: "M9 5 L17 12 L9 19 Z"
  })),
  down: () => /*#__PURE__*/React.createElement("svg", {
    viewBox: "0 0 24 24",
    fill: "currentColor"
  }, /*#__PURE__*/React.createElement("path", {
    d: "M5 9 L12 17 L19 9 Z"
  })),
  play: () => /*#__PURE__*/React.createElement("svg", {
    viewBox: "0 0 24 24",
    fill: "currentColor"
  }, /*#__PURE__*/React.createElement("path", {
    d: "M7 5 L19 12 L7 19 Z"
  })),
  go: () => /*#__PURE__*/React.createElement("svg", {
    viewBox: "0 0 24 24",
    fill: "none",
    stroke: "currentColor",
    strokeWidth: "2.6",
    strokeLinecap: "round",
    strokeLinejoin: "round"
  }, /*#__PURE__*/React.createElement("path", {
    d: "M19 12H5"
  }), /*#__PURE__*/React.createElement("path", {
    d: "M12 5l-7 7 7 7"
  })),
  share: () => /*#__PURE__*/React.createElement("svg", {
    viewBox: "0 0 24 24",
    fill: "none",
    stroke: "currentColor",
    strokeWidth: "2.2",
    strokeLinecap: "round",
    strokeLinejoin: "round"
  }, /*#__PURE__*/React.createElement("circle", {
    cx: "18",
    cy: "5",
    r: "3"
  }), /*#__PURE__*/React.createElement("circle", {
    cx: "6",
    cy: "12",
    r: "3"
  }), /*#__PURE__*/React.createElement("circle", {
    cx: "18",
    cy: "19",
    r: "3"
  }), /*#__PURE__*/React.createElement("path", {
    d: "M8.6 13.5l6.8 4M15.4 6.5l-6.8 4"
  })),
  print: () => /*#__PURE__*/React.createElement("svg", {
    viewBox: "0 0 24 24",
    fill: "none",
    stroke: "currentColor",
    strokeWidth: "2.2",
    strokeLinecap: "round",
    strokeLinejoin: "round"
  }, /*#__PURE__*/React.createElement("path", {
    d: "M6 9V3h12v6"
  }), /*#__PURE__*/React.createElement("path", {
    d: "M6 18H4a1 1 0 0 1-1-1v-5a1 1 0 0 1 1-1h16a1 1 0 0 1 1 1v5a1 1 0 0 1-1 1h-2"
  }), /*#__PURE__*/React.createElement("rect", {
    x: "6",
    y: "14",
    width: "12",
    height: "7",
    rx: "1"
  })),
  gift: () => /*#__PURE__*/React.createElement("svg", {
    viewBox: "0 0 24 24",
    fill: "none",
    stroke: "currentColor",
    strokeWidth: "2.1",
    strokeLinecap: "round",
    strokeLinejoin: "round"
  }, /*#__PURE__*/React.createElement("path", {
    d: "M20 12v8a1 1 0 0 1-1 1H5a1 1 0 0 1-1-1v-8"
  }), /*#__PURE__*/React.createElement("path", {
    d: "M2 8h20v4H2z"
  }), /*#__PURE__*/React.createElement("path", {
    d: "M12 8v13M12 8S10.5 4 8 4a2 2 0 0 0 0 4M12 8s1.5-4 4-4a2 2 0 0 1 0 4"
  })),
  mail: () => /*#__PURE__*/React.createElement("svg", {
    viewBox: "0 0 24 24",
    fill: "none",
    stroke: "currentColor",
    strokeWidth: "2.2",
    strokeLinecap: "round",
    strokeLinejoin: "round"
  }, /*#__PURE__*/React.createElement("rect", {
    x: "3",
    y: "5",
    width: "18",
    height: "14",
    rx: "2.5"
  }), /*#__PURE__*/React.createElement("path", {
    d: "M3.5 7l8.5 6 8.5-6"
  })),
  refresh: () => /*#__PURE__*/React.createElement("svg", {
    viewBox: "0 0 24 24",
    fill: "none",
    stroke: "currentColor",
    strokeWidth: "2.3",
    strokeLinecap: "round",
    strokeLinejoin: "round"
  }, /*#__PURE__*/React.createElement("path", {
    d: "M3 12a9 9 0 0 1 15.5-6.3L21 8"
  }), /*#__PURE__*/React.createElement("path", {
    d: "M21 3v5h-5"
  }), /*#__PURE__*/React.createElement("path", {
    d: "M21 12a9 9 0 0 1-15.5 6.3L3 16"
  }), /*#__PURE__*/React.createElement("path", {
    d: "M3 21v-5h5"
  })),
  hand: () => /*#__PURE__*/React.createElement("svg", {
    viewBox: "0 0 40 58",
    fill: "none"
  }, /*#__PURE__*/React.createElement("ellipse", {
    cx: "20",
    cy: "55",
    rx: "11",
    ry: "3.5",
    fill: "#000",
    opacity: ".16"
  }), /*#__PURE__*/React.createElement("path", {
    d: "M12.5 51 V17 a7.5 7.5 0 0 1 15 0 v29 a5 5 0 0 1-5 5 h-5 a5 5 0 0 1-5-5 z",
    fill: "#F7CBA6",
    stroke: "#00000018",
    strokeWidth: "1.5"
  }), /*#__PURE__*/React.createElement("path", {
    d: "M12.5 40 q7.5 4 15 0",
    stroke: "#E0A87E",
    strokeWidth: "1.4",
    strokeLinecap: "round",
    fill: "none"
  }), /*#__PURE__*/React.createElement("ellipse", {
    cx: "20",
    cy: "14.5",
    rx: "5.5",
    ry: "4.2",
    fill: "#fff",
    opacity: ".5"
  })),
  rowclear: () => /*#__PURE__*/React.createElement("svg", {
    viewBox: "0 0 24 24",
    fill: "none",
    stroke: "currentColor",
    strokeWidth: "2",
    strokeLinecap: "round",
    strokeLinejoin: "round"
  }, /*#__PURE__*/React.createElement("rect", {
    x: "3",
    y: "10",
    width: "18",
    height: "4.5",
    rx: "1",
    fill: "currentColor",
    stroke: "none"
  }), /*#__PURE__*/React.createElement("path", {
    d: "M6 6.5 6.8 8M12 5.5V7M18 6.5 17.2 8",
    opacity: ".9"
  }), /*#__PURE__*/React.createElement("path", {
    d: "M6 18 6.8 16.4M12 18.6V17M18 18 17.2 16.4",
    opacity: ".9"
  })),
  readaloud: () => /*#__PURE__*/React.createElement("svg", {
    viewBox: "0 0 24 24",
    fill: "none",
    stroke: "currentColor",
    strokeWidth: "2",
    strokeLinecap: "round",
    strokeLinejoin: "round"
  }, /*#__PURE__*/React.createElement("path", {
    d: "M4 15V9h3l4-3.5v13L7 15H4z",
    fill: "currentColor",
    stroke: "none"
  }), /*#__PURE__*/React.createElement("path", {
    d: "M15 9.5a3.2 3.2 0 0 1 0 5"
  }), /*#__PURE__*/React.createElement("path", {
    d: "M17.5 7a6 6 0 0 1 0 10"
  })),
  readoff: () => /*#__PURE__*/React.createElement("svg", {
    viewBox: "0 0 24 24",
    fill: "none",
    stroke: "currentColor",
    strokeWidth: "2",
    strokeLinecap: "round",
    strokeLinejoin: "round"
  }, /*#__PURE__*/React.createElement("path", {
    d: "M4 15V9h3l4-3.5v13L7 15H4z",
    fill: "currentColor",
    stroke: "none"
  }), /*#__PURE__*/React.createElement("path", {
    d: "M15.5 9.5l5 5M20.5 9.5l-5 5"
  }))
};
function Heart({
  lost
}) {
  return /*#__PURE__*/React.createElement("svg", {
    viewBox: "0 0 24 24",
    className: lost ? 'lost' : ''
  }, /*#__PURE__*/React.createElement("path", {
    fill: "#F33F3F",
    d: "M12 21s-7.5-4.7-9.6-9.5C.9 7.7 3.5 4 7.2 4c2 0 3.6 1 4.8 2.6C13.2 5 14.8 4 16.8 4c3.7 0 6.3 3.7 4.8 7.5C19.5 16.3 12 21 12 21z"
  }));
}
const TET_COLORS = ['#F2C230', '#E0519B', '#7E5BC2', '#3FA76C', '#5BB8E8', '#3F6BD6', '#D6463A', '#F37327', '#A9A4EC'];
/* per-level well themes — kick in from level 3, cycling. levels 1–2 use the default dark well. */
const LEVEL_THEMES = [{
  top: '#2A2547',
  bot: '#14102A',
  glow: 'rgba(243,115,39,.28)'
},
// orange
{
  top: '#1C2E4A',
  bot: '#0E1626',
  glow: 'rgba(91,184,232,.30)'
},
// cyan
{
  top: '#2C1E44',
  bot: '#160E28',
  glow: 'rgba(158,111,232,.30)'
},
// purple
{
  top: '#12332B',
  bot: '#0A1C18',
  glow: 'rgba(63,167,108,.30)'
},
// green
{
  top: '#3A2038',
  bot: '#1E0F1E',
  glow: 'rgba(224,81,155,.30)'
} // pink
];
function randColor(seed) {
  return TET_COLORS[Math.floor((Math.sin(seed * 99.13) * 0.5 + 0.5) * TET_COLORS.length) % TET_COLORS.length];
}

/* decorative tetris-block wall — memoised so it never re-renders mid-game */
const Wall = React.memo(function Wall({
  side,
  n
}) {
  const cells = useMemo(() => Array.from({
    length: n * 2
  }, (_, i) => randColor(i + (side === 'left' ? 7 : 31))), [side, n]);
  return /*#__PURE__*/React.createElement("div", {
    className: 'gm-wall ' + side,
    "aria-hidden": true
  }, cells.map((c, i) => /*#__PURE__*/React.createElement("div", {
    key: i,
    className: "gm-brick",
    style: {
      background: c
    }
  })));
});

/* ════════════════ Intro: home screen → (first time) animated explainer ════════════════ */
/* A stage that shows a mini game board and drives one tutorial beat with an animated finger. */
function ExStage({
  phase
}) {
  const WORD = 'כמיהה';
  const bins = ['געגוע', 'פחד', 'שפע', 'כעס']; // 0 = correct meaning
  const CORRECT = 0,
    WRONG = 2;
  const [ltoggle, setLtoggle] = useState(false); // move-scene: which arrow the finger presses
  useEffect(() => {
    if (phase !== 'move') return;
    const t = setInterval(() => setLtoggle(v => !v), 1050);
    return () => clearInterval(t);
  }, [phase]);

  // tower height per phase
  const tower = phase === 'mistake' ? ['#5BB8E8', '#E0519B', '#F2C230', '#7E5BC2', '#3FA76C'] : phase === 'correct' ? ['#5BB8E8', '#E0519B', '#F2C230'] : ['#5BB8E8', '#E0519B'];
  const towerCol = WRONG;
  const tileIdx = phase === 'move' ? ltoggle ? 0 : 3 : phase === 'correct' ? CORRECT : phase === 'mistake' ? WRONG : 1;
  const tileState = phase === 'correct' ? 'right' : phase === 'mistake' ? 'wrong' : 'live';
  const handPos = phase === 'move' ? ltoggle ? 'l' : 'r' : 'd';
  return /*#__PURE__*/React.createElement("div", {
    className: 'ex-stage ' + phase
  }, /*#__PURE__*/React.createElement("div", {
    className: "ex-lane"
  }, /*#__PURE__*/React.createElement("div", {
    className: 'ex-danger' + (phase === 'mistake' ? ' hot' : '')
  }), /*#__PURE__*/React.createElement("div", {
    className: 'ex-tile he ' + tileState,
    key: phase,
    style: {
      left: `${tileIdx * 25 + 12.5}%`
    }
  }, /*#__PURE__*/React.createElement("span", {
    className: "w"
  }, WORD), phase === 'correct' && /*#__PURE__*/React.createElement("span", {
    className: "badge good"
  }, "\u2713"), phase === 'mistake' && /*#__PURE__*/React.createElement("span", {
    className: "badge bad"
  }, "\u2717")), phase === 'speed' && /*#__PURE__*/React.createElement("div", {
    className: "ex-score-pop"
  }, "+320"), phase === 'correct' && /*#__PURE__*/React.createElement("div", {
    className: "ex-burst",
    style: {
      left: `calc(${towerCol * 25}% + 12.5%)`
    }
  }, [0, 1, 2, 3, 4, 5].map(i => /*#__PURE__*/React.createElement("span", {
    key: i,
    className: 'p p' + i
  }))), /*#__PURE__*/React.createElement("div", {
    className: "ex-pile",
    style: {
      left: `calc(${towerCol * 25}% + 5px)`
    }
  }, tower.map((c, i) => /*#__PURE__*/React.createElement("div", {
    key: phase + '-' + i,
    className: 'ex-brick' + (phase === 'mistake' && i === tower.length - 1 ? ' top new' : '') + (phase === 'correct' && i === tower.length - 1 ? ' shatter' : ''),
    style: {
      background: c
    }
  }))), /*#__PURE__*/React.createElement("div", {
    className: "ex-bins"
  }, bins.map((b, i) => {
    let cls = 'ex-bin';
    if (phase === 'correct' && i === CORRECT) cls += ' hit';else if (phase === 'mistake' && i === WRONG) cls += ' miss';else if (i === tileIdx) cls += ' target';
    return /*#__PURE__*/React.createElement("div", {
      key: i,
      className: cls
    }, b);
  }))), /*#__PURE__*/React.createElement("div", {
    className: "ex-ctrl"
  }, /*#__PURE__*/React.createElement("span", {
    className: 'ex-arrow l' + (handPos === 'l' ? ' hit' : '')
  }, /*#__PURE__*/React.createElement(Ico.left, null)), /*#__PURE__*/React.createElement("span", {
    className: 'ex-arrow d' + (handPos === 'd' ? ' hit' : '') + (phase === 'speed' ? ' fast' : '')
  }, /*#__PURE__*/React.createElement(Ico.down, null)), /*#__PURE__*/React.createElement("span", {
    className: 'ex-arrow r' + (handPos === 'r' ? ' hit' : '')
  }, /*#__PURE__*/React.createElement(Ico.right, null)), /*#__PURE__*/React.createElement("div", {
    className: 'ex-hand pos-' + handPos + (phase === 'speed' ? ' rapid' : '')
  }, /*#__PURE__*/React.createElement(Ico.hand, null))));
}

/* summary beat — the post-game reward, shown as a mini end-card */
function ExSummary() {
  const rows = [['כמיהה', 'געגוע'], ['נלוז', 'עקום, מושחת'], ['רהב', 'גאווה']];
  return /*#__PURE__*/React.createElement("div", {
    className: "ex-summary"
  }, /*#__PURE__*/React.createElement("div", {
    className: "ex-sum-title"
  }, "\u05D4\u05DE\u05D9\u05DC\u05D9\u05DD \u05E9\u05DC\u05D0 \u05D9\u05D3\u05E2\u05EA", /*#__PURE__*/React.createElement("span", {
    className: "dot"
  }, ".")), /*#__PURE__*/React.createElement("div", {
    className: "ex-sum-list"
  }, rows.map((r, i) => /*#__PURE__*/React.createElement("div", {
    key: i,
    className: "ex-sum-row",
    style: {
      animationDelay: i * 0.15 + 's'
    }
  }, /*#__PURE__*/React.createElement("span", {
    className: "en he"
  }, r[0]), /*#__PURE__*/React.createElement("span", {
    className: "he"
  }, r[1])))), /*#__PURE__*/React.createElement("div", {
    className: "ex-sum-actions"
  }, /*#__PURE__*/React.createElement("span", {
    className: "ex-sum-btn share"
  }, /*#__PURE__*/React.createElement(Ico.share, null), "\u05E9\u05D9\u05EA\u05D5\u05E3"), /*#__PURE__*/React.createElement("span", {
    className: "ex-sum-btn again"
  }, /*#__PURE__*/React.createElement(Ico.refresh, null), "\u05E1\u05D9\u05D1\u05D5\u05D1 \u05E2\u05DC \u05D0\u05DC\u05D5")));
}

/* perks & challenges beat — the final tutorial screen */
function ExPerks() {
  const perks = [{
    ic: 'fifty',
    t: '50 · 50',
    s: 'להסתיר שני פירושים שגויים'
  }, {
    ic: 'rowclear',
    t: 'ניפוץ שורה',
    s: 'מקצר את המגדל בשורה',
    badge: 'חדש'
  }, {
    ic: 'down',
    t: 'קצב מואץ',
    s: 'כל שלב המילים נופלות מהר יותר'
  }];
  return /*#__PURE__*/React.createElement("div", {
    className: "ex-perks"
  }, /*#__PURE__*/React.createElement("div", {
    className: "ex-perks-gift"
  }, /*#__PURE__*/React.createElement(Ico.gift, null)), /*#__PURE__*/React.createElement("div", {
    className: "ex-perks-list"
  }, perks.map((p, i) => /*#__PURE__*/React.createElement("div", {
    key: i,
    className: "ex-perk",
    style: {
      animationDelay: i * 0.12 + 's'
    }
  }, /*#__PURE__*/React.createElement("span", {
    className: 'ex-perk-ic ' + p.ic
  }, p.ic === 'fifty' ? /*#__PURE__*/React.createElement("span", {
    className: "fifty-txt"
  }, "50", /*#__PURE__*/React.createElement("br", null), "50") : Ico[p.ic]()), /*#__PURE__*/React.createElement("span", {
    className: "ex-perk-tx"
  }, /*#__PURE__*/React.createElement("span", {
    className: "t"
  }, p.t, p.badge && /*#__PURE__*/React.createElement("span", {
    className: "nw"
  }, p.badge)), /*#__PURE__*/React.createElement("span", {
    className: "s"
  }, p.s))))));
}
const EX_STEPS = [{
  key: 'move',
  title: 'מזיזים ובוחרים',
  cap: 'החליקו את המילה עם ◄ ► עד לפירוש הנכון'
}, {
  key: 'speed',
  title: 'מאיצים וצוברים',
  cap: 'כל לחיצה על ▼ מפילה מהר יותר — ומזניקה את הניקוד'
}, {
  key: 'correct',
  title: 'פירוש נכון = ניפוץ',
  cap: 'נחיתה על הפירוש הנכון מנפצת לבנה מהמגדל'
}, {
  key: 'mistake',
  title: 'טעות = המגדל גדל',
  cap: 'טעות משאירה לבנה. כשהמגדל מגיע לקו האדום — נפסלים'
}, {
  key: 'summary',
  title: 'המילים שלא ידעת',
  cap: 'בסוף מקבלים את רשימת המילים — לשיתוף, או לסיבוב נוסף שמתמקד בהן'
}, {
  key: 'perks',
  title: "צ'ופרים ואתגרים",
  cap: 'ככל שתתקדמו תקבלו יכולות חדשות — והקצב שבו צריך לענות מואץ'
}];
function Explainer({
  onNext,
  muted,
  toggleMute,
  toggleFs
}) {
  const [step, setStep] = useState(0);
  const [paused, setPaused] = useState(false);
  const last = EX_STEPS.length - 1;
  useEffect(() => {
    if (paused) return;
    const t = setTimeout(() => setStep(s => (s + 1) % EX_STEPS.length), step === last ? 5200 : 4200);
    return () => clearTimeout(t);
  }, [step, paused, last]);
  const go = i => {
    setPaused(true);
    setStep((i + EX_STEPS.length) % EX_STEPS.length);
  };
  const cur = EX_STEPS[step];
  return /*#__PURE__*/React.createElement("div", {
    className: "gm-app"
  }, /*#__PURE__*/React.createElement("div", {
    className: "gm-frame"
  }, /*#__PURE__*/React.createElement("div", {
    className: "gm-intro gm-explainer"
  }, /*#__PURE__*/React.createElement("div", {
    className: "gm-intro-actions"
  }, /*#__PURE__*/React.createElement("button", {
    className: "gm-round-btn",
    onClick: toggleFs,
    title: "\u05DE\u05E1\u05DA \u05DE\u05DC\u05D0"
  }, /*#__PURE__*/React.createElement(Ico.expand, null)), /*#__PURE__*/React.createElement("button", {
    className: "gm-round-btn fifty",
    onClick: toggleMute,
    title: "\u05E1\u05D0\u05D5\u05E0\u05D3"
  }, muted ? /*#__PURE__*/React.createElement(Ico.mute, null) : /*#__PURE__*/React.createElement(Ico.sound, null))), /*#__PURE__*/React.createElement("button", {
    className: "gm-intro-skip",
    onClick: onNext
  }, /*#__PURE__*/React.createElement("span", null, "\u05D3\u05DC\u05D2"), /*#__PURE__*/React.createElement(Ico.go, null)), /*#__PURE__*/React.createElement("div", {
    className: "gm-intro-brand ex-brand"
  }, /*#__PURE__*/React.createElement("img", {
    src: EZ_ICON,
    alt: ""
  }), /*#__PURE__*/React.createElement("span", {
    className: "brand-eazy"
  }, "eazy")), /*#__PURE__*/React.createElement("div", {
    className: "ex-visual",
    key: step
  }, cur.key === 'summary' ? /*#__PURE__*/React.createElement(ExSummary, null) : cur.key === 'perks' ? /*#__PURE__*/React.createElement(ExPerks, null) : /*#__PURE__*/React.createElement(ExStage, {
    phase: cur.key
  })), /*#__PURE__*/React.createElement("div", {
    className: "ex-textblock"
  }, /*#__PURE__*/React.createElement("div", {
    className: "ex-step-n"
  }, step + 1, /*#__PURE__*/React.createElement("span", {
    className: "tot"
  }, " / ", EX_STEPS.length)), /*#__PURE__*/React.createElement("div", {
    className: "ex-head"
  }, cur.title), /*#__PURE__*/React.createElement("div", {
    className: "ex-caption"
  }, cur.cap)), /*#__PURE__*/React.createElement("div", {
    className: "ex-dots"
  }, EX_STEPS.map((_, i) => /*#__PURE__*/React.createElement("button", {
    key: i,
    className: 'ex-dot' + (i === step ? ' on' : ''),
    onClick: () => go(i),
    "aria-label": 'שלב ' + (i + 1)
  }))), /*#__PURE__*/React.createElement("div", {
    className: "ex-nav"
  }, /*#__PURE__*/React.createElement("button", {
    className: "ex-nav-btn ghost",
    onClick: () => go(step - 1)
  }, /*#__PURE__*/React.createElement(Ico.right, null)), step === last ? /*#__PURE__*/React.createElement("button", {
    className: "gm-start ex-start",
    onClick: onNext
  }, /*#__PURE__*/React.createElement("span", null, "\u05DE\u05EA\u05D7\u05D9\u05DC\u05D9\u05DD \u05DC\u05E9\u05D7\u05E7"), /*#__PURE__*/React.createElement(Ico.go, null)) : /*#__PURE__*/React.createElement("button", {
    className: "gm-start ex-start",
    onClick: () => go(step + 1)
  }, /*#__PURE__*/React.createElement("span", null, "\u05D4\u05D1\u05D0"), /*#__PURE__*/React.createElement(Ico.left, null)), /*#__PURE__*/React.createElement("button", {
    className: "ex-nav-btn ghost",
    onClick: () => go(step + 1)
  }, /*#__PURE__*/React.createElement(Ico.left, null))))));
}
function MainIntro({
  onPick,
  muted,
  toggleMute,
  toggleFs
}) {
  const rain = useMemo(() => Array.from({
    length: 14
  }, (_, i) => ({
    left: (i * 7.3 + i % 3 * 4) % 96,
    size: 18 + i % 4 * 8,
    dur: 6 + i % 5 * 1.6,
    delay: -(i * 0.9),
    color: randColor(i + 3)
  })), []);
  const cats = window.VOCAB_CATEGORIES || [];
  return /*#__PURE__*/React.createElement("div", {
    className: "gm-app"
  }, /*#__PURE__*/React.createElement("div", {
    className: "gm-frame"
  }, /*#__PURE__*/React.createElement("div", {
    className: "gm-intro gm-home"
  }, /*#__PURE__*/React.createElement("div", {
    className: "gm-intro-rain",
    "aria-hidden": true
  }, rain.map((r, i) => /*#__PURE__*/React.createElement("div", {
    key: i,
    className: "tb",
    style: {
      left: r.left + '%',
      width: r.size,
      height: r.size,
      background: r.color,
      animationDuration: r.dur + 's',
      animationDelay: r.delay + 's'
    }
  }))), /*#__PURE__*/React.createElement("div", {
    className: "gm-intro-actions"
  }, /*#__PURE__*/React.createElement("button", {
    className: "gm-round-btn",
    onClick: toggleFs,
    title: "\u05DE\u05E1\u05DA \u05DE\u05DC\u05D0"
  }, /*#__PURE__*/React.createElement(Ico.expand, null)), /*#__PURE__*/React.createElement("button", {
    className: "gm-round-btn fifty",
    onClick: toggleMute,
    title: "\u05E1\u05D0\u05D5\u05E0\u05D3"
  }, muted ? /*#__PURE__*/React.createElement(Ico.mute, null) : /*#__PURE__*/React.createElement(Ico.sound, null))), /*#__PURE__*/React.createElement("button", {
    className: "gm-intro-home",
    title: "\u05DC\u05D0\u05EA\u05E8 ezway",
    onClick: () => {
      try {
        window.top.location.href = 'https://www.ezway.co.il';
      } catch (e) {
        window.open('https://www.ezway.co.il', '_blank');
      }
    }
  }, /*#__PURE__*/React.createElement(Ico.home, null)), /*#__PURE__*/React.createElement("div", {
    className: "gm-home-inner"
  }, /*#__PURE__*/React.createElement("div", {
    className: "gm-intro-brand"
  }, /*#__PURE__*/React.createElement("img", {
    src: EZ_ICON,
    alt: ""
  }), /*#__PURE__*/React.createElement("span", {
    className: "brand-eazy"
  }, "eazy")), /*#__PURE__*/React.createElement("h1", {
    className: "gm-home-title"
  }, "\u05D8\u05D8\u05E8\u05D9 \u05D0\u05D5\u05E6\u05E8 \u05DE\u05D9\u05DC\u05D9\u05DD", /*#__PURE__*/React.createElement("span", {
    className: "dot"
  }, ".")), /*#__PURE__*/React.createElement("p", {
    className: "gm-home-lead"
  }, "\u05DE\u05D9\u05DC\u05D4 \u05E0\u05D5\u05E4\u05DC\u05EA \u05DE\u05DC\u05DE\u05E2\u05DC\u05D4. ", /*#__PURE__*/React.createElement("br", {
    className: "m-br"
  }), "\u05D4\u05D6\u05D9\u05D6\u05D5 \u05D0\u05D5\u05EA\u05D4 \u05D0\u05DC \u05D4\u05E4\u05D9\u05E8\u05D5\u05E9 \u05D4\u05E0\u05DB\u05D5\u05DF ", /*#__PURE__*/React.createElement("br", {
    className: "m-br"
  }), "\u05DC\u05E4\u05E0\u05D9 \u05E9\u05D4\u05D9\u05D0 \u05E0\u05D5\u05D7\u05EA\u05EA."), /*#__PURE__*/React.createElement("button", {
    className: "gm-home-quiz",
    onClick: () => onPick({
      type: 'quiz'
    })
  }, /*#__PURE__*/React.createElement("span", {
    className: "q-ic"
  }, /*#__PURE__*/React.createElement(Ico.trophy, null)), /*#__PURE__*/React.createElement("span", {
    className: "q-tx"
  }, /*#__PURE__*/React.createElement("span", {
    className: "t"
  }, "\u05D1\u05D5\u05D7\u05DF \u05E4\u05EA\u05D9\u05D7\u05D4"), /*#__PURE__*/React.createElement("span", {
    className: "s"
  }, "10 \u05D1\u05D9\u05D8\u05D5\u05D9\u05D9\u05DD \u05D0\u05E7\u05D3\u05DE\u05D9\u05D9\u05DD \xB7 100 \u05E9\u05E0\u05D9\u05D5\u05EA")), /*#__PURE__*/React.createElement("span", {
    className: "q-go"
  }, /*#__PURE__*/React.createElement(Ico.go, null))), /*#__PURE__*/React.createElement("div", {
    className: "gm-home-or"
  }, /*#__PURE__*/React.createElement("span", null, "\u05D0\u05D5 \u05D1\u05D7\u05E8\u05D5 \u05E7\u05D8\u05D2\u05D5\u05E8\u05D9\u05D4")), /*#__PURE__*/React.createElement("div", {
    className: "gm-home-cats"
  }, cats.map((c, i) => /*#__PURE__*/React.createElement("button", {
    key: c.id,
    className: 'gm-cat cat' + i % 4,
    onClick: () => onPick({
      type: 'category',
      catId: c.id
    })
  }, /*#__PURE__*/React.createElement("span", {
    className: "cat-name"
  }, c.name)))), /*#__PURE__*/React.createElement("button", {
    className: "gm-home-all",
    onClick: () => onPick({
      type: 'all'
    })
  }, "\u05DB\u05DC \u05D4\u05E7\u05D8\u05D2\u05D5\u05E8\u05D9\u05D5\u05EA \u05D9\u05D7\u05D3")))));
}
function IntroScreen({
  onStart,
  muted,
  toggleMute,
  toggleFs
}) {
  const [stage, setStage] = useState('home');
  const pendingRef = useRef(null);
  const EXPLAINER_KEY = 'tv-explainer-seen-v1';
  const seen = () => {
    try {
      return localStorage.getItem(EXPLAINER_KEY) === '1';
    } catch (e) {
      return false;
    }
  };
  const begin = mode => {
    pendingRef.current = mode;
    if (seen()) onStart(mode);else setStage('explainer');
  };
  const finishExplainer = () => {
    try {
      localStorage.setItem(EXPLAINER_KEY, '1');
    } catch (e) {}
    onStart(pendingRef.current);
  };
  if (stage === 'explainer') return /*#__PURE__*/React.createElement(Explainer, {
    onNext: finishExplainer,
    muted: muted,
    toggleMute: toggleMute,
    toggleFs: toggleFs
  });
  return /*#__PURE__*/React.createElement(MainIntro, {
    onPick: begin,
    muted: muted,
    toggleMute: toggleMute,
    toggleFs: toggleFs
  });
}

/* ════════════════ End screen ════════════════ */
function EndScreen({
  score,
  missedWords,
  correctCount,
  answered,
  onRestart,
  onReviewRound
}) {
  const [note, setNote] = useState(null);
  // merge this round's mistakes into the persistent (per-browser) review list, once.
  const [review, setReview] = useState(() => addReview(missedWords));
  const roundCount = missedWords.length;
  const buildText = () => {
    const lines = review.map(w => `${w.en} — ${w.he}`).join('\n');
    return `טטרי אוצר מילים · רשימת המילים לחזרה\n\n${lines}\n\nמשחק אוצר מילים מבית eazy · ezway.co.il`;
  };
  const onShare = async () => {
    const text = buildText();
    try {
      if (navigator.share) {
        await navigator.share({
          title: 'טטרי אוצר מילים',
          text
        });
        return;
      }
    } catch (e) {
      if (e && e.name === 'AbortError') return;
    }
    try {
      await navigator.clipboard.writeText(text);
      setNote('הרשימה הועתקה — אפשר להדביק בכל מקום.');
      setTimeout(() => setNote(null), 2500);
    } catch (e) {
      setNote('לא ניתן לשתף בדפדפן הזה.');
      setTimeout(() => setNote(null), 2500);
    }
  };
  const onPrint = () => {
    try {
      window.print();
    } catch (e) {}
  };
  const onClear = () => {
    clearReview();
    setReview([]);
    setNote('רשימת החזרה נוקתה.');
    setTimeout(() => setNote(null), 2200);
  };
  const today = new Date().toLocaleDateString('he-IL');
  return /*#__PURE__*/React.createElement("div", {
    className: "gm-app"
  }, /*#__PURE__*/React.createElement("div", {
    className: "gm-frame"
  }, /*#__PURE__*/React.createElement("div", {
    className: "gm-end"
  }, /*#__PURE__*/React.createElement("div", {
    className: "gm-end-head"
  }, /*#__PURE__*/React.createElement("button", {
    className: "gm-end-home",
    title: "\u05D0\u05EA\u05E8 eazy",
    onClick: () => {
      try {
        window.top.location.href = 'https://www.ezway.co.il';
      } catch (e) {
        window.open('https://www.ezway.co.il', '_top');
      }
    }
  }, /*#__PURE__*/React.createElement(Ico.home, null)), /*#__PURE__*/React.createElement("div", {
    className: "gm-end-brand"
  }, /*#__PURE__*/React.createElement("img", {
    src: EZ_ICON,
    alt: ""
  }), /*#__PURE__*/React.createElement("span", {
    className: "brand-eazy"
  }, "eazy", /*#__PURE__*/React.createElement("span", {
    style: {
      color: 'var(--tx-orange)'
    }
  }, ".")))), /*#__PURE__*/React.createElement("div", {
    className: "gm-end-top"
  }, /*#__PURE__*/React.createElement("div", {
    className: "gm-end-title"
  }, "\u05E1\u05D5\u05E3 \u05E1\u05D9\u05D1\u05D5\u05D1", /*#__PURE__*/React.createElement("span", {
    className: "dot"
  }, ".")), /*#__PURE__*/React.createElement("div", {
    className: "gm-end-scorechip"
  }, /*#__PURE__*/React.createElement("span", {
    className: "lbl"
  }, "\u05E0\u05D9\u05E7\u05D5\u05D3"), /*#__PURE__*/React.createElement("span", {
    className: "num"
  }, score))), /*#__PURE__*/React.createElement("div", {
    className: "gm-end-stats"
  }, /*#__PURE__*/React.createElement("div", {
    className: "gm-stat"
  }, /*#__PURE__*/React.createElement("span", {
    className: "v"
  }, answered > 0 ? Math.round(correctCount / answered * 100) : 0, "%"), /*#__PURE__*/React.createElement("span", {
    className: "k"
  }, "\u05D0\u05D7\u05D5\u05D6 \u05D4\u05E6\u05DC\u05D7\u05D4")), /*#__PURE__*/React.createElement("div", {
    className: "gm-stat"
  }, /*#__PURE__*/React.createElement("span", {
    className: "v ok"
  }, correctCount), /*#__PURE__*/React.createElement("span", {
    className: "k"
  }, "\u05E0\u05DB\u05D5\u05E0\u05D5\u05EA")), /*#__PURE__*/React.createElement("div", {
    className: "gm-stat"
  }, /*#__PURE__*/React.createElement("span", {
    className: "v miss"
  }, Math.max(0, answered - correctCount)), /*#__PURE__*/React.createElement("span", {
    className: "k"
  }, "\u05D8\u05E2\u05D5\u05D9\u05D5\u05EA"))), /*#__PURE__*/React.createElement("div", {
    className: "gm-end-listwrap"
  }, review.length > 0 ? /*#__PURE__*/React.createElement(React.Fragment, null, /*#__PURE__*/React.createElement("div", {
    className: "gm-end-eye"
  }, "\u05E8\u05E9\u05D9\u05DE\u05EA \u05D4\u05DE\u05D9\u05DC\u05D9\u05DD \u05DC\u05D7\u05D6\u05E8\u05D4", /*#__PURE__*/React.createElement("span", {
    className: "cnt"
  }, review.length)), /*#__PURE__*/React.createElement("div", {
    className: "gm-end-sub"
  }, roundCount > 0 ? `${roundCount} נוספו בסיבוב הזה · ` : '', "\u05E0\u05E9\u05DE\u05E8 \u05D1\u05D3\u05E4\u05D3\u05E4\u05DF \u05D4\u05D6\u05D4 \u05D5\u05DE\u05EA\u05E2\u05D3\u05DB\u05DF \u05D1\u05DB\u05DC \u05E1\u05D9\u05D1\u05D5\u05D1"), /*#__PURE__*/React.createElement("div", {
    className: "gm-end-list"
  }, review.map((w, i) => /*#__PURE__*/React.createElement("div", {
    key: i,
    className: "gm-end-row"
  }, /*#__PURE__*/React.createElement("span", {
    className: "gm-end-en"
  }, w.en), /*#__PURE__*/React.createElement("span", {
    className: "gm-end-he"
  }, w.he))))) : /*#__PURE__*/React.createElement("div", {
    className: "gm-end-nomiss"
  }, /*#__PURE__*/React.createElement("span", {
    className: "hi"
  }, "\u05DE\u05D5\u05E9\u05DC\u05DD", /*#__PURE__*/React.createElement("span", {
    style: {
      color: 'var(--tx-orange)'
    }
  }, "!")), /*#__PURE__*/React.createElement("span", {
    className: "lo"
  }, "\u05D0\u05D9\u05DF \u05DE\u05D9\u05DC\u05D9\u05DD \u05DC\u05D7\u05D6\u05E8\u05D4."))), review.length > 0 && /*#__PURE__*/React.createElement(React.Fragment, null, /*#__PURE__*/React.createElement("div", {
    className: "gm-end-actions"
  }, /*#__PURE__*/React.createElement("button", {
    className: "gm-end-tool",
    onClick: onShare
  }, /*#__PURE__*/React.createElement(Ico.share, null), /*#__PURE__*/React.createElement("span", null, "\u05E9\u05D9\u05EA\u05D5\u05E3")), /*#__PURE__*/React.createElement("button", {
    className: "gm-end-tool",
    onClick: onPrint
  }, /*#__PURE__*/React.createElement(Ico.print, null), /*#__PURE__*/React.createElement("span", null, "\u05E9\u05DE\u05D9\u05E8\u05D4 / \u05D4\u05D3\u05E4\u05E1\u05D4"))), /*#__PURE__*/React.createElement("button", {
    className: "gm-end-clear",
    onClick: onClear
  }, "\u05E0\u05D9\u05E7\u05D5\u05D9 \u05E8\u05E9\u05D9\u05DE\u05EA \u05D4\u05D7\u05D6\u05E8\u05D4")), note && /*#__PURE__*/React.createElement("div", {
    className: "gm-end-note"
  }, note), /*#__PURE__*/React.createElement("div", {
    className: "gm-end-cta-row"
  }, review.length > 0 && /*#__PURE__*/React.createElement("button", {
    className: "gm-end-cta review",
    onClick: onReviewRound
  }, /*#__PURE__*/React.createElement("span", null, "\u05E1\u05D9\u05D1\u05D5\u05D1 \u05D8\u05E2\u05D5\u05D9\u05D5\u05EA"), /*#__PURE__*/React.createElement("span", {
    className: "badge"
  }, review.length)), /*#__PURE__*/React.createElement("button", {
    className: "gm-end-cta",
    onClick: onRestart
  }, /*#__PURE__*/React.createElement(Ico.go, null), /*#__PURE__*/React.createElement("span", null, "\u05E1\u05D9\u05D1\u05D5\u05D1 \u05D7\u05D3\u05E9"))), /*#__PURE__*/React.createElement("div", {
    className: "gm-print",
    "aria-hidden": true
  }, /*#__PURE__*/React.createElement("div", {
    className: "p-head"
  }, /*#__PURE__*/React.createElement("div", {
    className: "p-brand"
  }, /*#__PURE__*/React.createElement("img", {
    src: EZ_ICON,
    alt: "eazy"
  }), /*#__PURE__*/React.createElement("span", null, "eazy")), /*#__PURE__*/React.createElement("div", {
    className: "p-meta"
  }, "\u05D8\u05D8\u05E8\u05D9 \u05D0\u05D5\u05E6\u05E8 \u05DE\u05D9\u05DC\u05D9\u05DD \xB7 ", today)), /*#__PURE__*/React.createElement("h1", {
    className: "p-title"
  }, "\u05E8\u05E9\u05D9\u05DE\u05EA \u05D4\u05DE\u05D9\u05DC\u05D9\u05DD \u05DC\u05D7\u05D6\u05E8\u05D4"), /*#__PURE__*/React.createElement("div", {
    className: "p-score"
  }, review.length, " \u05DE\u05D9\u05DC\u05D9\u05DD"), /*#__PURE__*/React.createElement("table", {
    className: "p-table"
  }, /*#__PURE__*/React.createElement("tbody", null, review.map((w, i) => /*#__PURE__*/React.createElement("tr", {
    key: i
  }, /*#__PURE__*/React.createElement("td", {
    className: "p-num"
  }, i + 1), /*#__PURE__*/React.createElement("td", {
    className: "p-en"
  }, w.en), /*#__PURE__*/React.createElement("td", {
    className: "p-he"
  }, w.he))))), /*#__PURE__*/React.createElement("div", {
    className: "p-foot"
  }, "\u05DE\u05E9\u05D7\u05E7 \u05D0\u05D5\u05E6\u05E8 \u05DE\u05D9\u05DC\u05D9\u05DD \u05DE\u05D1\u05D9\u05EA eazy \xB7 ezway.co.il")))));
}

/* ════════════════ Main game ════════════════ */
const COLS = 4;
const ROWS = 9; // playable rows above the bins; overflow past the top = game over
const MAXSTACK = ROWS - 1; // a column this tall reaches the start height
function VocabGame() {
  const [started, setStarted] = useState(false);
  const [dict, setDict] = useState(null);
  const [used, setUsed] = useState([]);
  const [missed, setMissed] = useState([]);
  const [question, setQuestion] = useState(null);
  const [stacks, setStacks] = useState(() => [[], [], [], []]); // junk bricks left by mistakes
  const [score, setScore] = useState(0);
  const [streak, setStreak] = useState(0);
  const [col, setCol] = useState(1);
  const [phase, setPhase] = useState('falling'); // falling | resolving | over
  const [binFx, setBinFx] = useState({}); // {idx:'hit'|'miss'|'reveal'}
  const [pieceFx, setPieceFx] = useState(''); // ''|'correct'|'wrong'
  const [dimmed, setDimmed] = useState(() => new Set());
  const [fiftyUsed, setFiftyUsed] = useState(false);
  const [rowClearUsed, setRowClearUsed] = useState(false);
  const [toast, setToast] = useState(null);
  const [missBanner, setMissBanner] = useState(null); // {en,he} shown briefly on a mistake (flow mode)
  const [studyCard, setStudyCard] = useState(null); // {en,he,dictIdx} — study mode: waits for "next"
  const mistakeCountRef = useRef(0);
  const studyModeRef = useRef(null); // null | 'flow' | 'study'
  const [gate, setGate] = useState(null); // pausing modal: {kind:'level',sub} | {kind:'audio'}
  const [correctCount, setCorrectCount] = useState(0);
  const [timeLeft, setTimeLeft] = useState(QUIZ_SECONDS); // opening-quiz countdown
  const [pool, setPool] = useState(null); // correct-word pool: category / quiz / review / all
  const [muted, setMuted] = useState(Sound.muted);
  const pieceRef = useRef(null);
  const rafRef = useRef(0);
  const sim = useRef({
    fall: 0,
    col: 1,
    locked: true,
    soft: false,
    startT: 0
  });
  const stacksRef = useRef([[], [], [], []]);
  const pausedRef = useRef(false);
  const lastBonusRef = useRef(0);
  const prevLevelRef = useRef(1);
  const quizModeRef = useRef(false);
  const poolRef = useRef(null);
  useEffect(() => {
    pausedRef.current = !!gate;
  }, [gate]);
  const setStacksBoth = useCallback(updater => {
    setStacks(prev => {
      const next = updater(prev);
      stacksRef.current = next;
      return next;
    });
  }, []);
  const level = correctCount < 15 ? 1 : 2 + Math.floor((correctCount - 15) / 20);
  const speedMult = Math.pow(1.02, level - 1); // pace +2% each level
  const fallDur = Math.max(2.0, 6.2 / speedMult); // seconds top→bottom
  const basePts = 200 + (level - 1) * 80;
  const fiftyUnlocked = correctCount >= 15; // unlocked at 15 correct
  const rowClearUnlocked = correctCount >= 35; // unlocked at 35 correct
  // well theme: default (dark) for levels 1–2, then cycle the approved tints from level 3
  const wellStyle = level >= 3 ? (t => ({
    '--well-top': t.top,
    '--well-bot': t.bot,
    '--well-glow': t.glow,
    '--well-wm': 0.16
  }))(LEVEL_THEMES[(level - 3) % LEVEL_THEMES.length]) : undefined;

  /* ── load the Hebrew word bank ── */
  useEffect(() => {
    const bank = loadBank();
    if (bank.length >= 4) {
      setDict(bank);
    }
  }, []);

  /* ── draw a question whenever needed ── */
  useEffect(() => {
    if (!dict || !started || phase === 'over') return;
    if (question) return;
    const src = pool && pool.length > 0 ? pool : dict;
    const avail = src.map((_, i) => i).filter(i => !used.includes(i));
    if (avail.length === 0) {
      if (quizModeRef.current) {
        setPhase('over');
        return;
      } // opening quiz: end after the fixed set
      setUsed([]);
      return;
    }
    // quiz mode keeps the fixed order; free play is random
    const idx = quizModeRef.current ? avail[0] : avail[Math.random() * avail.length | 0];
    const q = buildQuestion(src[idx], dict, idx);
    setQuestion(q);
    // always spawn from the second column from the right (index 2, field is LTR)
    const startCol = 2;
    setCol(startCol);
    setDimmed(new Set());
    setPieceFx('');
    setBinFx({});
    setMissBanner(null);
    sim.current = {
      fall: 0,
      shown: 0,
      col: startCol,
      locked: false,
      soft: false,
      startT: performance.now()
    };
    setPhase('falling');
  }, [dict, started, question, used, phase, pool]);

  /* ── level-up → confetti celebration + refresh power-ups ── */
  const COMPLIMENTS = ['כל הכבוד!', 'מדהים!', 'אלוף/ה!', 'ממשיכים חזק!', 'מרשים ביותר!', 'וואו, איזה קצב!'];
  useEffect(() => {
    if (level > prevLevelRef.current) {
      prevLevelRef.current = level;
      Sound.play('levelup');
      // refresh the power-ups on every level-up
      setFiftyUsed(false);
      setRowClearUsed(false);
      const compliment = COMPLIMENTS[(level - 2) % COMPLIMENTS.length] || 'כל הכבוד!';
      let unlock = null;
      if (level === 2) unlock = {
        ic: 'fifty',
        t: 'נפתח לך גלגל הצלה 50 · 50'
      };else if (level === 3) unlock = {
        ic: 'rowclear',
        t: 'נפתח לך ניפוץ שורה'
      };
      const sub = `הקצב עולה ב-2% · +${basePts} לכל תשובה נכונה`;
      setGate(g => g ? g : {
        kind: 'level',
        level,
        compliment,
        unlock,
        sub
      });
    } else {
      prevLevelRef.current = Math.max(prevLevelRef.current, level);
    }
  }, [level, basePts]);

  /* ── after 5 correct answers — reserved for future perks (audio removed) ── */
  useEffect(() => {}, [correctCount]);

  /* ── opening-quiz countdown (100s) — pauses on any modal, ends the round at 0 ── */
  useEffect(() => {
    if (!started || !quizModeRef.current || phase === 'over') return;
    if (gate || studyCard) return; // pause during modals
    if (timeLeft <= 0) {
      setPhase('over');
      return;
    }
    const t = setTimeout(() => setTimeLeft(v => v - 1), 1000);
    return () => clearTimeout(t);
  }, [started, phase, gate, studyCard, timeLeft]);

  /* ── falling loop (rAF, drives the piece DOM directly) ── */
  useEffect(() => {
    if (!started || !question || phase !== 'falling') return;
    let last = performance.now();
    const tick = now => {
      const dt = Math.min(0.05, (now - last) / 1000);
      last = now;
      const s = sim.current;
      if (!s.locked && !pausedRef.current) {
        const v = 1 / fallDur * (s.soft ? 5 : 1);
        s.fall = Math.min(1, s.fall + v * dt);
        const stackLen = stacksRef.current[s.col].length;
        const rest = Math.max(0, (ROWS - 1 - stackLen) / (ROWS - 1)); // floor for this column
        const shown = Math.min(s.fall, rest);
        s.shown = shown;
        if (pieceRef.current) pieceRef.current.style.setProperty('--fall', shown.toFixed(4));
        if (s.fall >= rest) {
          s.fall = rest;
          s.shown = rest;
          s.locked = true;
          resolveAt(s.col);
          return;
        }
      }
      rafRef.current = requestAnimationFrame(tick);
    };
    rafRef.current = requestAnimationFrame(tick);
    return () => cancelAnimationFrame(rafRef.current);
  }, [started, question, phase, fallDur]);
  const move = useCallback(dir => {
    if (phase !== 'falling' || sim.current.locked || pausedRef.current) return;
    setCol(prev => {
      let c = Math.max(0, Math.min(3, prev + dir));
      while (dimmed.has(c) && c >= 0 && c <= 3) {
        c += dir;
      }
      if (c < 0 || c > 3 || dimmed.has(c)) {
        const allow = [0, 1, 2, 3].filter(x => !dimmed.has(x));
        c = allow.length ? allow.reduce((b, x) => Math.abs(x - prev) < Math.abs(b - prev) ? x : b, allow[0]) : prev;
      }
      // can't slide UNDER a pile taller than the piece's current height (Tetris collision)
      const restTarget = (ROWS - 1 - stacksRef.current[c].length) / (ROWS - 1);
      if (restTarget < sim.current.fall - 0.001) return prev;
      if (c !== prev) {
        sim.current.col = c;
        Sound.play('move');
      }
      return c;
    });
  }, [phase, dimmed]);
  const softDrop = useCallback(() => {
    if (phase !== 'falling' || sim.current.locked || pausedRef.current) return;
    sim.current.soft = true; // hold = keep accelerating
    sim.current.fall = Math.min(0.999, sim.current.fall + 0.05); // each tap nudges it down
    if (pieceRef.current) {
      const rest = (ROWS - 1 - stacksRef.current[sim.current.col].length) / (ROWS - 1);
      const shown = Math.min(sim.current.fall, rest);
      sim.current.shown = shown;
      pieceRef.current.style.setProperty('--fall', shown.toFixed(4));
    }
    Sound.play('move');
  }, [phase]);
  const softRelease = useCallback(() => {
    if (sim.current) sim.current.soft = false;
  }, []);

  /* ── resolve a landing ── */
  const resolveAt = useCallback(c => {
    setPhase('resolving');
    const q = question;
    if (!q) return;
    const correctCol = q.options.indexOf(q.he);
    const correct = c === correctCol;
    if (pieceRef.current) pieceRef.current.style.setProperty('--col', c);
    if (correct) {
      const elapsed = (performance.now() - sim.current.startT) / 1000;
      const speedMult = Math.max(1, Math.min(2, 2 - elapsed / Math.max(1, fallDur)));
      const ns = streak + 1;
      const now = Date.now();
      const cooldown = now - lastBonusRef.current >= 4 * 60 * 1000;
      let comboMult = 1,
        comboBonus = 0,
        comboLabel = null;
      if (ns >= 5 && ns % 5 === 0 && cooldown) {
        if (ns >= 20) {
          comboMult = 3;
          comboLabel = `רצף ${ns} ✦ ×3`;
        } else if (ns >= 10) {
          comboMult = 2;
          comboLabel = `רצף ${ns} ✦ ×2`;
        } else {
          comboBonus = 400;
          comboLabel = `רצף ${ns} ✦ +400`;
        }
        lastBonusRef.current = now;
      }
      const pts = Math.round(basePts * speedMult * comboMult) + comboBonus;
      setScore(s => s + pts);
      setStreak(ns);
      setCorrectCount(n => n + 1);
      setPieceFx('correct');
      setBinFx({
        [c]: 'hit'
      });
      // relief: a correct answer clears one brick off the tallest pile
      setStacksBoth(prev => {
        let ti = -1,
          max = 0;
        prev.forEach((s, i) => {
          if (s.length > max) {
            max = s.length;
            ti = i;
          }
        });
        if (ti < 0) return prev;
        const n = prev.map(a => a.slice());
        n[ti].pop();
        return n;
      });
      Sound.play(comboLabel ? 'streak' : 'hit');
      setToast(comboLabel ? {
        kind: 'streak',
        text: `${comboLabel} · +${pts}`
      } : {
        kind: 'win',
        text: `${speedMult >= 1.6 ? 'מהיר! ' : ''}+${pts}`
      });
      setTimeout(() => setToast(null), 1700);
      setTimeout(() => advance(q.dictIdx), 900);
    } else {
      setStreak(0);
      setPieceFx('wrong');
      setBinFx({
        [c]: 'miss',
        [correctCol]: 'reveal'
      });
      setMissed(m => m.some(w => String(w.en).toLowerCase() === String(q.en).toLowerCase()) ? m : [...m, {
        en: q.en,
        he: q.he
      }]);
      // a mistake leaves a brick behind in that column — Tetris-style.
      // compute overflow SYNCHRONOUSLY from the ref (the state updater runs later).
      const over = stacksRef.current[c].length + 1 >= MAXSTACK;
      setStacksBoth(prev => {
        const n = prev.map(a => a.slice());
        n[c] = [...n[c], randColor(Date.now() + c * 7)];
        return n;
      });
      Sound.play(over ? 'gameover' : 'miss');
      if (over) {
        setTimeout(() => setPhase('over'), 1700);
        return;
      }
      const isFirstMiss = mistakeCountRef.current === 0;
      mistakeCountRef.current++;
      if (isFirstMiss) {
        // first mistake ever → let the player choose how to handle mistakes from now on
        setGate({
          kind: 'firstmiss',
          en: q.en,
          he: q.he,
          dictIdx: q.dictIdx
        });
      } else if (studyModeRef.current === 'study') {
        // study mode → hold on the word until the player taps "next"
        setStudyCard({
          en: q.en,
          he: q.he,
          dictIdx: q.dictIdx
        });
      } else {
        // flow mode → brief banner, auto-advance
        setMissBanner({
          en: q.en,
          he: q.he
        });
        setTimeout(() => advance(q.dictIdx), 2000);
      }
    }
  }, [question, streak, basePts, fallDur, setStacksBoth]);
  const advance = useCallback(dictIdx => {
    setUsed(u => [...u, dictIdx]);
    setQuestion(null); // triggers next draw
  }, []);

  /* ── 50/50 ── */
  const useFifty = useCallback(() => {
    if (fiftyUsed || !fiftyUnlocked || phase !== 'falling' || !question) return;
    const correctCol = question.options.indexOf(question.he);
    const wrongs = [0, 1, 2, 3].filter(i => i !== correctCol);
    setDimmed(new Set(shuffle(wrongs).slice(0, 2)));
    setFiftyUsed(true);
    Sound.play('fifty');
  }, [fiftyUsed, fiftyUnlocked, phase, question]);

  /* ── ניפוץ שורה: clear the bottom row — removes one brick from every stacked column ── */
  const useRowClear = useCallback(() => {
    if (rowClearUsed || !rowClearUnlocked || phase !== 'falling') return;
    const any = stacksRef.current.some(s => s.length > 0);
    if (!any) return;
    setStacksBoth(prev => prev.map(col => col.slice(0, Math.max(0, col.length - 1))));
    setRowClearUsed(true);
    Sound.play('hit');
    setToast({
      kind: 'streak',
      text: 'ניפוץ שורה ✦ המגדל התקצר'
    });
    setTimeout(() => setToast(null), 1500);
  }, [rowClearUsed, rowClearUnlocked, phase, setStacksBoth]);

  /* ── keyboard ── */
  useEffect(() => {
    const onKey = e => {
      if (!started) return;
      if (e.key === 'ArrowLeft') {
        e.preventDefault();
        move(-1);
      } else if (e.key === 'ArrowRight') {
        e.preventDefault();
        move(1);
      } else if (e.key === 'ArrowDown' || e.key === ' ') {
        e.preventDefault();
        softDrop();
      }
    };
    const onUp = e => {
      if (e.key === 'ArrowDown' || e.key === ' ') softRelease();
    };
    window.addEventListener('keydown', onKey);
    window.addEventListener('keyup', onUp);
    return () => {
      window.removeEventListener('keydown', onKey);
      window.removeEventListener('keyup', onUp);
    };
  }, [started, move, softDrop, softRelease]);
  const toggleMute = useCallback(() => {
    const n = !Sound.muted;
    Sound.setMuted(n);
    setMuted(n);
  }, []);
  const toggleFs = useCallback(() => {
    try {
      const t = window.frameElement ? window.frameElement : document.documentElement;
      const d = window.frameElement ? window.parent.document : document;
      const fs = d.fullscreenElement || d.webkitFullscreenElement;
      if (!fs) {
        const r = t.requestFullscreen || t.webkitRequestFullscreen;
        if (r) {
          const p = r.call(t);
          if (p && p.then) p.then(() => {
            try {
              screen.orientation?.lock?.('portrait').catch(() => {});
            } catch (e) {}
          }).catch(() => {});
        }
      } else {
        const x = d.exitFullscreen || d.webkitExitFullscreen;
        if (x) x.call(d);
      }
    } catch (e) {}
  }, []);
  const start = useCallback(mode => {
    Sound.init();
    // mode: {type:'all'|'category'|'quiz', catId?}
    let nextPool = null;
    if (mode && mode.type === 'category' && mode.catId) {
      nextPool = (dict || []).filter(e => e.cat === mode.catId);
    } else if (mode && mode.type === 'quiz') {
      nextPool = buildQuiz(dict || []);
    }
    quizModeRef.current = !!(mode && mode.type === 'quiz');
    setTimeLeft(QUIZ_SECONDS);
    resetRound(nextPool && nextPool.length ? nextPool : null);
    setStarted(true);
  }, [dict, resetRound]);
  const resetRound = useCallback(nextPool => {
    setPool(nextPool);
    poolRef.current = nextPool;
    setUsed([]);
    setMissed([]);
    setScore(0);
    setStreak(0);
    setCorrectCount(0);
    setStacks([[], [], [], []]);
    stacksRef.current = [[], [], [], []];
    setQuestion(null);
    setPhase('falling');
    setFiftyUsed(false);
    setDimmed(new Set());
    setGate(null);
    setStudyCard(null);
    setMissBanner(null);
    setRowClearUsed(false);
    mistakeCountRef.current = 0;
    studyModeRef.current = null;
    prevLevelRef.current = 1;
    lastBonusRef.current = 0;
  }, []);
  const restart = useCallback(() => {
    setTimeLeft(QUIZ_SECONDS);
    resetRound(poolRef.current);
  }, [resetRound]);
  const goHome = useCallback(() => {
    quizModeRef.current = false;
    resetRound(null);
    setStarted(false);
  }, [resetRound]);
  const reviewRound = useCallback(() => {
    const words = getReview();
    if (words.length < 1) return;
    quizModeRef.current = false;
    resetRound(words);
  }, [resetRound]);

  /* ════════ render ════════ */
  if (!started) return /*#__PURE__*/React.createElement(IntroScreen, {
    onStart: start,
    muted: muted,
    toggleMute: toggleMute,
    toggleFs: toggleFs
  });
  if (phase === 'over') {
    return /*#__PURE__*/React.createElement(EndScreen, {
      score: score,
      missedWords: missed,
      correctCount: correctCount,
      answered: correctCount + mistakeCountRef.current,
      onRestart: restart,
      onReviewRound: reviewRound
    });
  }
  if (!dict || !question) {
    return /*#__PURE__*/React.createElement("div", {
      className: "gm-app"
    }, /*#__PURE__*/React.createElement("div", {
      className: "gm-frame",
      style: {
        alignItems: 'center',
        justifyContent: 'center'
      }
    }, /*#__PURE__*/React.createElement("div", {
      style: {
        color: '#fff',
        fontFamily: 'var(--font-body)'
      }
    }, "\u05D8\u05D5\u05E2\u05DF\u2026")));
  }
  const correctCol = question.options.indexOf(question.he);
  return /*#__PURE__*/React.createElement("div", {
    className: "gm-app"
  }, /*#__PURE__*/React.createElement("div", {
    className: "gm-frame"
  }, /*#__PURE__*/React.createElement("div", {
    className: "gm-top"
  }, /*#__PURE__*/React.createElement("div", {
    className: "gm-top-group"
  }, /*#__PURE__*/React.createElement("button", {
    className: "gm-round-btn",
    onClick: toggleMute,
    title: "\u05E1\u05D0\u05D5\u05E0\u05D3"
  }, muted ? /*#__PURE__*/React.createElement(Ico.mute, null) : /*#__PURE__*/React.createElement(Ico.sound, null)), fiftyUnlocked && /*#__PURE__*/React.createElement("button", {
    className: 'gm-round-btn fifty' + (fiftyUsed ? ' used' : ''),
    onClick: useFifty,
    title: "50/50",
    disabled: fiftyUsed
  }, /*#__PURE__*/React.createElement("span", {
    className: "ft"
  }, "50", /*#__PURE__*/React.createElement("br", null), "50")), rowClearUnlocked && /*#__PURE__*/React.createElement("button", {
    className: 'gm-round-btn rowclear' + (rowClearUsed ? ' used' : ''),
    onClick: useRowClear,
    title: "\u05E0\u05D9\u05E4\u05D5\u05E5 \u05E9\u05D5\u05E8\u05D4",
    disabled: rowClearUsed
  }, /*#__PURE__*/React.createElement(Ico.rowclear, null))), /*#__PURE__*/React.createElement("div", {
    className: "gm-level-chip"
  }, quizModeRef.current ? /*#__PURE__*/React.createElement("span", {
    className: 'lv timer' + (timeLeft <= 10 ? ' low' : '')
  }, Math.floor(timeLeft / 60), ":", String(timeLeft % 60).padStart(2, '0')) : /*#__PURE__*/React.createElement("span", {
    className: "lv"
  }, "\u05E9\u05DC\u05D1 ", /*#__PURE__*/React.createElement("b", null, level))), /*#__PURE__*/React.createElement("div", {
    className: "gm-top-group"
  }, /*#__PURE__*/React.createElement("button", {
    className: "gm-round-btn mail",
    title: "\u05E6\u05E8\u05D5 \u05E7\u05E9\u05E8",
    onClick: () => {
      try {
        window.top.location.href = 'https://www.ezway.co.il/contact/';
      } catch (e) {
        window.open('https://www.ezway.co.il/contact/', '_blank');
      }
    }
  }, /*#__PURE__*/React.createElement(Ico.mail, null)), /*#__PURE__*/React.createElement("button", {
    className: "gm-round-btn",
    onClick: toggleFs,
    title: "\u05DE\u05E1\u05DA \u05DE\u05DC\u05D0"
  }, /*#__PURE__*/React.createElement(Ico.expand, null)))), /*#__PURE__*/React.createElement("div", {
    className: "gm-well",
    style: wellStyle
  }, /*#__PURE__*/React.createElement(Wall, {
    side: "left",
    n: 14
  }), /*#__PURE__*/React.createElement(Wall, {
    side: "right",
    n: 14
  }), /*#__PURE__*/React.createElement("div", {
    className: "gm-field"
  }, /*#__PURE__*/React.createElement("div", {
    className: "gm-dangerline"
  }), stacks.map((colBricks, c) => colBricks.map((color, k) => /*#__PURE__*/React.createElement("div", {
    key: c + '-' + k,
    className: 'gm-stackbrick' + (k >= MAXSTACK - 2 ? ' danger' : ''),
    style: {
      '--col': c,
      '--k': k,
      background: color
    }
  }))), /*#__PURE__*/React.createElement("div", {
    className: "gm-ghost",
    style: {
      '--col': col
    }
  }), /*#__PURE__*/React.createElement("div", {
    ref: pieceRef,
    className: 'gm-piece he ' + pieceFx + (question.en.length > 9 ? ' twoline' : ''),
    style: {
      '--col': col,
      '--cx': col * 25 + 12.5 + '%',
      '--fall': sim.current.shown || 0
    }
  }, question.en), /*#__PURE__*/React.createElement("div", {
    className: "gm-bins"
  }, question.options.map((opt, i) => {
    let cls = 'gm-bin';
    if (binFx[i]) cls += ' ' + binFx[i];
    if (dimmed.has(i)) cls += ' dim';else if (phase === 'falling' && i === col) cls += ' target';
    return /*#__PURE__*/React.createElement("div", {
      key: i,
      className: cls
    }, opt);
  }))), toast && /*#__PURE__*/React.createElement("div", {
    className: 'gm-toast ' + toast.kind
  }, toast.text), missBanner && /*#__PURE__*/React.createElement("div", {
    className: "gm-missbanner"
  }, /*#__PURE__*/React.createElement("div", {
    className: "mb-word"
  }, /*#__PURE__*/React.createElement("span", {
    className: "en"
  }, missBanner.en), /*#__PURE__*/React.createElement("span", {
    className: "sep"
  }, "="), /*#__PURE__*/React.createElement("span", {
    className: "he"
  }, missBanner.he)), /*#__PURE__*/React.createElement("div", {
    className: "mb-note"
  }, "\u05D4\u05DE\u05D9\u05DC\u05D4 \u05EA\u05D5\u05E4\u05D9\u05E2 \u05D1\u05E1\u05D9\u05DB\u05D5\u05DD \u05D1\u05E1\u05D5\u05E3 \u05D4\u05DE\u05E9\u05D7\u05E7")), gate && /*#__PURE__*/React.createElement("div", {
    className: "gm-levelup"
  }, gate.kind === 'level' ? /*#__PURE__*/React.createElement(React.Fragment, null, /*#__PURE__*/React.createElement("div", {
    className: "gm-confetti",
    "aria-hidden": true
  }, Array.from({
    length: 28
  }).map((_, i) => /*#__PURE__*/React.createElement("span", {
    key: i,
    className: "cf",
    style: {
      left: (i * 3.4 + i % 5 * 2) % 100 + '%',
      background: TET_COLORS[i % TET_COLORS.length],
      animationDelay: -(i % 9) * 0.13 + 's',
      animationDuration: 2.4 + i % 4 * 0.5 + 's',
      transform: `rotate(${i * 40}deg)`
    }
  }))), /*#__PURE__*/React.createElement("div", {
    className: "gm-levelup-eyebrow"
  }, gate.compliment), /*#__PURE__*/React.createElement("div", {
    className: "gm-levelup-title"
  }, "\u05E9\u05DC\u05D1 ", gate.level, /*#__PURE__*/React.createElement("span", {
    className: "dot"
  }, "!")), gate.unlock && /*#__PURE__*/React.createElement("div", {
    className: 'gm-levelup-unlock ' + gate.unlock.ic
  }, /*#__PURE__*/React.createElement("span", {
    className: "ul-ic"
  }, gate.unlock.ic === 'fifty' ? /*#__PURE__*/React.createElement("span", {
    className: "fifty-txt"
  }, "50", /*#__PURE__*/React.createElement("br", null), "50") : Ico.rowclear()), /*#__PURE__*/React.createElement("span", {
    className: "ul-t"
  }, gate.unlock.t)), /*#__PURE__*/React.createElement("div", {
    className: "gm-levelup-sub"
  }, gate.sub), /*#__PURE__*/React.createElement("div", {
    className: "gm-levelup-btnrow"
  }, /*#__PURE__*/React.createElement("button", {
    className: "gm-levelup-cta",
    onClick: () => setGate(null)
  }, "\u05DE\u05DE\u05E9\u05D9\u05DB\u05D9\u05DD", /*#__PURE__*/React.createElement("span", {
    className: "dot"
  }, ".")))) : gate.kind === 'firstmiss' ? /*#__PURE__*/React.createElement(React.Fragment, null, /*#__PURE__*/React.createElement("div", {
    className: "gm-levelup-title"
  }, "\u05DE\u05D4 \u05D4\u05D4\u05E2\u05D3\u05E4\u05D4 \u05E9\u05DC\u05DA \u05DB\u05E9\u05D8\u05E2\u05D9\u05EA", /*#__PURE__*/React.createElement("span", {
    className: "dot"
  }, "?")), /*#__PURE__*/React.createElement("div", {
    className: "gm-missreveal"
  }, /*#__PURE__*/React.createElement("span", {
    className: "en"
  }, gate.en), /*#__PURE__*/React.createElement("span", {
    className: "sep"
  }, "="), /*#__PURE__*/React.createElement("span", {
    className: "he"
  }, gate.he)), /*#__PURE__*/React.createElement("div", {
    className: "gm-levelup-sub"
  }, "\u05D1\u05DB\u05DC \u05D8\u05E2\u05D5\u05EA \u05DC\u05E2\u05E6\u05D5\u05E8 \u05DC\u05D4\u05EA\u05E2\u05DE\u05E7 \u05D1\u05DE\u05D9\u05DC\u05D4 \u05D5\u05D0\u05D7\u05E8\u05D9 \u05D6\u05D4 \u05DC\u05DC\u05D7\u05D5\u05E5 \u05D4\u05D1\u05D0, \u05D0\u05D5 \u05E9\u05DE\u05E1\u05E4\u05D9\u05E7 \u05DC\u05DA \u05D4\u05E6\u05E6\u05D4 \u05D6\u05E8\u05D9\u05D6\u05D4 \u05D1\u05EA\u05E9\u05D5\u05D1\u05D4 \u05D4\u05E0\u05DB\u05D5\u05E0\u05D4 \u05D5\u05D4\u05DE\u05E9\u05DA \u05D0\u05D5\u05D8\u05D5\u05DE\u05D8\u05D9 \u05DC\u05E9\u05D0\u05DC\u05D4 \u05D4\u05D1\u05D0\u05D4? \u05D1\u05DB\u05DC \u05DE\u05E7\u05E8\u05D4 \u05DB\u05DC \u05D4\u05E9\u05D2\u05D9\u05D0\u05D5\u05EA \u05DE\u05E8\u05D5\u05DB\u05D6\u05D5\u05EA \u05D1\u05E1\u05D5\u05E3 \u05D4\u05DE\u05E9\u05D7\u05E7 \u05DC\u05E6\u05E4\u05D9\u05D4/\u05E9\u05D9\u05EA\u05D5\u05E3/\u05E1\u05D9\u05D1\u05D5\u05D1 \u05DE\u05E8\u05D5\u05DB\u05D6"), /*#__PURE__*/React.createElement("div", {
    className: "gm-levelup-btnrow col"
  }, /*#__PURE__*/React.createElement("button", {
    className: "gm-levelup-cta purple",
    onClick: () => {
      studyModeRef.current = 'study';
      setStudyCard({
        en: gate.en,
        he: gate.he,
        dictIdx: gate.dictIdx
      });
      setGate(null);
    }
  }, "\u05DC\u05E2\u05E6\u05D5\u05E8 \u05DC\u05D4\u05EA\u05E2\u05DE\u05E7"), /*#__PURE__*/React.createElement("button", {
    className: "gm-levelup-cta green",
    onClick: () => {
      studyModeRef.current = 'flow';
      const d = gate.dictIdx;
      setGate(null);
      advance(d);
    }
  }, "\u05DC\u05D4\u05DE\u05E9\u05D9\u05DA \u05D0\u05D5\u05D8\u05D5\u05DE\u05D8\u05D9\u05EA"))) : null), studyCard && /*#__PURE__*/React.createElement("div", {
    className: "gm-levelup study"
  }, /*#__PURE__*/React.createElement("div", {
    className: "gm-study-eyebrow"
  }, "\u05DB\u05D3\u05D0\u05D9 \u05DC\u05D6\u05DB\u05D5\u05E8", /*#__PURE__*/React.createElement("span", {
    className: "dot"
  }, ".")), /*#__PURE__*/React.createElement("div", {
    className: "gm-missreveal big"
  }, /*#__PURE__*/React.createElement("span", {
    className: "en"
  }, studyCard.en), /*#__PURE__*/React.createElement("span", {
    className: "sep"
  }, "="), /*#__PURE__*/React.createElement("span", {
    className: "he"
  }, studyCard.he)), /*#__PURE__*/React.createElement("div", {
    className: "gm-levelup-sub"
  }, "\u05D4\u05DE\u05D9\u05DC\u05D4 \u05EA\u05D7\u05DB\u05D4 \u05DC\u05DB\u05DD \u05D2\u05DD \u05D1\u05E1\u05D9\u05DB\u05D5\u05DD \u05D1\u05E1\u05D5\u05E3 \u05D4\u05DE\u05E9\u05D7\u05E7."), /*#__PURE__*/React.createElement("div", {
    className: "gm-levelup-btnrow"
  }, /*#__PURE__*/React.createElement("button", {
    className: "gm-levelup-cta",
    onClick: () => {
      const d = studyCard.dictIdx;
      setStudyCard(null);
      advance(d);
    }
  }, "\u05D4\u05D1\u05D0", /*#__PURE__*/React.createElement("span", {
    className: "dot"
  }, "."))))), /*#__PURE__*/React.createElement("div", {
    className: "gm-controls"
  }, /*#__PURE__*/React.createElement("div", {
    className: "gm-meta"
  }, /*#__PURE__*/React.createElement("button", {
    className: "gm-logo",
    onClick: goHome,
    title: "\u05DC\u05DE\u05E1\u05DA \u05D4\u05D1\u05D9\u05EA \u05E9\u05DC \u05D4\u05DE\u05E9\u05D7\u05E7"
  }, /*#__PURE__*/React.createElement("img", {
    src: EZ_ICON,
    alt: ""
  }), /*#__PURE__*/React.createElement("span", {
    className: "brand-eazy"
  }, "eazy", /*#__PURE__*/React.createElement("span", {
    className: "dot"
  }, "."))), /*#__PURE__*/React.createElement("div", {
    className: "gm-score"
  }, /*#__PURE__*/React.createElement("span", {
    className: "lbl"
  }, "\u05E0\u05D9\u05E7\u05D5\u05D3"), /*#__PURE__*/React.createElement("span", {
    className: "num"
  }, score))), /*#__PURE__*/React.createElement("div", {
    className: "gm-pad"
  }, /*#__PURE__*/React.createElement("button", {
    className: "gm-arcade",
    "aria-label": "\u05E9\u05DE\u05D0\u05DC\u05D4",
    onClick: () => move(-1)
  }, /*#__PURE__*/React.createElement(Ico.left, null)), /*#__PURE__*/React.createElement("button", {
    className: "gm-arcade down",
    "aria-label": "\u05D4\u05D0\u05E6\u05D4",
    onPointerDown: softDrop,
    onPointerUp: softRelease,
    onPointerLeave: softRelease
  }, /*#__PURE__*/React.createElement(Ico.down, null)), /*#__PURE__*/React.createElement("button", {
    className: "gm-arcade",
    "aria-label": "\u05D9\u05DE\u05D9\u05E0\u05D4",
    onClick: () => move(1)
  }, /*#__PURE__*/React.createElement(Ico.right, null))))));
}
window.Game = VocabGame;
})(); } catch (e) { __ds_ns.__errors.push({ path: "tetri-vocab/VocabGame.jsx", error: String((e && e.message) || e) }); }

// tetri-vocab/vocab-data.js
try { (() => {
/* ═══════════════════════════════════════════════════════════════
   טטרי אוצר מילים · eazy — מאגר המילים (אנלוגיות חקלאות)
   ───────────────────────────────────────────────────────────────
   נוצר מתוך קובץ האקסל שסופק. 91 מילים · 5 קטגוריות.
   לכל מילה: w=המילה · m=הפירוש הנכון · mis=[3 מסיחים] · cat=קטגוריה
   ═══════════════════════════════════════════════════════════════ */

window.VOCAB_CATEGORIES = [{
  id: "c1",
  name: "בעלי תפקידים ופעולות אדם"
}, {
  id: "c2",
  name: "קרקע, שטחים ומבנים"
}, {
  id: "c3",
  name: "פעולות חקלאיות"
}, {
  id: "c4",
  name: "כלים ואמצעים"
}, {
  id: "c5",
  name: "יבול, צמחים ותוצרים"
}, {
  id: "c6",
  name: "ביטויים לחיבור"
}];
window.VOCAB_WORDS = [
// ── בעלי תפקידים ופעולות אדם ──
{
  w: "אִכָּר",
  m: "עובד אדמה",
  mis: ["כלי חפירה", "מחסן תבואה", "כלי זַרְמֵל"],
  cat: "c1"
}, {
  w: "יוֹגֵב",
  m: "חקלאי",
  mis: ["מחסן תבואה", "שטח מרעה", "צמח רַנְבּוּל"],
  cat: "c1"
}, {
  w: "פַּלָּח",
  m: "איכר כפרי",
  mis: ["שטח מרעה", "מתקן מים", "פעולת לוּמְרָה"],
  cat: "c1"
}, {
  w: "אָרִיס",
  m: "חוכר שדה",
  mis: ["מתקן מים", "דגן מאכל", "שורש פַּלְמוּן"],
  cat: "c1"
}, {
  w: "אַגְרוֹנוֹם",
  m: "מומחה חקלאות",
  mis: ["דגן מאכל", "בית עופות", "מכל זִירְקָן"],
  cat: "c1"
}, {
  w: "כּוֹרֵם",
  m: "מגדל גפנים",
  mis: ["בית עופות", "מזון בהמות", "שדה בַּרְנוּם"],
  cat: "c1"
}, {
  w: "נוֹטֵעַ",
  m: "שותל עצים",
  mis: ["מזון בהמות", "חלקת צמחים", "ענף קוֹרְמָן"],
  cat: "c1"
}, {
  w: "זוֹרֵעַ",
  m: "מטמין גרעינים",
  mis: ["חלקת צמחים", "ראש דגן", "גרעין נַמְזִיק"],
  cat: "c1"
}, {
  w: "קוֹצֵר",
  m: "חותך תבואה",
  mis: ["ראש דגן", "גבעול יבש", "מתקן דוּלְפָּה"],
  cat: "c1"
}, {
  w: "בּוֹצֵר",
  m: "קוטף ענבים",
  mis: ["גבעול יבש", "מזלג חקלאי", "עשב מַרְלוּן"],
  cat: "c1"
}, {
  w: "מוֹסֵק",
  m: "קוטף זיתים",
  mis: ["מזלג חקלאי", "שורש מעובה", "בית חַרְזִיק"],
  cat: "c1"
}, {
  w: "דָּשׁ",
  m: "מפריד גרעינים",
  mis: ["שורש מעובה", "עצי הדר", "גבעול פוּלְדָּן"],
  cat: "c1"
}, {
  w: "חוֹרֵשׁ",
  m: "מהפך קרקע",
  mis: ["עצי הדר", "מכל תבואה", "כלי גַּנְמוּר"],
  cat: "c1"
}, {
  w: "מְנַכֵּשׁ",
  m: "מסיר עשבים",
  mis: ["מכל תבואה", "כלי חפירה", "צמח טַרְבִּישׁ"],
  cat: "c1"
}, {
  w: "מְדַשֵּׁן",
  m: "מזין אדמה",
  mis: ["כלי חפירה", "מחסן תבואה", "פעולת קַנְדֵּל"],
  cat: "c1"
}, {
  w: "גּוֹזֵם",
  m: "מקצר ענפים",
  mis: ["מחסן תבואה", "שטח מרעה", "שורש סוּמְרָה"],
  cat: "c1"
}, {
  w: "מְאַלֵּם",
  m: "קושר שיבולים",
  mis: ["שטח מרעה", "מתקן מים", "מכל נַרְגּוֹן"],
  cat: "c1"
}, {
  w: "רוֹעֶה",
  m: "שומר עדר",
  mis: ["מתקן מים", "דגן מאכל", "שדה דַּמְזוּל"],
  cat: "c1"
}, {
  w: "לוּלָן",
  m: "מגדל עופות",
  mis: ["דגן מאכל", "בית עופות", "ענף פִּלְקוֹר"],
  cat: "c1"
}, {
  w: "רַפְתָּן",
  m: "מגדל בקר",
  mis: ["בית עופות", "מזון בהמות", "גרעין רַגְמִיל"],
  cat: "c1"
},
// ── קרקע, שטחים ומבנים ──
{
  w: "נִיר",
  m: "שדה מעובד",
  mis: ["צרור שיבולים", "מומחה חקלאות", "מתקן בַּלְמוּר"],
  cat: "c2"
}, {
  w: "תֶּלֶם",
  m: "חריץ אדמה",
  mis: ["מומחה חקלאות", "מזון בהמות", "עשב זוֹרְפָּן"],
  cat: "c2"
}, {
  w: "רֶגֶב",
  m: "גוש קרקע",
  mis: ["מזון בהמות", "ריסוק גרגרים", "בית קִרְנוּל"],
  cat: "c2"
}, {
  w: "אֲדָמָה",
  m: "קרקע",
  mis: ["ריסוק גרגרים", "הוספת קומפוסט", "גבעול מַפְרִישׁ"],
  cat: "c2"
}, {
  w: "קַרְקַע",
  m: "אדמה",
  mis: ["הוספת קומפוסט", "מטמין גרעינים", "כלי שׁוּלְמָן"],
  cat: "c2"
}, {
  w: "שָׂדֶה",
  m: "שטח חקלאי",
  mis: ["מטמין גרעינים", "מתן מים", "צמח דַּרְקִית"],
  cat: "c2"
}, {
  w: "חֶלְקָה",
  m: "אזור תחום",
  mis: ["מתן מים", "כלי חפירה", "פעולת נִמְרוֹק"],
  cat: "c2"
}, {
  w: "עֲרוּגָה",
  m: "פס שתילה",
  mis: ["כלי חפירה", "מגדל עופות", "שורש זַרְמֵל"],
  cat: "c2"
}, {
  w: "מַטָּע",
  m: "עצי פרי",
  mis: ["מגדל עופות", "קוטף זיתים", "מכל רַנְבּוּל"],
  cat: "c2"
}, {
  w: "כֶּרֶם",
  m: "גפנים",
  mis: ["קוטף זיתים", "דגן מאכל", "שדה לוּמְרָה"],
  cat: "c2"
}, {
  w: "פַּרְדֵּס",
  m: "עצי הדר",
  mis: ["דגן מאכל", "הסרת עשבים", "ענף פַּלְמוּן"],
  cat: "c2"
}, {
  w: "בֻּסְתָּן",
  m: "גן פירות",
  mis: ["הסרת עשבים", "מזלף זעיר", "גרעין זִירְקָן"],
  cat: "c2"
}, {
  w: "אָחוּ",
  m: "מרחב עשב",
  mis: ["מזלף זעיר", "צרור שיבולים", "מתקן בַּרְנוּם"],
  cat: "c2"
}, {
  w: "מִרְעֶה",
  m: "אחו לבהמות",
  mis: ["צרור שיבולים", "מומחה חקלאות", "עשב קוֹרְמָן"],
  cat: "c2"
}, {
  w: "גֹּרֶן",
  m: "משטח דגן",
  mis: ["מומחה חקלאות", "מזון בהמות", "בית נַמְזִיק"],
  cat: "c2"
}, {
  w: "אָסָם",
  m: "מחסן תבואה",
  mis: ["מזון בהמות", "ריסוק גרגרים", "גבעול דוּלְפָּה"],
  cat: "c2"
}, {
  w: "מַמְגּוּרָה",
  m: "מכל תבואה",
  mis: ["ריסוק גרגרים", "הוספת קומפוסט", "כלי מַרְלוּן"],
  cat: "c2"
}, {
  w: "רֶפֶת",
  m: "בית בקר",
  mis: ["הוספת קומפוסט", "מטמין גרעינים", "צמח חַרְזִיק"],
  cat: "c2"
}, {
  w: "דִּיר",
  m: "בית צאן",
  mis: ["מטמין גרעינים", "מתן מים", "פעולת פוּלְדָּן"],
  cat: "c2"
}, {
  w: "לוּל",
  m: "בית עופות",
  mis: ["מתן מים", "כלי חפירה", "שורש גַּנְמוּר"],
  cat: "c2"
},
// ── פעולות חקלאיות ──
{
  w: "חֲרִישָׁה",
  m: "עיבוד קרקע",
  mis: ["כלי חפירה", "מגדל בקר", "מכל טַרְבִּישׁ"],
  cat: "c3"
}, {
  w: "זְרִיעָה",
  m: "הטמנת גרעינים",
  mis: ["מגדל בקר", "שטח חקלאי", "שדה קַנְדֵּל"],
  cat: "c3"
}, {
  w: "נְטִיעָה",
  m: "שתילת עצים",
  mis: ["שטח חקלאי", "דגן מאכל", "ענף סוּמְרָה"],
  cat: "c3"
}, {
  w: "שְׁתִילָה",
  m: "הכנסת צמח",
  mis: ["דגן מאכל", "בית עופות", "גרעין נַרְגּוֹן"],
  cat: "c3"
}, {
  w: "הַשְׁקָיָה",
  m: "מתן מים",
  mis: ["בית עופות", "מזון בהמות", "מתקן דַּמְזוּל"],
  cat: "c3"
}, {
  w: "עִדּוּר",
  m: "פירור קרקע",
  mis: ["מזון בהמות", "מזלג חקלאי", "עשב פִּלְקוֹר"],
  cat: "c3"
}, {
  w: "דִּשּׁוּן",
  m: "הזנת אדמה",
  mis: ["מזלג חקלאי", "שורש מעובה", "בית רַגְמִיל"],
  cat: "c3"
}, {
  w: "זִבּוּל",
  m: "הוספת קומפוסט",
  mis: ["שורש מעובה", "עצי הדר", "גבעול בַּלְמוּר"],
  cat: "c3"
}, {
  w: "נִכּוּשׁ",
  m: "הסרת עשבים",
  mis: ["עצי הדר", "מכל תבואה", "כלי זוֹרְפָּן"],
  cat: "c3"
}, {
  w: "דִּלּוּל",
  m: "הפחתת צפיפות",
  mis: ["מכל תבואה", "צמח צעיר", "צמח קִרְנוּל"],
  cat: "c3"
}, {
  w: "גִּזּוּם",
  m: "קיצור ענפים",
  mis: ["צמח צעיר", "בית צאן", "פעולת מַפְרִישׁ"],
  cat: "c3"
}, {
  w: "קָצִיר",
  m: "איסוף תבואה",
  mis: ["בית צאן", "מחסן תבואה", "שורש שׁוּלְמָן"],
  cat: "c3"
}, {
  w: "בָּצִיר",
  m: "קטיף ענבים",
  mis: ["מחסן תבואה", "כלי חפירה", "מכל דַּרְקִית"],
  cat: "c3"
}, {
  w: "מָסִיק",
  m: "קטיף זיתים",
  mis: ["כלי חפירה", "מגדל בקר", "שדה נִמְרוֹק"],
  cat: "c3"
}, {
  w: "אָסִיף",
  m: "איסוף תוצרת",
  mis: ["מגדל בקר", "שטח חקלאי", "ענף זַרְמֵל"],
  cat: "c3"
}, {
  w: "דַּיִשׁ",
  m: "הפרדת גרעינים",
  mis: ["שטח חקלאי", "דגן מאכל", "גרעין רַנְבּוּל"],
  cat: "c3"
}, {
  w: "טְחִינָה",
  m: "ריסוק גרגרים",
  mis: ["דגן מאכל", "בית עופות", "מתקן לוּמְרָה"],
  cat: "c3"
}, {
  w: "הַשְׁבָּחָה",
  m: "שיפור זנים",
  mis: ["בית עופות", "מזון בהמות", "עשב פַּלְמוּן"],
  cat: "c3"
}, {
  w: "הַרְכָּבָה",
  m: "חיבור צמחים",
  mis: ["מזון בהמות", "מזלג חקלאי", "בית זִירְקָן"],
  cat: "c3"
}, {
  w: "הַנְבָּטָה",
  m: "תחילת צמיחה",
  mis: ["מזלג חקלאי", "שורש מעובה", "גבעול בַּרְנוּם"],
  cat: "c3"
},
// ── כלים ואמצעים ──
{
  w: "מַחֲרֵשָׁה",
  m: "כלי עיבוד",
  mis: ["עצי הדר", "צמח צעיר", "כלי קוֹרְמָן"],
  cat: "c4"
}, {
  w: "מַעְדֵּר",
  m: "כלי חפירה",
  mis: ["צמח צעיר", "גוש קרקע", "צמח נַמְזִיק"],
  cat: "c4"
}, {
  w: "מַגָּל",
  m: "סכין קציר",
  mis: ["גוש קרקע", "מזון בהמות", "פעולת דוּלְפָּה"],
  cat: "c4"
}, {
  w: "חֶרְמֵשׁ",
  m: "להב ארוך",
  mis: ["מזון בהמות", "מכל תבואה", "שורש מַרְלוּן"],
  cat: "c4"
}, {
  w: "קִלְשׁוֹן",
  m: "מזלג חקלאי",
  mis: ["מכל תבואה", "שטח מרעה", "מכל חַרְזִיק"],
  cat: "c4"
}, {
  w: "אֵת",
  m: "כלי חפירה",
  mis: ["שטח מרעה", "מחסן תבואה", "שדה פוּלְדָּן"],
  cat: "c4"
}, {
  w: "טוּרִיָּה",
  m: "מעדר רחב",
  mis: ["מחסן תבואה", "הסרת עשבים", "ענף גַּנְמוּר"],
  cat: "c4"
}, {
  w: "מַזְמֵרָה",
  m: "מספרי ענפים",
  mis: ["הסרת עשבים", "דגן מאכל", "גרעין טַרְבִּישׁ"],
  cat: "c4"
}, {
  w: "מַקְצֵרָה",
  m: "מכונת תבואה",
  mis: ["דגן מאכל", "בית בקר", "מתקן קַנְדֵּל"],
  cat: "c4"
}, {
  w: "מַמְטֵרָה",
  m: "מתקן מים",
  mis: ["בית בקר", "גרעיני שדה", "עשב סוּמְרָה"],
  cat: "c4"
}, {
  w: "טַפְטֶפֶת",
  m: "מזלף זעיר",
  mis: ["גרעיני שדה", "איסוף תבואה", "בית נַרְגּוֹן"],
  cat: "c4"
}, {
  w: "אֵבוּס",
  m: "כלי האכלה",
  mis: ["איסוף תבואה", "מגדל עופות", "גבעול דַּמְזוּל"],
  cat: "c4"
},
// ── יבול, צמחים ותוצרים ──
{
  w: "תְּבוּאָה",
  m: "גרעיני שדה",
  mis: ["חוכר שדה", "מתקן מים", "כלי פִּלְקוֹר"],
  cat: "c5"
}, {
  w: "דָּגָן",
  m: "גרעיני מאכל",
  mis: ["מתקן מים", "קוטף זיתים", "צמח רַגְמִיל"],
  cat: "c5"
}, {
  w: "חִטָּה",
  m: "דגן מאכל",
  mis: ["קוטף זיתים", "עיבוד קרקע", "פעולת בַּלְמוּר"],
  cat: "c5"
}, {
  w: "שְׂעוֹרָה",
  m: "דגן קדום",
  mis: ["עיבוד קרקע", "מומחה חקלאות", "שורש זוֹרְפָּן"],
  cat: "c5"
}, {
  w: "שִׁבֹּלֶת",
  m: "ראש דגן",
  mis: ["מומחה חקלאות", "בית צאן", "מכל קִרְנוּל"],
  cat: "c5"
}, {
  w: "אֲלֻמָּה",
  m: "צרור שיבולים",
  mis: ["בית צאן", "כלי חפירה", "שדה מַפְרִישׁ"],
  cat: "c5"
}, {
  w: "עֹמֶר",
  m: "צרור תבואה",
  mis: ["כלי חפירה", "מגדל עופות", "ענף שׁוּלְמָן"],
  cat: "c5"
}, {
  w: "קַשׁ",
  m: "גבעול יבש",
  mis: ["מגדל עופות", "מתן מים", "גרעין דַּרְקִית"],
  cat: "c5"
}, {
  w: "תֶּבֶן",
  m: "קש קצוץ",
  mis: ["מתן מים", "שטח מרעה", "מתקן נִמְרוֹק"],
  cat: "c5"
}, {
  w: "מֹץ",
  m: "קליפת גרעין",
  mis: ["שטח מרעה", "הסרת עשבים", "עשב זַרְמֵל"],
  cat: "c5"
}, {
  w: "גַּרְעִין",
  m: "זרע פנימי",
  mis: ["הסרת עשבים", "מזלג חקלאי", "בית רַנְבּוּל"],
  cat: "c5"
}, {
  w: "זֶרַע",
  m: "מקור צמח",
  mis: ["מזלג חקלאי", "בית בקר", "גבעול לוּמְרָה"],
  cat: "c5"
}, {
  w: "שְׁתִיל",
  m: "צמח צעיר",
  mis: ["בית בקר", "חוכר שדה", "כלי פַּלְמוּן"],
  cat: "c5"
}, {
  w: "נֵצֶר",
  m: "ענף צעיר",
  mis: ["חוכר שדה", "מתקן מים", "צמח זִירְקָן"],
  cat: "c5"
}, {
  w: "יִחוּר",
  m: "ענף השרשה",
  mis: ["מתקן מים", "קוטף זיתים", "פעולת בַּרְנוּם"],
  cat: "c5"
}, {
  w: "פְּקַעַת",
  m: "שורש מעובה",
  mis: ["קוטף זיתים", "עיבוד קרקע", "שורש קוֹרְמָן"],
  cat: "c5"
}, {
  w: "מִסְפּוֹא",
  m: "מזון בהמות",
  mis: ["עיבוד קרקע", "מומחה חקלאות", "מכל נַמְזִיק"],
  cat: "c5"
}, {
  w: "שַׁחַת",
  m: "עשב מיובש",
  mis: ["מומחה חקלאות", "בית צאן", "שדה דוּלְפָּה"],
  cat: "c5"
}, {
  w: "יְבוּל",
  m: "תוצרת שדה",
  mis: ["בית צאן", "כלי חפירה", "ענף מַרְלוּן"],
  cat: "c5"
},
// ── ביטויים לחיבור ──
{
  w: "אבד עליו הכלח",
  m: "התיישן, אינו רלוונטי",
  mis: ["זכה להערכה", "נעשה נפוץ", "הותאם מחדש"],
  cat: "c6"
}, {
  w: "אורים ותומים",
  m: "מקור סמכות מוחלט",
  mis: ["ספק מתמשך", "רשימת אזהרות", "מדד זְרִיקוּת"],
  cat: "c6"
}, {
  w: "הלכה למעשה",
  m: "בפועל, למעשה",
  mis: ["באופן תיאורטי", "לכאורה בלבד", "כהוראת שעה"],
  cat: "c6"
}, {
  w: "למותר לציין",
  m: "ברור מאליו",
  mis: ["יש להוכיח", "מוטל בספק", "ראוי להסתרה"],
  cat: "c6"
}, {
  w: "אבן בוחן",
  m: "קריטריון, מבחן",
  mis: ["מכשול בדרך", "נקודת סיום", "מדד קַשְיוּת"],
  cat: "c6"
}, {
  w: "מן המפורסמות",
  m: "ידוע לכול",
  mis: ["שמועה לא בדוקה", "גילוי חדש", "ראוי לפרסום"],
  cat: "c6"
}, {
  w: "נקודת ארכימדס",
  m: "נקודת משען מכרעת",
  mis: ["חישוב גאומטרי", "טעות נפוצה", "מוקד תפוצה"],
  cat: "c6"
}, {
  w: "תנאי בלעדיו אין",
  m: "תנאי הכרחי",
  mis: ["המלצה בלבד", "תוספת רשות", "סייג משני"],
  cat: "c6"
}, {
  w: "משנה תוקף",
  m: "חיזוק והדגשה",
  mis: ["ביטול הדרגתי", "ספק מסוים", "עותק כפול"],
  cat: "c6"
}, {
  w: "בין השיטין",
  m: "במשתמע, לא במפורש",
  mis: ["בראש הפרק", "בכותרת בולטת", "בשולי הדף"],
  cat: "c6"
}, {
  w: "יש מאין",
  m: "יצירה מכלום",
  mis: ["העתקה מדויקת", "שיפור קיים", "מיחזור חומר"],
  cat: "c6"
}, {
  w: "קו פרשת מים",
  m: "נקודת מפנה",
  mis: ["המשך רציף", "סיכום עונתי", "גבול מנהלי"],
  cat: "c6"
}, {
  w: "פרדיגמה",
  m: "תבנית חשיבה מקובלת",
  mis: ["סתירה לוגית", "דוגמה בודדת", "חריגה נדירה"],
  cat: "c6"
}, {
  w: "אמפירי",
  m: "מבוסס על ניסיון",
  mis: ["מבוסס על השערה", "מבוסס על אמונה", "מבוסס על דמיון"],
  cat: "c6"
}, {
  w: "אקסיומה",
  m: "הנחת יסוד",
  mis: ["מסקנה סופית", "הוכחה מלאה", "סתירה פנימית"],
  cat: "c6"
}, {
  w: "דה פקטו",
  m: "למעשה, בפועל",
  mis: ["על פי חוק", "באופן זמני", "בכוונה תחילה"],
  cat: "c6"
}, {
  w: "דה יורה",
  m: "על פי חוק",
  mis: ["בפועל בלבד", "באופן חלקי", "בהסכמה שבשתיקה"],
  cat: "c6"
}, {
  w: "אד הוק",
  m: "לצורך מסוים בלבד",
  mis: ["באופן קבוע", "לטווח ארוך", "באורח כללי"],
  cat: "c6"
}, {
  w: "היבט",
  m: "צד, זווית ראייה",
  mis: ["מסקנה כוללת", "פתרון יחיד", "נתון מספרי"],
  cat: "c6"
}, {
  w: "חזון נפרץ",
  m: "דבר שכיח",
  mis: ["מראה נדיר", "תגלית מרעישה", "אירוע חד‑פעמי"],
  cat: "c6"
}];

/* בוחן פתיחה: null = בחירה אוטומטית אחידה (10 שאלות, מגוון מכל הקטגוריות). */
window.VOCAB_QUIZ = null;
})(); } catch (e) { __ds_ns.__errors.push({ path: "tetri-vocab/vocab-data.js", error: String((e && e.message) || e) }); }

// ui_kits/flyer/FlyerBulletList.jsx
try { (() => {
/* global React */
function FlyerBulletList({
  items,
  kind = "chevron"
}) {
  const src = kind === "chevron" ? "../../assets/bullet-chevron.svg" : "../../assets/bullet-target.svg";
  return /*#__PURE__*/React.createElement("ul", {
    style: fbl.list
  }, items.map((it, i) => /*#__PURE__*/React.createElement("li", {
    key: i,
    style: fbl.li
  }, /*#__PURE__*/React.createElement("img", {
    src: src,
    alt: "",
    style: fbl.bullet
  }), /*#__PURE__*/React.createElement("div", null, it.title && /*#__PURE__*/React.createElement("div", {
    style: fbl.t
  }, it.title), /*#__PURE__*/React.createElement("div", {
    style: fbl.b
  }, it.body || it)))));
}
const fbl = {
  list: {
    listStyle: "none",
    padding: 0,
    margin: 0,
    display: "grid",
    gap: 18
  },
  li: {
    display: "flex",
    gap: 18,
    alignItems: "flex-start",
    fontFamily: "var(--font-body)",
    fontSize: 22,
    lineHeight: 1.4,
    color: "var(--ez-ink)"
  },
  bullet: {
    width: 32,
    height: 32,
    flex: "none",
    marginTop: 4
  },
  t: {
    fontFamily: "var(--font-display)",
    fontWeight: 700,
    fontSize: 26,
    color: "var(--ez-ink)",
    marginBottom: 2
  },
  b: {
    fontFamily: "var(--font-body)",
    fontSize: 22,
    color: "var(--ez-fg-2)"
  }
};
window.FlyerBulletList = FlyerBulletList;
})(); } catch (e) { __ds_ns.__errors.push({ path: "ui_kits/flyer/FlyerBulletList.jsx", error: String((e && e.message) || e) }); }

// ui_kits/flyer/FlyerEventStamp.jsx
try { (() => {
/* global React */
function FlyerEventStamp({
  date,
  day,
  time
}) {
  return /*#__PURE__*/React.createElement("div", {
    style: es.row
  }, /*#__PURE__*/React.createElement("span", {
    style: es.date
  }, date), /*#__PURE__*/React.createElement("span", {
    style: es.bar
  }, "|"), /*#__PURE__*/React.createElement("span", {
    style: es.day
  }, day), /*#__PURE__*/React.createElement("span", {
    style: es.bar
  }, "|"), /*#__PURE__*/React.createElement("span", {
    style: es.time
  }, "\u05D1\u05E9\u05E2\u05D4 ", time));
}
const es = {
  row: {
    display: "flex",
    gap: 14,
    alignItems: "baseline",
    fontFamily: "var(--font-display)",
    fontWeight: 700,
    color: "var(--ez-orange)",
    fontSize: 38
  },
  date: {},
  day: {},
  time: {},
  bar: {
    color: "var(--ez-fg-3)",
    fontWeight: 300
  }
};
window.FlyerEventStamp = FlyerEventStamp;
})(); } catch (e) { __ds_ns.__errors.push({ path: "ui_kits/flyer/FlyerEventStamp.jsx", error: String((e && e.message) || e) }); }

// ui_kits/flyer/FlyerFrame.jsx
try { (() => {
/* global React */
function FlyerFrame({
  ratio = "square",
  children,
  photoSlot,
  dotPosition = "left"
}) {
  const dim = ratio === "portrait" ? {
    width: 1080,
    height: 1350
  } : {
    width: 1080,
    height: 1080
  };
  return /*#__PURE__*/React.createElement("div", {
    style: {
      ...ff.stage,
      ...dim
    }
  }, /*#__PURE__*/React.createElement("div", {
    style: ff.zBack,
    "aria-hidden": true
  }, /*#__PURE__*/React.createElement("div", {
    style: {
      ...ff.slash,
      top: "10%",
      right: "-6%",
      width: "70%",
      background: "var(--ez-lavender-soft)"
    }
  }), /*#__PURE__*/React.createElement("div", {
    style: {
      ...ff.slash,
      top: "22%",
      right: "20%",
      width: "62%",
      background: "#FFFFFF"
    }
  }), /*#__PURE__*/React.createElement("div", {
    style: {
      ...ff.slash,
      top: "60%",
      right: "-6%",
      width: "78%",
      background: "var(--ez-lavender-soft)"
    }
  }), /*#__PURE__*/React.createElement("div", {
    style: {
      ...ff.slash,
      top: "72%",
      right: "30%",
      width: "60%",
      background: "#FFFFFF"
    }
  })), photoSlot && /*#__PURE__*/React.createElement("div", {
    style: {
      ...ff.photoWrap,
      [dotPosition]: 0
    }
  }, photoSlot), /*#__PURE__*/React.createElement("img", {
    src: "../../assets/dot-cluster.svg",
    alt: "",
    "aria-hidden": true,
    style: {
      ...ff.dots,
      [dotPosition]: -40
    }
  }), /*#__PURE__*/React.createElement("div", {
    style: ff.content
  }, children));
}
const ff = {
  stage: {
    position: "relative",
    background: "var(--ez-paper-warm)",
    overflow: "hidden",
    fontFamily: "var(--font-display)"
  },
  zBack: {
    position: "absolute",
    inset: 0,
    zIndex: 0
  },
  slash: {
    position: "absolute",
    height: "10%",
    transform: "skew(-30deg)"
  },
  photoWrap: {
    position: "absolute",
    bottom: 0,
    width: "44%",
    height: "92%",
    zIndex: 2,
    display: "flex",
    alignItems: "flex-end"
  },
  dots: {
    position: "absolute",
    bottom: 60,
    width: 220,
    height: 220,
    zIndex: 1
  },
  content: {
    position: "relative",
    zIndex: 3,
    padding: "60px 70px",
    height: "100%",
    boxSizing: "border-box",
    display: "flex",
    flexDirection: "column",
    justifyContent: "space-between"
  }
};
window.FlyerFrame = FlyerFrame;
})(); } catch (e) { __ds_ns.__errors.push({ path: "ui_kits/flyer/FlyerFrame.jsx", error: String((e && e.message) || e) }); }

// ui_kits/flyer/FlyerHeadline.jsx
try { (() => {
/* global React */
function FlyerHeadline({
  children,
  tone = "lavender",
  size = "xl",
  align = "right"
}) {
  const colorMap = {
    lavender: "var(--ez-lavender)",
    indigo: "var(--ez-indigo)",
    ink: "var(--ez-ink)",
    orange: "var(--ez-orange)"
  };
  const sizeMap = {
    xl: 110,
    lg: 88,
    md: 64,
    sm: 44
  };
  return /*#__PURE__*/React.createElement("h1", {
    style: {
      fontFamily: "var(--font-display)",
      fontWeight: 700,
      color: colorMap[tone],
      fontSize: sizeMap[size],
      lineHeight: 0.95,
      margin: 0,
      letterSpacing: "-.01em",
      textAlign: align
    }
  }, children);
}
window.FlyerHeadline = FlyerHeadline;
function FlyerSubhead({
  children,
  tone = "ink"
}) {
  const colorMap = {
    ink: "var(--ez-ink)",
    orange: "var(--ez-orange)",
    soft: "var(--ez-fg-2)"
  };
  return /*#__PURE__*/React.createElement("p", {
    style: {
      fontFamily: "var(--font-body)",
      fontWeight: 400,
      fontSize: 26,
      lineHeight: 1.4,
      color: colorMap[tone],
      margin: "16px 0 0",
      maxWidth: 560
    }
  }, children);
}
window.FlyerSubhead = FlyerSubhead;
})(); } catch (e) { __ds_ns.__errors.push({ path: "ui_kits/flyer/FlyerHeadline.jsx", error: String((e && e.message) || e) }); }

// ui_kits/flyer/FlyerLogoBlock.jsx
try { (() => {
/* global React */
function FlyerLogoBlock({
  tagline = true,
  phone,
  layout = "row"
}) {
  return /*#__PURE__*/React.createElement("div", {
    style: {
      ...lb.wrap,
      flexDirection: layout === "stack" ? "column" : "row",
      alignItems: layout === "stack" ? "flex-start" : "center"
    }
  }, /*#__PURE__*/React.createElement("div", {
    style: lb.logoRow
  }, /*#__PURE__*/React.createElement("img", {
    src: "../../assets/logo-mark-orange.svg",
    alt: "",
    style: {
      width: 64,
      height: 64
    }
  }), /*#__PURE__*/React.createElement("span", {
    style: lb.word
  }, "eazy", /*#__PURE__*/React.createElement("span", {
    style: {
      color: "var(--ez-orange)"
    }
  }, "."))), tagline && /*#__PURE__*/React.createElement("div", {
    style: lb.tag
  }, "\u05E4\u05E9\u05D5\u05D8 \u05EA\u05E6\u05DC\u05D9\u05D7\u05D5", /*#__PURE__*/React.createElement("span", {
    style: {
      color: "var(--ez-orange)"
    }
  }, ".")), phone && /*#__PURE__*/React.createElement("div", {
    style: lb.phone,
    dir: "ltr"
  }, phone));
}
const lb = {
  wrap: {
    display: "flex",
    gap: 24
  },
  logoRow: {
    display: "flex",
    alignItems: "center",
    gap: 8
  },
  word: {
    fontFamily: "var(--font-display)",
    fontWeight: 400,
    fontSize: 56,
    color: "var(--ez-ink)",
    letterSpacing: "-.02em",
    lineHeight: 1,
    paddingBottom: 6
  },
  tag: {
    fontFamily: "var(--font-display)",
    fontWeight: 700,
    fontSize: 36,
    color: "var(--ez-orange)",
    lineHeight: 1
  },
  phone: {
    fontFamily: "var(--font-mono)",
    fontSize: 22,
    color: "var(--ez-ink)"
  }
};
window.FlyerLogoBlock = FlyerLogoBlock;
function PhotoPlaceholder({
  label = "צילום סטודנט · cut-out B&W"
}) {
  return /*#__PURE__*/React.createElement("div", {
    style: pp.frame
  }, /*#__PURE__*/React.createElement("div", {
    style: pp.label
  }, label));
}
const pp = {
  frame: {
    width: "100%",
    height: "100%",
    background: "linear-gradient(180deg,#dcdce0,#bcbcc4)",
    borderRadius: 4,
    display: "flex",
    alignItems: "center",
    justifyContent: "center",
    filter: "grayscale(1)"
  },
  label: {
    fontFamily: "var(--font-mono)",
    fontSize: 12,
    color: "#3a3a44",
    padding: "6px 10px",
    background: "rgba(255,255,255,.85)",
    borderRadius: 4
  }
};
window.PhotoPlaceholder = PhotoPlaceholder;
})(); } catch (e) { __ds_ns.__errors.push({ path: "ui_kits/flyer/FlyerLogoBlock.jsx", error: String((e && e.message) || e) }); }

// ui_kits/web/BannerCTA.jsx
try { (() => {
/* global React */
function BannerCTA({
  onCTA
}) {
  return /*#__PURE__*/React.createElement("section", {
    style: bn.wrap
  }, /*#__PURE__*/React.createElement("div", {
    style: bn.zBack,
    "aria-hidden": true
  }, /*#__PURE__*/React.createElement("div", {
    style: {
      ...bn.slash,
      top: 30,
      right: "-2%",
      width: "60%",
      background: "rgba(255,255,255,.18)"
    }
  }), /*#__PURE__*/React.createElement("div", {
    style: {
      ...bn.slash,
      top: 110,
      right: "20%",
      width: "70%",
      background: "rgba(255,255,255,.10)"
    }
  })), /*#__PURE__*/React.createElement("div", {
    style: bn.inner
  }, /*#__PURE__*/React.createElement("div", {
    style: bn.copy
  }, /*#__PURE__*/React.createElement("div", {
    style: bn.tag
  }, "\u05E4\u05E9\u05D5\u05D8 \u05EA\u05E6\u05DC\u05D9\u05D7\u05D5."), /*#__PURE__*/React.createElement("div", {
    style: bn.line
  }, "\u05D1\u05E4\u05E1\u05D9\u05DB\u05D5\u05DE\u05D8\u05E8\u05D9 \u05DB\u05D1\u05E8 \u05D1\u05EA\u05D9\u05DB\u05D5\u05DF.")), /*#__PURE__*/React.createElement("button", {
    style: bn.cta,
    onClick: onCTA
  }, "\u05DC\u05E8\u05D9\u05E9\u05D5\u05DD \u05D4\u05EA\u05E7\u05E9\u05E8\u05D5 1-700-70-70-07")));
}
const bn = {
  wrap: {
    background: "var(--ez-indigo)",
    color: "#fff",
    overflow: "hidden",
    position: "relative",
    padding: "56px 32px"
  },
  zBack: {
    position: "absolute",
    inset: 0
  },
  slash: {
    position: "absolute",
    height: 70,
    transform: "skew(-30deg)"
  },
  inner: {
    position: "relative",
    maxWidth: 1280,
    margin: "0 auto",
    display: "flex",
    justifyContent: "space-between",
    alignItems: "center",
    gap: 32,
    flexWrap: "wrap"
  },
  copy: {
    display: "grid",
    gap: 4
  },
  tag: {
    fontFamily: "var(--font-display)",
    fontWeight: 700,
    fontSize: 36,
    color: "var(--ez-orange)",
    lineHeight: 1
  },
  line: {
    fontFamily: "var(--font-display)",
    fontWeight: 700,
    fontSize: 32,
    color: "#fff",
    lineHeight: 1
  },
  cta: {
    background: "var(--ez-orange)",
    color: "#fff",
    border: 0,
    borderRadius: 999,
    padding: "16px 28px",
    fontFamily: "var(--font-display)",
    fontWeight: 700,
    fontSize: 16,
    cursor: "pointer"
  }
};
window.BannerCTA = BannerCTA;
})(); } catch (e) { __ds_ns.__errors.push({ path: "ui_kits/web/BannerCTA.jsx", error: String((e && e.message) || e) }); }

// ui_kits/web/CourseGrid.jsx
try { (() => {
/* global React */
function CourseGrid({
  onCTA
}) {
  const courses = [{
    tag: "תיכוניסטים",
    title: "פסיכומטרי לתלמידי תיכון",
    body: "קורס מקיף בקיץ, לתלמידי י״א–י״ב. בונים יסודות חזקים ופותרים מאות שאלות.",
    cta: "פרטים והרשמה"
  }, {
    tag: "כל הגילאים",
    title: "קורס פוקוס",
    body: "המסלול האינטנסיבי. מפגשים ממוקדים סביב נקודות החולשה שלכם, עד ציון היעד.",
    cta: "פרטים והרשמה"
  }, {
    tag: "אחרי הצבא",
    title: "להתקבל לתואר ראשון",
    body: "הקורס היחיד שמומלץ ע״י האוניברסיטאות עצמן, בשיתוף מרכזי הצעירים בעיר שלכם.",
    cta: "פרטים והרשמה"
  }];
  return /*#__PURE__*/React.createElement("section", {
    id: "courses",
    style: cg.wrap
  }, /*#__PURE__*/React.createElement("div", {
    style: cg.head
  }, /*#__PURE__*/React.createElement("div", {
    style: cg.eyebrow
  }, "\u05D4\u05E7\u05D5\u05E8\u05E1\u05D9\u05DD \u05E9\u05DC\u05E0\u05D5"), /*#__PURE__*/React.createElement("h2", {
    style: cg.h2
  }, "\u05D1\u05D5\u05D7\u05E8\u05D9\u05DD \u05DE\u05E1\u05DC\u05D5\u05DC", /*#__PURE__*/React.createElement("br", null), "\u05E9\u05DE\u05EA\u05D0\u05D9\u05DD \u05DC\u05DB\u05DD.")), /*#__PURE__*/React.createElement("div", {
    style: cg.grid
  }, courses.map(c => /*#__PURE__*/React.createElement("article", {
    key: c.title,
    style: cg.card
  }, /*#__PURE__*/React.createElement("div", {
    style: cg.cardTag
  }, c.tag), /*#__PURE__*/React.createElement("h3", {
    style: cg.cardTitle
  }, c.title), /*#__PURE__*/React.createElement("p", {
    style: cg.cardBody
  }, c.body), /*#__PURE__*/React.createElement("button", {
    style: cg.cardCta,
    onClick: onCTA
  }, c.cta, " \u2190")))));
}
const cg = {
  wrap: {
    background: "var(--ez-paper-warm)",
    padding: "96px 32px"
  },
  head: {
    maxWidth: 1280,
    margin: "0 auto 48px"
  },
  eyebrow: {
    fontFamily: "var(--font-display)",
    fontWeight: 700,
    fontSize: 14,
    color: "var(--ez-orange)",
    marginBottom: 8
  },
  h2: {
    fontFamily: "var(--font-display)",
    fontWeight: 700,
    fontSize: 56,
    lineHeight: 1,
    color: "var(--ez-lavender)",
    margin: 0,
    letterSpacing: "-.01em"
  },
  grid: {
    maxWidth: 1280,
    margin: "0 auto",
    display: "grid",
    gridTemplateColumns: "repeat(3, 1fr)",
    gap: 20
  },
  card: {
    background: "#fff",
    borderRadius: 14,
    border: "1px solid var(--ez-line)",
    padding: 28,
    display: "grid",
    gap: 12,
    alignContent: "start"
  },
  cardTag: {
    display: "inline-block",
    justifySelf: "start",
    background: "var(--ez-lavender-soft)",
    color: "#2c2960",
    padding: "5px 12px",
    borderRadius: 999,
    fontFamily: "var(--font-display)",
    fontWeight: 700,
    fontSize: 12
  },
  cardTitle: {
    fontFamily: "var(--font-display)",
    fontWeight: 700,
    fontSize: 26,
    lineHeight: 1.15,
    color: "var(--ez-ink)",
    margin: 0
  },
  cardBody: {
    fontFamily: "var(--font-body)",
    fontSize: 16,
    lineHeight: 1.5,
    color: "var(--ez-fg-2)",
    margin: 0
  },
  cardCta: {
    background: "transparent",
    color: "var(--ez-orange)",
    border: 0,
    fontFamily: "var(--font-display)",
    fontWeight: 700,
    fontSize: 15,
    padding: 0,
    marginTop: 4,
    justifySelf: "start",
    cursor: "pointer"
  }
};
window.CourseGrid = CourseGrid;
})(); } catch (e) { __ds_ns.__errors.push({ path: "ui_kits/web/CourseGrid.jsx", error: String((e && e.message) || e) }); }

// ui_kits/web/Footer.jsx
try { (() => {
/* global React */
function Footer() {
  return /*#__PURE__*/React.createElement("footer", {
    style: ft.wrap
  }, /*#__PURE__*/React.createElement("div", {
    style: ft.inner
  }, /*#__PURE__*/React.createElement("div", {
    style: ft.col
  }, /*#__PURE__*/React.createElement("div", {
    style: ft.logoRow
  }, /*#__PURE__*/React.createElement("img", {
    src: "../../assets/logo-mark-orange.svg",
    alt: "",
    style: {
      width: 46,
      height: 46
    }
  }), /*#__PURE__*/React.createElement("span", {
    style: ft.word
  }, "eazy", /*#__PURE__*/React.createElement("span", {
    style: {
      color: "var(--ez-orange)"
    }
  }, "."))), /*#__PURE__*/React.createElement("p", {
    style: ft.tag
  }, "\u05E4\u05E9\u05D5\u05D8 \u05EA\u05E6\u05DC\u05D9\u05D7\u05D5."), /*#__PURE__*/React.createElement("p", {
    style: ft.body
  }, "\u05D4\u05E7\u05D5\u05E8\u05E1 \u05D4\u05D9\u05D7\u05D9\u05D3 \u05DC\u05E4\u05E1\u05D9\u05DB\u05D5\u05DE\u05D8\u05E8\u05D9 \u05E9\u05DE\u05D5\u05DE\u05DC\u05E5 \u05E2\u05F4\u05D9 \u05D4\u05D0\u05D5\u05E0\u05D9\u05D1\u05E8\u05E1\u05D9\u05D8\u05D0\u05D5\u05EA \u05E2\u05E6\u05DE\u05DF.")), /*#__PURE__*/React.createElement("div", {
    style: ft.col
  }, /*#__PURE__*/React.createElement("div", {
    style: ft.head
  }, "\u05E7\u05D5\u05E8\u05E1\u05D9\u05DD"), /*#__PURE__*/React.createElement("a", {
    href: "#",
    style: ft.link
  }, "\u05E4\u05E1\u05D9\u05DB\u05D5\u05DE\u05D8\u05E8\u05D9 \u05D1\u05EA\u05D9\u05DB\u05D5\u05DF"), /*#__PURE__*/React.createElement("a", {
    href: "#",
    style: ft.link
  }, "\u05E7\u05D5\u05E8\u05E1 \u05E4\u05D5\u05E7\u05D5\u05E1"), /*#__PURE__*/React.createElement("a", {
    href: "#",
    style: ft.link
  }, "\u05D4\u05DB\u05E0\u05D4 \u05DC\u05D0\u05E7\u05D3\u05DE\u05D9\u05D4"), /*#__PURE__*/React.createElement("a", {
    href: "#",
    style: ft.link
  }, "eazy VOD")), /*#__PURE__*/React.createElement("div", {
    style: ft.col
  }, /*#__PURE__*/React.createElement("div", {
    style: ft.head
  }, "\u05E6\u05E8\u05D5 \u05E7\u05E9\u05E8"), /*#__PURE__*/React.createElement("a", {
    href: "tel:1-700-70-70-07",
    style: ft.link,
    dir: "ltr"
  }, "1-700-70-70-07"), /*#__PURE__*/React.createElement("a", {
    href: "mailto:hi@ezway.co.il",
    style: ft.link
  }, "hi@ezway.co.il"), /*#__PURE__*/React.createElement("a", {
    href: "#",
    style: ft.link
  }, "\u05D5\u05D5\u05D0\u05D8\u05E1\u05D0\u05E4 \u05E2\u05DD \u05DE\u05D3\u05E8\u05D9\u05DA")), /*#__PURE__*/React.createElement("div", {
    style: ft.col
  }, /*#__PURE__*/React.createElement("div", {
    style: ft.head
  }, "\u05E9\u05D5\u05EA\u05E4\u05D9\u05DD"), /*#__PURE__*/React.createElement("div", {
    style: ft.partners
  }, /*#__PURE__*/React.createElement("div", {
    style: ft.partner
  }, "\u05DE\u05E8\u05DB\u05D6\u05D9 \u05D4\u05E6\u05E2\u05D9\u05E8\u05D9\u05DD"), /*#__PURE__*/React.createElement("div", {
    style: ft.partner
  }, "\u05E2\u05EA\u05D9\u05D3\u05D9\u05DD \u05DC\u05E6\u05D4\u05F4\u05DC"), /*#__PURE__*/React.createElement("div", {
    style: ft.partner
  }, "\u05E7\u05E8\u05D9\u05D9\u05EA \u05D1\u05D9\u05D0\u05DC\u05D9\u05E7"), /*#__PURE__*/React.createElement("div", {
    style: ft.partner
  }, "\u05D8\u05D1\u05E8\u05D9\u05D4")))), /*#__PURE__*/React.createElement("div", {
    style: ft.bottom
  }, /*#__PURE__*/React.createElement("span", null, "\xA9 2026 E.Z.WAY \u05D1\u05E2\u05F4\u05DE \xB7 ezway.co.il"), /*#__PURE__*/React.createElement("span", null, "\u05EA\u05E7\u05E0\u05D5\u05DF \xB7 \u05DE\u05D3\u05D9\u05E0\u05D9\u05D5\u05EA \u05E4\u05E8\u05D8\u05D9\u05D5\u05EA \xB7 \u05E0\u05D2\u05D9\u05E9\u05D5\u05EA")));
}
const ft = {
  wrap: {
    background: "#161420",
    color: "#fff"
  },
  inner: {
    maxWidth: 1280,
    margin: "0 auto",
    padding: "64px 32px 32px",
    display: "grid",
    gridTemplateColumns: "1.4fr 1fr 1fr 1.2fr",
    gap: 32
  },
  col: {
    display: "grid",
    gap: 8
  },
  logoRow: {
    display: "flex",
    alignItems: "center",
    gap: 10
  },
  word: {
    fontFamily: "var(--font-display)",
    fontWeight: 400,
    fontSize: 30,
    color: "#fff",
    letterSpacing: "-.02em"
  },
  tag: {
    fontFamily: "var(--font-display)",
    fontWeight: 700,
    fontSize: 22,
    color: "var(--ez-orange)",
    margin: "8px 0 0"
  },
  body: {
    fontFamily: "var(--font-body)",
    fontSize: 14,
    lineHeight: 1.5,
    color: "rgba(255,255,255,.7)",
    maxWidth: 280,
    margin: 0
  },
  head: {
    fontFamily: "var(--font-display)",
    fontWeight: 700,
    fontSize: 14,
    color: "#fff",
    marginBottom: 6
  },
  link: {
    fontFamily: "var(--font-body)",
    fontSize: 14,
    color: "rgba(255,255,255,.7)",
    textDecoration: "none"
  },
  partners: {
    display: "grid",
    gridTemplateColumns: "1fr 1fr",
    gap: 6
  },
  partner: {
    background: "rgba(255,255,255,.06)",
    border: "1px solid rgba(255,255,255,.1)",
    borderRadius: 6,
    padding: "8px 10px",
    fontFamily: "var(--font-body)",
    fontSize: 12,
    color: "rgba(255,255,255,.7)",
    textAlign: "center"
  },
  bottom: {
    borderTop: "1px solid rgba(255,255,255,.08)",
    maxWidth: 1280,
    margin: "0 auto",
    padding: "20px 32px",
    display: "flex",
    justifyContent: "space-between",
    fontFamily: "var(--font-body)",
    fontSize: 12,
    color: "rgba(255,255,255,.5)"
  }
};
window.Footer = Footer;
})(); } catch (e) { __ds_ns.__errors.push({ path: "ui_kits/web/Footer.jsx", error: String((e && e.message) || e) }); }

// ui_kits/web/Hero.jsx
try { (() => {
/* global React */
function Hero({
  onCTA
}) {
  return /*#__PURE__*/React.createElement("section", {
    style: hero.wrap
  }, /*#__PURE__*/React.createElement("div", {
    style: hero.zBack,
    "aria-hidden": true
  }, /*#__PURE__*/React.createElement("div", {
    style: {
      ...hero.zSlash,
      top: 60,
      width: "62%",
      right: "-4%",
      background: "var(--ez-lavender-soft)"
    }
  }), /*#__PURE__*/React.createElement("div", {
    style: {
      ...hero.zSlash,
      top: 120,
      width: "70%",
      right: "10%",
      background: "var(--ez-lavender)"
    }
  }), /*#__PURE__*/React.createElement("div", {
    style: {
      ...hero.zSlash,
      top: 360,
      width: "78%",
      right: "-4%",
      background: "var(--ez-lavender-soft)"
    }
  }), /*#__PURE__*/React.createElement("div", {
    style: {
      ...hero.zSlash,
      top: 420,
      width: "66%",
      right: "16%",
      background: "var(--ez-lavender)"
    }
  })), /*#__PURE__*/React.createElement("div", {
    style: hero.inner
  }, /*#__PURE__*/React.createElement("div", {
    style: hero.copy
  }, /*#__PURE__*/React.createElement("div", {
    style: hero.eyebrow
  }, "\u05E7\u05D5\u05E8\u05E1 \u05E4\u05E1\u05D9\u05DB\u05D5\u05DE\u05D8\u05E8\u05D9"), /*#__PURE__*/React.createElement("h1", {
    style: hero.h1
  }, "\u05E4\u05E9\u05D5\u05D8", /*#__PURE__*/React.createElement("br", null), "\u05EA\u05E6\u05DC\u05D9\u05D7\u05D5."), /*#__PURE__*/React.createElement("p", {
    style: hero.sub
  }, "\u05D4\u05E7\u05D5\u05E8\u05E1 \u05D4\u05D9\u05D7\u05D9\u05D3 \u05E9\u05DE\u05D5\u05DE\u05DC\u05E5 \u05E2\u05F4\u05D9 \u05D4\u05D0\u05D5\u05E0\u05D9\u05D1\u05E8\u05E1\u05D9\u05D8\u05D0\u05D5\u05EA \u05E2\u05E6\u05DE\u05DF. \u05DE\u05E1\u05DC\u05D5\u05DC\u05D9\u05DD \u05DC\u05EA\u05D9\u05DB\u05D5\u05E0\u05D9\u05E1\u05D8\u05D9\u05DD, \u05D7\u05D9\u05D9\u05DC\u05D9\u05DD \u05D5\u05DE\u05D1\u05D5\u05D2\u05E8\u05D9\u05DD \u05E9\u05D7\u05D5\u05D6\u05E8\u05D9\u05DD \u05DC\u05DC\u05D9\u05DE\u05D5\u05D3\u05D9\u05DD."), /*#__PURE__*/React.createElement("div", {
    style: hero.row
  }, /*#__PURE__*/React.createElement("button", {
    style: hero.cta,
    onClick: onCTA
  }, "\u05D4\u05D9\u05E8\u05E9\u05DE\u05D5 \u05DC\u05E7\u05D5\u05E8\u05E1"), /*#__PURE__*/React.createElement("a", {
    href: "#courses",
    style: hero.link
  }, "\u05D0\u05D9\u05D6\u05D4 \u05E7\u05D5\u05E8\u05E1 \u05DE\u05EA\u05D0\u05D9\u05DD \u05DC\u05D9? \u2190"))), /*#__PURE__*/React.createElement("div", {
    style: hero.figure
  }, /*#__PURE__*/React.createElement("div", {
    style: hero.photoFrame
  }, /*#__PURE__*/React.createElement("div", {
    style: hero.photoLabel
  }, "\u05E6\u05D9\u05DC\u05D5\u05DD \u05E1\u05D8\u05D5\u05D3\u05E0\u05D8 \xB7 cut-out B&W"), /*#__PURE__*/React.createElement("img", {
    src: "../../assets/dot-cluster.svg",
    alt: "",
    style: hero.dots
  })))));
}
const hero = {
  wrap: {
    position: "relative",
    overflow: "hidden",
    background: "var(--ez-paper-warm)",
    minHeight: 620,
    isolation: "isolate"
  },
  zBack: {
    position: "absolute",
    inset: 0,
    zIndex: 0
  },
  zSlash: {
    position: "absolute",
    height: 100,
    transform: "skew(-30deg)",
    borderRadius: 2
  },
  inner: {
    position: "relative",
    zIndex: 1,
    maxWidth: 1280,
    margin: "0 auto",
    padding: "72px 32px 96px",
    display: "grid",
    gridTemplateColumns: "1.1fr 1fr",
    gap: 40,
    alignItems: "center"
  },
  copy: {
    display: "grid",
    gap: 18
  },
  eyebrow: {
    fontFamily: "var(--font-display)",
    fontWeight: 700,
    color: "var(--ez-orange)",
    fontSize: 14
  },
  h1: {
    fontFamily: "var(--font-display)",
    fontWeight: 700,
    fontSize: 110,
    lineHeight: 0.95,
    color: "var(--ez-ink)",
    margin: 0,
    letterSpacing: "-.02em"
  },
  sub: {
    fontFamily: "var(--font-body)",
    fontSize: 18,
    lineHeight: 1.45,
    color: "var(--ez-fg-2)",
    maxWidth: 460,
    margin: 0
  },
  row: {
    display: "flex",
    gap: 18,
    alignItems: "center",
    marginTop: 8
  },
  cta: {
    background: "var(--ez-orange)",
    color: "#fff",
    border: 0,
    borderRadius: 999,
    padding: "14px 32px",
    fontFamily: "var(--font-display)",
    fontWeight: 700,
    fontSize: 17,
    cursor: "pointer"
  },
  link: {
    fontFamily: "var(--font-display)",
    fontWeight: 700,
    fontSize: 15,
    color: "var(--ez-lavender-deep)",
    textDecoration: "none"
  },
  figure: {
    position: "relative",
    height: 460,
    display: "flex",
    justifyContent: "center",
    alignItems: "flex-end"
  },
  photoFrame: {
    position: "relative",
    width: 380,
    height: 460,
    background: "linear-gradient(180deg,#dcdce0,#bcbcc4)",
    borderRadius: 8,
    display: "flex",
    alignItems: "center",
    justifyContent: "center",
    overflow: "hidden",
    filter: "grayscale(1) contrast(1.05)"
  },
  photoLabel: {
    fontFamily: "var(--font-mono)",
    fontSize: 12,
    color: "#3a3a44",
    padding: "6px 12px",
    background: "rgba(255,255,255,.85)",
    borderRadius: 4
  },
  dots: {
    position: "absolute",
    left: -60,
    bottom: -40,
    width: 220,
    height: 220,
    opacity: .9,
    filter: "grayscale(0)"
  }
};
window.Hero = Hero;
})(); } catch (e) { __ds_ns.__errors.push({ path: "ui_kits/web/Hero.jsx", error: String((e && e.message) || e) }); }

// ui_kits/web/Includes.jsx
try { (() => {
/* global React */
function Includes() {
  const items = ["מפגש שבועי בכיתה + השלמות בלמידה מרחוק", "ספריית VOD מלאה — צפו שוב, מתי שצריך", "מענה ישיר מהמדריך/ה בוואטסאפ לכל שאלה", "התאמות בפסיכומטרי לבעלי לקויות למידה", "התחלה הדרגתית — ימים מדויקים יימסרו לקראת הקורס", "מועד ב׳ בבגרויות — נשלים לכם את החומר"];
  return /*#__PURE__*/React.createElement("section", {
    style: inc.wrap
  }, /*#__PURE__*/React.createElement("div", {
    style: inc.inner
  }, /*#__PURE__*/React.createElement("div", {
    style: inc.head
  }, /*#__PURE__*/React.createElement("div", {
    style: inc.eyebrow
  }, "\u05D4\u05DB\u05D9 \u05D7\u05E9\u05D5\u05D1 \u05DC\u05D3\u05E2\u05EA"), /*#__PURE__*/React.createElement("h2", {
    style: inc.h2
  }, "\u05DE\u05D4 \u05DB\u05DC\u05D5\u05DC \u05D1\u05E7\u05D5\u05E8\u05E1.")), /*#__PURE__*/React.createElement("ul", {
    style: inc.list
  }, items.map(t => /*#__PURE__*/React.createElement("li", {
    key: t,
    style: inc.li
  }, /*#__PURE__*/React.createElement("img", {
    src: "../../assets/bullet-target.svg",
    alt: "",
    style: inc.bullet
  }), /*#__PURE__*/React.createElement("span", null, t))))));
}
const inc = {
  wrap: {
    background: "#fff",
    padding: "96px 32px"
  },
  inner: {
    maxWidth: 1280,
    margin: "0 auto",
    display: "grid",
    gridTemplateColumns: "1fr 1.4fr",
    gap: 56,
    alignItems: "start"
  },
  head: {
    display: "grid",
    gap: 8
  },
  eyebrow: {
    fontFamily: "var(--font-display)",
    fontWeight: 700,
    fontSize: 14,
    color: "var(--ez-orange)"
  },
  h2: {
    fontFamily: "var(--font-display)",
    fontWeight: 700,
    fontSize: 56,
    lineHeight: 1,
    color: "var(--ez-ink)",
    margin: 0,
    letterSpacing: "-.01em"
  },
  list: {
    listStyle: "none",
    padding: 0,
    margin: 0,
    display: "grid",
    gap: 18,
    columnGap: 32,
    gridTemplateColumns: "1fr 1fr"
  },
  li: {
    display: "flex",
    gap: 14,
    alignItems: "flex-start",
    fontFamily: "var(--font-body)",
    fontSize: 17,
    lineHeight: 1.45,
    color: "var(--ez-ink)"
  },
  bullet: {
    width: 26,
    height: 26,
    flex: "none",
    marginTop: 2
  }
};
window.Includes = Includes;
})(); } catch (e) { __ds_ns.__errors.push({ path: "ui_kits/web/Includes.jsx", error: String((e && e.message) || e) }); }

// ui_kits/web/LeadForm.jsx
try { (() => {
/* global React */
const {
  useState: useStateLF
} = React;
function LeadForm({
  open,
  onClose
}) {
  const [done, setDone] = useStateLF(false);
  if (!open) return null;
  return /*#__PURE__*/React.createElement("div", {
    style: lf.scrim,
    onClick: onClose
  }, /*#__PURE__*/React.createElement("div", {
    style: lf.modal,
    onClick: e => e.stopPropagation()
  }, /*#__PURE__*/React.createElement("button", {
    style: lf.x,
    onClick: onClose,
    "aria-label": "\u05E1\u05D2\u05D5\u05E8"
  }, "\xD7"), !done ? /*#__PURE__*/React.createElement("form", {
    onSubmit: e => {
      e.preventDefault();
      setDone(true);
    },
    style: lf.form
  }, /*#__PURE__*/React.createElement("div", {
    style: lf.eyebrow
  }, "\u05D4\u05E9\u05D0\u05D9\u05E8\u05D5 \u05E4\u05E8\u05D8\u05D9\u05DD"), /*#__PURE__*/React.createElement("h3", {
    style: lf.h3
  }, "\u05E0\u05D7\u05D6\u05D5\u05E8 \u05D0\u05DC\u05D9\u05DB\u05DD \u05EA\u05D5\u05DA 24 \u05E9\u05E2\u05D5\u05EA."), /*#__PURE__*/React.createElement("label", {
    style: lf.label
  }, "\u05E9\u05DD \u05DE\u05DC\u05D0"), /*#__PURE__*/React.createElement("input", {
    style: lf.input,
    placeholder: "\u05D9\u05E9\u05E8\u05D0\u05DC \u05D9\u05E9\u05E8\u05D0\u05DC\u05D9",
    required: true
  }), /*#__PURE__*/React.createElement("label", {
    style: lf.label
  }, "\u05D8\u05DC\u05E4\u05D5\u05DF"), /*#__PURE__*/React.createElement("input", {
    style: {
      ...lf.input,
      textAlign: "right"
    },
    dir: "ltr",
    placeholder: "050-1234567",
    required: true
  }), /*#__PURE__*/React.createElement("label", {
    style: lf.label
  }, "\u05DE\u05E1\u05DC\u05D5\u05DC \u05E9\u05DE\u05E2\u05E0\u05D9\u05D9\u05DF \u05D0\u05EA\u05DB\u05DD"), /*#__PURE__*/React.createElement("select", {
    style: lf.input,
    defaultValue: "\u05E4\u05E1\u05D9\u05DB\u05D5\u05DE\u05D8\u05E8\u05D9 \u05DC\u05EA\u05D9\u05DB\u05D5\u05E0\u05D9\u05E1\u05D8\u05D9\u05DD"
  }, /*#__PURE__*/React.createElement("option", null, "\u05E4\u05E1\u05D9\u05DB\u05D5\u05DE\u05D8\u05E8\u05D9 \u05DC\u05EA\u05D9\u05DB\u05D5\u05E0\u05D9\u05E1\u05D8\u05D9\u05DD"), /*#__PURE__*/React.createElement("option", null, "\u05E7\u05D5\u05E8\u05E1 \u05E4\u05D5\u05E7\u05D5\u05E1"), /*#__PURE__*/React.createElement("option", null, "\u05D4\u05DB\u05E0\u05D4 \u05DC\u05D0\u05E7\u05D3\u05DE\u05D9\u05D4"), /*#__PURE__*/React.createElement("option", null, "\u05E2\u05D5\u05D3 \u05DC\u05D0 \u05D9\u05D5\u05D3\u05E2/\u05EA")), /*#__PURE__*/React.createElement("label", {
    style: lf.check
  }, /*#__PURE__*/React.createElement("input", {
    type: "checkbox",
    defaultChecked: true
  }), " \u05D0\u05E0\u05D9 \u05DE\u05D0\u05E9\u05E8/\u05EA \u05E7\u05D1\u05DC\u05EA \u05D3\u05D9\u05D5\u05D5\u05E8 \u05E4\u05E8\u05E1\u05D5\u05DE\u05D9"), /*#__PURE__*/React.createElement("button", {
    type: "submit",
    style: lf.cta
  }, "\u05E9\u05D9\u05DC\u05D7\u05D5")) : /*#__PURE__*/React.createElement("div", {
    style: lf.done
  }, /*#__PURE__*/React.createElement("div", {
    style: {
      fontSize: 56,
      lineHeight: 1,
      color: "var(--ez-orange)"
    }
  }, "\u2713"), /*#__PURE__*/React.createElement("h3", {
    style: lf.h3
  }, "\u05E7\u05D9\u05D1\u05DC\u05E0\u05D5, \u05EA\u05D5\u05D3\u05D4!"), /*#__PURE__*/React.createElement("p", {
    style: lf.body
  }, "\u05E0\u05D7\u05D6\u05D5\u05E8 \u05D0\u05DC\u05D9\u05DB\u05DD \u05EA\u05D5\u05DA 24 \u05E9\u05E2\u05D5\u05EA. \u05D1\u05D9\u05E0\u05EA\u05D9\u05D9\u05DD \u2014 \u05DE\u05D5\u05D6\u05DE\u05E0\u05D9\u05DD \u05DC\u05D4\u05E6\u05D9\u05E5 \u05D1\u2011VOD."), /*#__PURE__*/React.createElement("button", {
    style: lf.cta,
    onClick: onClose
  }, "\u05D7\u05D6\u05E8\u05D4 \u05DC\u05D0\u05EA\u05E8"))));
}
const lf = {
  scrim: {
    position: "fixed",
    inset: 0,
    background: "rgba(20,18,40,.5)",
    display: "flex",
    alignItems: "center",
    justifyContent: "center",
    zIndex: 100,
    padding: 16
  },
  modal: {
    position: "relative",
    background: "#fff",
    borderRadius: 16,
    padding: 32,
    width: 460,
    maxWidth: "100%",
    boxShadow: "var(--shadow-3)"
  },
  x: {
    position: "absolute",
    top: 12,
    left: 12,
    background: "transparent",
    border: 0,
    fontSize: 28,
    lineHeight: 1,
    color: "var(--ez-fg-3)",
    cursor: "pointer"
  },
  form: {
    display: "grid",
    gap: 8
  },
  eyebrow: {
    fontFamily: "var(--font-display)",
    fontWeight: 700,
    fontSize: 13,
    color: "var(--ez-orange)"
  },
  h3: {
    fontFamily: "var(--font-display)",
    fontWeight: 700,
    fontSize: 28,
    lineHeight: 1.1,
    margin: "0 0 12px 0",
    color: "var(--ez-ink)"
  },
  label: {
    fontFamily: "var(--font-display)",
    fontWeight: 700,
    fontSize: 13,
    color: "var(--ez-fg-2)",
    marginTop: 6
  },
  input: {
    fontFamily: "var(--font-body)",
    fontSize: 16,
    padding: "12px 14px",
    borderRadius: 8,
    border: "1px solid var(--ez-line)",
    outline: "none",
    width: "100%",
    boxSizing: "border-box"
  },
  check: {
    display: "flex",
    gap: 8,
    alignItems: "center",
    fontFamily: "var(--font-body)",
    fontSize: 14,
    color: "var(--ez-fg-2)",
    marginTop: 8
  },
  cta: {
    background: "var(--ez-orange)",
    color: "#fff",
    border: 0,
    borderRadius: 999,
    padding: "14px 24px",
    fontFamily: "var(--font-display)",
    fontWeight: 700,
    fontSize: 16,
    cursor: "pointer",
    marginTop: 12
  },
  done: {
    textAlign: "center",
    display: "grid",
    gap: 10,
    padding: "12px 0"
  },
  body: {
    fontFamily: "var(--font-body)",
    fontSize: 16,
    color: "var(--ez-fg-2)",
    margin: 0
  }
};
window.LeadForm = LeadForm;
})(); } catch (e) { __ds_ns.__errors.push({ path: "ui_kits/web/LeadForm.jsx", error: String((e && e.message) || e) }); }

// ui_kits/web/SiteHeader.jsx
try { (() => {
/* global React */
const {
  useState
} = React;
function SiteHeader({
  onCTA
}) {
  const links = ["דף הבית", "קורסים", "פסיכומטרי בתיכון", "VOD", "צרו קשר"];
  return /*#__PURE__*/React.createElement("header", {
    style: hdr.bar
  }, /*#__PURE__*/React.createElement("div", {
    style: hdr.inner
  }, /*#__PURE__*/React.createElement("a", {
    href: "#",
    style: hdr.logo
  }, /*#__PURE__*/React.createElement("img", {
    src: "../../assets/logo-mark-orange.svg",
    alt: "",
    style: {
      width: 38,
      height: 38
    }
  }), /*#__PURE__*/React.createElement("span", {
    style: hdr.word
  }, "eazy", /*#__PURE__*/React.createElement("span", {
    style: {
      color: "var(--ez-orange)"
    }
  }, "."))), /*#__PURE__*/React.createElement("nav", {
    style: hdr.nav
  }, links.map(l => /*#__PURE__*/React.createElement("a", {
    key: l,
    href: "#",
    style: hdr.link
  }, l))), /*#__PURE__*/React.createElement("div", {
    style: hdr.right
  }, /*#__PURE__*/React.createElement("a", {
    href: "tel:1-700-70-70-07",
    style: hdr.phone,
    dir: "ltr"
  }, "1-700-70-70-07"), /*#__PURE__*/React.createElement("button", {
    style: hdr.cta,
    onClick: onCTA
  }, "\u05DC\u05E8\u05D9\u05E9\u05D5\u05DD"))));
}
const hdr = {
  bar: {
    position: "sticky",
    top: 0,
    zIndex: 50,
    background: "rgba(255,255,255,.96)",
    borderBottom: "1px solid var(--ez-line)",
    backdropFilter: "saturate(1.1)"
  },
  inner: {
    maxWidth: 1280,
    margin: "0 auto",
    display: "flex",
    alignItems: "center",
    justifyContent: "space-between",
    padding: "14px 32px",
    gap: 24
  },
  logo: {
    display: "flex",
    alignItems: "center",
    gap: 10,
    textDecoration: "none"
  },
  word: {
    fontFamily: "var(--font-display)",
    fontWeight: 400,
    fontSize: 28,
    color: "var(--ez-ink)",
    letterSpacing: "-.02em",
    lineHeight: 1,
    paddingBottom: 4
  },
  nav: {
    display: "flex",
    gap: 26
  },
  link: {
    fontFamily: "var(--font-display)",
    fontWeight: 400,
    fontSize: 15,
    color: "var(--ez-fg-1)",
    textDecoration: "none"
  },
  right: {
    display: "flex",
    alignItems: "center",
    gap: 14
  },
  phone: {
    fontFamily: "var(--font-mono)",
    fontSize: 15,
    color: "var(--ez-fg-2)",
    textDecoration: "none"
  },
  cta: {
    background: "var(--ez-orange)",
    color: "#fff",
    border: 0,
    borderRadius: 999,
    padding: "10px 22px",
    fontFamily: "var(--font-display)",
    fontWeight: 700,
    fontSize: 14,
    cursor: "pointer"
  }
};
window.SiteHeader = SiteHeader;
})(); } catch (e) { __ds_ns.__errors.push({ path: "ui_kits/web/SiteHeader.jsx", error: String((e && e.message) || e) }); }

// word-game/design-canvas.jsx
try { (() => {
/* BEGIN USAGE */
// DesignCanvas.jsx — Figma-ish design canvas wrapper
// Warm gray grid bg + Sections + Artboards + PostIt notes.
// Exports (to window): DesignCanvas, DCSection, DCArtboard, DCPostIt.
// Artboards are reorderable (grip-drag), deletable, labels/titles are
// inline-editable, and any artboard can be opened in a fullscreen focus
// overlay (←/→/Esc). State persists to a .design-canvas.state.json sidecar
// via the host bridge. No assets, no deps.
//
// Usage:
//   <DesignCanvas>
//     <DCSection id="onboarding" title="Onboarding" subtitle="First-run variants">
//       <DCArtboard id="a" label="A · Dusk" width={260} height={480}>…</DCArtboard>
//       <DCArtboard id="b" label="B · Minimal" width={260} height={480}>…</DCArtboard>
//     </DCSection>
//   </DesignCanvas>
//
// Artboards are static design frames, not scroll regions — never use
// height: 100% + overflow: auto/scroll on inner elements; size each artboard
// to fit its content (explicit pixel height, or let it grow).
/* END USAGE */

const DC = {
  bg: '#f0eee9',
  grid: 'rgba(0,0,0,0.06)',
  label: 'rgba(60,50,40,0.7)',
  title: 'rgba(40,30,20,0.85)',
  subtitle: 'rgba(60,50,40,0.6)',
  postitBg: '#fef4a8',
  postitText: '#5a4a2a',
  font: '-apple-system, BlinkMacSystemFont, "Segoe UI", system-ui, sans-serif'
};

// One-time CSS injection (classes are dc-prefixed so they don't collide with
// the hosted design's own styles).
if (typeof document !== 'undefined' && !document.getElementById('dc-styles')) {
  const s = document.createElement('style');
  s.id = 'dc-styles';
  s.textContent = ['.dc-editable{cursor:text;outline:none;white-space:nowrap;border-radius:3px;padding:0 2px;margin:0 -2px}', '.dc-editable:focus{background:#fff;box-shadow:0 0 0 1.5px #c96442}', '[data-dc-slot]{transition:transform .18s cubic-bezier(.2,.7,.3,1)}', '[data-dc-slot].dc-dragging{transition:none;z-index:10;pointer-events:none}', '[data-dc-slot].dc-dragging .dc-card{box-shadow:0 12px 40px rgba(0,0,0,.25),0 0 0 2px #c96442;transform:scale(1.02)}',
  // isolation:isolate contains artboard content's z-indexes so a
  // z-indexed child (sticky navbar etc.) can't paint over .dc-header or
  // the .dc-menu popover that drops into the top of the card.
  '.dc-card{isolation:isolate;transition:box-shadow .15s,transform .15s}', '.dc-card *{scrollbar-width:none}', '.dc-card *::-webkit-scrollbar{display:none}',
  // Per-artboard header: grip + label on the left, delete/expand on the
  // right. Single flex row; when the artboard's on-screen width is too
  // narrow for both the label yields (ellipsis, then hidden entirely below
  // ~4ch via the container query) and the buttons stay on the row.
  '.dc-header{position:absolute;bottom:100%;left:-4px;margin-bottom:calc(4px * var(--dc-inv-zoom,1));z-index:2;', '  display:flex;align-items:center;container-type:inline-size}', '.dc-labelrow{display:flex;align-items:center;gap:4px;height:24px;flex:1 1 auto;min-width:0}', '.dc-grip{flex:0 0 auto;cursor:grab;display:flex;align-items:center;padding:5px 4px;border-radius:4px;transition:background .12s,opacity .12s}', '.dc-grip:hover{background:rgba(0,0,0,.08)}', '.dc-grip:active{cursor:grabbing}', '.dc-labeltext{flex:1 1 auto;min-width:0;cursor:pointer;border-radius:4px;padding:3px 6px;', '  display:flex;align-items:center;transition:background .12s;overflow:hidden}',
  // Below ~4ch of label room: hide the label entirely, and drop the grip to
  // hover-only (same reveal rule as .dc-btns) so a narrow header is clean
  // until the card is moused.
  '@container (max-width: 110px){', '  .dc-labeltext{display:none}', '  .dc-grip{opacity:0}', '  [data-dc-slot]:hover .dc-grip{opacity:1}', '}', '.dc-labeltext:hover{background:rgba(0,0,0,.05)}', '.dc-labeltext .dc-editable{overflow:hidden;text-overflow:ellipsis;max-width:100%}', '.dc-labeltext .dc-editable:focus{overflow:visible;text-overflow:clip}', '.dc-btns{flex:0 0 auto;margin-left:auto;display:flex;gap:2px;opacity:0;transition:opacity .12s}', '[data-dc-slot]:hover .dc-btns,.dc-btns:has(.dc-menu){opacity:1}', '.dc-expand,.dc-kebab{width:22px;height:22px;border-radius:5px;border:none;cursor:pointer;padding:0;', '  background:transparent;color:rgba(60,50,40,.7);display:flex;align-items:center;justify-content:center;', '  font:inherit;transition:background .12s,color .12s}', '.dc-expand:hover,.dc-kebab:hover{background:rgba(0,0,0,.06);color:#2a251f}',
  // Slot hosting an open menu floats above later siblings (which otherwise
  // paint on top — same z-index:auto, later DOM order) so the popup isn't
  // clipped by the next card.
  '[data-dc-slot]:has(.dc-menu){z-index:10}', '.dc-menu{position:absolute;top:100%;right:0;margin-top:4px;background:#fff;border-radius:8px;', '  box-shadow:0 8px 28px rgba(0,0,0,.18),0 0 0 1px rgba(0,0,0,.05);padding:4px;min-width:160px;z-index:10}', '.dc-menu button{display:block;width:100%;padding:7px 10px;border:0;background:transparent;', '  border-radius:5px;font-family:inherit;font-size:13px;font-weight:500;line-height:1.2;', '  color:#29261b;cursor:pointer;text-align:left;transition:background .12s;white-space:nowrap}', '.dc-menu button:hover{background:rgba(0,0,0,.05)}', '.dc-menu hr{border:0;border-top:1px solid rgba(0,0,0,.08);margin:4px 2px}', '.dc-menu .dc-danger{color:#c96442}', '.dc-menu .dc-danger:hover{background:rgba(201,100,66,.1)}',
  // Chrome (titles / labels / buttons) counter-scales against the viewport
  // zoom so it stays a constant on-screen size. --dc-inv-zoom is set by
  // DCViewport on every transform update and inherits to all descendants —
  // any overlay inside the world (e.g. a TweaksPanel on an artboard) can use
  // it the same way.
  //
  // The header uses transform:scale (out-of-flow, so layout impact doesn't
  // matter) with its world-space width set to card-width / inv-zoom so that
  // after counter-scaling its on-screen width exactly matches the card's —
  // that's what lets the container query + text-overflow behave against the
  // card's visible edge at every zoom level.
  //
  // The section head uses CSS zoom instead of transform so its layout box
  // grows with the counter-scale, pushing the card row down — otherwise the
  // constant-screen-size title would overflow into the (shrinking) world-
  // space gap and overlap the artboard headers at low zoom.
  '.dc-header{width:calc((100% + 4px) / var(--dc-inv-zoom,1));', '  transform:scale(var(--dc-inv-zoom,1));transform-origin:bottom left}', '.dc-sectionhead{zoom:var(--dc-inv-zoom,1)}'].join('\n');
  document.head.appendChild(s);
}
const DCCtx = React.createContext(null);

// Recursively unwrap React.Fragment so <>…</> grouping doesn't hide
// DCSection/DCArtboard children from the type-based walks below.
function dcFlatten(children) {
  const out = [];
  React.Children.forEach(children, c => {
    if (c && c.type === React.Fragment) out.push(...dcFlatten(c.props.children));else out.push(c);
  });
  return out;
}

// ─────────────────────────────────────────────────────────────
// DesignCanvas — stateful wrapper around the pan/zoom viewport.
// Owns runtime state (per-section order, renamed titles/labels, hidden
// artboards, focused artboard). Order/titles/labels/hidden persist to a
// .design-canvas.state.json
// sidecar next to the HTML. Reads go via plain fetch() so the saved
// arrangement is visible anywhere the HTML + sidecar are served together
// (omelette preview, direct link, downloaded zip). Writes go through the
// host's window.omelette bridge — editing requires the omelette runtime.
// Focus is ephemeral.
// ─────────────────────────────────────────────────────────────
const DC_STATE_FILE = '.design-canvas.state.json';
function DesignCanvas({
  children,
  minScale,
  maxScale,
  style
}) {
  const [state, setState] = React.useState({
    sections: {},
    focus: null
  });
  // Hold rendering until the sidecar read settles so the saved order/titles
  // appear on first paint (no source-order flash). didRead gates writes until
  // the read settles so the empty initial state can't clobber a slow read;
  // skipNextWrite suppresses the one echo-write that would otherwise follow
  // hydration.
  const [ready, setReady] = React.useState(false);
  const didRead = React.useRef(false);
  const skipNextWrite = React.useRef(false);
  React.useEffect(() => {
    let off = false;
    fetch('./' + DC_STATE_FILE).then(r => r.ok ? r.json() : null).then(saved => {
      if (off || !saved || !saved.sections) return;
      skipNextWrite.current = true;
      setState(s => ({
        ...s,
        sections: saved.sections
      }));
    }).catch(() => {}).finally(() => {
      didRead.current = true;
      if (!off) setReady(true);
    });
    const t = setTimeout(() => {
      if (!off) setReady(true);
    }, 150);
    return () => {
      off = true;
      clearTimeout(t);
    };
  }, []);
  React.useEffect(() => {
    if (!didRead.current) return;
    if (skipNextWrite.current) {
      skipNextWrite.current = false;
      return;
    }
    const t = setTimeout(() => {
      window.omelette?.writeFile(DC_STATE_FILE, JSON.stringify({
        sections: state.sections
      })).catch(() => {});
    }, 250);
    return () => clearTimeout(t);
  }, [state.sections]);

  // Build registries synchronously from children so FocusOverlay can read
  // them in the same render. Fragments are flattened; wrapping in other
  // elements still opts out of focus/reorder.
  const registry = {}; // slotId -> { sectionId, artboard }
  const sectionMeta = {}; // sectionId -> { title, subtitle, slotIds[] }
  const sectionOrder = [];
  dcFlatten(children).forEach(sec => {
    if (!sec || sec.type !== DCSection) return;
    const sid = sec.props.id ?? sec.props.title;
    if (!sid) return;
    sectionOrder.push(sid);
    const persisted = state.sections[sid] || {};
    const abs = [];
    dcFlatten(sec.props.children).forEach(ab => {
      if (!ab || ab.type !== DCArtboard) return;
      const aid = ab.props.id ?? ab.props.label;
      if (aid) abs.push([aid, ab]);
    });
    // hidden is scoped to one source revision — when the agent regenerates
    // (artboard-ID set changes), prior deletes don't apply to new content.
    const srcKey = abs.map(([k]) => k).join('\x1f');
    const hidden = persisted.srcKey === srcKey ? persisted.hidden || [] : [];
    const srcIds = [];
    abs.forEach(([aid, ab]) => {
      if (hidden.includes(aid)) return;
      registry[`${sid}/${aid}`] = {
        sectionId: sid,
        artboard: ab
      };
      srcIds.push(aid);
    });
    const kept = (persisted.order || []).filter(k => srcIds.includes(k));
    sectionMeta[sid] = {
      title: persisted.title ?? sec.props.title,
      subtitle: sec.props.subtitle,
      slotIds: [...kept, ...srcIds.filter(k => !kept.includes(k))]
    };
  });
  const api = React.useMemo(() => ({
    state,
    section: id => state.sections[id] || {},
    patchSection: (id, p) => setState(s => ({
      ...s,
      sections: {
        ...s.sections,
        [id]: {
          ...s.sections[id],
          ...(typeof p === 'function' ? p(s.sections[id] || {}) : p)
        }
      }
    })),
    setFocus: slotId => setState(s => ({
      ...s,
      focus: slotId
    }))
  }), [state]);

  // Esc exits focus; any outside pointerdown commits an in-progress rename.
  React.useEffect(() => {
    const onKey = e => {
      if (e.key === 'Escape') api.setFocus(null);
    };
    const onPd = e => {
      const ae = document.activeElement;
      if (ae && ae.isContentEditable && !ae.contains(e.target)) ae.blur();
    };
    document.addEventListener('keydown', onKey);
    document.addEventListener('pointerdown', onPd, true);
    return () => {
      document.removeEventListener('keydown', onKey);
      document.removeEventListener('pointerdown', onPd, true);
    };
  }, [api]);
  return /*#__PURE__*/React.createElement(DCCtx.Provider, {
    value: api
  }, /*#__PURE__*/React.createElement(DCViewport, {
    minScale: minScale,
    maxScale: maxScale,
    style: style
  }, ready && children), state.focus && registry[state.focus] && /*#__PURE__*/React.createElement(DCFocusOverlay, {
    entry: registry[state.focus],
    sectionMeta: sectionMeta,
    sectionOrder: sectionOrder
  }));
}

// ─────────────────────────────────────────────────────────────
// DCViewport — transform-based pan/zoom (internal)
//
// Input mapping (Figma-style):
//   • trackpad pinch  → zoom   (ctrlKey wheel; Safari gesture* events)
//   • trackpad scroll → pan    (two-finger)
//   • mouse wheel     → zoom   (notched; distinguished from trackpad scroll)
//   • middle-drag / primary-drag-on-bg → pan
//
// Transform state lives in a ref and is written straight to the DOM
// (translate3d + will-change) so wheel ticks don't go through React —
// keeps pans at 60fps on dense canvases.
// ─────────────────────────────────────────────────────────────
function DCViewport({
  children,
  minScale = 0.1,
  maxScale = 8,
  style = {}
}) {
  const vpRef = React.useRef(null);
  const worldRef = React.useRef(null);
  const tf = React.useRef({
    x: 0,
    y: 0,
    scale: 1
  });
  // Persist viewport across reloads so the user lands back where they were
  // after an agent edit or browser refresh. The sandbox origin is already
  // per-project; pathname keeps multiple canvas files in one project apart.
  const tfKey = 'dc-viewport:' + location.pathname;
  const saveT = React.useRef(0);
  const lastPostedScale = React.useRef();
  const apply = React.useCallback(() => {
    const {
      x,
      y,
      scale
    } = tf.current;
    const el = worldRef.current;
    if (!el) return;
    el.style.transform = `translate3d(${x}px, ${y}px, 0) scale(${scale})`;
    // Exposed for zoom-invariant chrome (labels, buttons, TweaksPanel).
    el.style.setProperty('--dc-inv-zoom', String(1 / scale));
    // Keep the host toolbar's % readout in sync with the canvas scale. Pan
    // ticks leave scale unchanged — skip the cross-frame post for those.
    if (lastPostedScale.current !== scale) {
      lastPostedScale.current = scale;
      window.parent.postMessage({
        type: '__dc_zoom',
        scale
      }, '*');
    }
    clearTimeout(saveT.current);
    saveT.current = setTimeout(() => {
      try {
        localStorage.setItem(tfKey, JSON.stringify(tf.current));
      } catch {}
    }, 200);
  }, [tfKey]);
  React.useLayoutEffect(() => {
    const flush = () => {
      clearTimeout(saveT.current);
      try {
        localStorage.setItem(tfKey, JSON.stringify(tf.current));
      } catch {}
    };
    try {
      const s = JSON.parse(localStorage.getItem(tfKey) || 'null');
      if (s && Number.isFinite(s.x) && Number.isFinite(s.y) && Number.isFinite(s.scale)) {
        tf.current = {
          x: s.x,
          y: s.y,
          scale: Math.min(maxScale, Math.max(minScale, s.scale))
        };
        apply();
      }
    } catch {}
    // Flush on pagehide and unmount so a reload within the 200ms debounce
    // window doesn't drop the last pan/zoom.
    window.addEventListener('pagehide', flush);
    return () => {
      window.removeEventListener('pagehide', flush);
      flush();
    };
  }, []);
  React.useEffect(() => {
    const vp = vpRef.current;
    if (!vp) return;
    const zoomAt = (cx, cy, factor) => {
      const r = vp.getBoundingClientRect();
      const px = cx - r.left,
        py = cy - r.top;
      const t = tf.current;
      const next = Math.min(maxScale, Math.max(minScale, t.scale * factor));
      const k = next / t.scale;
      // --dc-inv-zoom consumers (.dc-sectionhead's CSS zoom, each section's
      // marginBottom) reflow on every scale change, vertically shifting the
      // world layout — so a world point mathematically pinned under the cursor
      // drifts as you zoom (content creeps up on zoom-in, down on zoom-out).
      // Anchor the DOM element under the cursor instead: record its screen Y,
      // apply the transform + --dc-inv-zoom, then cancel whatever vertical
      // drift the reflow introduced so it stays put on screen.
      let marker = null,
        markerY0 = 0;
      if (k !== 1) {
        const hit = document.elementFromPoint(cx, cy);
        marker = hit && hit.closest ? hit.closest('[data-dc-slot],[data-dc-section]') : null;
        if (marker) markerY0 = marker.getBoundingClientRect().top;
      }
      // keep the world point under the cursor fixed
      t.x = px - (px - t.x) * k;
      t.y = py - (py - t.y) * k;
      t.scale = next;
      apply();
      if (marker) {
        // A pure zoom around (cx, cy) maps screen Y → cy + (Y - cy) * k. Any
        // departure after the --dc-inv-zoom reflow is the layout drift.
        const drift = marker.getBoundingClientRect().top - (cy + (markerY0 - cy) * k);
        if (Math.abs(drift) > 0.1) {
          t.y -= drift;
          apply();
        }
      }
    };

    // Mouse-wheel vs trackpad-scroll heuristic. A physical wheel sends
    // line-mode deltas (Firefox) or large integer pixel deltas with no X
    // component (Chrome/Safari, typically multiples of 100/120). Trackpad
    // two-finger scroll sends small/fractional pixel deltas, often with
    // non-zero deltaX. ctrlKey is set by the browser for trackpad pinch.
    const isMouseWheel = e => e.deltaMode !== 0 || e.deltaX === 0 && Number.isInteger(e.deltaY) && Math.abs(e.deltaY) >= 40;
    const onWheel = e => {
      e.preventDefault();
      if (isGesturing) return; // Safari: gesture* owns the pinch — discard concurrent wheels
      if ((e.ctrlKey || e.metaKey) && !isMouseWheel(e)) {
        // trackpad pinch, or ctrl/cmd + smooth-scroll mouse. Notched
        // wheels fall through to the fixed-step branch below.
        zoomAt(e.clientX, e.clientY, Math.exp(-e.deltaY * 0.01));
      } else if (isMouseWheel(e)) {
        // notched mouse wheel — fixed-ratio step per click
        zoomAt(e.clientX, e.clientY, Math.exp(-Math.sign(e.deltaY) * 0.18));
      } else {
        // trackpad two-finger scroll — pan
        tf.current.x -= e.deltaX;
        tf.current.y -= e.deltaY;
        apply();
      }
    };

    // Safari sends native gesture* events for trackpad pinch with a smooth
    // e.scale; preferring these over the ctrl+wheel fallback gives a much
    // better feel there. No-ops on other browsers. Safari also fires
    // ctrlKey wheel events during the same pinch — isGesturing makes
    // onWheel drop those entirely so they neither zoom nor pan.
    let gsBase = 1;
    let isGesturing = false;
    const onGestureStart = e => {
      e.preventDefault();
      isGesturing = true;
      gsBase = tf.current.scale;
    };
    const onGestureChange = e => {
      e.preventDefault();
      zoomAt(e.clientX, e.clientY, gsBase * e.scale / tf.current.scale);
    };
    const onGestureEnd = e => {
      e.preventDefault();
      isGesturing = false;
    };

    // Drag-pan: middle button anywhere, or primary button on canvas
    // background (anything that isn't an artboard or an inline editor).
    let drag = null;
    const onPointerDown = e => {
      const onBg = !e.target.closest('[data-dc-slot], .dc-editable');
      if (!(e.button === 1 || e.button === 0 && onBg)) return;
      e.preventDefault();
      vp.setPointerCapture(e.pointerId);
      drag = {
        id: e.pointerId,
        lx: e.clientX,
        ly: e.clientY
      };
      vp.style.cursor = 'grabbing';
    };
    const onPointerMove = e => {
      if (!drag || e.pointerId !== drag.id) return;
      tf.current.x += e.clientX - drag.lx;
      tf.current.y += e.clientY - drag.ly;
      drag.lx = e.clientX;
      drag.ly = e.clientY;
      apply();
    };
    const onPointerUp = e => {
      if (!drag || e.pointerId !== drag.id) return;
      vp.releasePointerCapture(e.pointerId);
      drag = null;
      vp.style.cursor = '';
    };

    // Host-driven zoom (toolbar % menu). Zooms around viewport centre so the
    // visible midpoint stays fixed — matching the host's iframe-zoom feel.
    const onHostMsg = e => {
      const d = e.data;
      if (d && d.type === '__dc_set_zoom' && typeof d.scale === 'number') {
        const r = vp.getBoundingClientRect();
        zoomAt(r.left + r.width / 2, r.top + r.height / 2, d.scale / tf.current.scale);
      } else if (d && d.type === '__dc_probe') {
        // Host's [readyGen] reset asks whether a canvas is present; it
        // fires on the iframe's native 'load', which for canvases with
        // images/fonts is after our mount-time announce, so re-announce.
        // Clear the pan-tick guard so apply() re-posts the current scale
        // even if it's unchanged — the host just reset dcScale to 1.
        window.parent.postMessage({
          type: '__dc_present'
        }, '*');
        lastPostedScale.current = undefined;
        apply();
      }
    };
    window.addEventListener('message', onHostMsg);
    // Announce canvas mode so the host toolbar proxies its % control here
    // instead of scaling the iframe element (which would just shrink the
    // viewport window of an infinite canvas). The apply() that follows emits
    // the initial __dc_zoom so the toolbar % is correct before first pinch.
    // lastPostedScale reset mirrors the __dc_probe handler: the layout
    // effect's restore-path apply() may already have posted the restored
    // scale (before __dc_present), so clear the guard to re-post it in order.
    window.parent.postMessage({
      type: '__dc_present'
    }, '*');
    lastPostedScale.current = undefined;
    apply();
    vp.addEventListener('wheel', onWheel, {
      passive: false
    });
    vp.addEventListener('gesturestart', onGestureStart, {
      passive: false
    });
    vp.addEventListener('gesturechange', onGestureChange, {
      passive: false
    });
    vp.addEventListener('gestureend', onGestureEnd, {
      passive: false
    });
    vp.addEventListener('pointerdown', onPointerDown);
    vp.addEventListener('pointermove', onPointerMove);
    vp.addEventListener('pointerup', onPointerUp);
    vp.addEventListener('pointercancel', onPointerUp);
    return () => {
      window.removeEventListener('message', onHostMsg);
      vp.removeEventListener('wheel', onWheel);
      vp.removeEventListener('gesturestart', onGestureStart);
      vp.removeEventListener('gesturechange', onGestureChange);
      vp.removeEventListener('gestureend', onGestureEnd);
      vp.removeEventListener('pointerdown', onPointerDown);
      vp.removeEventListener('pointermove', onPointerMove);
      vp.removeEventListener('pointerup', onPointerUp);
      vp.removeEventListener('pointercancel', onPointerUp);
    };
  }, [apply, minScale, maxScale]);
  const gridSvg = `url("data:image/svg+xml,%3Csvg width='120' height='120' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath d='M120 0H0v120' fill='none' stroke='${encodeURIComponent(DC.grid)}' stroke-width='1'/%3E%3C/svg%3E")`;
  return /*#__PURE__*/React.createElement("div", {
    ref: vpRef,
    className: "design-canvas",
    style: {
      height: '100vh',
      width: '100vw',
      background: DC.bg,
      overflow: 'hidden',
      overscrollBehavior: 'none',
      touchAction: 'none',
      position: 'relative',
      fontFamily: DC.font,
      boxSizing: 'border-box',
      ...style
    }
  }, /*#__PURE__*/React.createElement("div", {
    ref: worldRef,
    style: {
      position: 'absolute',
      top: 0,
      left: 0,
      transformOrigin: '0 0',
      willChange: 'transform',
      width: 'max-content',
      minWidth: '100%',
      minHeight: '100%',
      padding: '60px 0 80px'
    }
  }, /*#__PURE__*/React.createElement("div", {
    style: {
      position: 'absolute',
      inset: -6000,
      backgroundImage: gridSvg,
      backgroundSize: '120px 120px',
      pointerEvents: 'none',
      zIndex: -1
    }
  }), children));
}

// ─────────────────────────────────────────────────────────────
// DCSection — editable title + h-row of artboards in persisted order
// ─────────────────────────────────────────────────────────────
function DCSection({
  id,
  title,
  subtitle,
  children,
  gap = 48
}) {
  const ctx = React.useContext(DCCtx);
  const sid = id ?? title;
  const all = React.Children.toArray(dcFlatten(children));
  const artboards = all.filter(c => c && c.type === DCArtboard);
  const rest = all.filter(c => !(c && c.type === DCArtboard));
  const sec = ctx && sid && ctx.section(sid) || {};
  // Must match DesignCanvas's srcKey computation exactly (it filters falsy
  // IDs), or onDelete persists a srcKey that DesignCanvas never recognizes.
  const allIds = artboards.map(a => a.props.id ?? a.props.label).filter(Boolean);
  const srcKey = allIds.join('\x1f');
  const hidden = sec.srcKey === srcKey ? sec.hidden || [] : [];
  const srcOrder = allIds.filter(k => !hidden.includes(k));
  const order = React.useMemo(() => {
    const kept = (sec.order || []).filter(k => srcOrder.includes(k));
    return [...kept, ...srcOrder.filter(k => !kept.includes(k))];
  }, [sec.order, srcOrder.join('|')]);
  const byId = Object.fromEntries(artboards.map(a => [a.props.id ?? a.props.label, a]));

  // marginBottom counter-scales so the on-screen gap between sections stays
  // constant — otherwise at low zoom the (world-space) gap collapses while
  // the screen-constant sectionhead below it doesn't, and the title reads as
  // belonging to the section above. paddingBottom below is just enough for
  // the 24px artboard-header (abs-positioned above each card) plus ~8px, so
  // the title sits tight against its own row at every zoom.
  return /*#__PURE__*/React.createElement("div", {
    "data-dc-section": sid,
    style: {
      marginBottom: 'calc(80px * var(--dc-inv-zoom, 1))',
      position: 'relative'
    }
  }, /*#__PURE__*/React.createElement("div", {
    style: {
      padding: '0 60px'
    }
  }, /*#__PURE__*/React.createElement("div", {
    className: "dc-sectionhead",
    style: {
      paddingBottom: 36
    }
  }, /*#__PURE__*/React.createElement(DCEditable, {
    tag: "div",
    value: sec.title ?? title,
    onChange: v => ctx && sid && ctx.patchSection(sid, {
      title: v
    }),
    style: {
      fontSize: 28,
      fontWeight: 600,
      color: DC.title,
      letterSpacing: -0.4,
      marginBottom: 6,
      display: 'inline-block'
    }
  }), subtitle && /*#__PURE__*/React.createElement("div", {
    style: {
      fontSize: 16,
      color: DC.subtitle
    }
  }, subtitle))), /*#__PURE__*/React.createElement("div", {
    style: {
      display: 'flex',
      gap,
      padding: '0 60px',
      alignItems: 'flex-start',
      width: 'max-content'
    }
  }, order.map(k => /*#__PURE__*/React.createElement(DCArtboardFrame, {
    key: k,
    sectionId: sid,
    artboard: byId[k],
    order: order,
    label: (sec.labels || {})[k] ?? byId[k].props.label,
    onRename: v => ctx && ctx.patchSection(sid, x => ({
      labels: {
        ...x.labels,
        [k]: v
      }
    })),
    onReorder: next => ctx && ctx.patchSection(sid, {
      order: next
    }),
    onDelete: () => ctx && ctx.patchSection(sid, x => ({
      hidden: [...(x.srcKey === srcKey ? x.hidden || [] : []), k],
      srcKey
    })),
    onFocus: () => ctx && ctx.setFocus(`${sid}/${k}`)
  }))), rest);
}

// DCArtboard — marker; rendered by DCArtboardFrame via DCSection.
function DCArtboard() {
  return null;
}

// Per-artboard export (kind: 'png' | 'html'). Both paths share the same
// self-contained clone: computed styles baked in, @font-face / <img> /
// inline-style background-image urls inlined as data URIs. PNG wraps the
// clone in foreignObject→canvas at 3× the artboard's natural width×height
// (same pipeline the host uses for page captures); HTML wraps it in a
// minimal standalone document. Both are independent of viewport zoom.
async function dcExport(node, w, h, name, kind) {
  try {
    await document.fonts.ready;
  } catch {}
  const toDataURL = url => fetch(url).then(r => r.blob()).then(b => new Promise(res => {
    const fr = new FileReader();
    fr.onload = () => res(fr.result);
    fr.onerror = () => res(url);
    fr.readAsDataURL(b);
  })).catch(() => url);

  // Collect @font-face rules. ss.cssRules throws SecurityError on
  // cross-origin sheets (e.g. fonts.googleapis.com) — in that case fetch
  // the CSS text directly (those endpoints send ACAO:*) and regex-extract
  // the blocks. @import and @media/@supports are walked so nested
  // @font-face rules aren't missed.
  const fontRules = [],
    pending = [],
    seen = new Set();
  const scrapeCss = href => {
    if (seen.has(href)) return;
    seen.add(href);
    pending.push(fetch(href).then(r => r.text()).then(css => {
      for (const m of css.match(/@font-face\s*{[^}]*}/g) || []) fontRules.push({
        css: m,
        base: href
      });
      for (const m of css.matchAll(/@import\s+(?:url\()?['"]?([^'")\s;]+)/g)) scrapeCss(new URL(m[1], href).href);
    }).catch(() => {}));
  };
  const walk = (rules, base) => {
    for (const r of rules) {
      if (r.type === CSSRule.FONT_FACE_RULE) fontRules.push({
        css: r.cssText,
        base
      });else if (r.type === CSSRule.IMPORT_RULE && r.styleSheet) {
        const ibase = r.styleSheet.href || base;
        try {
          walk(r.styleSheet.cssRules, ibase);
        } catch {
          scrapeCss(ibase);
        }
      } else if (r.cssRules) walk(r.cssRules, base);
    }
  };
  for (const ss of document.styleSheets) {
    const base = ss.href || location.href;
    try {
      walk(ss.cssRules, base);
    } catch {
      if (ss.href) scrapeCss(ss.href);
    }
  }
  while (pending.length) await pending.shift();
  const fontCss = (await Promise.all(fontRules.map(async rule => {
    let out = rule.css,
      m;
    const re = /url\((['"]?)([^'")]+)\1\)/g;
    while (m = re.exec(rule.css)) {
      if (m[2].indexOf('data:') === 0) continue;
      let abs;
      try {
        abs = new URL(m[2], rule.base).href;
      } catch {
        continue;
      }
      out = out.split(m[0]).join('url("' + (await toDataURL(abs)) + '")');
    }
    return out;
  }))).join('\n');
  const cloneStyled = src => {
    if (src.nodeType === 8 || src.nodeType === 1 && src.tagName === 'SCRIPT') return document.createTextNode('');
    const dst = src.cloneNode(false);
    if (src.nodeType === 1) {
      const cs = getComputedStyle(src);
      let txt = '';
      for (let i = 0; i < cs.length; i++) txt += cs[i] + ':' + cs.getPropertyValue(cs[i]) + ';';
      dst.setAttribute('style', txt + 'animation:none;transition:none;');
      if (src.tagName === 'CANVAS') try {
        const im = document.createElement('img');
        im.src = src.toDataURL();
        im.setAttribute('style', txt);
        return im;
      } catch {}
    }
    for (let c = src.firstChild; c; c = c.nextSibling) dst.appendChild(cloneStyled(c));
    return dst;
  };
  const clone = cloneStyled(node);
  clone.setAttribute('xmlns', 'http://www.w3.org/1999/xhtml');
  // Drop the card's own shadow/radius so the export is a flush w×h rect;
  // the artboard's own background (if any) is already in the computed style.
  clone.style.boxShadow = 'none';
  clone.style.borderRadius = '0';
  const jobs = [];
  clone.querySelectorAll('img').forEach(el => {
    const s = el.getAttribute('src');
    if (s && s.indexOf('data:') !== 0) jobs.push(toDataURL(el.src).then(d => el.setAttribute('src', d)));
  });
  [clone, ...clone.querySelectorAll('*')].forEach(el => {
    const bg = el.style.backgroundImage;
    if (!bg) return;
    let m;
    const re = /url\(["']?([^"')]+)["']?\)/g;
    while (m = re.exec(bg)) {
      const tok = m[0],
        url = m[1];
      if (url.indexOf('data:') === 0) continue;
      jobs.push(toDataURL(url).then(d => {
        el.style.backgroundImage = el.style.backgroundImage.split(tok).join('url("' + d + '")');
      }));
    }
  });
  await Promise.all(jobs);
  const xml = new XMLSerializer().serializeToString(clone);
  const save = (blob, ext) => {
    if (!blob) return;
    const a = document.createElement('a');
    a.href = URL.createObjectURL(blob);
    a.download = name + '.' + ext;
    a.click();
    setTimeout(() => URL.revokeObjectURL(a.href), 1000);
  };
  if (kind === 'html') {
    const html = '<!doctype html><html><head><meta charset="utf-8"><title>' + name + '</title>' + (fontCss ? '<style>' + fontCss + '</style>' : '') + '</head><body style="margin:0">' + xml + '</body></html>';
    return save(new Blob([html], {
      type: 'text/html'
    }), 'html');
  }

  // PNG: the SVG's own width/height must be the output resolution — an
  // <img>-loaded SVG rasterizes at its intrinsic size, so sizing it at 1×
  // and ctx.scale()-ing up would just upscale a 1× bitmap. viewBox maps the
  // w×h foreignObject onto the px·w × px·h SVG canvas so the browser renders
  // the HTML at full resolution.
  const px = 3;
  const svg = '<svg xmlns="http://www.w3.org/2000/svg" width="' + w * px + '" height="' + h * px + '" viewBox="0 0 ' + w + ' ' + h + '"><foreignObject width="' + w + '" height="' + h + '">' + (fontCss ? '<style><![CDATA[' + fontCss + ']]></style>' : '') + xml + '</foreignObject></svg>';
  const img = new Image();
  await new Promise((res, rej) => {
    img.onload = res;
    img.onerror = () => rej(new Error('svg load failed'));
    img.src = 'data:image/svg+xml;charset=utf-8,' + encodeURIComponent(svg);
  });
  const cv = document.createElement('canvas');
  cv.width = w * px;
  cv.height = h * px;
  cv.getContext('2d').drawImage(img, 0, 0);
  cv.toBlob(blob => save(blob, 'png'), 'image/png');
}
function DCArtboardFrame({
  sectionId,
  artboard,
  label,
  order,
  onRename,
  onReorder,
  onFocus,
  onDelete
}) {
  const {
    id: rawId,
    label: rawLabel,
    width = 260,
    height = 480,
    children,
    style = {}
  } = artboard.props;
  const id = rawId ?? rawLabel;
  const ref = React.useRef(null);
  const cardRef = React.useRef(null);
  const menuRef = React.useRef(null);
  const [menuOpen, setMenuOpen] = React.useState(false);
  const [confirming, setConfirming] = React.useState(false);

  // ⋯ menu: close on any outside pointerdown. Two-click delete lives inside
  // the menu — first click arms the row, second commits; closing disarms.
  React.useEffect(() => {
    if (!menuOpen) {
      setConfirming(false);
      return;
    }
    const off = e => {
      if (!menuRef.current || !menuRef.current.contains(e.target)) setMenuOpen(false);
    };
    document.addEventListener('pointerdown', off, true);
    return () => document.removeEventListener('pointerdown', off, true);
  }, [menuOpen]);
  const doExport = kind => {
    setMenuOpen(false);
    if (!cardRef.current) return;
    const name = String(label || id || 'artboard').replace(/[^\w\s.-]+/g, '_');
    dcExport(cardRef.current, width, height, name, kind).catch(e => console.error('[design-canvas] export failed:', e));
  };

  // Live drag-reorder: dragged card sticks to cursor; siblings slide into
  // their would-be slots in real time via transforms. DOM order only
  // changes on drop.
  const onGripDown = e => {
    e.preventDefault();
    e.stopPropagation();
    const me = ref.current;
    // translateX is applied in local (pre-scale) space but pointer deltas and
    // getBoundingClientRect().left are screen-space — divide by the viewport's
    // current scale so the dragged card tracks the cursor at any zoom level.
    const scale = me.getBoundingClientRect().width / me.offsetWidth || 1;
    const peers = Array.from(document.querySelectorAll(`[data-dc-section="${sectionId}"] [data-dc-slot]`));
    const homes = peers.map(el => ({
      el,
      id: el.dataset.dcSlot,
      x: el.getBoundingClientRect().left
    }));
    const slotXs = homes.map(h => h.x);
    const startIdx = order.indexOf(id);
    const startX = e.clientX;
    let liveOrder = order.slice();
    me.classList.add('dc-dragging');
    const layout = () => {
      for (const h of homes) {
        if (h.id === id) continue;
        const slot = liveOrder.indexOf(h.id);
        h.el.style.transform = `translateX(${(slotXs[slot] - h.x) / scale}px)`;
      }
    };
    const move = ev => {
      const dx = ev.clientX - startX;
      me.style.transform = `translateX(${dx / scale}px)`;
      const cur = homes[startIdx].x + dx;
      let nearest = 0,
        best = Infinity;
      for (let i = 0; i < slotXs.length; i++) {
        const d = Math.abs(slotXs[i] - cur);
        if (d < best) {
          best = d;
          nearest = i;
        }
      }
      if (liveOrder.indexOf(id) !== nearest) {
        liveOrder = order.filter(k => k !== id);
        liveOrder.splice(nearest, 0, id);
        layout();
      }
    };
    const up = () => {
      document.removeEventListener('pointermove', move);
      document.removeEventListener('pointerup', up);
      const finalSlot = liveOrder.indexOf(id);
      me.classList.remove('dc-dragging');
      me.style.transform = `translateX(${(slotXs[finalSlot] - homes[startIdx].x) / scale}px)`;
      // After the settle transition, kill transitions + clear transforms +
      // commit the reorder in the same frame so there's no visual snap-back.
      setTimeout(() => {
        for (const h of homes) {
          h.el.style.transition = 'none';
          h.el.style.transform = '';
        }
        if (liveOrder.join('|') !== order.join('|')) onReorder(liveOrder);
        requestAnimationFrame(() => requestAnimationFrame(() => {
          for (const h of homes) h.el.style.transition = '';
        }));
      }, 180);
    };
    document.addEventListener('pointermove', move);
    document.addEventListener('pointerup', up);
  };
  return /*#__PURE__*/React.createElement("div", {
    ref: ref,
    "data-dc-slot": id,
    style: {
      position: 'relative',
      flexShrink: 0
    }
  }, /*#__PURE__*/React.createElement("div", {
    className: "dc-header",
    "data-omelette-chrome": "",
    style: {
      color: DC.label
    },
    onPointerDown: e => e.stopPropagation()
  }, /*#__PURE__*/React.createElement("div", {
    className: "dc-labelrow"
  }, /*#__PURE__*/React.createElement("div", {
    className: "dc-grip",
    onPointerDown: onGripDown,
    title: "Drag to reorder"
  }, /*#__PURE__*/React.createElement("svg", {
    width: "9",
    height: "13",
    viewBox: "0 0 9 13",
    fill: "currentColor"
  }, /*#__PURE__*/React.createElement("circle", {
    cx: "2",
    cy: "2",
    r: "1.1"
  }), /*#__PURE__*/React.createElement("circle", {
    cx: "7",
    cy: "2",
    r: "1.1"
  }), /*#__PURE__*/React.createElement("circle", {
    cx: "2",
    cy: "6.5",
    r: "1.1"
  }), /*#__PURE__*/React.createElement("circle", {
    cx: "7",
    cy: "6.5",
    r: "1.1"
  }), /*#__PURE__*/React.createElement("circle", {
    cx: "2",
    cy: "11",
    r: "1.1"
  }), /*#__PURE__*/React.createElement("circle", {
    cx: "7",
    cy: "11",
    r: "1.1"
  }))), /*#__PURE__*/React.createElement("div", {
    className: "dc-labeltext",
    onClick: onFocus,
    title: "Click to focus"
  }, /*#__PURE__*/React.createElement(DCEditable, {
    value: label,
    onChange: onRename,
    onClick: e => e.stopPropagation(),
    style: {
      fontSize: 15,
      fontWeight: 500,
      color: DC.label,
      lineHeight: 1
    }
  }))), /*#__PURE__*/React.createElement("div", {
    className: "dc-btns"
  }, /*#__PURE__*/React.createElement("div", {
    ref: menuRef,
    style: {
      position: 'relative'
    }
  }, /*#__PURE__*/React.createElement("button", {
    className: "dc-kebab",
    title: "More",
    onClick: () => setMenuOpen(o => !o)
  }, /*#__PURE__*/React.createElement("svg", {
    width: "12",
    height: "12",
    viewBox: "0 0 12 12",
    fill: "currentColor"
  }, /*#__PURE__*/React.createElement("circle", {
    cx: "2.5",
    cy: "6",
    r: "1.1"
  }), /*#__PURE__*/React.createElement("circle", {
    cx: "6",
    cy: "6",
    r: "1.1"
  }), /*#__PURE__*/React.createElement("circle", {
    cx: "9.5",
    cy: "6",
    r: "1.1"
  }))), menuOpen && /*#__PURE__*/React.createElement("div", {
    className: "dc-menu",
    onPointerDown: e => e.stopPropagation()
  }, /*#__PURE__*/React.createElement("button", {
    onClick: () => doExport('png')
  }, "Download PNG"), /*#__PURE__*/React.createElement("button", {
    onClick: () => doExport('html')
  }, "Download HTML"), /*#__PURE__*/React.createElement("hr", null), /*#__PURE__*/React.createElement("button", {
    className: "dc-danger",
    onClick: () => {
      if (confirming) {
        setMenuOpen(false);
        onDelete();
      } else setConfirming(true);
    }
  }, confirming ? 'Click again to delete' : 'Delete'))), /*#__PURE__*/React.createElement("button", {
    className: "dc-expand",
    onClick: onFocus,
    title: "Focus"
  }, /*#__PURE__*/React.createElement("svg", {
    width: "12",
    height: "12",
    viewBox: "0 0 12 12",
    fill: "none",
    stroke: "currentColor",
    strokeWidth: "1.6",
    strokeLinecap: "round"
  }, /*#__PURE__*/React.createElement("path", {
    d: "M7 1h4v4M5 11H1V7M11 1L7.5 4.5M1 11l3.5-3.5"
  }))))), /*#__PURE__*/React.createElement("div", {
    ref: cardRef,
    className: "dc-card",
    style: {
      borderRadius: 2,
      boxShadow: '0 1px 3px rgba(0,0,0,.08),0 4px 16px rgba(0,0,0,.06)',
      overflow: 'hidden',
      width,
      height,
      background: '#fff',
      ...style
    }
  }, children || /*#__PURE__*/React.createElement("div", {
    style: {
      height: '100%',
      display: 'flex',
      alignItems: 'center',
      justifyContent: 'center',
      color: '#bbb',
      fontSize: 13,
      fontFamily: DC.font
    }
  }, id)));
}

// Inline rename — commits on blur or Enter.
function DCEditable({
  value,
  onChange,
  style,
  tag = 'span',
  onClick
}) {
  const T = tag;
  return /*#__PURE__*/React.createElement(T, {
    className: "dc-editable",
    contentEditable: true,
    suppressContentEditableWarning: true,
    onClick: onClick,
    onPointerDown: e => e.stopPropagation(),
    onBlur: e => onChange && onChange(e.currentTarget.textContent),
    onKeyDown: e => {
      if (e.key === 'Enter') {
        e.preventDefault();
        e.currentTarget.blur();
      }
    },
    style: style
  }, value);
}

// ─────────────────────────────────────────────────────────────
// Focus mode — overlay one artboard; ←/→ within section, ↑/↓ across
// sections, Esc or backdrop click to exit.
// ─────────────────────────────────────────────────────────────
function DCFocusOverlay({
  entry,
  sectionMeta,
  sectionOrder
}) {
  const ctx = React.useContext(DCCtx);
  const {
    sectionId,
    artboard
  } = entry;
  const sec = ctx.section(sectionId);
  const meta = sectionMeta[sectionId];
  const peers = meta.slotIds;
  const aid = artboard.props.id ?? artboard.props.label;
  const idx = peers.indexOf(aid);
  const secIdx = sectionOrder.indexOf(sectionId);
  const go = d => {
    const n = peers[(idx + d + peers.length) % peers.length];
    if (n) ctx.setFocus(`${sectionId}/${n}`);
  };
  const goSection = d => {
    // Sections whose artboards are all deleted have slotIds:[] — step past
    // them to the next non-empty section so ↑/↓ doesn't dead-end.
    const n = sectionOrder.length;
    for (let i = 1; i < n; i++) {
      const ns = sectionOrder[((secIdx + d * i) % n + n) % n];
      const first = sectionMeta[ns] && sectionMeta[ns].slotIds[0];
      if (first) {
        ctx.setFocus(`${ns}/${first}`);
        return;
      }
    }
  };
  React.useEffect(() => {
    const k = e => {
      if (e.key === 'ArrowLeft') {
        e.preventDefault();
        go(-1);
      }
      if (e.key === 'ArrowRight') {
        e.preventDefault();
        go(1);
      }
      if (e.key === 'ArrowUp') {
        e.preventDefault();
        goSection(-1);
      }
      if (e.key === 'ArrowDown') {
        e.preventDefault();
        goSection(1);
      }
    };
    document.addEventListener('keydown', k);
    return () => document.removeEventListener('keydown', k);
  });
  const {
    width = 260,
    height = 480,
    children
  } = artboard.props;
  const [vp, setVp] = React.useState({
    w: window.innerWidth,
    h: window.innerHeight
  });
  React.useEffect(() => {
    const r = () => setVp({
      w: window.innerWidth,
      h: window.innerHeight
    });
    window.addEventListener('resize', r);
    return () => window.removeEventListener('resize', r);
  }, []);
  const scale = Math.max(0.1, Math.min((vp.w - 200) / width, (vp.h - 260) / height, 2));
  const [ddOpen, setDd] = React.useState(false);
  const Arrow = ({
    dir,
    onClick
  }) => /*#__PURE__*/React.createElement("button", {
    onClick: e => {
      e.stopPropagation();
      onClick();
    },
    style: {
      position: 'absolute',
      top: '50%',
      [dir]: 28,
      transform: 'translateY(-50%)',
      border: 'none',
      background: 'rgba(255,255,255,.08)',
      color: 'rgba(255,255,255,.9)',
      width: 44,
      height: 44,
      borderRadius: 22,
      fontSize: 18,
      cursor: 'pointer',
      display: 'flex',
      alignItems: 'center',
      justifyContent: 'center',
      transition: 'background .15s'
    },
    onMouseEnter: e => e.currentTarget.style.background = 'rgba(255,255,255,.18)',
    onMouseLeave: e => e.currentTarget.style.background = 'rgba(255,255,255,.08)'
  }, /*#__PURE__*/React.createElement("svg", {
    width: "18",
    height: "18",
    viewBox: "0 0 18 18",
    fill: "none",
    stroke: "currentColor",
    strokeWidth: "2",
    strokeLinecap: "round"
  }, /*#__PURE__*/React.createElement("path", {
    d: dir === 'left' ? 'M11 3L5 9l6 6' : 'M7 3l6 6-6 6'
  })));

  // Portal to body so position:fixed is the real viewport regardless of any
  // transform on DesignCanvas's ancestors (including the canvas zoom itself).
  return ReactDOM.createPortal(/*#__PURE__*/React.createElement("div", {
    onClick: () => ctx.setFocus(null),
    onWheel: e => e.preventDefault(),
    style: {
      position: 'fixed',
      inset: 0,
      zIndex: 100,
      background: 'rgba(24,20,16,.6)',
      backdropFilter: 'blur(14px)',
      fontFamily: DC.font,
      color: '#fff'
    }
  }, /*#__PURE__*/React.createElement("div", {
    onClick: e => e.stopPropagation(),
    style: {
      position: 'absolute',
      top: 0,
      left: 0,
      right: 0,
      height: 72,
      display: 'flex',
      alignItems: 'flex-start',
      padding: '16px 20px 0',
      gap: 16
    }
  }, /*#__PURE__*/React.createElement("div", {
    style: {
      position: 'relative'
    }
  }, /*#__PURE__*/React.createElement("button", {
    onClick: () => setDd(o => !o),
    style: {
      border: 'none',
      background: 'transparent',
      color: '#fff',
      cursor: 'pointer',
      padding: '6px 8px',
      borderRadius: 6,
      textAlign: 'left',
      fontFamily: 'inherit'
    }
  }, /*#__PURE__*/React.createElement("span", {
    style: {
      display: 'flex',
      alignItems: 'center',
      gap: 8
    }
  }, /*#__PURE__*/React.createElement("span", {
    style: {
      fontSize: 18,
      fontWeight: 600,
      letterSpacing: -0.3
    }
  }, meta.title), /*#__PURE__*/React.createElement("svg", {
    width: "11",
    height: "11",
    viewBox: "0 0 11 11",
    fill: "none",
    stroke: "currentColor",
    strokeWidth: "1.8",
    strokeLinecap: "round",
    style: {
      opacity: .7
    }
  }, /*#__PURE__*/React.createElement("path", {
    d: "M2 4l3.5 3.5L9 4"
  }))), meta.subtitle && /*#__PURE__*/React.createElement("span", {
    style: {
      display: 'block',
      fontSize: 13,
      opacity: .6,
      fontWeight: 400,
      marginTop: 2
    }
  }, meta.subtitle)), ddOpen && /*#__PURE__*/React.createElement("div", {
    style: {
      position: 'absolute',
      top: '100%',
      left: 0,
      marginTop: 4,
      background: '#2a251f',
      borderRadius: 8,
      boxShadow: '0 8px 32px rgba(0,0,0,.4)',
      padding: 4,
      minWidth: 200,
      zIndex: 10
    }
  }, sectionOrder.filter(sid => sectionMeta[sid].slotIds.length).map(sid => /*#__PURE__*/React.createElement("button", {
    key: sid,
    onClick: () => {
      setDd(false);
      const f = sectionMeta[sid].slotIds[0];
      if (f) ctx.setFocus(`${sid}/${f}`);
    },
    style: {
      display: 'block',
      width: '100%',
      textAlign: 'left',
      border: 'none',
      cursor: 'pointer',
      background: sid === sectionId ? 'rgba(255,255,255,.1)' : 'transparent',
      color: '#fff',
      padding: '8px 12px',
      borderRadius: 5,
      fontSize: 14,
      fontWeight: sid === sectionId ? 600 : 400,
      fontFamily: 'inherit'
    }
  }, sectionMeta[sid].title)))), /*#__PURE__*/React.createElement("div", {
    style: {
      flex: 1
    }
  }), /*#__PURE__*/React.createElement("button", {
    onClick: () => ctx.setFocus(null),
    onMouseEnter: e => e.currentTarget.style.background = 'rgba(255,255,255,.12)',
    onMouseLeave: e => e.currentTarget.style.background = 'transparent',
    style: {
      border: 'none',
      background: 'transparent',
      color: 'rgba(255,255,255,.7)',
      width: 32,
      height: 32,
      borderRadius: 16,
      fontSize: 20,
      cursor: 'pointer',
      lineHeight: 1,
      transition: 'background .12s'
    }
  }, "\xD7")), /*#__PURE__*/React.createElement("div", {
    style: {
      position: 'absolute',
      top: 64,
      bottom: 56,
      left: 100,
      right: 100,
      display: 'flex',
      flexDirection: 'column',
      alignItems: 'center',
      justifyContent: 'center',
      gap: 16
    }
  }, /*#__PURE__*/React.createElement("div", {
    onClick: e => e.stopPropagation(),
    style: {
      width: width * scale,
      height: height * scale,
      position: 'relative'
    }
  }, /*#__PURE__*/React.createElement("div", {
    style: {
      width,
      height,
      transform: `scale(${scale})`,
      transformOrigin: 'top left',
      background: '#fff',
      borderRadius: 2,
      overflow: 'hidden',
      boxShadow: '0 20px 80px rgba(0,0,0,.4)'
    }
  }, children || /*#__PURE__*/React.createElement("div", {
    style: {
      height: '100%',
      display: 'flex',
      alignItems: 'center',
      justifyContent: 'center',
      color: '#bbb'
    }
  }, aid))), /*#__PURE__*/React.createElement("div", {
    onClick: e => e.stopPropagation(),
    style: {
      fontSize: 14,
      fontWeight: 500,
      opacity: .85,
      textAlign: 'center'
    }
  }, (sec.labels || {})[aid] ?? artboard.props.label, /*#__PURE__*/React.createElement("span", {
    style: {
      opacity: .5,
      marginLeft: 10,
      fontVariantNumeric: 'tabular-nums'
    }
  }, idx + 1, " / ", peers.length))), /*#__PURE__*/React.createElement(Arrow, {
    dir: "left",
    onClick: () => go(-1)
  }), /*#__PURE__*/React.createElement(Arrow, {
    dir: "right",
    onClick: () => go(1)
  }), /*#__PURE__*/React.createElement("div", {
    onClick: e => e.stopPropagation(),
    style: {
      position: 'absolute',
      bottom: 20,
      left: '50%',
      transform: 'translateX(-50%)',
      display: 'flex',
      gap: 8
    }
  }, peers.map((p, i) => /*#__PURE__*/React.createElement("button", {
    key: p,
    onClick: () => ctx.setFocus(`${sectionId}/${p}`),
    style: {
      border: 'none',
      padding: 0,
      cursor: 'pointer',
      width: 6,
      height: 6,
      borderRadius: 3,
      background: i === idx ? '#fff' : 'rgba(255,255,255,.3)'
    }
  })))), document.body);
}

// ─────────────────────────────────────────────────────────────
// Post-it — absolute-positioned sticky note
// ─────────────────────────────────────────────────────────────
function DCPostIt({
  children,
  top,
  left,
  right,
  bottom,
  rotate = -2,
  width = 180
}) {
  return /*#__PURE__*/React.createElement("div", {
    style: {
      position: 'absolute',
      top,
      left,
      right,
      bottom,
      width,
      background: DC.postitBg,
      padding: '14px 16px',
      fontFamily: '"Comic Sans MS", "Marker Felt", "Segoe Print", cursive',
      fontSize: 14,
      lineHeight: 1.4,
      color: DC.postitText,
      boxShadow: '0 2px 8px rgba(0,0,0,0.12), 0 1px 2px rgba(0,0,0,0.08)',
      transform: `rotate(${rotate}deg)`,
      zIndex: 5
    }
  }, children);
}
Object.assign(window, {
  DesignCanvas,
  DCSection,
  DCArtboard,
  DCPostIt
});
})(); } catch (e) { __ds_ns.__errors.push({ path: "word-game/design-canvas.jsx", error: String((e && e.message) || e) }); }

// workshop-followup/doc-page.js
try { (() => {
// @ds-adherence-ignore -- omelette starter scaffold (raw elements/hex/px by design)
/* BEGIN USAGE */
/**
 * <doc-page> — paged-document shell for printable HTML.
 *
 * On screen the document renders as a single continuous sheet on a desk
 * background (Google Docs' pageless view): you scroll one tall page card.
 * There is no manual page-splitting — write the whole document as normal
 * flow inside <doc-page> and the browser's print engine paginates it at
 * export.
 *
 * At print the component injects `@page { size: …; margin: 0 }` (which
 * leaves Chrome no margin box to draw its date/URL/page-count header in)
 * and moves the visual margin onto the sheet's own padding, so the printed
 * page has the same inset you see on screen. Standard break-hygiene rules
 * (`break-inside: avoid` on figures, code blocks, images and table rows;
 * `orphans/widows: 3`) are applied so paragraphs and groups split cleanly.
 * On screen and at print, headings default to `text-wrap: balance` and
 * body text (p, li, blockquote, figcaption) to `text-wrap: pretty`, so
 * the document avoids widowed/orphaned words; the defaults have zero
 * specificity, so any text-wrap you declare on those elements wins.
 *
 * Usage:
 *   <style>doc-page:not(:defined){visibility:hidden}</style>
 *   <doc-page size="letter" margin="0.75in">
 *     <h1>Title</h1>
 *     <p>…body…</p>
 *   </doc-page>
 *   <script src="doc-page.js"></script>
 *
 * Attributes:
 *   size    — letter | a4 | legal (default letter)
 *   width / height — explicit CSS lengths, override `size`
 *   margin  — printable inset on every page (default 0.75in)
 *
 * Running header/footer (optional): give an element `slot="header"` or
 * `slot="footer"` and it repeats on every printed page via
 * `position: fixed`. To keep body text from sliding under it, the
 * component prints inside a single-cell table whose <thead>/<tfoot> are
 * spacers sized to the header/footer height — browsers repeat thead/tfoot
 * on every page, so each sheet's content starts below the header and ends
 * above the footer. On screen the header/footer render once at the
 * top/bottom of the sheet.
 *
 * Author content as static HTML so the user can click-to-edit any text
 * directly. Do not set width/padding/background on the document body —
 * the component owns the sheet box.
 */
/* END USAGE */

(() => {
  const PAPER = {
    letter: ['8.5in', '11in'],
    a4: ['210mm', '297mm'],
    legal: ['8.5in', '14in']
  };
  const CSS_LENGTH = /^\d+(\.\d+)?(px|in|mm|cm|pt|pc)$/;
  const safeLen = (v, fb) => CSS_LENGTH.test((v || '').trim()) ? v.trim() : fb;
  const stylesheet = `
    :host {
      position: relative;
      display: block;
      min-height: 100vh;
      background: #ece8dd;
      padding: 48px 24px;
      box-sizing: border-box;
      font-family: -apple-system, BlinkMacSystemFont, "Helvetica Neue", Arial, sans-serif;
      --doc-page-w: 8.5in;
      --doc-page-h: 11in;
      --doc-page-margin: 0.75in;
      --doc-hdr-h: 0px;
      --doc-ftr-h: 0px;
    }
    .sheet {
      width: var(--doc-page-w);
      margin: 0 auto;
      background: #fff;
      box-shadow: 0 2px 14px rgba(20, 20, 19, 0.12);
      border-radius: 2px;
      box-sizing: border-box;
      padding: var(--doc-page-margin);
    }
    .frame { width: 100%; border-collapse: collapse; }
    .frame td, .frame th { padding: 0; text-align: left; font-weight: inherit; }
    .hdr-space { height: var(--doc-hdr-h); }
    .ftr-space { height: var(--doc-ftr-h); }
    ::slotted([slot="header"]),
    ::slotted([slot="footer"]) { display: block; box-sizing: border-box; }
    @media print {
      :host { background: none; padding: 0; min-height: 0; }
      .sheet {
        width: auto; margin: 0; box-shadow: none; border-radius: 0;
        padding: 0 var(--doc-page-margin);
      }
      /* The thead/tfoot spacers repeat on every page, so they carry the
       * vertical page margin (which the sheet's own padding cannot, since
       * that padding is consumed once on the first/last page). The running
       * header/footer are fixed inside that band. */
      .hdr-space { height: max(var(--doc-page-margin), calc(var(--doc-hdr-h) + 0.35in)); }
      .ftr-space { height: max(var(--doc-page-margin), calc(var(--doc-ftr-h) + 0.35in)); }
      ::slotted([slot="header"]) {
        position: fixed; top: 0; left: 0; right: 0; margin: 0;
        padding: calc(var(--doc-page-margin) * 0.45) var(--doc-page-margin) 0;
      }
      ::slotted([slot="footer"]) {
        position: fixed; bottom: 0; left: 0; right: 0; margin: 0;
        padding: 0 var(--doc-page-margin) calc(var(--doc-page-margin) * 0.45);
      }
    }
  `;
  class DocPage extends HTMLElement {
    static get observedAttributes() {
      return ['size', 'width', 'height', 'margin'];
    }
    constructor() {
      super();
      this._root = this.attachShadow({
        mode: 'open'
      });
      this._mo = typeof MutationObserver === 'function' ? new MutationObserver(() => this._scheduleMeasure()) : null;
    }
    get pageWidth() {
      const named = PAPER[(this.getAttribute('size') || '').toLowerCase()];
      return safeLen(this.getAttribute('width'), named ? named[0] : PAPER.letter[0]);
    }
    get pageHeight() {
      const named = PAPER[(this.getAttribute('size') || '').toLowerCase()];
      return safeLen(this.getAttribute('height'), named ? named[1] : PAPER.letter[1]);
    }
    get pageMargin() {
      return safeLen(this.getAttribute('margin'), '0.75in');
    }
    connectedCallback() {
      if (!this._sheet) this._render();
      this._syncSize();
      this._syncPrintPageRule();
      this._ensureTextWrapDefaults();
      if (this._mo) this._mo.observe(this, {
        subtree: true,
        childList: true,
        characterData: true,
        attributes: true
      });
      this._onResize = () => this._scheduleMeasure();
      window.addEventListener('resize', this._onResize);
      if (document.fonts && document.fonts.ready) {
        document.fonts.ready.then(() => this._scheduleMeasure());
      }
      this._scheduleMeasure();
    }
    disconnectedCallback() {
      window.removeEventListener('resize', this._onResize);
      if (this._mo) this._mo.disconnect();
      if (this._raf) {
        cancelAnimationFrame(this._raf);
        this._raf = null;
      }
      // Drop the head rules when the last doc-page leaves, so a deleted
      // document's @page geometry and text-wrap defaults can't apply to
      // whatever replaces it.
      if (!document.querySelector('doc-page')) {
        ['doc-page-print', 'doc-page-text-wrap'].forEach(id => {
          const tag = document.getElementById(id);
          if (tag) tag.remove();
        });
      }
    }
    attributeChangedCallback() {
      if (!this._sheet) return;
      this._syncSize();
      this._syncPrintPageRule();
      this._scheduleMeasure();
    }
    _render() {
      this._root.innerHTML = `
        <style>${stylesheet}</style>
        <style id="vars"></style>
        <div class="sheet" data-screen-label="Document">
          <table class="frame" role="presentation">
            <thead><tr><th><div class="hdr-space"><slot name="header"></slot></div></th></tr></thead>
            <tbody><tr><td class="body"><slot></slot></td></tr></tbody>
            <tfoot><tr><td><div class="ftr-space"><slot name="footer"></slot></div></td></tr></tfoot>
          </table>
        </div>`;
      this._sheet = this._root.querySelector('.sheet');
      this._vars = this._root.getElementById('vars');
    }

    /** Runtime sizing lives in a shadow <style> :host rule, never on the
     *  light-DOM host element, so serialize-persist can't write it back. */
    _syncSize(hdrH, ftrH) {
      this._vars.textContent = ':host{' + '--doc-page-w:' + this.pageWidth + ';' + '--doc-page-h:' + this.pageHeight + ';' + '--doc-page-margin:' + this.pageMargin + ';' + '--doc-hdr-h:' + (hdrH || 0) + 'px;' + '--doc-ftr-h:' + (ftrH || 0) + 'px}';
    }

    /** @page is a no-op inside shadow DOM, so the rule lives in <head>.
     *  Re-appended on every sync so it stays last in source order — the
     *  @page cascade is source-order per descriptor, so this rule wins
     *  over any other @page rule in the document. */
    _syncPrintPageRule() {
      const id = 'doc-page-print';
      let tag = document.getElementById(id);
      if (!tag) {
        tag = document.createElement('style');
        tag.id = id;
      }
      document.head.appendChild(tag);
      tag.textContent = '@page { size: ' + this.pageWidth + ' ' + this.pageHeight + '; margin: 0; } ' + '@media print { html, body { margin: 0 !important; padding: 0 !important; background: none !important; height: auto !important; overflow: visible !important; } ' + 'h1,h2,h3,h4,h5,h6 { break-after: avoid; } ' + 'figure,pre,blockquote,img,svg,tr { break-inside: avoid; } ' + 'p,li { orphans: 3; widows: 3; } ' + '* { -webkit-print-color-adjust: exact; print-color-adjust: exact; } ' + '*, *::before, *::after { animation-delay: -99s !important; animation-duration: .001s !important; ' + 'animation-iteration-count: 1 !important; animation-fill-mode: both !important; ' + 'animation-play-state: running !important; transition-duration: 0s !important; } }';
    }

    /** Typographic defaults for document text: balance headings, avoid
     *  widowed/orphaned words in body copy (browsers without text-wrap
     *  support drop the declarations). Zero-specificity via :where() so
     *  any text-wrap authored on those elements wins; document-level so the
     *  rules reach the slotted (light DOM) content — shadow styles can't.
     *  data-omelette-injected marks the tag for the host editor to strip
     *  at serialize, so it is never written back as authored source. */
    _ensureTextWrapDefaults() {
      if (document.getElementById('doc-page-text-wrap')) return;
      const tag = document.createElement('style');
      tag.id = 'doc-page-text-wrap';
      tag.setAttribute('data-omelette-injected', '');
      tag.textContent = ':where(h1,h2,h3,h4,h5,h6){text-wrap:balance}' + ':where(p,li,blockquote,figcaption){text-wrap:pretty}';
      document.head.appendChild(tag);
    }
    _scheduleMeasure() {
      if (this._raf) return;
      this._raf = requestAnimationFrame(() => {
        this._raf = null;
        this._measure();
      });
    }

    /** Slot heights feed the print spacers (--doc-hdr-h / --doc-ftr-h), so
     *  they re-measure on content mutation, resize, and font load. */
    _measure() {
      const hdr = this.querySelector(':scope > [slot="header"]');
      const ftr = this.querySelector(':scope > [slot="footer"]');
      this._syncSize(hdr ? hdr.offsetHeight : 0, ftr ? ftr.offsetHeight : 0);
    }
  }
  if (!customElements.get('doc-page')) {
    customElements.define('doc-page', DocPage);
  }
})();
})(); } catch (e) { __ds_ns.__errors.push({ path: "workshop-followup/doc-page.js", error: String((e && e.message) || e) }); }

// workshop-followup/habits-data.js
try { (() => {
/* eazy – קטלוג הרגלי למידה: תוכן.
   הטיפים מבוססים על "8 דרכים להטמיע הרגלי למידה מנצחים" (winning-habits-implant.pdf):
   להתחיל בקטן · לעגן להרגל קיים · להפוך לגלוי · לצ'פר מיידית · זהות · Never Miss Twice · סביבה תומכת · ניסוי וטעיה */

const HABITS = [{
  id: 'hatrama',
  name: 'הטרמה',
  tagline: 'מבוא קצר לפני כל שיעור',
  why: 'המוח לא אוהב ללמוד מאפס. כשמגיעים לשיעור אחרי מבוא – השיעור הופך מחשיפה ראשונה לחזרה שנייה: הכול מתחבר מהר יותר ונשאר. יש אצלנו מבוא כמעט לכל תוכן.',
  tips: ['להתחיל בקטן: 5 דקות מבוא במערכת ערב לפני השיעור. גם רפרוף על הכותרות בלבד שווה – העיקר שהמוח יפגוש את המושגים פעם ראשונה לפני הכיתה.', 'לעגן להרגל קיים: מיד אחרי ארוחת הערב ביום שלפני השיעור – פותחים את המבוא. פעולה קבועה אחרי עוגן קבוע, וזה מפסיק לדרוש כוח רצון.', 'להפוך לגלוי: קבעו ביומן הדיגיטלי תזכורת חוזרת "מבוא לשיעור מחר" יום לפני כל מפגש. מה שלא רואים – לא קורה.']
}, {
  id: 'encoding',
  name: 'קידוד אישי',
  tagline: 'ללמוד בערוץ שמתאים לכם',
  why: 'מידע שנכנס בערוץ הטבעי שלכם – שמיעתי, חזותי או תנועתי – דורש פחות מאמץ ונשמר טוב יותר. רוב הלומדים מעולם לא בדקו מה הערוץ שלהם.',
  tips: ['ניסוי, טעיה ושיפור: השבוע קחו נושא אחד ולמדו אותו בשלוש דרכים – הקלטה והאזנה, סכימה מצוירת, הסבר בקול תוך הליכה. מה שנדבק הכי חזק – זה הערוץ שלכם.', 'שמיעתיים: הקליטו לעצמכם סיכום קולי של 2 דקות בסוף כל למידה, והאזינו לו בדרך לשיעור הבא. כמו פודקאסט אישי.', 'חזותיים: הפכו כל עמוד מסוכם למפה אחת – חצים, צבעים, מסגרות. אם אי אפשר לצייר את זה, עוד לא באמת הבנתם את זה.']
}, {
  id: 'explain',
  name: 'להסביר לאחרים',
  tagline: 'הדרך המהירה להפנמה',
  why: 'אי אפשר להסביר משהו שלא באמת הבנתם. ההסבר חושף בדיוק איפה החורים – ומקבע את מה שכן יושב. מי שמלמד, לומד פעמיים.',
  tips: ['להתחיל בקטן: רעיון אחד מהשיעור, הסבר של 2 דקות לחבר או לבן משפחה. לא צריך הרצאה – צריך ניסוח בקול שלכם.', 'לעגן: בסוף כל שיעור, לפני שקמים – הודעה קולית לחבר מהקורס: "הדבר הכי חשוב שלמדתי היום". 60 שניות שמכפילות את הזכירה.', 'אין קהל? מסבירים בקול לעצמכם, לקיר או לחתול. המוח לא מבדיל – הניסוח בקול רם הוא שעושה את העבודה.']
}, {
  id: 'active',
  name: 'למידה פעילה',
  tagline: 'לשאול, לכתוב, להגיב',
  why: 'המוח זוכר את מה שהוא עשה – לא את מה שעבר לידו. שאלה אחת ששאלתם שווה יותר מעשר שורות שהעתקתם מהלוח.',
  tips: ['כלל השאלה האחת: לא יוצאים משיעור בלי לשאול לפחות שאלה אחת. אם לא בקול – לכתוב אותה ולשלוח למורה אחרי.', 'לכתוב בניסוח שלכם: במקום להעתיק מהלוח, תרגמו כל רעיון למשפט משלכם. ההבדל בין מזכירה לבין לומד.', "לצ'פר מיידית: הייתם פעילים שיעור שלם? מגיע פרס קטן מיד אחרי – הפסקת קפה טובה, פרק בסדרה. המוח מחבר פעולה לתגמול."]
}, {
  id: 'review48',
  name: 'חזרה תוך 24–48 שעות',
  tagline: 'אקטיבית, עם תרגול מגוון',
  why: 'עקומת השכחה אכזרית: בלי חזרה, אחרי יומיים נשאר פחות מחצי. חזרה אקטיבית אחת בזמן הנכון חוסכת שעות של שינון מחדש לפני המבחן.',
  tips: ['לעגן ולקבוע: 15 דקות "חזרה" ביומן, יום אחרי כל שיעור, באותה שעה קבועה. חזרה שלא קבועה ביומן – לא קיימת.', 'אקטיבית = לפתור, לא לקרוא: 5 שאלות במערכת האונליין על מה שנלמד אתמול. קריאה חוזרת מרגישה כמו למידה – פתרון הוא למידה.', 'Never Miss Twice: פספסתם חזרה? קורה, לא נשבר כלום. הכלל היחיד – לא מפספסים גם את הבאה. פספוס אחד זה תקלה, שניים זה הרגל חדש.']
}, {
  id: 'neto',
  name: 'ללמוד נטו',
  tagline: 'בלי הסחות. כשלומדים – לומדים',
  why: 'כל הצצה בטלפון עולה כ־20 דקות של חזרה לריכוז מלא. שעה נטו שווה שלוש שעות ברוטו – אתם פשוט מקבלים את הזמן שלכם בחזרה.',
  tips: ['סביבה תומכת: הטלפון לא לידכם הפוך – הוא בחדר אחר. אם הוא בטווח יד, הוא מנצח. תרחיקו את הפיתוי במקום להילחם בו.', 'שיטת פומודורו: מכוונים טיימר ל-25 דקות ולומדים נטו – בלי טלפון, בלי טאבים מיותרים – ואז 5 דקות הפסקה מלאה (לקום, לשתות, להזיז את הגוף). כל מחזור כזה הוא "פומודורו" אחד; אחרי ארבעה לוקחים הפסקה ארוכה של 15–20 דקות. הקסם הוא בגבול הברור: 25 דקות זה קצר מספיק כדי שלא תדחו את ההתחלה, ומספיק ארוך כדי להיכנס לעומק. התחילו מפומודורו אחד ביום – אחרי שבוע תרצו עוד.', "לצ'פר גלוי: טבלה על הקיר – וי על כל סשן נטו. אחרי כמה ימים שרשרת הווי־ים עצמה הופכת לפרס שלא רוצים לשבור."]
}, {
  id: 'friends',
  name: 'ללמוד עם חברים',
  tagline: 'מחויבות + הסברים הדדיים',
  why: 'קשה לבטל למידה כשמישהו מחכה לכם. מחויבות חברתית היא מנוע ההתמדה החזק ביותר – ובונוס: כשמסבירים אחד לשני, מקבלים שני הרגלים במחיר אחד.',
  tips: ['שותף קבוע, שעה קבועה: פגישת למידה שבועית אחת עם אותו חבר, באותו יום ושעה. עוגן שקשה לבטל בלי להרגיש לא נעים.', 'לחלק ולהחליף: כל אחד מכין נושא אחד ומלמד את השני. חצי מהעבודה, כפול מהלמידה.', 'גם "לבד ביחד" עובד: יושבים בספרייה או בזום, כל אחד על החומר שלו. עצם הנוכחות של מישהו לידכם מייצרת מחויבות ומרחיקה את הטלפון.']
}, {
  id: 'uphill',
  name: 'לאהוב עליות',
  tagline: 'גז דווקא איפה שקשה',
  why: 'הקושי הוא לא סימן שאתם לא מתאימים – הוא הסימן שהמוח בונה חיבור חדש. מה שקל לא משנה אתכם; רק העלייה בונה שריר.',
  tips: ['לבנות זהות: במקום "אני גרוע בזה" – "אני מהאנשים שנותנים גז בעלייה". ברגע שתופסים את עצמכם כך, מתנהגים כך. זה לא סיסמה, זה מנגנון.', 'כלל השאלה הנוספת: כשנושא קשה ובא לוותר – עוד שאלה אחת בדיוק, ורק אז מחליטים. כמעט תמיד השאלה הזאת שוברת את המחסום.', 'יומן עליות: רשמו כל נושא שהיה קשה – ונפתר. כשקשה שוב, פותחים את הרשימה. ההוכחה הכי טובה שגם העלייה הזאת נגמרת בפסגה.']
}];
const PRINCIPLES = [{
  name: 'אלימינציה',
  desc: 'לא בטוחים בתשובה? פסלו את מה שבטוח לא. לעיתים קרובות פסילת 3 תשובות מהירה יותר ממציאת הנכונה.'
}, {
  name: 'קריאה פעילה',
  desc: 'קודם מבינים מה בדיוק מבקשים – ורק אז פותרים. שאלה שהובנה נכון היא חצי פתרון.'
}, {
  name: 'זיקוק ומיצוי נתונים',
  desc: 'כל משפט ונתון בשאלה הוא רמז בלשי. אם נתון לא שימש אתכם – כנראה פספסתם משהו.'
}, {
  name: 'אינטואיציה',
  desc: 'לפעמים יודעים את התשובה בלי לדעת לנמק – וזה בסדר להשתמש בזה. במבחן רב-ברירה אף אחד לא מבקש מכם להציג דרך פתרון, רק לסמן את התשובה הנכונה – כך שתחושת בטן מאומנת היא כלי לגיטימי לחלוטין. סמכו עליה, במיוחד כשהיא מצומצמת אחרי אלימינציה.'
}, {
  name: 'שיטה',
  desc: 'עובדים מתודי ומסודר, לפי השיטה מהקורס. שיטה קבועה משחררת את הראש לחשוב על השאלה עצמה.'
}, {
  name: 'תרגול מגוון',
  desc: 'בספרים, במערכת האונליין, לבד, עם חברים, לפני ואחרי השיעור. גיוון הופך ידע לשליטה.'
}, {
  name: 'הצבת מספרים',
  desc: 'עיקרון באוויר? הציבו מספר קונקרטי ותראו מה קורה. הפשטה הופכת לחשבון פשוט.'
}, {
  name: 'ביטחון עצמי',
  desc: 'לסמוך על עצמכם. עניתם אחרי עבודה נכונה? ממשיכים הלאה בלי לפקפק בכל צעד.'
}];
})(); } catch (e) { __ds_ns.__errors.push({ path: "workshop-followup/habits-data.js", error: String((e && e.message) || e) }); }

// workshop-followup/מקור-לעריכה/habits-data.js
try { (() => {
/* eazy – קטלוג הרגלי למידה: תוכן.
   הטיפים מבוססים על "8 דרכים להטמיע הרגלי למידה מנצחים" (winning-habits-implant.pdf):
   להתחיל בקטן · לעגן להרגל קיים · להפוך לגלוי · לצ'פר מיידית · זהות · Never Miss Twice · סביבה תומכת · ניסוי וטעיה */

const HABITS = [{
  id: 'hatrama',
  name: 'הטרמה',
  tagline: 'מבוא קצר לפני כל שיעור',
  why: 'המוח לא אוהב ללמוד מאפס. כשמגיעים לשיעור אחרי מבוא – השיעור הופך מחשיפה ראשונה לחזרה שנייה: הכול מתחבר מהר יותר ונשאר. יש אצלנו מבוא כמעט לכל תוכן.',
  tips: ['להתחיל בקטן: 5 דקות מבוא במערכת ערב לפני השיעור. גם רפרוף על הכותרות בלבד שווה – העיקר שהמוח יפגוש את המושגים פעם ראשונה לפני הכיתה.', 'לעגן להרגל קיים: מיד אחרי ארוחת הערב ביום שלפני השיעור – פותחים את המבוא. פעולה קבועה אחרי עוגן קבוע, וזה מפסיק לדרוש כוח רצון.', 'להפוך לגלוי: קבעו ביומן הדיגיטלי תזכורת חוזרת "מבוא לשיעור מחר" יום לפני כל מפגש. מה שלא רואים – לא קורה.']
}, {
  id: 'encoding',
  name: 'קידוד אישי',
  tagline: 'ללמוד בערוץ שמתאים לכם',
  why: 'מידע שנכנס בערוץ הטבעי שלכם – שמיעתי, חזותי או תנועתי – דורש פחות מאמץ ונשמר טוב יותר. רוב הלומדים מעולם לא בדקו מה הערוץ שלהם.',
  tips: ['ניסוי, טעיה ושיפור: השבוע קחו נושא אחד ולמדו אותו בשלוש דרכים – הקלטה והאזנה, סכימה מצוירת, הסבר בקול תוך הליכה. מה שנדבק הכי חזק – זה הערוץ שלכם.', 'שמיעתיים: הקליטו לעצמכם סיכום קולי של 2 דקות בסוף כל למידה, והאזינו לו בדרך לשיעור הבא. כמו פודקאסט אישי.', 'חזותיים: הפכו כל עמוד מסוכם למפה אחת – חצים, צבעים, מסגרות. אם אי אפשר לצייר את זה, עוד לא באמת הבנתם את זה.']
}, {
  id: 'explain',
  name: 'להסביר לאחרים',
  tagline: 'הדרך המהירה להפנמה',
  why: 'אי אפשר להסביר משהו שלא באמת הבנתם. ההסבר חושף בדיוק איפה החורים – ומקבע את מה שכן יושב. מי שמלמד, לומד פעמיים.',
  tips: ['להתחיל בקטן: רעיון אחד מהשיעור, הסבר של 2 דקות לחבר או לבן משפחה. לא צריך הרצאה – צריך ניסוח בקול שלכם.', 'לעגן: בסוף כל שיעור, לפני שקמים – הודעה קולית לחבר מהקורס: "הדבר הכי חשוב שלמדתי היום". 60 שניות שמכפילות את הזכירה.', 'אין קהל? מסבירים בקול לעצמכם, לקיר או לחתול. המוח לא מבדיל – הניסוח בקול רם הוא שעושה את העבודה.']
}, {
  id: 'active',
  name: 'למידה פעילה',
  tagline: 'לשאול, לכתוב, להגיב',
  why: 'המוח זוכר את מה שהוא עשה – לא את מה שעבר לידו. שאלה אחת ששאלתם שווה יותר מעשר שורות שהעתקתם מהלוח.',
  tips: ['כלל השאלה האחת: לא יוצאים משיעור בלי לשאול לפחות שאלה אחת. אם לא בקול – לכתוב אותה ולשלוח למורה אחרי.', 'לכתוב בניסוח שלכם: במקום להעתיק מהלוח, תרגמו כל רעיון למשפט משלכם. ההבדל בין מזכירה לבין לומד.', "לצ'פר מיידית: הייתם פעילים שיעור שלם? מגיע פרס קטן מיד אחרי – הפסקת קפה טובה, פרק בסדרה. המוח מחבר פעולה לתגמול."]
}, {
  id: 'review48',
  name: 'חזרה תוך 24–48 שעות',
  tagline: 'אקטיבית, עם תרגול מגוון',
  why: 'עקומת השכחה אכזרית: בלי חזרה, אחרי יומיים נשאר פחות מחצי. חזרה אקטיבית אחת בזמן הנכון חוסכת שעות של שינון מחדש לפני המבחן.',
  tips: ['לעגן ולקבוע: 15 דקות "חזרה" ביומן, יום אחרי כל שיעור, באותה שעה קבועה. חזרה שלא קבועה ביומן – לא קיימת.', 'אקטיבית = לפתור, לא לקרוא: 5 שאלות במערכת האונליין על מה שנלמד אתמול. קריאה חוזרת מרגישה כמו למידה – פתרון הוא למידה.', 'Never Miss Twice: פספסתם חזרה? קורה, לא נשבר כלום. הכלל היחיד – לא מפספסים גם את הבאה. פספוס אחד זה תקלה, שניים זה הרגל חדש.']
}, {
  id: 'neto',
  name: 'ללמוד נטו',
  tagline: 'בלי הסחות. כשלומדים – לומדים',
  why: 'כל הצצה בטלפון עולה כ־20 דקות של חזרה לריכוז מלא. שעה נטו שווה שלוש שעות ברוטו – אתם פשוט מקבלים את הזמן שלכם בחזרה.',
  tips: ['סביבה תומכת: הטלפון לא לידכם הפוך – הוא בחדר אחר. אם הוא בטווח יד, הוא מנצח. תרחיקו את הפיתוי במקום להילחם בו.', 'שיטת פומודורו: מכוונים טיימר ל-25 דקות ולומדים נטו – בלי טלפון, בלי טאבים מיותרים – ואז 5 דקות הפסקה מלאה (לקום, לשתות, להזיז את הגוף). כל מחזור כזה הוא "פומודורו" אחד; אחרי ארבעה לוקחים הפסקה ארוכה של 15–20 דקות. הקסם הוא בגבול הברור: 25 דקות זה קצר מספיק כדי שלא תדחו את ההתחלה, ומספיק ארוך כדי להיכנס לעומק. התחילו מפומודורו אחד ביום – אחרי שבוע תרצו עוד.', "לצ'פר גלוי: טבלה על הקיר – וי על כל סשן נטו. אחרי כמה ימים שרשרת הווי־ים עצמה הופכת לפרס שלא רוצים לשבור."]
}, {
  id: 'friends',
  name: 'ללמוד עם חברים',
  tagline: 'מחויבות + הסברים הדדיים',
  why: 'קשה לבטל למידה כשמישהו מחכה לכם. מחויבות חברתית היא מנוע ההתמדה החזק ביותר – ובונוס: כשמסבירים אחד לשני, מקבלים שני הרגלים במחיר אחד.',
  tips: ['שותף קבוע, שעה קבועה: פגישת למידה שבועית אחת עם אותו חבר, באותו יום ושעה. עוגן שקשה לבטל בלי להרגיש לא נעים.', 'לחלק ולהחליף: כל אחד מכין נושא אחד ומלמד את השני. חצי מהעבודה, כפול מהלמידה.', 'גם "לבד ביחד" עובד: יושבים בספרייה או בזום, כל אחד על החומר שלו. עצם הנוכחות של מישהו לידכם מייצרת מחויבות ומרחיקה את הטלפון.']
}, {
  id: 'uphill',
  name: 'לאהוב עליות',
  tagline: 'גז דווקא איפה שקשה',
  why: 'הקושי הוא לא סימן שאתם לא מתאימים – הוא הסימן שהמוח בונה חיבור חדש. מה שקל לא משנה אתכם; רק העלייה בונה שריר.',
  tips: ['לבנות זהות: במקום "אני גרוע בזה" – "אני מהאנשים שנותנים גז בעלייה". ברגע שתופסים את עצמכם כך, מתנהגים כך. זה לא סיסמה, זה מנגנון.', 'כלל השאלה הנוספת: כשנושא קשה ובא לוותר – עוד שאלה אחת בדיוק, ורק אז מחליטים. כמעט תמיד השאלה הזאת שוברת את המחסום.', 'יומן עליות: רשמו כל נושא שהיה קשה – ונפתר. כשקשה שוב, פותחים את הרשימה. ההוכחה הכי טובה שגם העלייה הזאת נגמרת בפסגה.']
}];
const PRINCIPLES = [{
  name: 'אלימינציה',
  desc: 'לא בטוחים בתשובה? פסלו את מה שבטוח לא. לעיתים קרובות פסילת 3 תשובות מהירה יותר ממציאת הנכונה.'
}, {
  name: 'קריאה פעילה',
  desc: 'קודם מבינים מה בדיוק מבקשים – ורק אז פותרים. שאלה שהובנה נכון היא חצי פתרון.'
}, {
  name: 'זיקוק ומיצוי נתונים',
  desc: 'כל משפט ונתון בשאלה הוא רמז בלשי. אם נתון לא שימש אתכם – כנראה פספסתם משהו.'
}, {
  name: 'אינטואיציה',
  desc: 'לפעמים יודעים את התשובה בלי לדעת לנמק – וזה בסדר להשתמש בזה. במבחן רב-ברירה אף אחד לא מבקש מכם להציג דרך פתרון, רק לסמן את התשובה הנכונה – כך שתחושת בטן מאומנת היא כלי לגיטימי לחלוטין. סמכו עליה, במיוחד כשהיא מצומצמת אחרי אלימינציה.'
}, {
  name: 'שיטה',
  desc: 'עובדים מתודי ומסודר, לפי השיטה מהקורס. שיטה קבועה משחררת את הראש לחשוב על השאלה עצמה.'
}, {
  name: 'תרגול מגוון',
  desc: 'בספרים, במערכת האונליין, לבד, עם חברים, לפני ואחרי השיעור. גיוון הופך ידע לשליטה.'
}, {
  name: 'הצבת מספרים',
  desc: 'עיקרון באוויר? הציבו מספר קונקרטי ותראו מה קורה. הפשטה הופכת לחשבון פשוט.'
}, {
  name: 'ביטחון עצמי',
  desc: 'לסמוך על עצמכם. עניתם אחרי עבודה נכונה? ממשיכים הלאה בלי לפקפק בכל צעד.'
}];
})(); } catch (e) { __ds_ns.__errors.push({ path: "workshop-followup/מקור-לעריכה/habits-data.js", error: String((e && e.message) || e) }); }

__ds_ns.EzButton = __ds_scope.EzButton;

})();
