Commit Graph
100 Commits
Author SHA1 Message Date
hz 854c887a1a Center login panel content, pin legal links to the bottom
Making the auth panel a fixed height (to kill the scrollbar) left the
shorter views (login, reset) stranded at the top with dead space below.
Split panel_content into a main_column (header, message, mode views -
expand-fill, center-aligned) and the legal footer as a sibling that
stays pinned to the panel's bottom edge regardless of which view is
showing or how tall its content is.

Verified headlessly: top/bottom whitespace above and below the active
view's content is now equal (e.g. login 174/174, steam 2/2), and the
footer's position doesn't move between modes.
2026-07-25 09:10:19 -05:00
hz ce4db7cec8 Remove the login panel scrollbar
The auth panel was a fixed 710x820 (640x790 on narrower desktop
windows) regardless of which view was showing, but Register and the
Steam linking form need up to ~990px to lay out without scrolling -
so the inner ScrollContainer was always kicking in for those views.

- Tightened form spacing (_new_form separation 16->10, field height
  68->56, panel_content separation 24->16, page margins 56->28) to
  shrink how much height each view actually needs.
- Size the panel to the tallest view's real requirement (1000/1010),
  clamped to whatever height the window actually has so a short window
  shrinks the panel - and lets the ScrollContainer take over as a
  fallback - instead of the panel overflowing off-screen.

Verified headlessly across 1920x1080, 1366x768, and a narrow
compact-desktop width: no scrollbar in any mode at the two common
resolutions, and the panel now stays within the window (falling back
to scrolling only for the two tallest forms on the 768px-tall case,
rather than clipping off both edges of the screen as a fixed height
would have).
2026-07-25 00:52:12 -05:00
hz 191aa685fa Fix shadowed category_label warning in the report-question form
A local category_label in _build_report_modal() shadowed the
class-level category_label field (the question's topic tag near the
stem). Renamed the local to report_category_label.
2026-07-25 00:52:02 -05:00
hz 65ae99e2ce Update exe boot splash to the current shield logo
boot_splash/image was still on ranaze-loader-icon-v1.png, the mark
from before the app rebranded to the shield "RZ" logo (c91e70d). Point
it at assets/branding/ranaze-mark.png, the same mark already used for
the in-app header brand throughout the current UI.
2026-07-25 00:31:57 -05:00
hz b7b290c63b Fix deployment_environment default so the debugger reads UAT
project.godot's API URLs already pointed at UAT (us3q.ranaze.com), but
deployment_environment itself was still "development" - a leftover
label that never matched the actual origin. Since the UAT-only feature
gates (Dynamic Questions, CCS Cases, Flashcards) check for the literal
"uat" value, running from the Godot editor/debugger hid all three even
though it's UAT in every other respect.

Set it to "uat" to match reality, and update the two places that
sed-patch this value at build time (web/Dockerfile for the UAT/PRD web
builds, tools/export_steam_release.sh for the Steam build) so they
still match the source string they're replacing.
2026-07-25 00:30:14 -05:00
hz c1a71b1192 Feature-gate Flashcards to UAT only
Same treatment as Dynamic Questions and CCS Cases: hide the nav
sidebar entry and the dashboard's "flashcards due" review card unless
step3/deployment_environment is "uat".
2026-07-25 00:30:06 -05:00
hz f3a2e65627 Skip UAT/PRD deploys for changes that don't touch the deployable
Docs, local release tooling (tools/), and the GDScript test suite
(never executed by this pipeline, and irrelevant to the API image,
the exported web build, or k8s manifests) don't need a full deploy.
workflow_dispatch still allows a manual run for any of these if ever
needed.
2026-07-24 23:36:09 -05:00
hz bca31bd142 Add a Steam release export script pointed at production
project.godot stays checked in against UAT (us3q.ranaze.com) so the
Godot editor/debugger keeps testing against UAT. This script patches a
local copy to prd/s3q.ranaze.com just for the Windows Desktop export -
the same swap web/Dockerfile already does for UAT vs PRD web builds -
runs the export, then always restores the original file.

Verified: after a run, `git diff project.godot` is clean and the
exported .pck contains s3q.ranaze.com with no trace of us3q.ranaze.com.
2026-07-24 23:32:48 -05:00
hz 0e473343d0 Fix stale web_responsive_test icon assertion
It checked for a "DynamicQuestionsIcon" mode card that no longer
exists in study_selector.gd (that mode moved to its own nav item and
screen a while back), so it always failed. CCS Cases is now also
UAT-gated and won't be present in the default test environment either,
so point the check at Question Bank, the one mode card that's always
rendered.
2026-07-24 23:17:59 -05:00
hz 6df0a88fd4 Feature-gate Dynamic Questions and CCS Cases to UAT only
Both are still in progress and shouldn't be reachable in production
(or local dev) yet - hide every entry point (nav sidebar, the
dashboard's "dynamic concepts due" review card, and the CCS Cases
mode card on the study selector) unless step3/deployment_environment
is "uat", the same setting that already drives the UAT badge. Added
Brand.is_uat_environment() as the shared check.
2026-07-24 23:12:47 -05:00
hz 118c215608 Add a setting to turn off follow-up questions
The optional "FOLLOW-UP QUESTIONS" reinforcement section shown during
answer review is now gated behind a Settings toggle (on by default),
persisted locally the same way as dark mode and interface sounds.
2026-07-24 23:01:06 -05:00
hz cd1648fe38 Shorten "Skip question" button to "Skip" 2026-07-24 22:14:24 -05:00
hz f1b290aa73 Dock the question toolbar in line with the brand row
The toolbar had followed the progress group down into the row below
the branding after it moved there - readers expect actions docked to
the top brand row, not hanging off the question count.
2026-07-24 22:10:49 -05:00
hz 50f54b1bec Polish question player header/toolbar and add configurable block size
- Fix the toolbar wrapping onto two rows: its minimum width was tuned
  for an older, narrower button set and never widened back out after
  reverting to bare icon buttons.
- Drop the "Time elapsed"/"Ctrl+Enter" readout next to Submit - it was
  clutter; the underlying timer logic keeps running unseen.
- Move the RanaZe brand mark above the question-count row instead of
  sharing a line with it.
- Progress text drops the word "Question" everywhere ("1 of 10"), and
  core/dynamic sessions now cycle against a configurable block size
  (Settings > Question block size, default 10) instead of counting up
  forever.
2026-07-24 21:57:03 -05:00
hz 62e65fd22c Add Windows Desktop export with RanaZe branding
Replace the default Godot boot splash and exe icon with the RanaZe
mark so a Windows build reads as RanaZe from first launch, not the
engine it's built on.
2026-07-24 21:56:53 -05:00
hz 5197234210 Drop toolbar text labels in favor of hover tooltips
Varying label widths (especially when a button hides itself, e.g.
"Labs" on a question with no lab results) broke even spacing between
icons. Every toolbar button already has a tooltip_text carrying the
same label as hover text, so drop the labels/wrapper containers
entirely and go back to plain, uniformly-spaced 44x44 icon buttons.
2026-07-24 21:05:34 -05:00
hz 576b48d581 Fix toolbar gaps and theme toggle shape
- A toolbar icon that hides itself at runtime (labs, notes,
  flashcard, bookmark) left its text label behind, showing as an
  orphaned label floating in a gap. The label's wrapper now tracks
  the button's own visibility.
- The theme toggle used a distinct circular pill shape; changed it
  to match the same rounded-square box every other toolbar icon uses.
2026-07-24 19:55:49 -05:00
hz d073f82a76 Fit the toolbar on a single row
The 11 labeled groups are wider than the old bare-icon buttons, so
the toolbar's allotted minimum width (tuned for the old layout) was
too narrow and forced a wrap onto two rows. Widened it and raised
the compact-mode breakpoint to match.
2026-07-24 03:23:14 -05:00
hz a94cc5188f Fix bottom-bar time caption for core sessions
Core sessions show a per-question stopwatch that counts up (no fixed
deadline, just a pacing signal), not a countdown - it was incorrectly
labeled "Time remaining" like the simulation/Timed countdown; now
reads "Time elapsed" to match what the number actually does.
2026-07-24 03:16:30 -05:00
hz 0902cc238a Un-collapse the question toolbar - show every action directly
The 6-item + "More" overflow popup made the toolbar feel sparse and
hid frequently-used actions (flag, report, flashcard, theme) behind
an extra click. Reverting to a flat toolbar where every action is
directly visible and labeled, including text size (grouped A-/A+
under one "Text size" caption instead of behind a popup).
2026-07-24 03:03:40 -05:00
hz 974de67032 Redesign question bank screen to match new mockup
Adapts the quiz screen's header, toolbar, choice cards, and bottom bar
to the designer's new layout:

- Header: adds the RanaZe logo/wordmark and a question-progress bar +
  percentage alongside the existing "Question N of M" text.
- Toolbar: consolidates 12 icon-only/chip buttons into 6 labeled items
  (Text size, Calculator, Clear highlight, Notes, Bookmark, More), with
  a new "More" popup holding the rest (labs, flag, report, flashcard,
  theme toggle, feedback). The underlying buttons are reparented, not
  duplicated, so every existing theming/visibility/state call site
  keeps working unmodified.
- Category tag: shows the question's discipline (falling back to
  system) above the stem.
- Choice cards: every choice now renders as a subtly-bordered rounded
  card even before answering, not just a flat divider row; the
  currently-selected pre-submit choice shows a checkmark.
- Bottom bar: merges the Skip/Submit row and the timer row into one -
  Skip as a plain link, a centered "X of Y" progress bar, and a
  time slot that shows the existing countdown when a limit applies or
  a new count-up stopwatch ("Time elapsed") otherwise, plus a
  Ctrl+Enter/Cmd+Enter submit shortcut with a visible hint.
2026-07-24 02:28:22 -05:00
hz edcc0def5d Fix CCS category order search 2026-07-23 23:14:38 -05:00
hz b9d4687b1b Fix dynamic Elo clamp updates 2026-07-23 23:01:52 -05:00
hz 0ec486f132 Stabilize UAT API pod selection 2026-07-23 17:03:02 -05:00
hz 32c455bba0 Improve dynamic question learning loop 2026-07-23 16:50:53 -05:00
hz c91e70deb5 Update app branding to the new shield "RZ" logo
Replaces the OS/window icon with the new dark-background logo design,
and derives a transparent shield-mark cutout (via chroma-key against
the flat background) for the in-app login/sidebar mark and the web
loading-screen logo. Brand.ranaze_mark_texture() no longer needs the
AtlasTexture crop since the new source asset is already tightly
cropped to the mark.
2026-07-23 16:24:49 -05:00
hz fae38d2ded Adapt dynamic question difficulty to learner Elo 2026-07-23 16:18:44 -05:00
hz 5b5741de37 Show selection percentages on unselected distractors during review
Previously only the correct choice and any choice the student actually
selected got a percentage badge once reviewing; never-selected
distractors were left blank. Now every choice shows its selection
percentage as soon as the question is answered, matching the earlier
change that made unselected distractors render red like the rest of
the review UI.
2026-07-23 15:54:39 -05:00
hz b1b83dae05 Fix dynamic mastery first-attempt upsert 2026-07-23 15:25:06 -05:00
hz 332da7c181 Fix stale-node crash in UI sound auto-wiring
node_added already fires once per node as it enters the tree (including
every descendant of a newly-added subtree), so the recursive call_deferred
in _on_node_added was redundant and held a raw Node reference across a
frame boundary. If that node got freed before the deferred call fired
(e.g. a container torn down and rebuilt the same frame), the engine's
message queue couldn't marshal the argument and threw "Cannot convert
argument 1 from Object to Object". Wiring synchronously removes the
window entirely.

Also silences the intentional integer division in _duration_text,
matching the same annotation already applied to _elapsed_simulated_text.
2026-07-23 15:13:56 -05:00
hz 48f404518f Fix GDScript editor warnings (shadowed vars, unused param, integer division)
Renames locals/params that shadowed base-class properties (Node.name,
Control.size, BoxContainer.alignment), prefixes an intentionally-unused
parameter, and annotates a deliberate integer division so the console
stays clean during development.
2026-07-23 14:30:48 -05:00
hz 4a4bed2ac5 Add missing lucide/link.svg icon
The connected-accounts "Connect" button in progress_profile.gd
referenced res://assets/icons/lucide/link.svg, which didn't exist,
causing a resource-load error whenever the Steam/Google linking row
rendered.
2026-07-23 14:26:26 -05:00
hz 88688d3eb0 Add Steam and Google brand icons to login OAuth buttons
Steam uses a theme-aware monochrome glyph (light/dark variants) since
the button background flips between navy and white; Google keeps its
official 4-color mark, which reads fine on either background.
2026-07-23 14:19:17 -05:00
hz 92c5688b55 Upgrade dynamic questions to authored parity 2026-07-23 14:11:18 -05:00
hz e174b5db15 Return dynamic question runs to dashboard 2026-07-23 13:52:24 -05:00
hz 403944b249 Assign IDs when promoting dynamic blueprints 2026-07-23 13:40:53 -05:00
hz 8390d795e5 Publish dynamic questions during UAT deploy 2026-07-23 13:30:22 -05:00
hz 6a6e703aa4 Fix dynamic questions sidebar icon 2026-07-23 13:19:32 -05:00
hz fcbc288a49 Add data-driven dynamic question mode 2026-07-23 12:33:23 -05:00
hz 50f07a77a5 Add exam-style question calculator 2026-07-23 05:19:12 -05:00
hz ba155fd38a Fix distractor explanations rendering on unanswered questions
Guarded the answer-review render path (teaching cards, review
follow-ups, distractor explanations) on current_answer/pending_correct_advance
directly rather than solely on correct_review_panel.visible, and added
the same guard inside _render_unselected_distractor_explanations
itself. This closes a path where a fresh, never-answered question
could show wrong-answer explanations immediately, before any
selection or submission.

Also: unselected distractors now render in the same red "wrong" card
style as selected/locked-wrong choices once a question is being
reviewed, instead of staying in the plain default row style. And
removed the redundant percentage badge that was floating above the
in-progress follow-up quiz prompt, since the choice button above it
already shows the same percentage.
2026-07-23 05:07:27 -05:00
hz 8e216eac32 Rebuild CCS case workflow 2026-07-23 04:43:02 -05:00
hz 489b9c3d7c Fix text zoom not actually syncing, and expose it in Settings
Two real gaps meant the account-synced zoom (from the previous
"sync through the account" change) never reached the screen:
_load_cache() updated AccountProfileService.preferences but never
emitted profile_changed, so question_player.gd/ccs_service.gd (already
built and listening before login even happens) never found out a
cached value had loaded. And nothing forced a server refresh
right after login - it only fired if the user happened to open the
profile/progress screen, so a fresh device/session had no path to
the true synced value at all.

main.gd now calls AccountProfileService.refresh() once per login
(not on every silent token refresh) so the real preferences GET
always runs right after signing in, on any device.

Also added Question bank/CCS case text size steppers to the Settings
screen next to dark mode, per user request, reusing the same
AccountProfileService/CCSService plumbing as the in-screen A-/A+
buttons.
2026-07-23 04:37:45 -05:00
hz b3a8dec379 Simplify resolved wrong-answer explanation cards per design feedback
Drop the redundant header row (duplicate percentage badge + collapse
chevron), the "Why this is appropriate/less appropriate:"/"Why this
is incorrect:" heading labels, and the nested sub-box - now that
these cards live inside their own choice's colored border, all of
that was repeating what the color and position already say. Both the
selected-wrong-choice resolved follow-up and the never-selected
distractor cards now just show the plain explanation sentence, with
the leading "Correct."/"Incorrect." verdict word stripped too.

Removing the toggle chevron removes the only way to reach the
collapse/expand behavior, so that machinery (_collapse_resolved_followups,
_toggle_followup_state, the "collapsed" state field) comes out too
rather than linger unreachable.
2026-07-23 04:19:10 -05:00
hz d69a1fd0e3 Sync text zoom preference through the account instead of local settings
Local user://settings.cfg meant zoom level didn't follow a student
across devices/browsers. Question bank and CCS text scale now live on
the user's study profile in Mongo (QuestionTextScale/CcsTextScale),
synced through a new PUT /api/profile/me/text-scale endpoint and the
existing preferences GET/cache already used for study preferences.

Both question_player.gd and ccs_service.gd read the synced value at
startup and react to AccountProfileService.profile_changed so a value
pulled down after login (or changed from another session) applies
without a restart. Backend validates the 0.85-1.35 range and updates
only the field(s) provided via a targeted $set, so it can't clobber
the other scale or the unrelated study-profile preferences.
2026-07-23 03:59:02 -05:00
hz b88f38f29b Persist text zoom level across sessions
Question bank and CCS case text-size (A-/A+) previously reset to 1.0
on every app launch. Both now load their saved scale from
user://settings.cfg at startup and save on every adjustment, mirroring
the existing pattern used for dark/light mode and sound preferences.
2026-07-23 03:42:17 -05:00
hz c62eff8846 Auto-flag questions with media at write time, not just via one-time sweep
The flag-media-questions CLI command only caught questions that
existed in the DB when it ran once. Any question created, imported,
or edited afterward could add media without ever being flagged for
review, since nothing gated new writes going forward. CreateAsync,
UpdateAsync, and UpsertManyByExternalIdAsync now all run new/updated
questions through ApplyMediaReviewGate, which flags any question that
has media and isn't already flagged.
2026-07-23 03:29:57 -05:00
hz 59ffaf4376 Move distractor explanations inline instead of a repeated bottom section
The "WHY OTHER OPTIONS ARE INCORRECT" aggregate section duplicated
explanations that selected wrong choices already showed inside their
own resolved follow-up quiz. Removed that section entirely; choices
the user never picked now get their "why incorrect" explanation
docked directly inside their own card (reusing the same followup
panel/attached-card styling), so every distractor's explanation lives
with its choice instead of in a separate list at the bottom.
2026-07-23 02:01:29 -05:00
hz 4db5b9d374 Drop the redundant status icon and "Review: B..." label from follow-up panels
The choice button above the panel already shows the letter badge,
choice text, and percentage, so repeating them in the panel header
was redundant now that the panel is docked inside the choice's card.
Keeps the collapse toggle, now named FollowupToggle since the old
FollowupSummary button it lived on is gone.
2026-07-23 01:47:11 -05:00
hz 2a2ff29389 Remove redundant "Correct Answer: X" heading from the review panel
Now that the explanation panel is docked inside the correct choice's
own green card, the heading was redundant with the badge/border color
already conveying it's the correct answer.
2026-07-23 01:42:31 -05:00
hz 5ba7af9d3e Redesign flag/report icons as vector assets and dock review panels inside their choice card
Flag question now uses a clean vector flag (dark/light SVG variants,
replacing a hand-drawn pixel-art icon that got muddied by the shared
toolbar icon-tint override). Report question is now a megaphone
instead of a second flag glyph, since both toolbar buttons looked
identical before.

The correct-answer explanation and the wrong-answer follow-up quiz
previously rendered as separate bordered boxes sitting below the
entire choice list. Both now dock inside their own choice's card:
the explanation panel reparents onto the correct choice's row, the
follow-up panel was already there but visually detached. A shared
_attached_panel_box style drops the shared border/corner between the
choice button and its panel so they read as one continuous card.
2026-07-23 01:23:53 -05:00
hz b822fe5314 Redesign clear-highlight icon as an eraser with sparkles
Also drop a stale custom_minimum_size(0, 54) reset left over in
_set_choice_button_text from before the answer row redesign - it was
silently overriding the button's real 68px minimum height on every
question load and on every elimination/strikethrough toggle, which is
why choice rows never actually got taller and why striking a choice
through visibly shrank its card.
2026-07-23 00:42:50 -05:00
hz 5f3289bb8e Vertically center the question+choices block before an answer is submitted
Fixes the large empty gap below the answer choices reported after the
answer-row redesign - the stem+choices VBox was pinned to the top of an
expand-filled scroll panel with all the leftover height sitting unused
below choice E. Now centers that block when unanswered and reverts to
top alignment once the explanation/review content grows underneath it.
2026-07-23 00:33:52 -05:00
hz 9d18704ad0 Render answer-choice badges as SVGs and give rows more breathing room
StyleBoxFlat-drawn circles kept looking rough at this size even after
tuning corner detail/antialiasing, so the badges are now two small SVG
assets (outline and filled) tinted per-state via modulate instead -
crisp regardless of size. Also increased row height, badge size, and
margins across the board; the previous pass's padding bump was too
timid and the rows still read as cramped.
2026-07-23 00:14:49 -05:00
hz aef287ac26 Fix pixelated circle badges with a seam through the center
icon_circle_box's perfectly-circular StyleBoxFlat (corner radius equal
to half the box size, no straight edges between corners) is a known
Godot degenerate case that draws a faint seam through the middle when
antialiasing is on and looks faceted at low corner_detail. Bumping
corner_detail and disabling antialiasing renders a clean circle at
these small badge/icon sizes instead - affects every icon_circle_box
call site (answer badges, stat tiles, avatars, etc.), not just the
question player.
2026-07-22 23:48:00 -05:00
hz 6c388dfa5e Redesign answer choice rows into a cleaner divided list
Unselected/eliminated choices now sit in a flat list with a thin
bottom divider instead of each getting its own bordered box, and only
the selected/correct/wrong choice pops out as a rounded, tinted card -
closer to the reference mockup and less visually busy than every
option looking like an separate boxed card.
2026-07-22 23:18:13 -05:00
hz b56d48d570 Fix eliminated-choice strikethrough disappearing on wrong/correct reveal
A choice that was crossed out (right-click) and also happened to be
locked as the submitted-wrong choice, or revealed as the correct
answer, silently lost its strikethrough because the percentage-badge
branches took precedence over the elimination check in the same
if/elif chain. Decoupled the two so a choice can show both the
strikethrough and its reveal percentage at once.
2026-07-22 23:10:41 -05:00
hz f17797becc Don't show the session-expiry warning to actively-used sessions
The warning was purely a token-expiry countdown with no concept of
user activity, so it interrupted people who had been clicking through
questions the whole time. AuthState now tracks real input activity
globally and silently refreshes the session in the background when
the user has interacted recently, only surfacing the "Stay logged in?"
dialog for sessions that are genuinely idle. A failed background
refresh still surfaces the dialog rather than silently logging the
user out.
2026-07-22 22:52:38 -05:00
hz 9f62444a63 Add a review-flag state for questions, independent of publish status
Flagged questions disappear from every student-facing surface (search,
exam simulation sampling, the missed-question review queue, bookmarks,
direct fetch) while staying published - flagging and unpublishing are
now separate, reversible actions with their own audit trail (who
flagged it, when, why). Backend-only for now: SUPER-only flag/unflag/
list endpoints, no client UI. Includes a one-time CLI sweep
(flag-media-questions) to flag every existing question with an image
so they can be reviewed.
2026-07-22 22:42:19 -05:00
hz e8d615985b Reveal the flashcard answer by tapping the card, not a separate button
Matches the mockup: the "Show Answer" button is replaced by an in-card
"Tap card to reveal answer" hint, and clicking anywhere on the card
reveals it (guarded the same way Space already was - only while at the
live card and not yet revealed).
2026-07-22 17:21:23 -05:00
hz 7f76ca0fdc Add system (curated) vs. user-uploaded flashcards
System decks/notes are owned by a reserved sentinel user id, reusing
all existing per-user store/index plumbing unchanged. Regular users
see them under a separate "Official Decks" section, can study them
with fully independent per-user FSRS progress (lazily materialized on
first visit), but can never edit or archive them - enforced both in
the client (no Edit/Archive controls) and server-side (ownership guard
on every mutating endpoint). Includes a small idempotent seed command
(`dotnet run -- seed-flashcards`) for testing, since there's no in-app
authoring UI yet.
2026-07-22 15:52:19 -05:00
hz 3a01e9156c Keep the app sidebar visible on the flashcards study screen
The study screen was still treated as a fullscreen immersive view (like
the question player), hiding the main nav sidebar entirely. The mockup
and the user's request both call for keeping the app's left menu while
studying, with the deck panel living inside the screen alongside it.
2026-07-22 01:20:48 -05:00
hz 09b670d5d4 Close the gap between the flashcards study screen and the mockup
Add real session-history navigation (Previous/Next/Shuffle), compact
side panels, and a segmented progress row to match the mockup layout.
Flashcards now opens straight into Study, with library management
moved into the Options menu ("Manage Flashcards") and Export hidden
from the UI (Import stays). Shuffle is backed by a real, due-before-new
randomized pick on the backend, not a decorative toggle.
2026-07-22 00:43:52 -05:00
hz 70aa425fde Rebuild flashcard study screen from mockup, with real backend-backed stats
Study screen now matches the provided mockup's layout: a "Current
Deck" panel with a circular mastery-progress ring, and a "Spaced
Repetition" panel (New/Due/Learning/Review counts, streak, daily
goal) on either side of the card. Kept the app's real global sidebar
rather than the mockup's own nav, per direction.

Mastery/Streak/Daily Goal weren't tracked anywhere, so this adds real
backend support rather than showing fabricated numbers:
- Mastered = graduated to review state AND FSRS stability >= 21 days
  (FlashcardScheduleStore.MasteryStabilityDaysThreshold), stricter
  than the plain Review-state count
- CurrentStreakDays = consecutive UTC days with a review, computed
  from review-log timestamps in the new pure FlashcardScheduling
  .ComputeStreakDays (unit tested, habit-streak semantics: doesn't
  reset to 0 the instant a new day starts before today's first review)
- DailyGoal/ReviewsToday reuse the account's existing ReviewsPerDay
  setting rather than inventing a new one
Also removes the exit "X" button in favor of the same Escape/pause
menu the question-player flow uses (main.gd's shared app_menu, with
an "Exit Study Session" action), and adds a new circular_progress.gd
reusable ring control plus a real "Options" menu (bury/suspend the
current card) wired to schedule endpoints that had no UI before.
2026-07-21 23:20:14 -05:00
hz 72fb6e4776 Rework flashcards library to match the rest of the app's visual language
Compared side-by-side against Dashboard, the library screen used
entirely different visual primitives: a gradient primary button
Dashboard doesn't use anywhere, per-row bordered cards with low
contrast against the dark background, and a translucent pill badge
instead of the icon-circle pattern used everywhere else (stat tiles,
review queue, recent activity).

- Study/Save/Commit import now use Dashboard's actual primary button
  style (flat ROYAL_BLUE, not the login/session-dialog gradient)
- Added a stat-tile row (Due today / New available / Decks) using
  Dashboard's exact icon-circle + value + label construction, replacing
  the due/new counts previously crammed into the deck dropdown's text
- The note list now lives in one bordered card with a section title
  (matching Dashboard's chart/list panels) instead of each row being
  its own separate low-contrast card
- Per-row card-type indicator is now an icon circle (clipboard-list /
  notebook-pen) matching the Recent Activity list pattern, instead of
  a translucent color-coded pill badge
2026-07-21 22:47:21 -05:00
hz 109581874d Fix invisible divider/caption colors on the study card's first paint
refresh_theme_controls() colored the divider and the ANSWER/KEY
TAKEAWAY captions, but it only ran on an actual theme toggle - never
at initial build. Confirmed live: the divider was invisible (default
white on a white card) and the captions rendered as plain body text
instead of the intended accent color until you toggled dark mode
once. Call refresh_theme_controls() once at the end of _build() so
the correct colors apply immediately, which also fixes the same
latent gap in empty_label's color.
2026-07-21 22:18:24 -05:00
hz 7e19366dcb Redesign flashcards for visual hierarchy and button consistency
Study card: label the answer and "key takeaway" as distinct sections
with a real visible divider (previously an all-but-invisible
HSeparator) instead of one undifferentiated block of text. Also fixes
a real gap where a cloze card's extra field was silently dropped,
since only basic notes combined answer+extra into one label. Bigger
card, gradient Show-Answer button matching the app's signature CTA
style instead of a duller flat teal, and the Undo button now hides
itself when there's nothing to undo instead of sitting there disabled
looking identical to a real action.

Library: colored type badge per card (Basic/Cloze) instead of plain
gray text, more breathing room inside each row, Study promoted to the
same gradient CTA style, and Edit/Archive given a real secondary
button treatment instead of default theme buttons. Note editor fields
renamed ("Back / Extra takeaway" + a separate "Extra" field was
genuinely confusing) and now show which deck a card is being saved to.
2026-07-21 22:05:36 -05:00
hz b00b321d6f Fix Import/Export dropdowns not dismissing
They only closed via their own trigger button or a menu item -
clicking outside, pressing Escape, or opening the other dropdown
while one was open left it stuck on screen (confirmed opening both
stacked on top of each other). Add a shared invisible backdrop
(mirroring main.gd's drawer-backdrop pattern) that closes whichever
dropdown is open on outside click or Escape, and have opening one
close the other first.
2026-07-21 17:37:51 -05:00
hz 15e9f9779e Fix flashcard study/next 400s from a malformed studyDayStartUtc
current_study_day_start_utc() passed use_space=true to
Time.get_datetime_string_from_unix_time(), producing "2026-07-21
00:00:00Z" (space separator) instead of ISO-8601. The server's
System.Text.Json DateTime converter rejects that with a 400, which
the client surfaces as a generic "could not be loaded" error -
blocking every study session. Confirmed against the live API: the
space-separated value 400s, the corrected T-separated value returns
a card.
2026-07-21 17:02:51 -05:00
hz ace04ab268 Fix low-contrast session-expiry dialog in dark mode
The panel's shared Brand.panel_box background is ~80% opaque, which
compounded with the dialog's own dim backdrop let the screen behind
show through and washed out the card against it. Force full opacity
on this dialog's panel specifically, since other panel_box overlays
still rely on the shared translucency.
2026-07-21 16:47:54 -05:00
hz 4dfbd811b9 Wire flashcard CSV/JSON import/export and fix theme/responsive gaps
Import and export were stubbed with status-text placeholders; wire them
to the existing backend endpoints with a real file picker (web JS
bridge or native FileDialog) and browser/desktop download, plus an
import preview with create/update/skip/error counts before commit.

Also fix the library and study screens' theme-refresh handlers, which
were no-op stubs so cards never restyled on a theme toggle, and add
responsive layout handling for narrow viewports.
2026-07-21 16:41:26 -05:00
hz 48a8c8361d Add flashcards feature with spaced repetition scheduling
Adds a full flashcards system: FSRS-based scheduling, cloze/basic
card types, CSV import/export, media storage, and study UI, wired
into navigation and the dashboard alongside existing question flows.
2026-07-21 15:08:52 -05:00
hz 29b89dc404 Remove redundant follow-up retry action 2026-07-20 23:59:07 -05:00
hz c2d000cc48 Add automated UAT smoke tests 2026-07-20 23:54:11 -05:00
hz e5b567eec8 Fix connected account button warning 2026-07-20 22:02:50 -05:00
hz 3d63aa9729 Restart API when deployment secrets change 2026-07-20 22:01:51 -05:00
hz 72fd1e3e0f Add provider-neutral Google authentication 2026-07-20 21:42:56 -05:00
hz 48e19f138e Default local client endpoints to UAT 2026-07-20 21:13:20 -05:00
hz 468f6f7e01 Move PRD web service to available NodePort 2026-07-20 21:02:06 -05:00
hz 975b8c5357 Include CCS fixtures in deployment test image 2026-07-20 20:40:08 -05:00
hz c31242a500 Run deployment tests from Docker build context 2026-07-20 20:38:48 -05:00
hz 7829b10b23 Run deployment tests in .NET SDK container 2026-07-20 20:37:22 -05:00
hz 17747d96a0 Add isolated UAT and production environments 2026-07-20 20:32:22 -05:00
hz 4e0ca70157 Use Kubernetes for auth deployment gate 2026-07-20 17:29:34 -05:00
hz 5c406a271f Merge authentication into Questions API 2026-07-20 17:21:15 -05:00
hz 2dd4fa6420 Keep Stripe checkout in a popup 2026-07-20 16:42:17 -05:00
hz d142da2f78 Fix web redirects and loader rendering 2026-07-20 16:29:24 -05:00
hz 121e80b2ea Prefer high-performing distractors 2026-07-20 02:44:58 -05:00
hz dae3a31b71 Add legal consent and reliable external redirects 2026-07-20 02:16:20 -05:00
hz 2615ab4773 Fix Steam sign in navigation on web 2026-07-20 01:37:50 -05:00
hz c55341b076 Reduce web export build disk usage 2026-07-20 01:08:16 -05:00
hz f93b7ac380 Complete resilient Steam login flow 2026-07-20 00:30:06 -05:00
hz d176640cff Rebrand app as RanaZe Step 3 Trainer 2026-07-20 00:04:29 -05:00
hz 743399f647 Improve donation defaults and light contrast 2026-07-19 23:12:51 -05:00
hz df94247b3b Make Stripe checkout redirect resilient 2026-07-19 23:02:56 -05:00
hz a00dc81aa9 Fix Stripe checkout browser handoff 2026-07-19 22:56:11 -05:00
hz dec5e74aa7 Add Stripe donation flow 2026-07-19 22:26:33 -05:00
hz f12904bf73 Unify CCS case management flow 2026-07-19 21:29:24 -05:00
hz dacf2b89b2 Implement responsive profile and account data controls 2026-07-19 13:39:15 -05:00
hz 7508d4fe1d Implement persistent review queue 2026-07-19 12:51:24 -05:00