# Project export: Kurriculum

This document was generated by HackStack to give an AI agent context about a hackathon project. Sections are labeled with their provenance; content marked as truncated was cut to keep this document small.

## Project metadata

- Hackathon: Cal Hacks 10.0
- Tagline: OK! Kreate your Kurriculum!
- Devpost: https://devpost.com/software/kurriculum
- GitHub: https://github.com/Sofor-Devs/Kurriculum
- Team: 2 GitHub contributor(s) — Fozhan Babaeiyan (3 commits), Soroush Mirzaee (2 commits)

## Devpost submission (written by the team)

### Inspiration

The inspiration for "Kurriculum" stemmed from our experiences as K-12 educators. We found that creating comprehensive curricula and session plans for high school projects was a challenging and time-consuming task. To make this process more efficient and teacher-friendly, we decided to develop a web application that would generate customized curricula based on user input.

### What it does

"Kurriculum" is a web application that simplifies curriculum planning for educators. Users fill out a form with details such as the project description and the number of sessions per week. The application then leverages Together.ai's API and Convex's API to create a personalized curriculum and provides a list of relevant resources. This streamlines the curriculum planning process and saves educators valuable time.

### How we built it

We built "Kurriculum" by utilizing Together.ai's API and Convex's API to access and manage the necessary data for curriculum generation. We developed a user-friendly interface that allows educators to input their project details and preferences. The application uses these inputs to generate a curriculum, complete with session plans and resource recommendations.

### Challenges we ran into

During the development of "Kurriculum," we faced challenges in integrating and optimizing the use of Together.ai's and Convex's APIs. Ensuring that the generated curricula were truly tailored to the user's needs and aligning them with educational standards was also a complex task. We had to strike a balance between automation and personalization.

### Accomplishments we're proud of

We're proud of creating a tool that directly addresses a common pain point for educators. "Kurriculum" streamlines the curriculum planning process, making it more efficient and accessible. We're also proud of successfully integrating two powerful APIs to enhance the application's capabilities.

### What we learned

Throughout this project, we learned the importance of API integration and how it can significantly enhance the functionality of a web application. We also gained a deeper understanding of the intricacies of curriculum planning and the value of automating and simplifying this process for educators.

### What's next

The next steps for "Kurriculum" involve refining and expanding its features. We plan to continually improve the AI algorithms to generate even more customized and high-quality curricula. Additionally, we aim to incorporate feedback from educators to make the tool even more user-centric. Our long-term vision is to establish "Kurriculum" as an essential resource for educators, not only for high school projects but across various grade levels and subjects.

## README (from the GitHub repository)

A Web application that will generate a curriculum when given prompts using AI API, written with HTML, CSS, JavaScript and React.


## Detected evidence (automated analysis)

Indexed codebase: 27 recognized source files, 42 KB.
- CSS (language) — detected in the code
- HTML (language) — detected in the code
- JavaScript (language) — detected in the code
- React (technology) — detected in the code
- Tailwind CSS (technology) — detected in the code
- TypeScript (language) — detected in the code

## Codebase structure (from repository index)

### Files (35 of 35)

```
_gitignore
.eslintrc.cjs
.gitignore
app.js
components.json
convex/_generated/api.d.ts
convex/_generated/api.js
convex/_generated/dataModel.d.ts
convex/_generated/server.d.ts
convex/_generated/server.js
convex/_schema.ts
convex/myFunctions.ts
convex/README.md
convex/tsconfig.json
index.html
package.json
postcss.config.js
README.md
src/App.tsx
src/components/typography/code.tsx
src/components/typography/link.tsx
src/components/ui/button.tsx
src/components/ui/checkbox.tsx
src/components/ui/input.tsx
src/components/ui/label.tsx
src/index.css
src/lib/utils.tsx
src/main.tsx
src/models/CurriculumGenerator.tsx
src/vite-env.d.ts
style.css
tailwind.config.js
tsconfig.json
tsconfig.node.json
vite.config.ts
```

### Dependencies

- package.json: @hookform/resolvers@^3.3.2, @radix-ui/react-checkbox@^1.0.4, @radix-ui/react-icons@^1.3.0, @radix-ui/react-label@^2.0.2, @radix-ui/react-slot@^1.0.2, @types/node@^20.7.0, @types/react@^18.2.21, @types/react-dom@^18.2.7, @typescript-eslint/eslint-plugin@^6.7.0, @typescript-eslint/parser@^6.7.0, @vitejs/plugin-react@^4.0.4, autoprefixer@^10.4.16, axios@^1.6.0, class-variance-authority@^0.7.0, clsx@^2.0.0, cmdk@^0.2.0, convex@^1.4.1, date-fns@^2.30.0, eslint@^8.49.0, eslint-plugin-react-hooks@^4.6.0, eslint-plugin-react-refresh@^0.4.3, npm-run-all@^4.1.5, postcss@^8.4.30, react@^18.2.0, react-day-picker@^8.9.1, react-dom@^18.2.0, react-hook-form@^7.47.0, tailwind-merge@^1.14.0, tailwindcss@^3.3.3, tailwindcss-animate@^1.0.7, typescript@^5.2.2, vite@^4.4.9, zod@^3.22.4

### Recent commits (newest first)

- Merge branch 'main' of https://github.com/Sofor-Devs/Kurriculum
- Backend Initial Commit
- button and theme
- Update README.md
- Add files via upload
- Merge pull request #2 from get-convex/bonus-exercises
- Reformat
- Reformat
- Add bonus challenge exercises
- Relax eslint settings, reformat
- Call out intentional breakage & minor fixes
- Fix footer
- upgrade convex
- eslint
- Remove unused ui components/deps
- Install Node directly (not NVM)
- Mention intentional breakage earlier to avoid confusion
- Upgrade shadcn
- fix git URLs
- link to Convex

## Key source files (fetched from GitHub, selected and truncated for size)

### package.json

```
{
  "name": "convex-hack-pack",
  "private": true,
  "version": "0.0.0",
  "type": "module",
  "scripts": {
    "dev": "npm-run-all dev:init --parallel dev:frontend dev:backend",
    "dev:frontend": "vite --open",
    "dev:backend": "convex dev",
    "dev:init": "convex dev --until-success && convex dashboard",
    "build": "tsc && vite build",
    "lint": "eslint . --ext ts,tsx ",
    "preview": "vite preview"
  },
  "dependencies": {
    "@hookform/resolvers": "^3.3.2",
    "@radix-ui/react-checkbox": "^1.0.4",
    "@radix-ui/react-icons": "^1.3.0",
    "@radix-ui/react-label": "^2.0.2",
    "@radix-ui/react-slot": "^1.0.2",
    "axios": "^1.6.0",
    "class-variance-authority": "^0.7.0",
    "clsx": "^2.0.0",
    "cmdk": "^0.2.0",
    "convex": "^1.4.1",
    "date-fns": "^2.30.0",
    "react": "^18.2.0",
    "react-day-picker": "^8.9.1",
    "react-dom": "^18.2.0",
    "react-hook-form": "^7.47.0",
    "tailwind-merge": "^1.14.0",
    "tailwindcss-animate": "^1.0.7",
    "zod": "^3.22.4"
  },
  "devDependencies": {
    "@types/node": "^20.7.0",
    "@types/react": "^18.2.21",
    "@types/react-dom": "^18.2.7",
    "@typescript-eslint/eslint-plugin": "^6.7.0",
    "@typescript-eslint/parser": "^6.7.0",
    "@vitejs/plugin-react": "^4.0.4",
    "autoprefixer": "^10.4.16",
    "eslint": "^8.49.0",
    "eslint-plugin-react-hooks": "^4.6.0",
    "eslint-plugin-react-refresh": "^0.4.3",
    "npm-run-all": "^4.1.5",
    "postcss": "^8.4.30",
    "tailwindcss": "^3.3.3",
    "typescript": "^5.2.2",
    "vite": "^4.4.9"
  }
}

```

### app.js

```javascript
//Select DOM
const todoInput = document.querySelector(".todo-input");
const todoButton = document.querySelector(".todo-button");
const todoList = document.querySelector(".todo-list");
const filterOption = document.querySelector(".filter-todo");

//Event Listeners
document.addEventListener("DOMContentLoaded", getTodos);
todoButton.addEventListener("click", addTodo);
todoList.addEventListener("click", deleteTodo);
filterOption.addEventListener("click", filterTodo);

//Functions

function addTodo(e) {
  //Prevent natural behaviour
  e.preventDefault();
  //Create todo div
  const todoDiv = document.createElement("div");
  todoDiv.classList.add("todo");
  //Create list
  const newTodo = document.createElement("li");
  newTodo.innerText = todoInput.value;
  //Save to local - do this last
  //Save to local
  saveLocalTodos(todoInput.value);
  //
  newTodo.classList.add("todo-item");
  todoDiv.appendChild(newTodo);
  todoInput.value = "";
  //Create Completed Button
  const completedButton = document.createElement("button");
  completedButton.innerHTML = `<i class="fas fa-check"></i>`;
  completedButton.classList.add("complete-btn");
  todoDiv.appendChild(completedButton);
  //Create trash button
  const trashButton = document.createElement("button");
  trashButton.innerHTML = `<i class="fas fa-trash"></i>`;
  trashButton.classList.add("trash-btn");
  todoDiv.appendChild(trashButton);
  //attach final Todo
  todoList.appendChild(todoDiv);
}

function deleteTodo(e) {
  const item = e.target;

  if (item.classList[0] === "trash-btn") {
    // e.target.parentElement.remove();
    const todo = item.parentElement;
    todo.classList.add("fall");
    //at the end
    removeLocalTodos(todo);
    todo.addEventListener("transitionend", e => {
      todo.remove();
    });
  }
  if (item.classList[0] === "complete-btn") {
    const todo = item.parentElement;
    todo.classList.toggle("completed");
    console.log(todo);
  }
}

function filterTodo(e) {
  const todos = todoList.childNodes;
  todos.forEach(function(todo) {
    switch (e.target.value) {
      case "all":
        todo.style.display = "flex";
        break;
      case "completed":
        if (todo.classList.contains("completed")) {
          todo.style.display = "flex";
        } else {
          todo.style.display = "none";
        }
        break;
      case "uncompleted":
        if (!todo.classList.contains("completed")) {
          todo.style.display = "flex";
        } else {
          todo.style.display = "none";
        }
    }
  });
}

function saveLocalTodos(todo) {
  let todos;
  if (localStorage.getItem("todos") === null) {
    todos = [];
  } else {
    todos = JSON.parse(localStorage.getItem("todos"));
  }
  todos.push(todo);
  localStorage.setItem("todos", JSON.stringify(todos));
}
function removeLocalTodos(todo) {
  let todos;
  if (localStorage.getItem("todos") === null) {
    todos = [];
  } else {
    todos = JSON.parse(localStorage.getItem("todos"));
  }
  const todoIndex = todo.children[0].innerText;
  todos.splice(todos.indexOf(todoIndex), 1);
  localStorage.setItem("todos", JSON.stringify(todos));
}

function getTodos() {
  let todos;
  if (localStorage.getItem("todos") === null) {
    todos = [];
  } else {
    todos = JSON.parse(localStorage.getItem("todos"));
  }
  todos.forEach(function(todo) {
    //Create todo div
    const todoDiv = document.createElement("div");
    todoDiv.classList.add("todo");
    //Create list
    const newTodo = document.createElement("li");
    newTodo.innerText = todo;
    newTodo.classList.add("todo-item");
    todoDiv.appendChild(newTodo);
    todoInput.value = "";
    //Create Completed Button
    const completedButton = document.createElement("button");
    completedButton.innerHTML = `<i class="fas fa-check"></i>`;
    completedButton.classList.add("complete-btn");
    todoDiv.appendChild(completedButton);
    //Create trash button
    const trashButton = document.createElement("button");
    trashButton.innerHTML = `<i class="fas fa-trash"></i>`;
    trashButton.classList.add("trash-btn");
    todoDiv.appendChild(trashButton);
    //attach final Todo
    todoList.appendChild(todoDiv);
  });
}

```

### src/main.tsx

```typescript
import { ConvexProvider, ConvexReactClient } from "convex/react";
import React from "react";
import ReactDOM from "react-dom/client";
import App from "./App";
import "./index.css";

const convex = new ConvexReactClient(import.meta.env.VITE_CONVEX_URL as string);

ReactDOM.createRoot(document.getElementById("root")!).render(
  <React.StrictMode>
    <ConvexProvider client={convex}>
      <App />
    </ConvexProvider>
  </React.StrictMode>
);

```

### src/App.tsx

```typescript
import { useAction, useMutation, useQuery } from "convex/react"
import { api } from "../convex/_generated/api"
import { useState } from "react"
import { Button } from "@/components/ui/button"
import { Input } from "@/components/ui/input"
import { Checkbox } from "@/components/ui/checkbox"
import { Label } from "@/components/ui/label"

function App() {
  const [newIdea, setNewIdea] = useState("")
  const [includeRandom, setIncludeRandom] = useState(true)


  const ideas = useQuery(api.myFunctions.listIdeas)
  const saveCurriculum = useMutation(api.myFunctions.saveCurriculum)
  const generateIdea = useAction(api.myFunctions.fetchRandomIdea)

  return (
    <>
      <main className="container max-w-2xl flex flex-col gap-8">
        <h1 className="text-3xl font-extrabold mt-8 text-center">
          Get hacking with Convex
        </h1>

        <h2 className="text-center">Let's brainstorm apps to build!</h2>

        <div className="flex gap-2">
          <Input
            type="text"
            value={newIdea}
            onChange={(event) => setNewIdea(event.target.value)}
            placeholder="Type your app idea here"
          />
          <Button
            disabled={!newIdea}
            title={
              newIdea
                ? "Save your idea to the database"
                : "You must enter an idea first"
            }
            onClick={async () => {
              await saveCurriculum({ description: newIdea.trim()})
              setNewIdea("")
            }}
            className="min-w-fit"
          >
            Save idea
          </Button>
        </div>

        <div className="flex justify-between items-center">
          <Button
            onClick={async () => {
              await generateIdea()
            }}
            title="Save a randomly generated app idea to the database"
          >
            Generate a random app idea
          </Button>

          <div
            className="flex gap-2"
            title="Uh oh, this checkbox doesn't work! Until we fix it ;)"
          >
            <Checkbox
              id="show-random"
              checked={includeRandom}
              onCheckedChange={() => setIncludeRandom(!includeRandom)}
            />
            <Label htmlFor="show-random">Include random ideas</Label>
          </div>
        </div>

        <ul>
          {ideas?.map((document, i) => (
            <li key={i}>
              {document.random ? "🤖 " : "💡 "}
              {document.idea}
            </li>
          ))}
        </ul>
      </main>
      <footer className="text-center text-xs mb-5 mt-10 w-full">
        <p>
          Built with <a href="https://convex.dev">Convex</a>,{" "}
          <a href="https://www.typescriptlang.org">TypeScript</a>,{" "}
          <a href="https://react.dev">React</a>, and{" "}
          <a href="https://vitejs.dev">Vite</a>
        </p>
        <p>
          Random app ideas thanks to{" "}
          <a target="_blank" href="https://appideagenerator.com/">
            appideagenerator.com
          </a>
        </p>
      </footer>
    </>
  )
}

export default App

```

### convex/_generated/server.js

```javascript
/* eslint-disable */
/**
 * Generated utilities for implementing server-side Convex query and mutation functions.
 *
 * THIS CODE IS AUTOMATICALLY GENERATED.
 *
 * Generated by convex@1.4.1.
 * To regenerate, run `npx convex dev`.
 * @module
 */

import {
  actionGeneric,
  httpActionGeneric,
  queryGeneric,
  mutationGeneric,
  internalActionGeneric,
  internalMutationGeneric,
  internalQueryGeneric,
} from "convex/server";

/**
 * Define a query in this Convex app's public API.
 *
 * This function will be allowed to read your Convex database and will be accessible from the client.
 *
 * @param func - The query function. It receives a {@link QueryCtx} as its first argument.
 * @returns The wrapped query. Include this as an `export` to name it and make it accessible.
 */
export const query = queryGeneric;

/**
 * Define a query that is only accessible from other Convex functions (but not from the client).
 *
 * This function will be allowed to read from your Convex database. It will not be accessible from the client.
 *
 * @param func - The query function. It receives a {@link QueryCtx} as its first argument.
 * @returns The wrapped query. Include this as an `export` to name it and make it accessible.
 */
export const internalQuery = internalQueryGeneric;

/**
 * Define a mutation in this Convex app's public API.
 *
 * This function will be allowed to modify your Convex database and will be accessible from the client.
 *
 * @param func - The mutation function. It receives a {@link MutationCtx} as its first argument.
 * @returns The wrapped mutation. Include this as an `export` to name it and make it accessible.
 */
export const mutation = mutationGeneric;

/**
 * Define a mutation that is only accessible from other Convex functions (but not from the client).
 *
 * This function will be allowed to modify your Convex database. It will not be accessible from the client.
 *
 * @param func - The mutation function. It receives a {@link MutationCtx} as its first argument.
 * @returns The wrapped mutation. Include this as an `export` to name it and make it accessible.
 */
export const internalMutation = internalMutationGeneric;

/**
 * Define an action in this Convex app's public API.
 *
 * An action is a function which can execute any JavaScript code, including non-deterministic
 * code and code with side-effects, like calling third-party services.
 * They can be run in Convex's JavaScript environment or in Node.js using the "use node" directive.
 * They can interact with the database indirectly by calling queries and mutations using the {@link ActionCtx}.
 *
 * @param func - The action. It receives an {@link ActionCtx} as its first argument.
 * @returns The wrapped action. Include this as an `export` to name it and make it accessible.
 */
export const action = actionGeneric;

/**
 * Define an action that is only accessible from other Convex functions (but not from the client).
 *
 * @param func - The function. It receives an {@link ActionCtx} as its first argument.
 * @returns The wrapped function. Include this as an `export` to name it and make it accessible.
 */
export const internalAction = internalActionGeneric;

/**
 * Define a Convex HTTP action.
 *
 * @param func - The function. It receives an {@link ActionCtx} as its first argument, and a `Request` object
 * as its second.
 * @returns The wrapped endpoint function. Route a URL path to this function in `convex/http.js`.
 */
export const httpAction = httpActionGeneric;

```

### postcss.config.js

```javascript
export default {
  plugins: {
    tailwindcss: {},
    autoprefixer: {},
  },
}

```

### vite.config.ts

```typescript
import path from "path";
import react from "@vitejs/plugin-react";
import { defineConfig } from "vite";

// https://vitejs.dev/config/
export default defineConfig({
  plugins: [react()],
  resolve: {
    alias: {
      "@": path.resolve(__dirname, "./src"),
    },
  },
});

```

### index.html

```html
<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <link rel="icon" type="image/svg+xml" href="/vite.svg" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Convex Hack Pack</title>
  </head>
  <body>
    <div id="root"></div>
    <script type="module" src="/src/main.tsx"></script>
  </body>
</html>

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Kurriculum</title>
    <link
      href="https://fonts.googleapis.com/css?family=Poppins&display=swap"
      rel="stylesheet"
    />
    <link
      rel="stylesheet"
      href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.12.1/css/all.min.css"
      integrity="sha256-mmgLkCYLUQbXn0B1SRqzHar6dCnv9oZFPEC1g1cwlkk="
      crossorigin="anonymous"
    />
    <link rel="stylesheet" href="./style.css" />
  </head>
  <body>
    <header>
      <h1>Kreate with Kurriculum</h1>
    </header>
    <form>
      <!-- <input type="text" class="todo-input" /> -->
      <button class="todo-button" type="submit">
        <i class="fas fa-plus-square"></i>
      </button>
      <!-- <div class="select">
        <select name="todos" class="filter-todo">
          <option value="all">All</option>
          <option value="completed">Completed</option>
          <option value="uncompleted">Uncompleted</option>
        </select>
      </div> -->
    </form>
    <div class="todo-container">
      <ul class="todo-list"></ul>
    </div>

    <script src="./app.js"></script>
  </body>
</html>

```

### tailwind.config.js

```javascript
/** @type {import('tailwindcss').Config} */
module.exports = {
  darkMode: ["class"],
  content: ["./index.html", "./src/**/*.{js,ts,jsx,tsx}"],
  theme: {
    container: {
      center: true,
      padding: "2rem",
      screens: {
        "2xl": "1400px",
      },
    },
    extend: {
      colors: {
        border: "hsl(var(--border))",
        input: "hsl(var(--input))",
        ring: "hsl(var(--ring))",
        background: "hsl(var(--background))",
        foreground: "hsl(var(--foreground))",
        primary: {
          DEFAULT: "hsl(var(--primary))",
          foreground: "hsl(var(--primary-foreground))",
        },
        secondary: {
          DEFAULT: "hsl(var(--secondary))",
          foreground: "hsl(var(--secondary-foreground))",
        },
        destructive: {
          DEFAULT: "hsl(var(--destructive))",
          foreground: "hsl(var(--destructive-foreground))",
        },
        muted: {
          DEFAULT: "hsl(var(--muted))",
          foreground: "hsl(var(--muted-foreground))",
        },
        accent: {
          DEFAULT: "hsl(var(--accent))",
          foreground: "hsl(var(--accent-foreground))",
        },
        popover: {
          DEFAULT: "hsl(var(--popover))",
          foreground: "hsl(var(--popover-foreground))",
        },
        card: {
          DEFAULT: "hsl(var(--card))",
          foreground: "hsl(var(--card-foreground))",
        },
      },
      borderRadius: {
        lg: "var(--radius)",
        md: "calc(var(--radius) - 2px)",
        sm: "calc(var(--radius) - 4px)",
      },
      keyframes: {
        "accordion-down": {
          from: { height: 0 },
          to: { height: "var(--radix-accordion-content-height)" },
        },
        "accordion-up": {
          from: { height: "var(--radix-accordion-content-height)" },
          to: { height: 0 },
        },
      },
      animation: {
        "accordion-down": "accordion-down 0.2s ease-out",
        "accordion-up": "accordion-up 0.2s ease-out",
      },
    },
  },
  plugins: [require("tailwindcss-animate")],
};

```

### style.css

```css
* {
  margin: 0;
  padding: 0;
  box-sizing: border-box;
/* CSS HSL */
/* --jet: hsla(330, 2%, 18%, 1);
--aquamarine: hsla(152, 100%, 76%, 1);
--myrtle-green: hsla(180, 47%, 31%, 1);
--platinum: hsla(0, 0%, 90%, 1);
--timberwolf: hsla(0, 2%, 84%, 1); */
}
body {
  background-image: linear-gradient(120deg,hsla(180, 47%, 31%, 1) 0%, hsla(0, 2%, 84%, 1) 100%);
  /* background-image: radial-gradient(120deg,hsla(180, 47%, 31%, 1) 0%, hsla(0, 0%, 90%, 1) 100%); */
  color: hsla(0, 0%, 90%, 1);
  font-family: "Poppins", sans-serif;
  min-height: 100vh;
}
header {
  font-size: 2rem;
}

header,
form {
  min-height: 20vh;
  display: flex;
  justify-content: center;
  align-items: center;
}
form input,
form button {
  padding: 0.5rem;
  font-size: 2rem;
  border: none;
  background: hsla(0, 0%, 90%, 1);
}
form button {
  color:hsla(180, 47%, 31%, 1);
  background:hsla(0, 0%, 90%, 1);
  border-radius: 22%;
  cursor: pointer;
  transition: all 0.3s ease;
}
form button:hover {
  border-radius: 42%;
  background: hsla(152, 100%, 76%, 1);
  color: hsla(0, 0%, 90%, 1);
}

.todo-container {
  height: 20px;
  display: flex;
  justify-content: center;
  align-items: center;
}

.todo-list {
  min-width: 30%;
  list-style: none;
}

.todo {
  margin: 0.5rem;
  background:hsla(0, 0%, 90%, 1);
  font-size: 1.5rem;
  color:hsla(330, 2%, 18%, 1);
  display: flex;
  justify-content: space-between;
  align-items: center;
  transition: all 1s ease;
}
.filter-todo {
  padding: 1rem;
}
.todo li {
  flex: 1;
}

.trash-btn,
.complete-btn {
  background: hsla(180, 47%, 31%, 1);
  color: hsla(0, 0%, 90%, 1);
  border: none;
  padding: 1rem;
  cursor: pointer;
  font-size: 1rem;
}
.complete-btn {
  background: rgb(11, 212, 162);
}
.todo-item {
  padding: 0rem 0.5rem;
}

.fa-trash,
.fa-check {
  pointer-events: none;
}

.fall {
  transform: translateY(10rem) rotateZ(20deg);
  opacity: 0;
}

.completed {
  text-decoration: line-through;
  opacity: 0.5;
}

/*CUSTOM SELECTOR */
select {
  -webkit-appearance: none;
  -moz-appearance: none;
  -ms-appearance: none;
  appearance: none;
  outline: 0;
  box-shadow: none;
  border: 0 !important;
  background-image: none;
}

/* Custom Select */
.select {
  margin: 1rem;
  position: relative;
  overflow: hidden;
}
select {
  color: hsla(180, 47%, 31%, 1);
  font-family: "Poppins", sans-serif;
  cursor: pointer;
  width: 12rem;
}
/* Arrow */
.select::after {
  content: "\25BC";
  position: absolute;
  top: 0;
  right: 0;
  padding: 1rem;
  background:hsla(180, 47%, 31%, 1);
  cursor: pointer;
  pointer-events: none;
}
/* Transition */
/*
.select:hover::after {
  transform: scale(1.5);
}
*/

```

[16 more indexed source files omitted to keep this export small. The full file list is in the Codebase structure section above.]