<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
  <channel>
    <title>Women Detectives on Premières</title>
    <link>https://premieres.stephanejacquet.fr/chapters/women_detectives/</link>
    <description>Recent content in Women Detectives on Premières</description>
    <generator>Hugo -- gohugo.io</generator>
    <language>en</language>
    <copyright>Copyright © 2026 Stéphane Jacquet.</copyright>
    <lastBuildDate>Mon, 01 Jan 0001 00:00:00 +0000</lastBuildDate><atom:link href="https://premieres.stephanejacquet.fr/chapters/women_detectives/index.xml" rel="self" type="application/rss+xml" />
    
    <item>
      <title>Adjective order</title>
      <link>https://premieres.stephanejacquet.fr/chapters/women_detectives/adjectives/</link>
      <pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate>
      
      <guid>https://premieres.stephanejacquet.fr/chapters/women_detectives/adjectives/</guid>
      <description>&lt;h1 class=&#34;relative group&#34;&gt;🎯 Adjectives&#xA;    &lt;div id=&#34;-adjectives&#34; class=&#34;anchor&#34;&gt;&lt;/div&gt;&#xA;    &#xA;    &lt;span&#xA;        class=&#34;absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none&#34;&gt;&#xA;        &lt;a class=&#34;text-primary-300 dark:text-neutral-700 !no-underline&#34; href=&#34;#-adjectives&#34; aria-label=&#34;Anchor&#34;&gt;#&lt;/a&gt;&#xA;    &lt;/span&gt;&#xA;    &#xA;&lt;/h1&gt;&#xA;&lt;hr&gt;&#xA;&#xA;&lt;h2 class=&#34;relative group&#34;&gt;🧱 1. What is an Adjective?&#xA;    &lt;div id=&#34;-1-what-is-an-adjective&#34; class=&#34;anchor&#34;&gt;&lt;/div&gt;&#xA;    &#xA;    &lt;span&#xA;        class=&#34;absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none&#34;&gt;&#xA;        &lt;a class=&#34;text-primary-300 dark:text-neutral-700 !no-underline&#34; href=&#34;#-1-what-is-an-adjective&#34; aria-label=&#34;Anchor&#34;&gt;#&lt;/a&gt;&#xA;    &lt;/span&gt;&#xA;    &#xA;&lt;/h2&gt;&#xA;&lt;p&gt;An &lt;strong&gt;adjective&lt;/strong&gt; is a word that describes a &lt;strong&gt;noun&lt;/strong&gt; or a &lt;strong&gt;pronoun&lt;/strong&gt;.&lt;br&gt;&#xA;It gives information about &lt;em&gt;what something is like&lt;/em&gt;.&lt;br&gt;&#xA;In linguistic terms, an adjective &lt;em&gt;modifies&lt;/em&gt; a noun.&lt;/p&gt;&#xA;&lt;p&gt;&lt;strong&gt;Examples&lt;/strong&gt;:&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;A &lt;strong&gt;beautiful&lt;/strong&gt; painting&lt;/li&gt;&#xA;&lt;li&gt;An &lt;strong&gt;ugly&lt;/strong&gt; one&lt;/li&gt;&#xA;&lt;li&gt;The &lt;strong&gt;old&lt;/strong&gt; house&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;hr&gt;&#xA;&#xA;&lt;h2 class=&#34;relative group&#34;&gt;🧭 2. Where Do Adjectives Go?&#xA;    &lt;div id=&#34;-2-where-do-adjectives-go&#34; class=&#34;anchor&#34;&gt;&lt;/div&gt;&#xA;    &#xA;    &lt;span&#xA;        class=&#34;absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none&#34;&gt;&#xA;        &lt;a class=&#34;text-primary-300 dark:text-neutral-700 !no-underline&#34; href=&#34;#-2-where-do-adjectives-go&#34; aria-label=&#34;Anchor&#34;&gt;#&lt;/a&gt;&#xA;    &lt;/span&gt;&#xA;    &#xA;&lt;/h2&gt;&#xA;&lt;p&gt;Adjectives usually come:&lt;/p&gt;</description>
      
    </item>
    
    <item>
      <title>Lexicon</title>
      <link>https://premieres.stephanejacquet.fr/chapters/women_detectives/lexicon/</link>
      <pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate>
      
      <guid>https://premieres.stephanejacquet.fr/chapters/women_detectives/lexicon/</guid>
      <description>&lt;style&gt;&#xA;    .lexicon-list {&#xA;      margin: 1.5rem 0;&#xA;      padding: 0;&#xA;    }&#xA;    .lexicon-list dt {&#xA;      margin: 0;&#xA;      padding: 0;&#xA;      font-weight: 600;&#xA;      font-size: 1.05rem;&#xA;    }&#xA;    .lexicon-list dd {&#xA;      margin: 0.15rem 0 1rem 0;&#xA;      padding: 0;&#xA;      color: inherit;&#xA;      opacity: 0.85;&#xA;    }&#xA;    .lexicon-list dd p {&#xA;      margin: 0;&#xA;    }&#xA;  &lt;/style&gt;&#xA;  &lt;h2&gt;📖 Women Detectives &amp;mdash; Vocabulary&lt;/h2&gt;&lt;dl class=&#34;lexicon-list&#34;&gt;&#xA;        &lt;dt id=&#34;to-gossip&#34;&gt;g&lt;span class=&#34;stressed-vowel&#34;&gt;o&lt;/span&gt;ssip&lt;/dt&gt;&#xA;        &lt;dd&gt;(to) talk about other people&amp;rsquo;s private business behind their back&lt;/dd&gt;&#xA;        &lt;dt id=&#34;to-miss&#34;&gt;(to) miss&lt;/dt&gt;&#xA;        &lt;dd&gt;to not see, hear, or notice something&lt;/dd&gt;&#xA;        &lt;dt id=&#34;to-notice&#34;&gt;(to) n&lt;span class=&#34;stressed-vowel&#34;&gt;o&lt;/span&gt;tice&lt;/dt&gt;&#xA;        &lt;dd&gt;if you notice something or someone, you realise they exist&lt;/dd&gt;&#xA;        &lt;dt id=&#34;to-shave&#34;&gt;(to) shave&lt;/dt&gt;&#xA;        &lt;dd&gt;(to) cut off hair very close using a razor&lt;/dd&gt;&#xA;        &lt;dt id=&#34;to-solve-a-crime&#34;&gt;(to) s&lt;span class=&#34;stressed-vowel&#34;&gt;o&lt;/span&gt;lve a cr&lt;span class=&#34;stressed-vowel&#34;&gt;i&lt;/span&gt;me&lt;/dt&gt;&#xA;        &lt;dd&gt;&lt;/dd&gt;&#xA;        &lt;dt id=&#34;to-turn-the-tables&#34;&gt;(to) t&lt;span class=&#34;stressed-vowel&#34;&gt;u&lt;/span&gt;rn the t&lt;span class=&#34;stressed-vowel&#34;&gt;a&lt;/span&gt;bles&lt;/dt&gt;&#xA;        &lt;dd&gt;if you turn the tables, you reverse a situation to your advantage&lt;/dd&gt;&#xA;        &lt;dt id=&#34;active&#34;&gt;&lt;span class=&#34;stressed-vowel&#34;&gt;a&lt;/span&gt;ctive&lt;/dt&gt;&#xA;        &lt;dd&gt;≠ passive&lt;/dd&gt;&#xA;        &lt;dt id=&#34;cunning&#34;&gt;c&lt;span class=&#34;stressed-vowel&#34;&gt;u&lt;/span&gt;nning&lt;/dt&gt;&#xA;        &lt;dd&gt;clever&lt;/dd&gt;&#xA;        &lt;dt id=&#34;determined&#34;&gt;det&lt;span class=&#34;stressed-vowel&#34;&gt;e&lt;/span&gt;rmined&lt;/dt&gt;&#xA;        &lt;dd&gt;showing determination&lt;/dd&gt;&#xA;        &lt;dt id=&#34;downsize&#34;&gt;d&lt;span class=&#34;stressed-vowel&#34;&gt;o&lt;/span&gt;&lt;span class=&#34;stressed-vowel&#34;&gt;w&lt;/span&gt;nsize&lt;/dt&gt;&#xA;        &lt;dd&gt;(to) make smaller&lt;/dd&gt;&#xA;        &lt;dt id=&#34;equal&#34;&gt;&lt;span class=&#34;stressed-vowel&#34;&gt;e&lt;/span&gt;qual&lt;/dt&gt;&#xA;        &lt;dd&gt;≠ unequal&lt;/dd&gt;&#xA;        &lt;dt id=&#34;evidence&#34;&gt;&lt;span class=&#34;stressed-vowel&#34;&gt;e&lt;/span&gt;vidence&lt;/dt&gt;&#xA;        &lt;dd&gt;proof&lt;/dd&gt;&#xA;        &lt;dt id=&#34;gossip&#34;&gt;g&lt;span class=&#34;stressed-vowel&#34;&gt;o&lt;/span&gt;ssip&lt;/dt&gt;&#xA;        &lt;dd&gt;une commmère&lt;/dd&gt;&#xA;        &lt;dt id=&#34;insufferable&#34;&gt;ins&lt;span class=&#34;stressed-vowel&#34;&gt;u&lt;/span&gt;fferable&lt;/dt&gt;&#xA;        &lt;dd&gt;extremely annoying or unpleasant&lt;/dd&gt;&#xA;        &lt;dt id=&#34;investigation&#34;&gt;inv&lt;span class=&#34;stressed-vowel&#34;&gt;e&lt;/span&gt;stig&lt;span class=&#34;stressed-vowel&#34;&gt;a&lt;/span&gt;tion&lt;/dt&gt;&#xA;        &lt;dd&gt;enquiry&lt;/dd&gt;&#xA;        &lt;dt id=&#34;menial&#34;&gt;m&lt;span class=&#34;stressed-vowel&#34;&gt;e&lt;/span&gt;nial&lt;/dt&gt;&#xA;        &lt;dd&gt;menial work is boring, needs no skill, and is not important&lt;/dd&gt;&#xA;        &lt;dt id=&#34;professional&#34;&gt;prof&lt;span class=&#34;stressed-vowel&#34;&gt;e&lt;/span&gt;ssional&lt;/dt&gt;&#xA;        &lt;dd&gt;≠ amateur&lt;/dd&gt;&#xA;        &lt;dt id=&#34;proper&#34;&gt;pr&lt;span class=&#34;stressed-vowel&#34;&gt;o&lt;/span&gt;per&lt;/dt&gt;&#xA;        &lt;dd&gt;the real or of good standards&lt;/dd&gt;&#xA;        &lt;dt id=&#34;set&#34;&gt;set&lt;/dt&gt;&#xA;        &lt;dd&gt;if a film or story is set in a particular place or period, the aciton is taking place there or then.&lt;/dd&gt;&#xA;        &lt;dt id=&#34;skill&#34;&gt;skill&lt;/dt&gt;&#xA;        &lt;dd&gt;the ability to do something well because you have learned or practised it&lt;/dd&gt;&#xA;        &lt;dt id=&#34;spinster&#34;&gt;sp&lt;span class=&#34;stressed-vowel&#34;&gt;i&lt;/span&gt;nster&lt;/dt&gt;&#xA;        &lt;dd&gt;an unmarried women, usually one who is no longer young and seems unlikely to marry&lt;/dd&gt;&#xA;        &lt;dt id=&#34;traditional&#34;&gt;trad&lt;span class=&#34;stressed-vowel&#34;&gt;i&lt;/span&gt;tional&lt;/dt&gt;&#xA;        &lt;dd&gt;≠ modern&lt;/dd&gt;&#xA;        &lt;dt id=&#34;unconventional&#34;&gt;&lt;span class=&#34;stressed-vowel&#34;&gt;u&lt;/span&gt;nconv&lt;span class=&#34;stressed-vowel&#34;&gt;e&lt;/span&gt;ntional&lt;/dt&gt;&#xA;        &lt;dd&gt;unusual&lt;/dd&gt;&#xA;        &lt;dt id=&#34;unfair&#34;&gt;unf&lt;span class=&#34;stressed-vowel&#34;&gt;a&lt;/span&gt;&lt;span class=&#34;stressed-vowel&#34;&gt;i&lt;/span&gt;r&lt;/dt&gt;&#xA;        &lt;dd&gt;unjust&lt;/dd&gt;&#xA;    &lt;/dl&gt;&#xA;    &lt;p&gt;&#xA;      &lt;a href=&#34;https://premieres.stephanejacquet.fr/chapters/women_detectives/&#34;&gt;&amp;larr; Return to Women Detectives&lt;/a&gt;&#xA;    &lt;/p&gt;</description>
      
    </item>
    
    <item>
      <title>Flashcards</title>
      <link>https://premieres.stephanejacquet.fr/chapters/women_detectives/flashcards/</link>
      <pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate>
      
      <guid>https://premieres.stephanejacquet.fr/chapters/women_detectives/flashcards/</guid>
      <description>&lt;div class=&#34;flashcards-container&#34;&gt;&#xA;&lt;div style=&#34;display:flex; justify-content:space-between; align-items:baseline; gap:1rem; flex-wrap:wrap;&#34;&gt;&#xA;&lt;h2&gt;🧠 Women Detectives &amp;mdash; Flashcards&lt;/h2&gt;&#xA;&lt;a href=&#34;https://premieres.stephanejacquet.fr/login/&#34; id=&#34;auth-link&#34; class=&#34;login-link&#34; style=&#34;color:#007bff; text-decoration:none; font-size:0.9rem; white-space:nowrap;&#34;&gt;Login&lt;/a&gt;&#xA;&lt;/div&gt;&#xA;&lt;div class=&#34;flashcards-header&#34;&gt;&#xA;&lt;div class=&#34;flashcards-controls&#34;&gt;&#xA;&lt;div class=&#34;mode-selector&#34;&gt;&#xA;&lt;label class=&#34;mode-option&#34;&gt;&#xA;&lt;input type=&#34;radio&#34; name=&#34;study-mode&#34; value=&#34;term-to-definition&#34; checked&gt;&#xA;&lt;span&gt;Term → Definition&lt;/span&gt;&#xA;&lt;/label&gt;&#xA;&lt;label class=&#34;mode-option&#34;&gt;&#xA;&lt;input type=&#34;radio&#34; name=&#34;study-mode&#34; value=&#34;definition-to-term&#34;&gt;&#xA;&lt;span&gt;Definition → Term&lt;/span&gt;&#xA;&lt;/label&gt;&#xA;&lt;/div&gt;&#xA;&lt;div class=&#34;control-buttons&#34;&gt;&#xA;&lt;button id=&#34;mode-toggle-btn&#34; class=&#34;btn btn-secondary&#34;&gt;📖 Browse&lt;/button&gt;&#xA;&lt;button id=&#34;early-review-btn&#34; class=&#34;btn btn-info&#34;&gt;⏰ Early Review&lt;/button&gt;&#xA;&lt;button id=&#34;reset-progress&#34; class=&#34;btn btn-outline&#34;&gt;🔄 Reset&lt;/button&gt;&#xA;&lt;/div&gt;&#xA;&lt;div class=&#34;progress-display&#34;&gt;&#xA;&lt;span id=&#34;current-card&#34;&gt;1&lt;/span&gt; / &lt;span id=&#34;total-cards&#34;&gt;24&lt;/span&gt;&#xA;&lt;/div&gt;&#xA;&lt;/div&gt;&#xA;&lt;/div&gt;&#xA;&lt;div class=&#34;flashcard-wrapper&#34;&gt;&#xA;&lt;div class=&#34;flashcard&#34; id=&#34;flashcard&#34;&gt;&#xA;&lt;div class=&#34;flashcard-inner&#34;&gt;&#xA;&lt;div class=&#34;flashcard-front&#34;&gt;&#xA;&lt;div class=&#34;card-content&#34;&gt;&#xA;&lt;div class=&#34;question&#34; id=&#34;card-question&#34;&gt;&lt;/div&gt;&#xA;&lt;div class=&#34;card-hint&#34;&gt;Tap to reveal answer&lt;/div&gt;&#xA;&lt;/div&gt;&#xA;&lt;/div&gt;&#xA;&lt;div class=&#34;flashcard-back&#34;&gt;&#xA;&lt;div class=&#34;card-content&#34;&gt;&#xA;&lt;div class=&#34;question-small&#34; id=&#34;card-question-back&#34;&gt;&lt;/div&gt;&#xA;&lt;div class=&#34;answer&#34; id=&#34;card-answer&#34;&gt;&lt;/div&gt;&#xA;&lt;div class=&#34;card-hint&#34;&gt;Tap to flip back&lt;/div&gt;&#xA;&lt;/div&gt;&#xA;&lt;/div&gt;&#xA;&lt;/div&gt;&#xA;&lt;/div&gt;&#xA;&lt;/div&gt;&#xA;&lt;div class=&#34;flashcards-navigation&#34;&gt;&#xA;&lt;div class=&#34;nav-top&#34;&gt;&#xA;&lt;button id=&#34;next-btn&#34; class=&#34;btn btn-primary&#34;&gt;Next →&lt;/button&gt;&#xA;&lt;/div&gt;&#xA;&lt;div class=&#34;nav-middle&#34;&gt;&#xA;&lt;div class=&#34;difficulty-buttons&#34;&gt;&#xA;&lt;button id=&#34;again-btn&#34; class=&#34;btn btn-danger-dark&#34;&gt;🚫 Again&lt;/button&gt;&#xA;&lt;button id=&#34;hard-btn&#34; class=&#34;btn btn-danger&#34;&gt;😰 Hard&lt;/button&gt;&#xA;&lt;button id=&#34;medium-btn&#34; class=&#34;btn btn-warning&#34;&gt;🤔 Medium&lt;/button&gt;&#xA;&lt;button id=&#34;easy-btn&#34; class=&#34;btn btn-success&#34;&gt;😊 Easy&lt;/button&gt;&#xA;&lt;/div&gt;&#xA;&lt;/div&gt;&#xA;&lt;div class=&#34;nav-bottom&#34;&gt;&#xA;&lt;button id=&#34;prev-btn&#34; class=&#34;btn btn-primary&#34;&gt;← Previous&lt;/button&gt;&#xA;&lt;/div&gt;&#xA;&lt;/div&gt;&#xA;&lt;div class=&#34;progress-stats&#34;&gt;&#xA;&lt;div class=&#34;stat&#34;&gt;&#xA;&lt;span class=&#34;stat-label&#34;&gt;Reviewed:&lt;/span&gt;&#xA;&lt;span id=&#34;reviewed-count&#34;&gt;0&lt;/span&gt;&#xA;&lt;/div&gt;&#xA;&lt;div class=&#34;stat&#34;&gt;&#xA;&lt;span class=&#34;stat-label&#34;&gt;Again:&lt;/span&gt;&#xA;&lt;span id=&#34;again-count&#34;&gt;0&lt;/span&gt;&#xA;&lt;/div&gt;&#xA;&lt;div class=&#34;stat&#34;&gt;&#xA;&lt;span class=&#34;stat-label&#34;&gt;Hard:&lt;/span&gt;&#xA;&lt;span id=&#34;hard-count&#34;&gt;0&lt;/span&gt;&#xA;&lt;/div&gt;&#xA;&lt;div class=&#34;stat&#34;&gt;&#xA;&lt;span class=&#34;stat-label&#34;&gt;Medium:&lt;/span&gt;&#xA;&lt;span id=&#34;medium-count&#34;&gt;0&lt;/span&gt;&#xA;&lt;/div&gt;&#xA;&lt;div class=&#34;stat&#34;&gt;&#xA;&lt;span class=&#34;stat-label&#34;&gt;Easy:&lt;/span&gt;&#xA;&lt;span id=&#34;easy-count&#34;&gt;0&lt;/span&gt;&#xA;&lt;/div&gt;&#xA;&lt;div class=&#34;stat&#34;&gt;&#xA;&lt;span class=&#34;stat-label&#34;&gt;Due:&lt;/span&gt;&#xA;&lt;span id=&#34;review-count&#34;&gt;0&lt;/span&gt;&#xA;&lt;/div&gt;&#xA;&lt;/div&gt;&#xA;&lt;div class=&#34;completion-message&#34; id=&#34;completion-message&#34; style=&#34;display: none;&#34;&gt;&#xA;&lt;div class=&#34;completion-content&#34;&gt;&#xA;&lt;div class=&#34;completion-icon&#34;&gt;🎉&lt;/div&gt;&#xA;&lt;h3 class=&#34;completion-title&#34;&gt;Great Job!&lt;/h3&gt;&#xA;&lt;p class=&#34;completion-text&#34; id=&#34;completion-text&#34;&gt;&lt;/p&gt;&#xA;&lt;div class=&#34;completion-actions&#34;&gt;&#xA;&lt;button id=&#34;early-review-option&#34; class=&#34;btn btn-info&#34; style=&#34;display: none;&#34;&gt;⏰ Review Early Cards&lt;/button&gt;&#xA;&lt;button id=&#34;browse-all-option&#34; class=&#34;btn btn-secondary&#34;&gt;📖 Browse All Cards&lt;/button&gt;&#xA;&lt;button id=&#34;close-completion&#34; class=&#34;btn btn-primary&#34;&gt;✨ Done&lt;/button&gt;&#xA;&lt;/div&gt;&#xA;&lt;/div&gt;&#xA;&lt;/div&gt;&#xA;&lt;/div&gt;&#xA;&lt;style&gt;&#xA; &#xA;.stressed-vowel {&#xA;color: red !important;&#xA;font-weight: bold;&#xA;}&#xA; &#xA;.btn-danger-dark {&#xA;background: #8b0000;&#xA;color: white;&#xA;}&#xA;.btn-danger-dark:hover {&#xA;background: #a00000;&#xA;transform: translateY(-1px);&#xA;box-shadow: 0 2px 8px rgba(0,0,0,0.2);&#xA;}&#xA; &#xA;.flashcards-container {&#xA;max-width: 600px;&#xA;margin: 0 auto;&#xA;padding: 1rem;&#xA;font-family: -apple-system, BlinkMacSystemFont, &#39;Segoe UI&#39;, Roboto, sans-serif;&#xA;display: flex;&#xA;flex-direction: column;&#xA;box-sizing: border-box;&#xA;gap: 1rem;&#xA;}&#xA;.flashcards-header {&#xA;display: flex;&#xA;justify-content: space-between;&#xA;align-items: center;&#xA;margin-bottom: 1rem;&#xA;flex-wrap: wrap;&#xA;gap: 1rem;&#xA;}&#xA;.flashcards-header h3 {&#xA;margin: 0;&#xA;color: inherit;&#xA;font-size: clamp(1.2rem, 4vw, 1.5rem);&#xA;}&#xA;.flashcards-controls {&#xA;display: flex;&#xA;align-items: center;&#xA;gap: 1.2rem;&#xA;flex-wrap: wrap;&#xA;padding: 0.5rem 0;&#xA;}&#xA;.mode-selector {&#xA;display: flex;&#xA;gap: 0.8rem;&#xA;align-items: center;&#xA;}&#xA;.mode-option {&#xA;display: flex;&#xA;align-items: center;&#xA;gap: 0.5rem;&#xA;cursor: pointer;&#xA;padding: 0.5rem 0.75rem;&#xA;border-radius: 20px;&#xA;background: #f8f9fa;&#xA;border: 1px solid #ced4da;&#xA;color: #212529;&#xA;transition: all 0.2s ease;&#xA;font-size: clamp(0.75rem, 3vw, 0.9rem);&#xA;white-space: nowrap;&#xA;}&#xA;.mode-option span {&#xA;color: #212529;&#xA;}&#xA;.mode-option:hover {&#xA;background: #e9ecef;&#xA;}&#xA;.mode-option input[type=&#34;radio&#34;] {&#xA;margin: 0;&#xA;}&#xA;.mode-option input[type=&#34;radio&#34;]:checked + span {&#xA;font-weight: bold;&#xA;color: #007bff;&#xA;}&#xA;.control-buttons {&#xA;display: flex;&#xA;gap: 0.8rem;&#xA;}&#xA;.progress-display {&#xA;background: #f5f5f5;&#xA;padding: 0.5rem 0.75rem;&#xA;border-radius: 20px;&#xA;border: 1px solid #ced4da;&#xA;font-weight: bold;&#xA;color: #212529;&#xA;font-size: clamp(0.8rem, 3vw, 0.9rem);&#xA;}&#xA;.flashcard-wrapper {&#xA;perspective: 1000px;&#xA;margin: 1.5rem 0;&#xA;display: flex;&#xA;align-items: center;&#xA;}&#xA;.flashcard {&#xA;width: 100%;&#xA;height: clamp(220px, 35vh, 320px);&#xA;position: relative;&#xA;cursor: pointer;&#xA;transition: transform 0.3s ease;&#xA;}&#xA;.flashcard:hover {&#xA;transform: translateY(-2px);&#xA;}&#xA;.flashcard-inner {&#xA;position: relative;&#xA;width: 100%;&#xA;height: 100%;&#xA;text-align: center;&#xA;transition: transform 0.6s;&#xA;transform-style: preserve-3d;&#xA;}&#xA;.flashcard.flipped .flashcard-inner {&#xA;transform: rotateY(180deg);&#xA;}&#xA;.flashcard-front, .flashcard-back {&#xA;position: absolute;&#xA;width: 100%;&#xA;height: 100%;&#xA;backface-visibility: hidden;&#xA;border-radius: 15px;&#xA;box-shadow: 0 4px 20px rgba(0,0,0,0.1);&#xA;display: flex;&#xA;align-items: center;&#xA;justify-content: center;&#xA;}&#xA;.flashcard-front {&#xA;background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);&#xA;color: white;&#xA;}&#xA;.flashcard-back {&#xA;background: linear-gradient(135deg, #f093fb 0%, #f5576c 100%);&#xA;color: white;&#xA;transform: rotateY(180deg);&#xA;}&#xA;.card-content {&#xA;padding: clamp(1.5rem, 5vw, 2.5rem);&#xA;width: 100%;&#xA;height: 100%;&#xA;display: flex;&#xA;flex-direction: column;&#xA;justify-content: center;&#xA;box-sizing: border-box;&#xA;overflow: hidden;&#xA;}&#xA;&#xA; &#xA;.term, .question {&#xA;    font-size: clamp(1.4rem, 5vw, 2rem);&#xA;    font-weight: bold;&#xA;    margin-bottom: 1rem;&#xA;    text-shadow: 0 2px 4px rgba(0,0,0,0.3);&#xA;    line-height: 1.3;&#xA;    overflow-wrap: break-word;&#xA;    hyphens: auto;&#xA;    display: flex;&#xA;    align-items: center;&#xA;    justify-content: center;&#xA;    text-align: center;&#xA;    height: 100%;&#xA;    margin: 0 auto;&#xA;     &#xA;    white-space: pre-wrap;&#xA;}&#xA;&#xA;&#xA;&#xA;&#xA;&#xA;&#xA;&#xA;.term-small, .question-small {&#xA;font-size: clamp(0.85rem, 3.2vw, 1.1rem);&#xA;font-weight: bold;&#xA;margin-bottom: 0.75rem;&#xA;opacity: 0.8;&#xA;line-height: 1.3;&#xA;overflow-wrap: break-word;&#xA;text-align: center;&#xA;}&#xA;.definition, .answer {&#xA;font-size: clamp(1.4rem, 5vw, 2rem);&#xA;font-weight: bold;&#xA;margin-bottom: 1rem;&#xA;text-shadow: 0 2px 4px rgba(0,0,0,0.3);&#xA;line-height: 1.3;&#xA;overflow-wrap: break-word;&#xA;hyphens: auto;&#xA;flex: 1;&#xA;display: flex;&#xA;align-items: center;&#xA;justify-content: center;&#xA;text-align: center;&#xA;}&#xA;.card-hint {&#xA;font-size: clamp(0.7rem, 2.3vw, 0.85rem);&#xA;opacity: 0.7;&#xA;font-style: italic;&#xA;margin-top: auto;&#xA;text-align: center;&#xA;}&#xA;.flashcards-navigation {&#xA;display: flex;&#xA;flex-direction: column;&#xA;gap: 0.75rem;&#xA;margin: 1.5rem 0;&#xA;}&#xA;.nav-top, .nav-bottom {&#xA;display: flex;&#xA;justify-content: center;&#xA;}&#xA;.nav-middle {&#xA;display: flex;&#xA;justify-content: center;&#xA;}&#xA;.difficulty-buttons {&#xA;display: flex;&#xA;gap: 0.8rem;&#xA;justify-content: center;&#xA;flex-wrap: wrap;&#xA;}&#xA;.btn {&#xA;padding: clamp(0.4rem, 1.8vw, 0.6rem) clamp(0.8rem, 2.5vw, 1rem);&#xA;border: none;&#xA;border-radius: 8px;&#xA;cursor: pointer;&#xA;font-weight: 500;&#xA;transition: all 0.2s ease;&#xA;font-size: clamp(0.75rem, 2.8vw, 0.85rem);&#xA;white-space: nowrap;&#xA;min-width: fit-content;&#xA;}&#xA;.btn:hover {&#xA;transform: translateY(-1px);&#xA;box-shadow: 0 2px 8px rgba(0,0,0,0.2);&#xA;}&#xA;.btn-primary { background: #007bff; color: white; }&#xA;.btn-secondary { background: #6c757d; color: white; }&#xA;.btn-secondary:hover { background: #5a6268; }&#xA;.btn-success { background: #28a745; color: white; }&#xA;.btn-warning { background: #ffc107; color: #212529; }&#xA;.btn-danger { background: #dc3545; color: white; }&#xA;.btn-outline { background: white; border: 2px solid #495057; color: #212529; }&#xA;.btn-outline:hover { background: #495057; color: white; }&#xA;.btn-info { background: #17a2b8; color: white; }&#xA;.btn-info:hover { background: #138496; }&#xA;.btn:disabled {&#xA;opacity: 0.5;&#xA;cursor: not-allowed;&#xA;transform: none;&#xA;}&#xA;.progress-stats {&#xA;display: grid;&#xA;grid-template-columns: repeat(auto-fit, minmax(70px, 1fr));&#xA;gap: 0.75rem;&#xA;background: #f8f9fa;&#xA;border: 1px solid #ced4da;&#xA;padding: 0.75rem;&#xA;border-radius: 10px;&#xA;margin-top: 1rem;&#xA;}&#xA;.stat {&#xA;text-align: center;&#xA;flex: 1;&#xA;min-width: 70px;&#xA;}&#xA;.stat-label {&#xA;display: block;&#xA;font-size: clamp(0.65rem, 2.3vw, 0.75rem);&#xA;color: #666;&#xA;text-transform: uppercase;&#xA;letter-spacing: 0.5px;&#xA;}&#xA;.stat span:last-child {&#xA;display: block;&#xA;font-size: clamp(1rem, 3.5vw, 1.3rem);&#xA;font-weight: bold;&#xA;color: #333;&#xA;margin-top: 0.25rem;&#xA;}&#xA;.completion-message {&#xA;position: fixed;&#xA;top: 0;&#xA;left: 0;&#xA;width: 100%;&#xA;height: 100%;&#xA;background: rgba(0, 0, 0, 0.8);&#xA;display: flex;&#xA;align-items: center;&#xA;justify-content: center;&#xA;z-index: 1000;&#xA;backdrop-filter: blur(5px);&#xA;}&#xA;.completion-content {&#xA;background: white;&#xA;padding: 2rem;&#xA;border-radius: 20px;&#xA;text-align: center;&#xA;max-width: 90%;&#xA;max-height: 90%;&#xA;overflow-y: auto;&#xA;box-shadow: 0 20px 40px rgba(0, 0, 0, 0.3);&#xA;animation: completionSlideIn 0.3s ease-out;&#xA;}&#xA;@keyframes completionSlideIn {&#xA;from {&#xA;opacity: 0;&#xA;transform: translateY(-50px) scale(0.9);&#xA;}&#xA;to {&#xA;opacity: 1;&#xA;transform: translateY(0) scale(1);&#xA;}&#xA;}&#xA;.completion-icon {&#xA;font-size: 4rem;&#xA;margin-bottom: 1rem;&#xA;animation: bounce 1s ease-in-out infinite alternate;&#xA;}&#xA;@keyframes bounce {&#xA;from { transform: translateY(0); }&#xA;to { transform: translateY(-10px); }&#xA;}&#xA;.completion-title {&#xA;color: #333;&#xA;margin-bottom: 1rem;&#xA;font-size: 2rem;&#xA;font-weight: bold;&#xA;}&#xA;.completion-text {&#xA;color: #666;&#xA;margin-bottom: 2rem;&#xA;font-size: 1.1rem;&#xA;line-height: 1.5;&#xA;}&#xA;.completion-actions {&#xA;display: flex;&#xA;gap: 1rem;&#xA;justify-content: center;&#xA;flex-wrap: wrap;&#xA;}&#xA;.completion-actions .btn {&#xA;min-width: 120px;&#xA;}&#xA; &#xA;@media (max-width: 768px) {&#xA;.flashcards-container { padding: 0.75rem; gap: 0.75rem; }&#xA;.flashcards-header { flex-direction: column; align-items: flex-start; margin-bottom: 0.75rem; gap: 0.75rem; }&#xA;.flashcards-controls { flex-direction: column; align-items: flex-start; gap: 0.75rem; width: 100%; }&#xA;.mode-selector { width: 100%; justify-content: flex-start; }&#xA;.control-buttons { width: 100%; justify-content: flex-start; }&#xA;.progress-display { align-self: flex-start; }&#xA;.flashcard { height: clamp(180px, 30vh, 250px); }&#xA;.flashcard-wrapper { margin: 1rem 0; }&#xA;.flashcards-navigation { margin: 1rem 0; gap: 0.5rem; }&#xA;.card-content { padding: clamp(1.2rem, 4vw, 2rem); }&#xA;.difficulty-buttons { gap: 0.5rem; }&#xA;.progress-stats { grid-template-columns: repeat(3, 1fr); gap: 0.5rem; }&#xA;}&#xA;@media (max-width: 480px) {&#xA;.flashcards-container { padding: 0.5rem; }&#xA;.flashcard { height: clamp(150px, 28vh, 220px); }&#xA;.flashcard-wrapper { margin: 0.75rem 0; }&#xA;.flashcards-navigation { margin: 0.75rem 0; }&#xA;.card-content { padding: clamp(1rem, 3.5vw, 1.5rem); }&#xA;.completion-content { padding: 1.5rem; margin: 1rem; }&#xA;.completion-icon { font-size: 3rem; }&#xA;.completion-title { font-size: 1.5rem; }&#xA;.completion-text { font-size: 1rem; }&#xA;.completion-actions { flex-direction: column; align-items: center; }&#xA;.completion-actions .btn { width: 100%; max-width: 200px; }&#xA;.progress-stats { grid-template-columns: repeat(2, 1fr); }&#xA;.difficulty-buttons { flex-wrap: wrap; gap: 0.3rem; }&#xA;.difficulty-buttons .btn { flex: 1; min-width: 60px; font-size: 0.7rem; padding: 0.3rem 0.5rem; }&#xA; &#xA;.difficulty-buttons .btn { text-indent: -1ch; overflow: hidden; white-space: nowrap; }&#xA;}&#xA;@media (max-height: 500px) and (orientation: landscape) {&#xA;.flashcard { height: clamp(120px, 45vh, 180px); }&#xA;.flashcard-wrapper { margin: 0.5rem 0; }&#xA;.flashcards-navigation { margin: 0.5rem 0; gap: 0.3rem; }&#xA;.flashcards-header h3 { font-size: 1rem; }&#xA;.progress-stats { padding: 0.5rem; }&#xA;.card-content { padding: clamp(0.8rem, 3vw, 1.2rem); }&#xA;}&#xA;&lt;/style&gt;&#xA;&lt;script src=&#34;https://unpkg.com/@supabase/supabase-js@2&#34;&gt;&lt;/script&gt;&#xA;&lt;script&gt;&#xA;&#xA;const { createClient } = supabase;&#xA;const supabaseClient = createClient(&#xA;&#39;https://xjurrqzjvhzjweufgivl.supabase.co&#39;,&#xA;&#39;eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJzdXBhYmFzZSIsInJlZiI6InhqdXJycXpqdmh6andldWZnaXZsIiwicm9sZSI6ImFub24iLCJpYXQiOjE3NDg5NDUzMTIsImV4cCI6MjA2NDUyMTMxMn0.rimZk-g9-RmvQCbQJ5Phk0lKwOue6pPlgibO-LKHqmM&#39;&#xA;);&#xA;&#xA;let authCheckInProgress = false;&#xA;let lastAuthCheck = 0;&#xA;const AUTH_CHECK_THROTTLE = 5000; &#xA;async function updateAuthLink() {&#xA;const now = Date.now();&#xA;if (authCheckInProgress || (now - lastAuthCheck) &lt; AUTH_CHECK_THROTTLE) {&#xA;return; &#xA;}&#xA;authCheckInProgress = true;&#xA;lastAuthCheck = now;&#xA;const authLink = document.getElementById(&#39;auth-link&#39;);&#xA;if (!authLink) {&#xA;authCheckInProgress = false;&#xA;return;&#xA;}&#xA;try {&#xA;const { data: { session }, error } = await supabaseClient.auth.getSession();&#xA;if (error || !session?.user) {&#xA;authLink.textContent = &#39;Login&#39;;&#xA;authLink.href = &#39;/login/&#39;;&#xA;authLink.onclick = null;&#xA;return;&#xA;}&#xA;authLink.textContent = &#39;Logout&#39;;&#xA;authLink.onclick = async function(e) {&#xA;e.preventDefault();&#xA;try {&#xA;await supabaseClient.auth.signOut();&#xA;window.location.reload();&#xA;} catch (err) {&#xA;window.location.reload();&#xA;}&#xA;};&#xA;} catch (err) {&#xA;authLink.textContent = &#39;Login&#39;;&#xA;authLink.href = &#39;/login/&#39;;&#xA;authLink.onclick = null;&#xA;} finally {&#xA;authCheckInProgress = false;&#xA;}&#xA;}&#xA;&#xA;class FlashcardSystem {&#xA;constructor() {&#xA;&#xA;this.flashcards = [&#xA;&#xA;&#xA;{&#xA;term: &#34;\&#34;investigation\&#34;&#34;,&#xA;definition: &#34;\&#34;enquiry\&#34;&#34;,&#xA;stressed: &#34;\&#34;inv*estig*ation\&#34;&#34;,&#xA;id: &#34;\&#34;8f7825f0bc502bfe1d601af4599fd586590126281b524ef2c96599aa43a54a80\&#34;&#34;&#xA;},&#xA;&#xA;&#xA;&#xA;{&#xA;term: &#34;\&#34;evidence\&#34;&#34;,&#xA;definition: &#34;\&#34;proof\&#34;&#34;,&#xA;stressed: &#34;\&#34;*evidence\&#34;&#34;,&#xA;id: &#34;\&#34;d0d99b2ff3a64c5ad50422236a5a6950d34fe0ddf494c1b1ecf4456ddd012a9f\&#34;&#34;&#xA;},&#xA;&#xA;&#xA;&#xA;{&#xA;term: &#34;\&#34;professional\&#34;&#34;,&#xA;definition: &#34;\&#34;≠ amateur\&#34;&#34;,&#xA;stressed: &#34;\&#34;prof*essional\&#34;&#34;,&#xA;id: &#34;\&#34;3ed080e82ed40f3406e773625e030bf932bfafd17eb5c16cc03db8a254213cbc\&#34;&#34;&#xA;},&#xA;&#xA;&#xA;&#xA;{&#xA;term: &#34;\&#34;active\&#34;&#34;,&#xA;definition: &#34;\&#34;≠ passive\&#34;&#34;,&#xA;stressed: &#34;\&#34;*active\&#34;&#34;,&#xA;id: &#34;\&#34;7e9bd8334dde41982a10ad35dfaa5af1e7374e3bdf56117b68056d2a5df6a87b\&#34;&#34;&#xA;},&#xA;&#xA;&#xA;&#xA;{&#xA;term: &#34;\&#34;traditional\&#34;&#34;,&#xA;definition: &#34;\&#34;≠ modern\&#34;&#34;,&#xA;stressed: &#34;\&#34;trad*itional\&#34;&#34;,&#xA;id: &#34;\&#34;b0ed8930796aec42842167a30fe2ded52606ae4f94c8139f67b4545d0025e280\&#34;&#34;&#xA;},&#xA;&#xA;&#xA;&#xA;{&#xA;term: &#34;\&#34;unconventional\&#34;&#34;,&#xA;definition: &#34;\&#34;unusual\&#34;&#34;,&#xA;stressed: &#34;\&#34;*unconv*entional\&#34;&#34;,&#xA;id: &#34;\&#34;308dd2a61f833a2435dc8baf1528ea73b96662d342220c06029a59d430d6ffab\&#34;&#34;&#xA;},&#xA;&#xA;&#xA;&#xA;{&#xA;term: &#34;\&#34;unfair\&#34;&#34;,&#xA;definition: &#34;\&#34;unjust\&#34;&#34;,&#xA;stressed: &#34;\&#34;unf*a*ir\&#34;&#34;,&#xA;id: &#34;\&#34;e6d59c229877a069019af4532c26865ba6ceab48a67fc35dfcada62fb6c0464c\&#34;&#34;&#xA;},&#xA;&#xA;&#xA;&#xA;{&#xA;term: &#34;\&#34;equal\&#34;&#34;,&#xA;definition: &#34;\&#34;≠ unequal\&#34;&#34;,&#xA;stressed: &#34;\&#34;*equal\&#34;&#34;,&#xA;id: &#34;\&#34;d428424a44abfa3c98dba717cd21a97667e4d0c7a6705176037f1e2fbb60b1c3\&#34;&#34;&#xA;},&#xA;&#xA;&#xA;&#xA;{&#xA;term: &#34;\&#34;determined\&#34;&#34;,&#xA;definition: &#34;\&#34;showing determination\&#34;&#34;,&#xA;stressed: &#34;\&#34;det*ermined\&#34;&#34;,&#xA;id: &#34;\&#34;03cd887e72c19fbca3f07573b3b54acf71ea3232651d4ebe5cc6e3bd01161ea5\&#34;&#34;&#xA;},&#xA;&#xA;&#xA;&#xA;{&#xA;term: &#34;\&#34;(to) gossip\&#34;&#34;,&#xA;definition: &#34;\&#34;(to) talk about other people&#39;s private business behind their back\&#34;&#34;,&#xA;stressed: &#34;\&#34;g*ossip\&#34;&#34;,&#xA;id: &#34;\&#34;96e0cad5ed468e5b57ed3309a5d6f9521910d03e8d64445da0474c7d36f36ad8\&#34;&#34;&#xA;},&#xA;&#xA;&#xA;&#xA;{&#xA;term: &#34;\&#34;gossip\&#34;&#34;,&#xA;definition: &#34;\&#34;une commmère\&#34;&#34;,&#xA;stressed: &#34;\&#34;g*ossip\&#34;&#34;,&#xA;id: &#34;\&#34;4019c974f9837b883ef12203ce5de159f8c05374dd108e4b5cc3b179c52e80e9\&#34;&#34;&#xA;},&#xA;&#xA;&#xA;&#xA;{&#xA;term: &#34;\&#34;cunning\&#34;&#34;,&#xA;definition: &#34;\&#34;clever\&#34;&#34;,&#xA;stressed: &#34;\&#34;c*unning\&#34;&#34;,&#xA;id: &#34;\&#34;126ff588a692e8b15e3da562c8923769c7ba3b696eaac9a28757abb6b24e2b4c\&#34;&#34;&#xA;},&#xA;&#xA;&#xA;&#xA;&#xA;&#xA;{&#xA;term: &#34;\&#34;insufferable\&#34;&#34;,&#xA;definition: &#34;\&#34;extremely annoying or unpleasant\&#34;&#34;,&#xA;stressed: &#34;\&#34;ins*ufferable\&#34;&#34;,&#xA;id: &#34;\&#34;664a3e00b4f6ac94530902313cc4255faa63bf2a372ef1be44ff5f065cae9791\&#34;&#34;&#xA;},&#xA;&#xA;&#xA;&#xA;{&#xA;term: &#34;\&#34;(to) miss\&#34;&#34;,&#xA;definition: &#34;\&#34;to not see, hear, or notice something\&#34;&#34;,&#xA;stressed: &#34;\&#34;(to) miss\&#34;&#34;,&#xA;id: &#34;\&#34;24698fe2744d2ec80f5a0983f6e037b80dcaa939eda29e518334ad021f1816dc\&#34;&#34;&#xA;},&#xA;&#xA;&#xA;&#xA;{&#xA;term: &#34;\&#34;(to) notice\&#34;&#34;,&#xA;definition: &#34;\&#34;if you notice something or someone, you realise they exist\&#34;&#34;,&#xA;stressed: &#34;\&#34;(to) n*otice\&#34;&#34;,&#xA;id: &#34;\&#34;de29f1e229ccc7bd43afc41355f07f772a094643ce430ca4467647722f58a684\&#34;&#34;&#xA;},&#xA;&#xA;&#xA;&#xA;{&#xA;term: &#34;\&#34;skill\&#34;&#34;,&#xA;definition: &#34;\&#34;the ability to do something well because you have learned or practised it\&#34;&#34;,&#xA;stressed: &#34;\&#34;skill\&#34;&#34;,&#xA;id: &#34;\&#34;f92e3f58111b185356bf3571e06e94b418fde53b335e08d0c5088262fe016509\&#34;&#34;&#xA;},&#xA;&#xA;&#xA;&#xA;{&#xA;term: &#34;\&#34;spinster\&#34;&#34;,&#xA;definition: &#34;\&#34;an unmarried women, usually one who is no longer young and seems unlikely to marry\&#34;&#34;,&#xA;stressed: &#34;\&#34;sp*inster\&#34;&#34;,&#xA;id: &#34;\&#34;1064359b16c2f437075a4e61117a337f3a05f1d9baf0ffd3ec1e835e17f52250\&#34;&#34;&#xA;},&#xA;&#xA;&#xA;&#xA;{&#xA;term: &#34;\&#34;(to) turn the tables\&#34;&#34;,&#xA;definition: &#34;\&#34;if you turn the tables, you reverse a situation to your advantage\&#34;&#34;,&#xA;stressed: &#34;\&#34;(to) t*urn the t*ables\&#34;&#34;,&#xA;id: &#34;\&#34;178e2b0f99d217dd424591195f2e456645e89ff3c571062b01666c6c4f06176d\&#34;&#34;&#xA;},&#xA;&#xA;&#xA;&#xA;{&#xA;term: &#34;\&#34;proper\&#34;&#34;,&#xA;definition: &#34;\&#34;the real or of good standards\&#34;&#34;,&#xA;stressed: &#34;\&#34;pr*oper\&#34;&#34;,&#xA;id: &#34;\&#34;8fba0154402a8d8a4d17973c13be405214fdd75e4c38a42aa55adf32e28ac4bf\&#34;&#34;&#xA;},&#xA;&#xA;&#xA;&#xA;{&#xA;term: &#34;\&#34;menial\&#34;&#34;,&#xA;definition: &#34;\&#34;menial work is boring, needs no skill, and is not important\&#34;&#34;,&#xA;stressed: &#34;\&#34;m*enial\&#34;&#34;,&#xA;id: &#34;\&#34;b3b44f74675ad739bc29a4b33d440b46960470d871cad80b14310896822d5542\&#34;&#34;&#xA;},&#xA;&#xA;&#xA;&#xA;{&#xA;term: &#34;\&#34;set\&#34;&#34;,&#xA;definition: &#34;\&#34;if a film or story is set in a particular place or period, the aciton is taking place there or then.\&#34;&#34;,&#xA;stressed: &#34;\&#34;set\&#34;&#34;,&#xA;id: &#34;\&#34;4cbd7d7f661c25fb2e1946d6e1b302368834f68123c9cec5e6c5b250be8326eb\&#34;&#34;&#xA;},&#xA;&#xA;&#xA;&#xA;{&#xA;term: &#34;\&#34;(to) shave\&#34;&#34;,&#xA;definition: &#34;\&#34;(to) cut off hair very close using a razor\&#34;&#34;,&#xA;stressed: &#34;\&#34;(to) shave\&#34;&#34;,&#xA;id: &#34;\&#34;b5cddb17e23c3983e3823cea63c0d8e95d34c6b0f542c364083e1fe505870c5a\&#34;&#34;&#xA;},&#xA;&#xA;&#xA;&#xA;{&#xA;term: &#34;\&#34;downsize\&#34;&#34;,&#xA;definition: &#34;\&#34;(to) make smaller\&#34;&#34;,&#xA;stressed: &#34;\&#34;d*o*wnsize\&#34;&#34;,&#xA;id: &#34;\&#34;a2525a669d2d1ca147a064eba1daa5281fe4cc6a27c293fa172d2b19dd2cc1b8\&#34;&#34;&#xA;},&#xA;&#xA;&#xA;].filter(card =&gt; card.term.trim() &amp;&amp; card.definition.trim());&#xA;&#xA;this.setId = &#34;/chapters/women_detectives/&#34;.replace(/\/+$/, &#39;&#39;).replace(/^\//, &#39;&#39;);&#xA;this.setTitle = &#34;Women Detectives&#34;;&#xA;this.cardData = {};&#xA;this.sessionStats = { reviewed: 0 }; &#xA;this.reviewedInSession = new Set();&#xA;this.currentIndex = 0;&#xA;this.isFlipped = false;&#xA;this.studyMode = &#39;term-to-definition&#39;;&#xA;this.viewMode = &#39;browse&#39;; &#xA;this.cardOrder = [...Array(this.flashcards.length).keys()];&#xA;&#xA;this.initDOM();&#xA;this.setupEventListeners();&#xA;&#xA;this.loadProgress().then(() =&gt; {&#xA;this.initializeSession();&#xA;this.updateDisplay();&#xA;});&#xA;}&#xA;&#xA;&#xA;&#xA;&#xA;processStressedText(text) {&#xA;    if (!text) return text;&#xA;    &#xA;    &#xA;    &#xA;    let processed = text.replace(/(\s?)\*([ayeiouwAEYIOUáéíóúÁÉÍÓÚ])/g, &#39;$1&lt;span class=&#34;stressed-vowel&#34;&gt;$2&lt;/span&gt;&#39;);&#xA;    &#xA;    return processed;&#xA;}&#xA;&#xA;&#xA;&#xA;&#xA;initDOM() {&#xA;this.elements = {&#xA;flashcard: document.getElementById(&#39;flashcard&#39;),&#xA;cardQuestion: document.getElementById(&#39;card-question&#39;),&#xA;cardQuestionBack: document.getElementById(&#39;card-question-back&#39;),&#xA;cardAnswer: document.getElementById(&#39;card-answer&#39;),&#xA;currentCard: document.getElementById(&#39;current-card&#39;),&#xA;totalCards: document.getElementById(&#39;total-cards&#39;),&#xA;prevBtn: document.getElementById(&#39;prev-btn&#39;),&#xA;nextBtn: document.getElementById(&#39;next-btn&#39;),&#xA;modeToggleBtn: document.getElementById(&#39;mode-toggle-btn&#39;),&#xA;earlyReviewBtn: document.getElementById(&#39;early-review-btn&#39;),&#xA;resetBtn: document.getElementById(&#39;reset-progress&#39;),&#xA;againBtn: document.getElementById(&#39;again-btn&#39;),&#xA;hardBtn: document.getElementById(&#39;hard-btn&#39;),&#xA;mediumBtn: document.getElementById(&#39;medium-btn&#39;),&#xA;easyBtn: document.getElementById(&#39;easy-btn&#39;),&#xA;reviewedCount: document.getElementById(&#39;reviewed-count&#39;),&#xA;againCount: document.getElementById(&#39;again-count&#39;),&#xA;hardCount: document.getElementById(&#39;hard-count&#39;),&#xA;mediumCount: document.getElementById(&#39;medium-count&#39;),&#xA;easyCount: document.getElementById(&#39;easy-count&#39;),&#xA;reviewCount: document.getElementById(&#39;review-count&#39;),&#xA;completionMessage: document.getElementById(&#39;completion-message&#39;),&#xA;completionText: document.getElementById(&#39;completion-text&#39;),&#xA;earlyReviewOption: document.getElementById(&#39;early-review-option&#39;),&#xA;modeRadios: document.querySelectorAll(&#39;input[name=&#34;study-mode&#34;]&#39;)&#xA;};&#xA;}&#xA;setupEventListeners() {&#xA;this.elements.flashcard.addEventListener(&#39;click&#39;, () =&gt; this.flipCard());&#xA;this.elements.prevBtn.addEventListener(&#39;click&#39;, () =&gt; this.prevCard());&#xA;this.elements.nextBtn.addEventListener(&#39;click&#39;, () =&gt; this.nextCard());&#xA;this.elements.modeToggleBtn.addEventListener(&#39;click&#39;, () =&gt; this.toggleViewMode());&#xA;this.elements.earlyReviewBtn.addEventListener(&#39;click&#39;, () =&gt; this.handleEarlyReview());&#xA;this.elements.resetBtn.addEventListener(&#39;click&#39;, () =&gt; this.resetProgress());&#xA;&#xA;this.elements.againBtn.addEventListener(&#39;click&#39;, () =&gt; this.markDifficulty(&#39;again&#39;));&#xA;this.elements.hardBtn.addEventListener(&#39;click&#39;, () =&gt; this.markDifficulty(&#39;hard&#39;));&#xA;this.elements.mediumBtn.addEventListener(&#39;click&#39;, () =&gt; this.markDifficulty(&#39;medium&#39;));&#xA;this.elements.easyBtn.addEventListener(&#39;click&#39;, () =&gt; this.markDifficulty(&#39;easy&#39;));&#xA;this.elements.modeRadios.forEach(radio =&gt; {&#xA;radio.addEventListener(&#39;change&#39;, (e) =&gt; this.changeStudyMode(e.target.value));&#xA;});&#xA;document.getElementById(&#39;close-completion&#39;).addEventListener(&#39;click&#39;, () =&gt; {&#xA;this.elements.completionMessage.style.display = &#39;none&#39;;&#xA;});&#xA;document.getElementById(&#39;early-review-option&#39;).addEventListener(&#39;click&#39;, () =&gt; {&#xA;this.elements.completionMessage.style.display = &#39;none&#39;;&#xA;this.startEarlyReview();&#xA;});&#xA;document.getElementById(&#39;browse-all-option&#39;).addEventListener(&#39;click&#39;, () =&gt; {&#xA;this.elements.completionMessage.style.display = &#39;none&#39;;&#xA;this.startBrowseMode();&#xA;});&#xA;}&#xA;&#xA;shuffleArray(array) {&#xA;const shuffled = [...array]; &#xA;for (let i = shuffled.length - 1; i &gt; 0; i--) {&#xA;const j = Math.floor(Math.random() * (i + 1));&#xA;[shuffled[i], shuffled[j]] = [shuffled[j], shuffled[i]];&#xA;}&#xA;return shuffled;&#xA;}&#xA;&#xA;getDueCards(includeEarly = false) {&#xA;const now = Date.now();&#xA;const allIndices = [...Array(this.flashcards.length).keys()];&#xA;if (includeEarly) {&#xA;const earlyThreshold = now + (24 * 60 * 60 * 1000);&#xA;return allIndices.filter(idx =&gt; {&#xA;const card = this.cardData[idx];&#xA;return !card || !card.nextReview || card.nextReview &lt;= earlyThreshold;&#xA;});&#xA;} else {&#xA;return allIndices.filter(idx =&gt; {&#xA;const card = this.cardData[idx];&#xA;return !card || !card.nextReview || card.nextReview &lt;= now;&#xA;});&#xA;}&#xA;}&#xA;&#xA;updateCardWithSM2(cardIndex, difficulty) {&#xA;if (!this.cardData[cardIndex]) {&#xA;this.cardData[cardIndex] = {&#xA;interval: 0,&#xA;easeFactor: 2.5,&#xA;reviewCount: 0,&#xA;lastReviewed: Date.now(),&#xA;nextReview: Date.now()&#xA;};&#xA;}&#xA;const card = this.cardData[cardIndex];&#xA;card.reviewCount++;&#xA;card.lastReviewed = Date.now();&#xA;card.lastDifficulty = difficulty; &#xA;let quality;&#xA;switch (difficulty) {&#xA;case &#39;again&#39;: quality = 0; break;&#xA;case &#39;hard&#39;: quality = 2; break;&#xA;case &#39;medium&#39;: quality = 3; break;&#xA;case &#39;easy&#39;: quality = 5; break;&#xA;default: quality = 3;&#xA;}&#xA;&#xA;if (quality &gt;= 3) {&#xA;if (card.reviewCount === 1) {&#xA;card.interval = quality === 5 ? 2 : 1; &#xA;} else if (card.reviewCount === 2) {&#xA;card.interval = 6;&#xA;} else {&#xA;card.interval = Math.round(card.interval * card.easeFactor);&#xA;}&#xA;} else {&#xA;card.interval = quality === 0 ? 0.007 : 1; &#xA;}&#xA;&#xA;if (quality === 0) {&#xA;card.easeFactor = Math.max(1.3, card.easeFactor - 0.2);&#xA;} else if (quality === 2) {&#xA;card.easeFactor = Math.max(1.3, card.easeFactor - 0.15);&#xA;} else if (quality === 3) {&#xA;card.easeFactor = Math.max(1.3, card.easeFactor - 0.02);&#xA;} else if (quality === 5) {&#xA;card.easeFactor = Math.min(2.6, card.easeFactor + 0.1);&#xA;}&#xA;card.nextReview = card.lastReviewed + (card.interval * 24 * 60 * 60 * 1000);&#xA;}&#xA;&#xA;async markDifficulty(level) {&#xA;if (!this.isFlipped) {&#xA;this.flipCard();&#xA;return;&#xA;}&#xA;if (this.viewMode !== &#39;study&#39;) {&#xA;return;&#xA;}&#xA;const cardIndex = this.cardOrder[this.currentIndex];&#xA;&#xA;if (!this.reviewedInSession.has(cardIndex)) {&#xA;this.sessionStats.reviewed++;&#xA;this.reviewedInSession.add(cardIndex);&#xA;}&#xA;&#xA;this.updateCardWithSM2(cardIndex, level);&#xA;&#xA;await this.saveProgress();&#xA;this.updateStatsDisplay();&#xA;&#xA;if (level === &#39;again&#39;) {&#xA;if (this.currentIndex &lt; this.cardOrder.length - 1) {&#xA;this.currentIndex++;&#xA;} else {&#xA;this.currentIndex = 0;&#xA;}&#xA;this.updateCard();&#xA;} else {&#xA;&#xA;this.cardOrder.splice(this.currentIndex, 1);&#xA;if (this.currentIndex &gt;= this.cardOrder.length &amp;&amp; this.cardOrder.length &gt; 0) {&#xA;this.currentIndex = this.cardOrder.length - 1;&#xA;}&#xA;if (this.cardOrder.length &gt; 0) {&#xA;this.updateCard();&#xA;} else {&#xA;this.saveProgress();&#xA;this.showCompletionMessage();&#xA;}&#xA;}&#xA;}&#xA;&#xA;startStudyMode() {&#xA;const dueCards = this.getDueCards();&#xA;if (dueCards.length &gt; 0) {&#xA;this.viewMode = &#39;study&#39;;&#xA;&#xA;this.cardOrder = this.shuffleArray(dueCards);&#xA;this.currentIndex = 0;&#xA;this.updateModeButton(&#39;📚 Studying&#39;, &#39;btn-primary&#39;);&#xA;this.updateCard();&#xA;} else {&#xA;this.checkForEarlyReview();&#xA;}&#xA;}&#xA;startEarlyReview() {&#xA;const allEarly = this.getDueCards(true);&#xA;const dueNow = this.getDueCards(false);&#xA;const earlyOnly = allEarly.filter(idx =&gt; !dueNow.includes(idx));&#xA;if (earlyOnly.length &gt; 0) {&#xA;this.viewMode = &#39;study&#39;;&#xA;&#xA;this.cardOrder = this.shuffleArray(earlyOnly);&#xA;this.currentIndex = 0;&#xA;this.updateModeButton(&#39;📚 Studying&#39;, &#39;btn-primary&#39;);&#xA;this.updateCard();&#xA;} else {&#xA;alert(&#34;No cards are available for early review right now.&#34;);&#xA;}&#xA;}&#xA;startBrowseMode() {&#xA;this.viewMode = &#39;browse&#39;;&#xA;&#xA;this.cardOrder = [...Array(this.flashcards.length).keys()];&#xA;this.currentIndex = 0;&#xA;this.updateModeButton(&#39;📖 Browsing&#39;, &#39;btn-secondary&#39;);&#xA;this.updateCard();&#xA;}&#xA;checkForEarlyReview() {&#xA;const allEarly = this.getDueCards(true);&#xA;const dueNow = this.getDueCards(false);&#xA;const earlyCount = allEarly.length - dueNow.length;&#xA;if (earlyCount &gt; 0) {&#xA;const message = `No cards are due right now, but you have ${earlyCount} card${earlyCount !== 1 ? &#39;s&#39; : &#39;&#39;} due within 24 hours.\n\nWould you like to review them early?`;&#xA;if (confirm(message)) {&#xA;this.startEarlyReview();&#xA;} else {&#xA;this.viewMode = &#39;browse&#39;;&#xA;this.startBrowseMode();&#xA;}&#xA;} else {&#xA;this.showCompletionMessage();&#xA;this.viewMode = &#39;browse&#39;;&#xA;}&#xA;}&#xA;&#xA;updateModeButton(text, className) {&#xA;this.elements.modeToggleBtn.textContent = text;&#xA;this.elements.modeToggleBtn.className = `btn ${className}`;&#xA;&#xA;const difficultyButtons = document.querySelector(&#39;.difficulty-buttons&#39;);&#xA;if (difficultyButtons) {&#xA;if (this.viewMode === &#39;study&#39;) {&#xA;difficultyButtons.style.display = &#39;flex&#39;;&#xA;} else {&#xA;difficultyButtons.style.display = &#39;none&#39;;&#xA;}&#xA;}&#xA;}&#xA;toggleViewMode() {&#xA;if (this.viewMode === &#39;browse&#39;) {&#xA;this.startStudyMode();&#xA;} else {&#xA;this.startBrowseMode();&#xA;}&#xA;&#xA;this.saveProgressSilent();&#xA;}&#xA;handleEarlyReview() {&#xA;const allEarly = this.getDueCards(true);&#xA;const dueNow = this.getDueCards(false);&#xA;const earlyCount = allEarly.length - dueNow.length;&#xA;if (earlyCount &gt; 0) {&#xA;this.startEarlyReview();&#xA;} else if (dueNow.length &gt; 0) {&#xA;alert(&#34;You have cards due for review! Use the Study button instead.&#34;);&#xA;} else {&#xA;alert(&#34;No cards are available for early review right now.&#34;);&#xA;}&#xA;}&#xA;&#xA;updateCard() {&#xA;if (this.flashcards.length === 0) {&#xA;this.elements.cardQuestion.innerHTML = &#34;No flashcards available&#34;;&#xA;this.elements.cardQuestionBack.innerHTML = &#34;No flashcards available&#34;;&#xA;this.elements.cardAnswer.innerHTML = &#34;Please add lexicon data to the front matter&#34;;&#xA;return;&#xA;}&#xA;if (this.currentIndex &lt; 0 || this.currentIndex &gt;= this.cardOrder.length) {&#xA;this.currentIndex = 0;&#xA;}&#xA;const cardIndex = this.cardOrder[this.currentIndex];&#xA;const card = this.flashcards[cardIndex];&#xA;if (!card) {&#xA;console.error(&#39;Invalid card at index:&#39;, cardIndex);&#xA;return;&#xA;}&#xA;let question, answer;&#xA;if (this.studyMode === &#39;term-to-definition&#39;) {&#xA;&#xA;question = card.stressed || card.term;&#xA;answer = card.definition;&#xA;} else {&#xA;question = card.definition;&#xA;&#xA;answer = card.stressed || card.term;&#xA;}&#xA;&#xA;this.elements.cardQuestion.innerHTML = this.processStressedText(question);&#xA;this.elements.cardQuestionBack.innerHTML = this.processStressedText(question);&#xA;this.elements.cardAnswer.innerHTML = this.processStressedText(answer);&#xA;this.elements.currentCard.textContent = this.currentIndex + 1;&#xA;this.elements.totalCards.textContent = this.cardOrder.length;&#xA;&#xA;this.elements.prevBtn.disabled = this.currentIndex === 0;&#xA;this.elements.nextBtn.disabled = this.currentIndex === this.cardOrder.length - 1;&#xA;&#xA;this.isFlipped = false;&#xA;this.elements.flashcard.classList.remove(&#39;flipped&#39;);&#xA;}&#xA;&#xA;updateStatsDisplay() {&#xA;const totalReviewed = Object.values(this.cardData).filter(card =&gt; card &amp;&amp; card.reviewCount &gt; 0).length;&#xA;const needsReview = this.getDueCards().length;&#xA;&#xA;const difficultyStats = { again: 0, hard: 0, medium: 0, easy: 0 };&#xA;for (let i = 0; i &lt; this.flashcards.length; i++) {&#xA;const card = this.cardData[i];&#xA;if (card &amp;&amp; card.lastDifficulty) {&#xA;difficultyStats[card.lastDifficulty]++;&#xA;}&#xA;}&#xA;this.elements.reviewedCount.textContent = totalReviewed;&#xA;this.elements.reviewCount.textContent = needsReview;&#xA;&#xA;if (this.elements.againCount) this.elements.againCount.textContent = difficultyStats.again;&#xA;if (this.elements.hardCount) this.elements.hardCount.textContent = difficultyStats.hard;&#xA;if (this.elements.mediumCount) this.elements.mediumCount.textContent = difficultyStats.medium;&#xA;this.elements.easyCount.textContent = difficultyStats.easy;&#xA;}&#xA;updateDisplay() {&#xA;this.updateCard();&#xA;this.updateStatsDisplay();&#xA;&#xA;const radio = document.querySelector(`input[value=&#34;${this.studyMode}&#34;]`);&#xA;if (radio) radio.checked = true;&#xA;&#xA;if (this.viewMode === &#39;study&#39;) {&#xA;this.updateModeButton(&#39;📚 Studying&#39;, &#39;btn-primary&#39;);&#xA;} else {&#xA;this.updateModeButton(&#39;📖 Browsing&#39;, &#39;btn-secondary&#39;);&#xA;}&#xA;}&#xA;&#xA;flipCard() {&#xA;this.isFlipped = !this.isFlipped;&#xA;this.elements.flashcard.classList.toggle(&#39;flipped&#39;);&#xA;}&#xA;nextCard() {&#xA;if (this.currentIndex &lt; this.cardOrder.length - 1) {&#xA;this.currentIndex++;&#xA;this.updateCard();&#xA;&#xA;if (this.viewMode === &#39;study&#39;) {&#xA;this.saveProgressSilent();&#xA;}&#xA;}&#xA;}&#xA;prevCard() {&#xA;if (this.currentIndex &gt; 0) {&#xA;this.currentIndex--;&#xA;this.updateCard();&#xA;&#xA;if (this.viewMode === &#39;study&#39;) {&#xA;this.saveProgressSilent();&#xA;}&#xA;}&#xA;}&#xA;changeStudyMode(mode) {&#xA;this.studyMode = mode;&#xA;this.updateCard();&#xA;&#xA;this.saveProgressSilent();&#xA;}&#xA;&#xA;showCompletionMessage() {&#xA;this.viewMode = &#39;browse&#39;;&#xA;this.updateModeButton(&#39;📖 Browsing&#39;, &#39;btn-secondary&#39;);&#xA;const nextReview = this.getNextReviewTime();&#xA;const allEarly = this.getDueCards(true);&#xA;const dueNow = this.getDueCards(false);&#xA;const earlyCards = allEarly.length - dueNow.length;&#xA;let message = &#34;You&#39;ve reviewed all due cards!&#34;;&#xA;if (nextReview) {&#xA;const timeUntil = nextReview - Date.now();&#xA;const hoursUntil = Math.ceil(timeUntil / (1000 * 60 * 60));&#xA;const daysUntil = Math.ceil(timeUntil / (1000 * 60 * 60 * 24));&#xA;if (hoursUntil &lt; 24) {&#xA;message += ` Next cards will be ready in about ${hoursUntil} hour${hoursUntil !== 1 ? &#39;s&#39; : &#39;&#39;}.`;&#xA;} else {&#xA;message += ` Next cards will be ready in about ${daysUntil} day${daysUntil !== 1 ? &#39;s&#39; : &#39;&#39;}.`;&#xA;}&#xA;}&#xA;this.elements.completionText.textContent = message;&#xA;if (earlyCards &gt; 0) {&#xA;this.elements.earlyReviewOption.style.display = &#39;inline-block&#39;;&#xA;this.elements.earlyReviewOption.textContent = `⏰ Review ${earlyCards} Early Card${earlyCards !== 1 ? &#39;s&#39; : &#39;&#39;}`;&#xA;} else {&#xA;this.elements.earlyReviewOption.style.display = &#39;none&#39;;&#xA;}&#xA;this.elements.completionMessage.style.display = &#39;flex&#39;;&#xA;this.saveProgressSilent();&#xA;}&#xA;getNextReviewTime() {&#xA;const now = Date.now();&#xA;let earliest = null;&#xA;for (let i = 0; i &lt; this.flashcards.length; i++) {&#xA;const card = this.cardData[i];&#xA;if (card &amp;&amp; card.nextReview &amp;&amp; card.nextReview &gt; now) {&#xA;if (!earliest || card.nextReview &lt; earliest) {&#xA;earliest = card.nextReview;&#xA;}&#xA;}&#xA;}&#xA;return earliest;&#xA;}&#xA;&#xA;resetProgress() {&#xA;this.cardData = {};&#xA;this.sessionStats = { reviewed: 0 };&#xA;this.reviewedInSession = new Set();&#xA;this.viewMode = &#39;browse&#39;;&#xA;this.cardOrder = [...Array(this.flashcards.length).keys()];&#xA;this.currentIndex = 0;&#xA;this.updateDisplay();&#xA;this.saveProgressSilent();&#xA;}&#xA;&#xA;initializeSession() {&#xA;if (this.viewMode === &#39;study&#39;) {&#xA;const dueCards = this.getDueCards();&#xA;if (dueCards.length &gt; 0) {&#xA;&#xA;this.cardOrder = this.shuffleArray(dueCards);&#xA;this.currentIndex = 0;&#xA;this.updateModeButton(&#39;📚 Studying&#39;, &#39;btn-primary&#39;);&#xA;} else {&#xA;this.viewMode = &#39;browse&#39;;&#xA;this.cardOrder = [...Array(this.flashcards.length).keys()];&#xA;this.currentIndex = Math.min(this.currentIndex, this.cardOrder.length - 1);&#xA;this.updateModeButton(&#39;📖 Browsing&#39;, &#39;btn-secondary&#39;);&#xA;}&#xA;} else {&#xA;&#xA;this.cardOrder = [...Array(this.flashcards.length).keys()];&#xA;this.currentIndex = Math.min(this.currentIndex, this.cardOrder.length - 1);&#xA;this.updateModeButton(&#39;📖 Browsing&#39;, &#39;btn-secondary&#39;);&#xA;}&#xA;}&#xA;&#xA;async saveProgress() {&#xA;this.saveToLocalStorage();&#xA;try {&#xA;const { data: { session }, error } = await supabaseClient.auth.getSession();&#xA;if (error || !session?.user?.id) {&#xA;return;&#xA;}&#xA;const progressData = {&#xA;user_id: session.user.id,&#xA;set_id: this.setId,&#xA;set_title: this.setTitle,&#xA;card_data: {&#xA;cardOrder: this.cardOrder,&#xA;currentIndex: this.currentIndex,&#xA;studyMode: this.studyMode,&#xA;viewMode: this.viewMode,&#xA;cardData: this.cardData&#xA;},&#xA;stats: this.sessionStats,&#xA;updated_at: new Date().toISOString()&#xA;};&#xA;const { error: saveError } = await supabaseClient&#xA;.from(&#39;flashcard_progress&#39;)&#xA;.upsert(progressData, { onConflict: &#39;user_id,set_id&#39; });&#xA;if (saveError) {&#xA;console.error(&#39;Supabase save error:&#39;, saveError);&#xA;}&#xA;} catch (e) {&#xA;console.error(&#39;Error saving progress:&#39;, e);&#xA;}&#xA;}&#xA;&#xA;async saveProgressSilent() {&#xA;this.saveToLocalStorage();&#xA;try {&#xA;const { data: { session }, error } = await supabaseClient.auth.getSession();&#xA;if (error || !session?.user?.id) {&#xA;return;&#xA;}&#xA;const progressData = {&#xA;user_id: session.user.id,&#xA;set_id: this.setId,&#xA;set_title: this.setTitle,&#xA;card_data: {&#xA;cardOrder: this.cardOrder,&#xA;currentIndex: this.currentIndex,&#xA;studyMode: this.studyMode,&#xA;viewMode: this.viewMode,&#xA;cardData: this.cardData&#xA;},&#xA;stats: this.sessionStats,&#xA;updated_at: new Date().toISOString()&#xA;};&#xA;await supabaseClient&#xA;.from(&#39;flashcard_progress&#39;)&#xA;.upsert(progressData, { onConflict: &#39;user_id,set_id&#39; });&#xA;} catch (e) {&#xA;console.error(&#39;Error saving progress silently:&#39;, e);&#xA;}&#xA;}&#xA;async loadProgress() {&#xA;&#xA;this.cardData = {};&#xA;this.sessionStats = { reviewed: 0 };&#xA;this.reviewedInSession = new Set();&#xA;try {&#xA;const { data: { session }, error } = await supabaseClient.auth.getSession();&#xA;if (error || !session?.user?.id) {&#xA;this.loadFromLocalStorage();&#xA;return;&#xA;}&#xA;const { data, error: dbError } = await supabaseClient&#xA;.from(&#39;flashcard_progress&#39;)&#xA;.select(&#39;*&#39;)&#xA;.eq(&#39;user_id&#39;, session.user.id)&#xA;.eq(&#39;set_id&#39;, this.setId)&#xA;.single();&#xA;if (dbError &amp;&amp; dbError.code !== &#39;PGRST116&#39;) {&#xA;console.error(&#39;Database error:&#39;, dbError);&#xA;this.loadFromLocalStorage();&#xA;return;&#xA;}&#xA;if (data) {&#xA;this.loadFromData(data);&#xA;&#xA;await this.migrateLocalStorageIfNewer(data.updated_at);&#xA;} else {&#xA;this.loadFromLocalStorage();&#xA;if (session?.user) {&#xA;await this.saveProgressSilent();&#xA;}&#xA;}&#xA;} catch (e) {&#xA;console.error(&#39;Error loading progress:&#39;, e);&#xA;this.loadFromLocalStorage();&#xA;}&#xA;}&#xA;&#xA;loadFromData(data) {&#xA;if (data.card_data) {&#xA;this.cardOrder = this.validateArray(data.card_data.cardOrder, this.flashcards.length) ||&#xA;[...Array(this.flashcards.length).keys()];&#xA;this.cardData = this.validateCardData(data.card_data.cardData) || {};&#xA;this.currentIndex = Math.max(0, Math.min(data.card_data.currentIndex || 0, this.cardOrder.length - 1));&#xA;this.studyMode = [&#39;term-to-definition&#39;, &#39;definition-to-term&#39;].includes(data.card_data.studyMode) ?&#xA;data.card_data.studyMode : &#39;term-to-definition&#39;;&#xA;this.viewMode = [&#39;browse&#39;, &#39;study&#39;].includes(data.card_data.viewMode) ?&#xA;data.card_data.viewMode : &#39;browse&#39;;&#xA;}&#xA;if (data.stats &amp;&amp; typeof data.stats === &#39;object&#39;) {&#xA;this.sessionStats = {&#xA;reviewed: data.stats.reviewed || 0&#xA;};&#xA;}&#xA;}&#xA;loadFromLocalStorage() {&#xA;const storageKey = `flashcards_${this.setId}`;&#xA;const saved = localStorage.getItem(storageKey);&#xA;if (saved) {&#xA;try {&#xA;const data = JSON.parse(saved);&#xA;this.loadFromData({&#xA;card_data: {&#xA;cardOrder: data.cardOrder,&#xA;cardData: data.cardData,&#xA;currentIndex: data.currentIndex,&#xA;studyMode: data.studyMode,&#xA;viewMode: data.viewMode&#xA;},&#xA;stats: data.sessionStats&#xA;});&#xA;} catch (e) {&#xA;console.error(&#39;Error parsing localStorage:&#39;, e);&#xA;}&#xA;}&#xA;}&#xA;async migrateLocalStorageIfNewer(dbUpdatedAt) {&#xA;const storageKey = `flashcards_${this.setId}`;&#xA;const saved = localStorage.getItem(storageKey);&#xA;if (!saved) return;&#xA;try {&#xA;const localData = JSON.parse(saved);&#xA;const localUpdated = new Date(localData.lastUpdated || 0);&#xA;const dbUpdated = new Date(dbUpdatedAt);&#xA;if (localUpdated &gt; dbUpdated) {&#xA;this.loadFromData({&#xA;card_data: {&#xA;cardOrder: localData.cardOrder,&#xA;cardData: localData.cardData,&#xA;currentIndex: localData.currentIndex,&#xA;studyMode: localData.studyMode,&#xA;viewMode: localData.viewMode&#xA;},&#xA;stats: localData.sessionStats&#xA;});&#xA;await this.saveProgressSilent();&#xA;}&#xA;} catch (e) {&#xA;console.error(&#39;Error during migration:&#39;, e);&#xA;}&#xA;}&#xA;saveToLocalStorage() {&#xA;const storageKey = `flashcards_${this.setId}`;&#xA;const data = {&#xA;cardOrder: this.cardOrder,&#xA;currentIndex: this.currentIndex,&#xA;studyMode: this.studyMode,&#xA;viewMode: this.viewMode,&#xA;cardData: this.cardData,&#xA;sessionStats: this.sessionStats,&#xA;lastUpdated: new Date().toISOString(),&#xA;setTitle: this.setTitle&#xA;};&#xA;try {&#xA;localStorage.setItem(storageKey, JSON.stringify(data));&#xA;} catch (e) {&#xA;console.error(&#39;Error saving to localStorage:&#39;, e);&#xA;}&#xA;}&#xA;&#xA;validateArray(arr, expectedLength) {&#xA;if (!Array.isArray(arr) || arr.length !== expectedLength) return null;&#xA;return arr.every(idx =&gt; Number.isInteger(idx) &amp;&amp; idx &gt;= 0 &amp;&amp; idx &lt; expectedLength) ? arr : null;&#xA;}&#xA;validateCardData(data) {&#xA;if (!data || typeof data !== &#39;object&#39;) return null;&#xA;const validated = {};&#xA;for (const [key, value] of Object.entries(data)) {&#xA;if (value &amp;&amp; typeof value === &#39;object&#39; &amp;&amp;&#xA;typeof value.interval === &#39;number&#39; &amp;&amp;&#xA;typeof value.easeFactor === &#39;number&#39;) {&#xA;validated[key] = value;&#xA;}&#xA;}&#xA;return validated;&#xA;}&#xA;}&#xA;&#xA;document.addEventListener(&#39;DOMContentLoaded&#39;, () =&gt; {&#xA;updateAuthLink();&#xA;window.flashcardSystem = new FlashcardSystem();&#xA;});&#xA;&#xA;supabaseClient.auth.onAuthStateChange(async (event, session) =&gt; {&#xA;console.log(&#39;Auth state changed:&#39;, event);&#xA;updateAuthLink();&#xA;&#xA;});&#xA;&#xA;window.addEventListener(&#39;focus&#39;, () =&gt; {&#xA;setTimeout(updateAuthLink, 1000); &#xA;});&#xA;&lt;/script&gt;</description>
      
    </item>
    
  </channel>
</rss>
