Function bodies 373 total
action_go_pull method · python · L120-L124 (5 LOC)garmin_extract/screens/main_menu.py
def action_go_pull(self) -> None:
self._cursor = 1
from garmin_extract.screens.data_pull import DataPullScreen
self.app.push_screen(DataPullScreen())action_go_automation method · python · L126-L130 (5 LOC)garmin_extract/screens/main_menu.py
def action_go_automation(self) -> None:
self._cursor = 2
from garmin_extract.screens.automation import AutomationScreen
self.app.push_screen(AutomationScreen())_MfaModal class · python · L25-L78 (54 LOC)garmin_extract/screens/pull_progress.py
class _MfaModal(ModalScreen[None]):
"""Pop-up dialog to capture an MFA code and write it to .mfa_code."""
BINDINGS = [Binding("escape", "dismiss", "Cancel", show=True)]
CSS = """
_MfaModal {
align: center middle;
}
#mfa-box {
width: 52;
height: auto;
border: round $warning;
padding: 1 2;
}
#mfa-title {
text-style: bold;
color: $warning;
margin-bottom: 1;
}
#mfa-hint {
color: $text-muted;
margin-bottom: 1;
}
#mfa-error {
color: $error;
height: 1;
}
"""
def compose(self) -> ComposeResult:
with Static(id="mfa-box"):
yield Static("MFA Code Required", id="mfa-title")
yield Static(
"Check your email for a 6-digit code and enter it below.",
id="mfa-hint",
)
yield Input(placeholder="000000", id="mfa-input", max_length=6)
yield Static("compose method · python · L59-L67 (9 LOC)garmin_extract/screens/pull_progress.py
def compose(self) -> ComposeResult:
with Static(id="mfa-box"):
yield Static("MFA Code Required", id="mfa-title")
yield Static(
"Check your email for a 6-digit code and enter it below.",
id="mfa-hint",
)
yield Input(placeholder="000000", id="mfa-input", max_length=6)
yield Static("", id="mfa-error")on_input_submitted method · python · L72-L78 (7 LOC)garmin_extract/screens/pull_progress.py
def on_input_submitted(self, event: Input.Submitted) -> None:
code = event.value.strip()
if not code:
self.query_one("#mfa-error", Static).update("Please enter the 6-digit code.")
return
MFA_FILE.write_text(code + "\n")
self.dismiss()_RuntimeCredsModal class · python · L84-L144 (61 LOC)garmin_extract/screens/pull_progress.py
class _RuntimeCredsModal(ModalScreen[tuple[str, str] | None]):
"""Prompt for email + password when no credentials are saved anywhere."""
BINDINGS = [Binding("escape", "dismiss", "Cancel", show=True)]
CSS = """
_RuntimeCredsModal {
align: center middle;
}
#rc-box {
width: 58;
height: auto;
border: round $primary;
padding: 1 2;
}
#rc-title {
text-style: bold;
margin-bottom: 1;
}
#rc-hint {
color: $text-muted;
margin-bottom: 1;
}
#rc-error {
color: $error;
height: 1;
}
"""
def compose(self) -> ComposeResult:
with Static(id="rc-box"):
yield Static("Enter Garmin Connect Credentials", id="rc-title")
yield Static(
"No saved credentials found. These will not be stored.",
id="rc-hint",
)
yield Input(placeholder="Email", id="rc-email")
yield Incompose method · python · L117-L126 (10 LOC)garmin_extract/screens/pull_progress.py
def compose(self) -> ComposeResult:
with Static(id="rc-box"):
yield Static("Enter Garmin Connect Credentials", id="rc-title")
yield Static(
"No saved credentials found. These will not be stored.",
id="rc-hint",
)
yield Input(placeholder="Email", id="rc-email")
yield Input(placeholder="Password", password=True, id="rc-password")
yield Static("", id="rc-error")Methodology: Repobility · https://repobility.com/research/state-of-ai-code-2026/
on_input_submitted method · python · L131-L144 (14 LOC)garmin_extract/screens/pull_progress.py
def on_input_submitted(self, event: Input.Submitted) -> None:
if event.input.id == "rc-email":
self.query_one("#rc-password", Input).focus()
return
email = self.query_one("#rc-email", Input).value.strip()
password = self.query_one("#rc-password", Input).value.strip()
if not email:
self.query_one("#rc-error", Static).update("Email is required.")
self.query_one("#rc-email", Input).focus()
return
if not password:
self.query_one("#rc-error", Static).update("Password is required.")
return
self.dismiss((email, password))_DayState class · python · L151-L156 (6 LOC)garmin_extract/screens/pull_progress.py
class _DayState:
date_str: str
total: int = 0
done: int = 0
failed: int = 0
status: str = "pending" # pending | active | done | skipped__init__ method · python · L226-L264 (39 LOC)garmin_extract/screens/pull_progress.py
def __init__(
self,
start_date: str,
days: int,
label: str,
no_skip: bool = False,
rebuild_only: bool = False,
zip_path: str = "",
) -> None:
super().__init__()
self._start_date = start_date
self._days = days
self._label = label
self._no_skip = no_skip
self._rebuild_only = rebuild_only
self._zip_path = zip_path
self._done = False
self._mfa_shown = False
self._email = ""
self._password = ""
self._proc: subprocess.Popen | None = None
# Determine display mode
if days > 1:
self._mode = "day"
self._day_states: list[_DayState] = self._init_day_states()
self._current_day_index: int = -1
self._metrics_per_day: int = 0
elif days == 1:
self._mode = "metric"
self._live_metrics: list[tuple[str, str]] = [] # (name, "done"|"fail")
secompose method · python · L268-L283 (16 LOC)garmin_extract/screens/pull_progress.py
def compose(self) -> ComposeResult:
yield Header(show_clock=True)
with Horizontal(id="progress-layout"):
yield RichLog(id="log-panel", highlight=True, markup=True, wrap=True)
with Vertical(id="metric-panel"):
yield Static(self._label, id="metric-header")
yield Static("", id="metric-subheader")
yield Static(self._initial_panel_body(), id="metric-list")
with Vertical(id="status-bar"):
yield ProgressBar(
total=self._overall_total,
id="progress-bar",
show_eta=False,
)
yield Static("Starting...", id="status-label")
yield Footer()on_mount method · python · L285-L299 (15 LOC)garmin_extract/screens/pull_progress.py
def on_mount(self) -> None:
# Rebuild/import don't need Garmin credentials
if self._rebuild_only or self._zip_path:
self._start_pull()
return
from garmin_extract._credentials import load_credentials
email, password = load_credentials()
if password:
self._email = email
self._password = password
self._start_pull()
else:
self.app.push_screen(_RuntimeCredsModal(), self._on_runtime_creds)_on_runtime_creds method · python · L301-L307 (7 LOC)garmin_extract/screens/pull_progress.py
def _on_runtime_creds(self, creds: tuple[str, str] | None) -> None:
if creds is None:
# User cancelled — go back
self.app.pop_screen()
return
self._email, self._password = creds
self._start_pull()_start_pull method · python · L309-L311 (3 LOC)garmin_extract/screens/pull_progress.py
def _start_pull(self) -> None:
cmd = self._build_cmd()
self.run_worker(lambda: self._do_pull(cmd), thread=True, name="puller")_initial_panel_body method · python · L315-L320 (6 LOC)garmin_extract/screens/pull_progress.py
def _initial_panel_body(self) -> str:
if self._mode == "day":
return self._render_day_list()
if self._mode == "metric":
return "[dim]Waiting for first metric...[/]"
return "[dim]Starting...[/]"Open data scored by Repobility · https://repobility.com
_build_cmd method · python · L324-L346 (23 LOC)garmin_extract/screens/pull_progress.py
def _build_cmd(self) -> list[str]:
if self._rebuild_only:
return [sys.executable, "-u", str(ROOT / "reports" / "build_garmin_csvs.py")]
if self._zip_path:
return [
sys.executable,
"-u",
str(ROOT / "pullers" / "garmin_import_export.py"),
"--zip",
self._zip_path,
]
cmd = [
sys.executable,
"-u",
str(ROOT / "pullers" / "garmin.py"),
"--date",
self._start_date,
"--days",
str(self._days),
]
if self._no_skip:
cmd.append("--no-skip")
return cmd_init_day_states method · python · L350-L358 (9 LOC)garmin_extract/screens/pull_progress.py
def _init_day_states(self) -> list[_DayState]:
states: list[_DayState] = []
try:
start = date.fromisoformat(self._start_date)
for i in range(self._days):
states.append(_DayState((start + timedelta(days=i)).isoformat()))
except ValueError:
pass
return states_do_pull method · python · L362-L391 (30 LOC)garmin_extract/screens/pull_progress.py
def _do_pull(self, cmd: list[str]) -> None:
# Build subprocess env — inject credentials so keyring/runtime creds
# reach garmin.py even though it calls load_dotenv() internally.
env = os.environ.copy()
if self._email:
env["GARMIN_EMAIL"] = self._email
if self._password:
env["GARMIN_PASSWORD"] = self._password
try:
proc = subprocess.Popen(
cmd,
stdout=subprocess.PIPE,
stderr=subprocess.STDOUT,
stdin=subprocess.DEVNULL,
text=True,
cwd=str(ROOT),
env=env,
)
self._proc = proc
assert proc.stdout is not None
for raw_line in iter(proc.stdout.readline, ""):
line = raw_line.rstrip("\n")
self.app.call_from_thread(self._on_line, line)
proc.wait()
self._proc = None
self.app.call_from_th_on_line method · python · L395-L417 (23 LOC)garmin_extract/screens/pull_progress.py
def _on_line(self, line: str) -> None:
self.query_one("#log-panel", RichLog).write(line)
stripped = line.strip()
# ── "[2025-04-06] Pulling N metrics..." ──
if stripped.startswith("[") and "] Pulling " in stripped and "metrics" in stripped:
self._handle_day_start(stripped)
return
# ── "[2025-04-06] Already pulled — skipping" ──
if "Already pulled" in stripped and "skipping" in stripped:
self._handle_day_skipped(stripped)
return
# ── " ✓/✗ metric_name" ──
if stripped.startswith("✓") or stripped.startswith("✗"):
self._handle_metric_line(stripped)
return
# ── file-based MFA prompt ──
if "Run: echo YOUR_CODE" in stripped and not self._mfa_shown:
self._mfa_shown = True
self.app.push_screen(_MfaModal())_handle_day_start method · python · L419-L459 (41 LOC)garmin_extract/screens/pull_progress.py
def _handle_day_start(self, stripped: str) -> None:
try:
date_str = stripped[1 : stripped.index("]")]
# Parse metric count from "Pulling N metrics..."
parts = stripped.split()
count_idx = next((i for i, p in enumerate(parts) if p == "Pulling"), -1)
n_metrics = int(parts[count_idx + 1]) if count_idx >= 0 else 0
except (ValueError, IndexError):
return
if self._mode == "day":
# Find matching day state
idx = next(
(i for i, s in enumerate(self._day_states) if s.date_str == date_str),
-1,
)
if idx == -1:
self._day_states.append(_DayState(date_str))
idx = len(self._day_states) - 1
self._current_day_index = idx
self._day_states[idx].status = "active"
self._day_states[idx].total = n_metrics
if self._metrics_per_day == 0 and n_metrics > _handle_day_skipped method · python · L461-L479 (19 LOC)garmin_extract/screens/pull_progress.py
def _handle_day_skipped(self, stripped: str) -> None:
try:
date_str = stripped[1 : stripped.index("]")]
except ValueError:
return
if self._mode == "day":
idx = next(
(i for i, s in enumerate(self._day_states) if s.date_str == date_str),
-1,
)
if idx >= 0:
self._day_states[idx].status = "skipped"
# Advance progress by one day's worth of metrics (or 1 if unknown)
advance = self._metrics_per_day if self._metrics_per_day else 1
self._overall_done += advance
self.query_one("#progress-bar", ProgressBar).advance(advance)
self._refresh_day_list()
self._set_status(f"Skipped {date_str} (already pulled)")_handle_metric_line method · python · L481-L518 (38 LOC)garmin_extract/screens/pull_progress.py
def _handle_metric_line(self, stripped: str) -> None:
parts = stripped.split()
if not parts:
return
metric_name = parts[-1]
is_ok = stripped.startswith("✓")
state = "done" if is_ok else "fail"
if self._mode == "metric":
self._live_metrics.append((metric_name, state))
self._day_done += 1
self.query_one("#progress-bar", ProgressBar).advance(1)
self._refresh_metric_list()
self._set_status(f"{self._day_done} / {self._day_total or '?'} metrics")
elif self._mode == "day" and self._current_day_index >= 0:
ds = self._day_states[self._current_day_index]
if is_ok:
ds.done += 1
else:
ds.failed += 1
# Only advance progress up to the announced total — per-activity
# sub-requests emit extra ✓/✗ lines that exceed the day's metric count.
tally = ds.done + ds.failed
_on_done method · python · L522-L543 (22 LOC)garmin_extract/screens/pull_progress.py
def _on_done(self, returncode: int) -> None:
self._done = True
log = self.query_one("#log-panel", RichLog)
# For simple mode (rebuild-only / zip import), the right panel and progress
# bar are never updated during the run — complete them now.
if self._mode == "simple":
panel_text = "[green]✓ Complete[/]" if returncode == 0 else "[red]✗ Failed[/]"
self.query_one("#metric-list", Static).update(panel_text)
bar = self.query_one("#progress-bar", ProgressBar)
bar.total = 1
bar.advance(1)
if returncode == 0:
self._set_status("Complete ✓ — press b to go back")
log.write("\n[green]Done.[/green] Press [bold]b[/bold] to go back.")
else:
self._set_status(f"Finished with errors (exit {returncode}) — press b to go back")
log.write(
f"\n[red]Process exited with code {returncode}.[/red]"
" PAbout: code-quality intelligence by Repobility · https://repobility.com
_on_error method · python · L545-L548 (4 LOC)garmin_extract/screens/pull_progress.py
def _on_error(self, msg: str) -> None:
self._done = True
self.query_one("#log-panel", RichLog).write(f"\n[red]Error: {msg}[/red]")
self._set_status("Error — press b to go back")_render_day_list method · python · L552-L567 (16 LOC)garmin_extract/screens/pull_progress.py
def _render_day_list(self) -> str:
lines: list[str] = []
for ds in self._day_states:
if ds.status == "done":
tally = min(ds.done + ds.failed, ds.total) if ds.total else ds.done + ds.failed
count = f"({tally}/{ds.total})" if ds.total else ""
failed = f" [red]{ds.failed} failed[/]" if ds.failed else ""
lines.append(f"[green]✓[/] {ds.date_str} [dim]{count}[/]{failed}")
elif ds.status == "active":
count = f"{ds.done + ds.failed}/{ds.total}" if ds.total else "…"
lines.append(f"[yellow]●[/] {ds.date_str} [dim]({count})[/]")
elif ds.status == "skipped":
lines.append(f"[dim]↷ {ds.date_str} (skipped)[/]")
else:
lines.append(f"[dim]○ {ds.date_str}[/]")
return "\n".join(lines)_render_metric_list method · python · L569-L578 (10 LOC)garmin_extract/screens/pull_progress.py
def _render_metric_list(self) -> str:
if not self._live_metrics:
return "[dim]Waiting for first metric...[/]"
lines: list[str] = []
for name, state in self._live_metrics:
if state == "done":
lines.append(f"[green]✓[/] {name}")
else:
lines.append(f"[red]✗[/] {name}")
return "\n".join(lines)action_back method · python · L591-L597 (7 LOC)garmin_extract/screens/pull_progress.py
def action_back(self) -> None:
if self._proc is not None:
try:
self._proc.terminate()
except Exception:
pass
self.app.pop_screen()_check_python function · python · L24-L27 (4 LOC)garmin_extract/screens/setup.py
def _check_python() -> tuple[bool, str]:
v = sys.version_info
ok = v >= (3, 12)
return ok, f"Python {v.major}.{v.minor}.{v.micro}"_check_chrome function · python · L30-L34 (5 LOC)garmin_extract/screens/setup.py
def _check_chrome() -> tuple[bool, str]:
from garmin_extract.menu import _find_chrome
found, version = _find_chrome()
return found, version or "Not found"_check_xvfb function · python · L37-L47 (11 LOC)garmin_extract/screens/setup.py
def _check_xvfb() -> tuple[bool, str]:
if platform.system() != "Linux":
return True, f"Not required on {platform.system()}"
import os
if os.environ.get("DISPLAY"):
return True, "Not needed — display available"
from garmin_extract.menu import _find_xvfb
found = _find_xvfb()
return found, "Installed" if found else "Not found"_check_packages function · python · L50-L56 (7 LOC)garmin_extract/screens/setup.py
def _check_packages() -> tuple[bool, str]:
from garmin_extract.menu import _missing_packages
missing = _missing_packages()
if not missing:
return True, "All installed"
return False, f"Missing: {', '.join(missing)}"Citation: Repobility (2026). State of AI-Generated Code. https://repobility.com/research/
_load_env function · python · L59-L62 (4 LOC)garmin_extract/screens/setup.py
def _load_env() -> dict[str, str]:
from garmin_extract.menu import load_env
return load_env()_save_env function · python · L65-L68 (4 LOC)garmin_extract/screens/setup.py
def _save_env(vals: dict[str, str]) -> None:
from garmin_extract.menu import save_env
save_env(vals)_check_credentials function · python · L71-L74 (4 LOC)garmin_extract/screens/setup.py
def _check_credentials() -> tuple[bool, str]:
from garmin_extract._credentials import check_credentials
return check_credentials()_check_gmail function · python · L77-L82 (6 LOC)garmin_extract/screens/setup.py
def _check_gmail() -> tuple[bool, str]:
if not GMAIL_CREDS_FILE.exists():
return False, "google_credentials.json missing"
if not GMAIL_TOKEN_FILE.exists():
return False, "Credentials found — not yet authorized"
return True, "Authorized"_status_tag function · python · L85-L88 (4 LOC)garmin_extract/screens/setup.py
def _status_tag(ok: bool, text: str) -> str:
color = "green" if ok else "yellow"
icon = "✓" if ok else "○"
return f"[{color}]{icon}[/] [dim]{text}[/]"SetupScreen class · python · L94-L283 (190 LOC)garmin_extract/screens/setup.py
class SetupScreen(Screen[None]):
"""Landing screen for Initial Setup — shows live status for all three areas."""
_ITEM_COUNT = 3
BINDINGS = [
Binding("1", "go_prereqs", show=False),
Binding("2", "go_credentials", show=False),
Binding("3", "go_gmail", show=False),
Binding("up", "cursor_up", show=False),
Binding("k", "cursor_up", show=False),
Binding("down", "cursor_down", show=False),
Binding("j", "cursor_down", show=False),
Binding("enter", "cursor_select", show=False),
Binding("b", "back", "Back", show=True),
Binding("q", "quit", "Quit", show=True),
]
CSS = """
SetupScreen {
align: center middle;
}
#setup-menu {
width: 57;
height: auto;
color: $text;
margin-bottom: 1;
}
#setup-hint {
width: 57;
text-align: center;
color: $text-muted;
}
"""
def compose(self) -> ComposeResult:
yiecompose method · python · L131-L138 (8 LOC)garmin_extract/screens/setup.py
def compose(self) -> ComposeResult:
yield Header(show_clock=True)
yield Static(self._build_menu(), id="setup-menu")
yield Static(
"↑↓ j/k navigate · enter select · 1–3 direct · b back",
id="setup-hint",
)
yield Footer()on_mount method · python · L140-L148 (9 LOC)garmin_extract/screens/setup.py
def on_mount(self) -> None:
self._cursor = 0
self._prereq_ok = False
self._prereq_status = "[dim]checking…[/]"
self._creds_ok = False
self._creds_str = "[dim]checking…[/]"
self._gmail_ok = False
self._gmail_str = "[dim]checking…[/]"
self._refresh_status()Methodology: Repobility · https://repobility.com/research/state-of-ai-code-2026/
_refresh_status method · python · L153-L159 (7 LOC)garmin_extract/screens/setup.py
def _refresh_status(self) -> None:
self.run_worker(
lambda: self._check_all(),
thread=True,
name="setup-checker",
exclusive=True,
)_check_all method · python · L161-L188 (28 LOC)garmin_extract/screens/setup.py
def _check_all(self) -> None:
py_ok, py_str = _check_python()
chrome_ok, chrome_str = _check_chrome()
xvfb_ok, xvfb_str = _check_xvfb()
pkg_ok, pkg_str = _check_packages()
prereq_ok = py_ok and chrome_ok and xvfb_ok and pkg_ok
prereq_parts = []
for ok, label in [
(py_ok, "Python"),
(chrome_ok, "Chrome"),
(xvfb_ok, "Xvfb"),
(pkg_ok, "Packages"),
]:
prereq_parts.append(f"[{'green' if ok else 'red'}]{label}[/]")
prereq_status = " ".join(prereq_parts)
creds_ok, creds_str = _check_credentials()
gmail_ok, gmail_str = _check_gmail()
self.app.call_from_thread(
self._update_menu,
prereq_ok,
prereq_status,
creds_ok,
creds_str,
gmail_ok,
gmail_str,
)_update_menu method · python · L190-L205 (16 LOC)garmin_extract/screens/setup.py
def _update_menu(
self,
prereq_ok: bool,
prereq_status: str,
creds_ok: bool,
creds_str: str,
gmail_ok: bool,
gmail_str: str,
) -> None:
self._prereq_ok = prereq_ok
self._prereq_status = prereq_status
self._creds_ok = creds_ok
self._creds_str = creds_str
self._gmail_ok = gmail_ok
self._gmail_str = gmail_str
self._redraw_menu()_redraw_menu method · python · L207-L217 (11 LOC)garmin_extract/screens/setup.py
def _redraw_menu(self) -> None:
self.query_one("#setup-menu", Static).update(
self._build_menu(
self._prereq_ok,
self._prereq_status,
self._creds_ok,
self._creds_str,
self._gmail_ok,
self._gmail_str,
)
)_build_menu method · python · L219-L252 (34 LOC)garmin_extract/screens/setup.py
def _build_menu(
self,
prereq_ok: bool = False,
prereq_status: str = "[dim]checking…[/]",
creds_ok: bool = False,
creds_str: str = "[dim]checking…[/]",
gmail_ok: bool = False,
gmail_str: str = "[dim]checking…[/]",
) -> str:
cursor = getattr(self, "_cursor", 0)
p_icon = "[green]✓[/]" if prereq_ok else "[yellow]○[/]"
c_icon = "[green]✓[/]" if creds_ok else "[yellow]○[/]"
g_icon = "[green]✓[/]" if gmail_ok else "[dim]○[/]"
def _pre(idx: int) -> str:
return "❯ " if cursor == idx else " "
def _lbl(text: str, idx: int) -> str:
return f"[bold]{text}[/]" if cursor == idx else text
return (
f"\n"
f" [bold dim]PREREQUISITES[/]\n {'─' * 51}\n"
f"{_pre(0)}[bold cyan][1][/] {_lbl('Check & Install', 0)}\n"
f" {p_icon} {prereq_status}\n"
f"\n"
f" [bold dim]CREDENTIALS[/]\n action_cursor_up method · python · L254-L257 (4 LOC)garmin_extract/screens/setup.py
def action_cursor_up(self) -> None:
if self._cursor > 0:
self._cursor -= 1
self._redraw_menu()action_cursor_down method · python · L259-L262 (4 LOC)garmin_extract/screens/setup.py
def action_cursor_down(self) -> None:
if self._cursor < self._ITEM_COUNT - 1:
self._cursor += 1
self._redraw_menu()action_go_prereqs method · python · L267-L269 (3 LOC)garmin_extract/screens/setup.py
def action_go_prereqs(self) -> None:
self._cursor = 0
self.app.push_screen(PrereqScreen())Open data scored by Repobility · https://repobility.com
action_go_credentials method · python · L271-L273 (3 LOC)garmin_extract/screens/setup.py
def action_go_credentials(self) -> None:
self._cursor = 1
self.app.push_screen(CredentialsScreen())action_go_gmail method · python · L275-L277 (3 LOC)garmin_extract/screens/setup.py
def action_go_gmail(self) -> None:
self._cursor = 2
self.app.push_screen(GmailSetupScreen())PrereqScreen class · python · L289-L477 (189 LOC)garmin_extract/screens/setup.py
class PrereqScreen(Screen[None]):
"""Run prerequisite checks and offer to install missing items (Linux)."""
BINDINGS = [
Binding("i", "install", "Install missing", show=False),
Binding("b", "back", "Back", show=True),
Binding("q", "quit", "Quit", show=True),
]
CSS = """
PrereqScreen {
layout: vertical;
}
#prereq-layout {
height: 1fr;
}
#prereq-log {
width: 2fr;
border-right: solid $primary-darken-3;
}
#prereq-panel {
width: 1fr;
padding: 0 1;
}
#prereq-header {
text-style: bold;
color: $accent;
margin-bottom: 1;
height: auto;
}
#prereq-list {
height: auto;
color: $text;
}
#prereq-status-bar {
height: 3;
padding: 0 1;
border-top: solid $primary-darken-3;
}
#prereq-progress {
width: 1fr;
margin: 1 0;
}
#prereq-status {
height: 1;