Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 21 additions & 0 deletions LICENSE
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
MIT License

Copyright (c) 2026 [Your Name/Organization]
Copy link

Copilot AI Mar 12, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The LICENSE file still contains a [Your Name/Organization] placeholder. Please replace it with the actual copyright holder (and year range if applicable) so the licensing terms are unambiguous.

Suggested change
Copyright (c) 2026 [Your Name/Organization]
Copyright (c) 2026 Example Corp

Copilot uses AI. Check for mistakes.

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
225 changes: 225 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,225 @@
# UI Conformity Experiment

> **Beta UI Diagnostic Dashboard**: A behavioral research tool investigating AI authority bias in user interface design preferences

[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)

## Overview

This repository contains a web-based behavioral experiment designed to investigate whether "AI Recommended" labels influence users' UI design preferences. The study employs a randomized between-subjects design to measure conformity effects in human-computer interaction.
Copy link

Copilot AI Mar 12, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

README claims the study uses a randomized between-subjects design, but the implementation sets condition purely from the ?condition=ai URL parameter (otherwise defaults to control). Please update the wording to reflect URL-based assignment (and/or document how to achieve random assignment externally if desired).

Copilot uses AI. Check for mistakes.

### Research Question

**Does an "AI Recommended" label influence users' UI design preferences?**

## Quick Start

```bash
# Clone the repository
git clone https://github.com/hashexplaindata/Conformity-experiment.git
cd Conformity-experiment

# Start a local server
python -m http.server 8000

# Access the experiment
# Control condition: http://localhost:8000/code/index.html?condition=control
# AI label condition: http://localhost:8000/code/index.html?condition=ai
```

## Project Structure

```
Conformity-experiment/
├── code/ # Application files
│ ├── index.html # Main experiment page (147 lines)
│ ├── experiment.js # Core behavioral engine (489 lines)
│ └── style.css # Styling & animations (281 lines)
Comment on lines +35 to +37
Copy link

Copilot AI Mar 12, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The line counts in the project tree are already out of date (e.g., index.html is 148 lines, experiment.js 490, style.css 282). Since these will drift frequently, consider removing line counts or generating them automatically.

Suggested change
│ ├── index.html # Main experiment page (147 lines)
│ ├── experiment.js # Core behavioral engine (489 lines)
│ └── style.css # Styling & animations (281 lines)
│ ├── index.html # Main experiment page
│ ├── experiment.js # Core behavioral engine
│ └── style.css # Styling & animations

Copilot uses AI. Check for mistakes.
├── docs/ # Documentation & ethics
│ ├── README.md # Quick reference guide
│ ├── METHODS.md # Formal research methodology
│ ├── RUNBOOK.md # Step-by-step operational guide
│ ├── IRB_CHECKLIST.md # Ethics compliance checklist
│ ├── CONSENT.txt # Participant consent form
│ └── DEBRIEF.txt # Post-study disclosure
├── .github/workflows/ # CI/CD pipelines
│ └── codeql.yml # Security scanning
├── firebase.json # Firebase hosting configuration
└── .firebaserc # Firebase project reference
```

## Experimental Design

### Conditions

- **Control Group**: Views 6 pairs of UI mockups with neutral labels ("Option A" / "Option B")
- **Treatment Group**: Views identical pairs with "✨ AI Recommended" badges on designated options

### Trial Domains (Iqra University Context)

1. **Information Density** - Course Schedule (List vs. Grid)
2. **Data Visualization** - HEC Attendance Warning (Circular gauge vs. Progress bar)
3. **Financial Overview** - Fee Voucher (Card vs. Centered layout)
4. **Campus Event** - Event Display (Visual-dominant vs. Compact)
5. **Interaction** - QEC Faculty Evaluation (Radio buttons vs. Slider)
6. **Navigation** - Digital Library (Floating search vs. Header-integrated)

### Data Collection

Each participant record captures:
- **Primary DV**: Whether the AI-labeled option was selected
- **Reaction time**: Millisecond-accurate (`performance.now()`)
- **AI familiarity**: 5-point Likert scale covariate
- **Semantic justification**: Free-text explanation (optional)
- **Metadata**: UUID, condition, trial sequence, timestamps

## Features

### Technical Highlights

- 🎯 **Client-side randomization** - 50/50 condition assignment
Copy link

Copilot AI Mar 12, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Client-side randomization - 50/50 condition assignment is not accurate: experiment.js derives CFG.CONDITION from the URL parameter and does not randomly assign participants to conditions. Update this bullet to match the implementation (e.g., URL-driven assignment) or implement the described randomization.

Suggested change
- 🎯 **Client-side randomization** - 50/50 condition assignment
- 🎯 **URL-driven condition assignment** - Experiment condition set via `?condition=control|ai`

Copilot uses AI. Check for mistakes.
- ⚡ **Millisecond-accurate telemetry** - `performance.now()` reaction time tracking
- 🔥 **Firebase integration** - Automatic Firestore sync (`conformity_telemetry` collection)
- 🎨 **Modern UI** - Dark theme with Bento grid design and radial glow effects
- 🔒 **Privacy-first** - Anonymous UUIDs, no PII collection
- 📱 **Responsive** - Mobile and desktop compatible
- 🚫 **Anti-manipulation** - Browser back-navigation prevention

### Research Features

- Counterbalanced AI badge assignment
- Randomized trial order
Comment on lines +90 to +91
Copy link

Copilot AI Mar 12, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The README lists Counterbalanced AI badge assignment and Randomized trial order, but the code uses a fixed trial.target per trial and iterates through TRIALS sequentially (only left/right position is randomized). Please update these research feature bullets to reflect what actually happens, or add the missing counterbalancing/shuffle logic.

Suggested change
- Counterbalanced AI badge assignment
- Randomized trial order
- Fixed AI badge assignment per trial (consistent across participants)
- Fixed trial order across participants

Copilot uses AI. Check for mistakes.
- Left/Right position randomization (prevents motor habituation)
- Covariate collection (AI familiarity)
- Qualitative data capture (semantic justification)

## Deployment Options

### 1. Local Development
```bash
python -m http.server 8000
```

### 2. Firebase Hosting
```bash
npm install -g firebase-tools
firebase login
firebase deploy --only hosting
```

### 3. GitHub Pages
1. Enable in repository Settings > Pages
2. Access at: `https://[username].github.io/Conformity-experiment/code/index.html?condition=control`

### 4. Netlify
1. Drag `code/` folder to [app.netlify.com/drop](https://app.netlify.com/drop)
2. Share generated URL with condition parameters

## Documentation

| Document | Purpose |
|----------|---------|
| [`docs/README.md`](docs/README.md) | Quick reference and file overview |
| [`docs/METHODS.md`](docs/METHODS.md) | Formal research methodology (copy-paste ready) |
| [`docs/RUNBOOK.md`](docs/RUNBOOK.md) | Step-by-step operational guide for running sessions |
| [`docs/IRB_CHECKLIST.md`](docs/IRB_CHECKLIST.md) | 15-point ethical review checklist |
| [`docs/CONSENT.txt`](docs/CONSENT.txt) | Participant informed consent template |
| [`docs/DEBRIEF.txt`](docs/DEBRIEF.txt) | Post-study disclosure statement |

## Ethical Considerations

✅ **IRB-Ready**: Includes informed consent, debrief, and ethics checklist
✅ **Minimal Risk**: Viewing UI mockups only
✅ **Voluntary**: Participants can withdraw at any time
✅ **Anonymous**: UUID-based identification, no PII
✅ **Transparent**: Full disclosure of manipulation in debrief
✅ **Withdrawal Rights**: 7-day data withdrawal window with Participant ID

## Requirements

- **Browser**: Chrome 90+, Firefox 88+, Safari 14+, Edge 90+
- **Server** (optional): Python 3.x, Node.js, or any HTTP server
- **Firebase** (optional): For data persistence and hosting

## Data Format

Data is stored in **tidy data long format** with the following schema:

```javascript
{
participant_id: "abc123xyz...", // Anonymous UUID
experimental_condition: "ai_labeled", // "control" or "ai_labeled"
ai_familiarity_covariate: 3, // 1-5 Likert scale
trial_sequence: 1, // 1-6
ui_domain: "Information Density...", // Trial category
ai_badge_position: "B", // "A", "B", or "none"
user_selection: "B", // "A" or "B"
Comment on lines +150 to +156
Copy link

Copilot AI Mar 12, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The documented data schema doesn't match what experiment.js actually writes: participant_id is not a UUID, and ai_badge_position/user_selection are stored as strings like "Layout A"/"Layout B" (not just "A"/"B"). Please align the schema example and field comments with the real payload keys/values to avoid analysis mistakes.

Suggested change
participant_id: "abc123xyz...", // Anonymous UUID
experimental_condition: "ai_labeled", // "control" or "ai_labeled"
ai_familiarity_covariate: 3, // 1-5 Likert scale
trial_sequence: 1, // 1-6
ui_domain: "Information Density...", // Trial category
ai_badge_position: "B", // "A", "B", or "none"
user_selection: "B", // "A" or "B"
participant_id: "abc123xyz...", // Anonymous participant ID (non-UUID string)
experimental_condition: "ai_labeled", // "control" or "ai_labeled"
ai_familiarity_covariate: 3, // 1-5 Likert scale
trial_sequence: 1, // 1-6
ui_domain: "Information Density...", // Trial category
ai_badge_position: "Layout B", // "Layout A", "Layout B", or "none"
user_selection: "Layout B", // "Layout A" or "Layout B"

Copilot uses AI. Check for mistakes.
chose_target_layout: true, // Boolean
reaction_time_ms: 2341, // Milliseconds
semantic_justification: "I prefer...", // Free text
timestamp: 1710278400000 // Unix ms
}
```

## Usage

### For Researchers

1. Review [`docs/METHODS.md`](docs/METHODS.md) for study design
2. Follow [`docs/RUNBOOK.md`](docs/RUNBOOK.md) for session operations
3. Complete [`docs/IRB_CHECKLIST.md`](docs/IRB_CHECKLIST.md) for ethics approval
4. Configure Firebase credentials (or use localStorage fallback)
Copy link

Copilot AI Mar 12, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The README mentions a localStorage fallback, but the current Firebase error path only logs a TODO comment and does not persist results to localStorage when sync fails. Please remove/qualify the fallback claim or implement an actual local persistence + retry/export mechanism.

Suggested change
4. Configure Firebase credentials (or use localStorage fallback)
4. Configure Firebase credentials (primary data store; no automatic localStorage fallback is currently implemented)

Copilot uses AI. Check for mistakes.
5. Deploy and share condition-specific URLs with participants

### For Developers

```javascript
// Configuration
const CFG = {
NUM_TRIALS: 6,
CONDITION: 'ai_labeled' | 'control',
COLLECTION: 'conformity_telemetry'
};

// Trial definition structure
const TRIAL = {
domain: 'Trial Category Name',
renderA: () => `<div>...</div>`, // Option A HTML
renderB: () => `<div>...</div>`, // Option B HTML
target: 'A' | 'B' // Hypothesized preference
};
Comment on lines +178 to +190
Copy link

Copilot AI Mar 12, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The For Developers snippet uses TypeScript-style union types inside a JavaScript object ('ai_labeled' | 'control', 'A' | 'B'), which is not valid JavaScript and may confuse readers copying it. Consider rewriting as plain JS comments/examples or explicitly marking the block as TypeScript/pseudocode.

Copilot uses AI. Check for mistakes.
```

## Contributing

This is an academic research project. For questions or collaboration inquiries, please open an issue.

## License

MIT License - See [LICENSE](LICENSE) for details

## Citation

If you use this experiment framework in your research, please cite:

```bibtex
@software{conformity_experiment_2026,
title = {UI Conformity Experiment: AI Authority Bias in Interface Design},
author = {[Your Name]},
year = {2026},
url = {https://github.com/hashexplaindata/Conformity-experiment}
}
```

## Acknowledgments

- Built with vanilla JavaScript for maximum portability
- Firebase for data persistence
- Iqra University and Pakistan HEC for contextual realism

---

**Version**: 2.0 | **Last Updated**: 2026-03-12 | **Status**: Production Ready

For operational guidance, see [`docs/RUNBOOK.md`](docs/RUNBOOK.md)
For methodology details, see [`docs/METHODS.md`](docs/METHODS.md)
6 changes: 3 additions & 3 deletions docs/IRB_CHECKLIST.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,12 +11,12 @@
| 5 | Minimal risk | YES | Task involves viewing UI mockups and clicking |
| 6 | Deception disclosed | YES | Debrief explains AI label manipulation |
| 7 | Debrief provided | YES | Available at study completion and as DEBRIEF.txt |
| 8 | Data security | YES | Data stored locally on participant devices |
| 8 | Data security | YES | Data synced to Firebase Firestore with secure access rules |
Copy link

Copilot AI Mar 12, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The IRB checklist notes data is synced with “secure access rules”, but the repository does not include any Firestore security rules configuration (e.g., firestore.rules). Please either add the rules file / deployment instructions, or reword this as a requirement for the study operator to configure in Firebase Console.

Suggested change
| 8 | Data security | YES | Data synced to Firebase Firestore with secure access rules |
| 8 | Data security | YES | Data synced to Firebase Firestore; study operator must configure appropriate security rules in Firebase Console before deployment |

Copilot uses AI. Check for mistakes.
| 9 | No vulnerable populations targeted | YES | 18+ adults only |
| 10 | Aggregate reporting only | YES | No individual results published |
| 11 | Contact information provided | YES | Researcher contact in consent and debrief |
| 12 | No physical or psychological harm | YES | Viewing interface designs only |
| 13 | Data retention policy | N/A | Local CSV files; no server storage |
| 13 | Data retention policy | YES | Firebase cloud storage with configurable retention |
Copy link

Copilot AI Mar 12, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Firebase cloud storage with configurable retention is presented as already satisfied, but the repo doesn’t document/implement any retention configuration (e.g., TTL policy, deletion job, or documented manual process). Please clarify what mechanism enforces retention, or change the status/notes to reflect that this must be configured operationally.

Suggested change
| 13 | Data retention policy | YES | Firebase cloud storage with configurable retention |
| 13 | Data retention policy | OPERATIONAL CONFIG REQUIRED | Firebase cloud storage; retention to be configured operationally (e.g., TTL, deletion job, or documented manual process) |

Copilot uses AI. Check for mistakes.
| 14 | Compensation disclosed | N/A | No compensation offered |
| 15 | Conflicts of interest | NONE | Academic research only |

Expand All @@ -33,4 +33,4 @@
- [ ] Approval #: _______________

---
_Template version: 1.0 | 2026-02-27_
_Template version: 2.0 | 2026-03-12_
72 changes: 33 additions & 39 deletions docs/METHODS.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,58 +18,51 @@ Participants were recruited from [classroom / online panel]. Inclusion criteria:

A between-subjects experimental design with two conditions:

- **Control condition:** Participants viewed 8 pairs of UI mockups with neutral labels ("Option A" / "Option B") and selected their preferred design.
- **AI Label condition:** Participants viewed the same 8 pairs, but one option in each pair displayed a " AI Recommended" badge.
- **Control condition:** Participants viewed 6 pairs of UI mockups with neutral labels ("Option A" / "Option B") and selected their preferred design.
- **AI Label condition:** Participants viewed the same 6 pairs, but one option in each pair displayed a " AI Recommended" badge.

Assignment to conditions was randomized (50/50) using client-side JavaScript random number generation at the point of entry.
Copy link

Copilot AI Mar 12, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This section says participants are randomly assigned (50/50) via client-side JavaScript, but the current implementation sets condition from the URL (?condition=ai => ai_labeled, else control). Please update the Methods text to reflect URL-based assignment (or adjust the code to actually randomize).

Suggested change
Assignment to conditions was randomized (50/50) using client-side JavaScript random number generation at the point of entry.
Assignment to conditions was determined via the experiment URL query parameter (`?condition=control` or `?condition=ai`), which mapped participants to the control and AI label conditions, respectively.

Copilot uses AI. Check for mistakes.

## Stimuli

Eight pairs of high-fidelity UI mockups were created covering common interface patterns:
Six pairs of high-fidelity UI mockups were created covering common interface patterns in the context of Iqra University and Pakistan Higher Education Commission (HEC):

1. E-commerce product card (button color: blue vs. green)
2. Settings page (toggle alignment: left vs. right)
3. Analytics dashboard widget (chart type: bar vs. line)
4. Signup form (CTA copy: "Sign Up" vs. "Get Started")
5. Pricing table (highlighted tier: Basic vs. Pro)
6. Navigation sidebar (icon style: outlined vs. filled)
7. Notification banner (position: top vs. inline)
8. Search results (layout: list vs. grid)
1. **Information Density (Course Schedule)** - List view vs. Bento grid layout
2. **Data Visualization (HEC Attendance Warning)** - Circular gauge with 78% attendance vs. Linear progress bar
3. **Financial Overview (Fee Voucher)** - Card-based layout vs. Centered layout for semester fees
4. **Campus Event (Visual Dominance)** - Visual-dominant poster vs. Compact text-heavy layout
5. **Interaction (QEC Faculty Evaluation)** - Radio button scale vs. Interactive slider for rating
6. **Navigation Hierarchy (Digital Library)** - Floating search button vs. Header-integrated search

Each pair shared identical layout and functionality, differing only in a single design attribute. Pairs were rendered as CSS/HTML mockups within the experiment page. In the AI condition, one option per pair received a visually prominent " AI Recommended" badge. The assignment of which option received the badge was counterbalanced across pairs.
Each pair shared identical content and functionality, differing only in a single design attribute (layout pattern, visualization type, or interaction method). Pairs were rendered as inline CSS/HTML mockups within the experiment page. In the AI condition, one option per pair received a visually prominent " AI Recommended" badge. The assignment of which option (A or B) received the badge was predetermined based on hypothesized modern design preferences (e.g., Bento grid over list, circular gauge over bar chart).

## Procedure

1. Participants accessed the experiment via a URL that randomly redirected them to one of two conditions.
1. Participants accessed the experiment via a URL with condition parameter (`?condition=control` or `?condition=ai`).
2. A welcome screen explained the task and obtained informed consent.
3. Participants completed 8 trials presented in randomized order.
4. On each trial, two UI mockups appeared side-by-side (left/right placement randomized).
5. Participants clicked to select their preferred design.
6. After selection, they rated their confidence on a 5-point scale (1 = not at all confident, 5 = very confident).
7. Upon completion, participants saw a summary and could download their responses.
3. Participants rated their AI familiarity on a 5-point Likert scale (covariate: 1=Never used → 5=Daily user).
4. Participants completed 6 trials presented in randomized order.
5. On each trial, two UI mockups appeared side-by-side (left/right placement randomized).
Comment on lines +44 to +45
Copy link

Copilot AI Mar 12, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Methods states trials were presented in randomized order, but experiment.js advances sequentially through the TRIALS array (no shuffle). Please either update the document to describe a fixed trial order, or implement trial-order randomization and record the resulting order in the saved data.

Copilot uses AI. Check for mistakes.
6. Participants clicked to select their preferred design.
7. Reaction time was automatically captured using `performance.now()` for millisecond accuracy.
8. After all trials, participants provided an optional free-text justification explaining their selection strategy.
9. Upon completion, participants saw a confirmation screen with their anonymous Participant ID and data sync status.

## Measures

- **Primary DV:** Choice (A or B) — coded as whether the AI-preferred option was selected
- **Primary DV:** Choice (A or B) — coded as whether the AI-labeled option was selected (`chose_target_layout` boolean)
- **Secondary DVs:**
- Confidence rating (1–5 Likert scale)
- Reaction time (ms) — time from trial display to choice click
- **Between-subjects IV:** Condition (control vs. AI label)
- **Metadata:** Participant UUID, trial order, pair ID, timestamp

## Metadata

- Participant UUID
- Condition (control vs. AI label)
- AI familiarity covariate
- Trial sequence
- UI domain
- AI badge position
- User selection
- Choice (target layout)
- Reaction time (ms)
- Semantic justification
- Timestamp
- Reaction time (ms) — Time from trial display to choice click, measured via `performance.now()`
- Semantic justification — Free-text explanation of decision-making strategy (optional)
- **Between-subjects IV:** Condition (`control` vs. `ai_labeled`)
- **Covariate:** AI familiarity (1–5 Likert scale: Never used, Rarely, Occasionally, Frequently, Daily)
- **Metadata:**
- Participant UUID (anonymous identifier)
- Trial sequence (1-6, randomized order)
- UI domain (trial category name)
- AI badge position (which option had the badge: "A", "B", or "none" for control)
- User selection ("A" or "B")
Comment on lines +63 to +64
Copy link

Copilot AI Mar 12, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The listed metadata values for AI badge position and User selection are documented as "A"/"B", but the actual telemetry stores strings like Layout A/Layout B (and none for control). Please align the documented value format to the current payload so downstream analysis doesn't miscode these fields.

Suggested change
- AI badge position (which option had the badge: "A", "B", or "none" for control)
- User selection ("A" or "B")
- AI badge position (which option had the badge: "Layout A", "Layout B", or "none" for control)
- User selection ("Layout A" or "Layout B")

Copilot uses AI. Check for mistakes.
- Timestamp (Unix milliseconds)

## Ethics

Expand All @@ -79,7 +72,8 @@ Each pair shared identical layout and functionality, differing only in a single
- A debrief statement was provided upon completion explaining the true purpose of the study and the manipulation.
- Participants could withdraw at any time by closing their browser.
- The study involved minimal risk (viewing interface mockups and clicking preferences).
- Data was stored locally on participant devices (CSV download) and not transmitted to external servers.
- Data was synced to Firebase Firestore (`conformity_telemetry` collection) with fallback to localStorage for offline participants.
Copy link

Copilot AI Mar 12, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ethics section claims there is a localStorage fallback for offline participants, but the code currently does not implement any local persistence on Firebase failure (it only logs a TODO comment). Please remove/qualify this statement or add the fallback behavior described.

Suggested change
- Data was synced to Firebase Firestore (`conformity_telemetry` collection) with fallback to localStorage for offline participants.
- Data was synced to Firebase Firestore (`conformity_telemetry` collection); offline submissions made without a stable connection might not be recorded.

Copilot uses AI. Check for mistakes.
- Participants were informed they could request data withdrawal within 7 days using their Participant ID.

---
_Copy-paste this text into your Methods section. Update bracketed placeholders as needed._
_Last updated: 2026-03-12 | Copy-paste this text into your Methods section. Update bracketed placeholders as needed._
Loading
Loading