Skip to content

fix(design): visual rhythm, token consistency, accessibility, and polish#62

Merged
projectamazonph merged 1 commit into
mainfrom
fix/design-review-visual-rhythm
Jul 20, 2026
Merged

fix(design): visual rhythm, token consistency, accessibility, and polish#62
projectamazonph merged 1 commit into
mainfrom
fix/design-review-visual-rhythm

Conversation

@projectamazonph

@projectamazonph projectamazonph commented Jul 20, 2026

Copy link
Copy Markdown
Owner

Summary

Two-pass design review of the full frontend surface (29 files changed, 518 insertions, 304 deletions).

Token System

  • 19 alias tokens added to globals.css (--color-text, --color-surface, --color-border, etc.), fixing 167 undefined token references across admin, tools, live-classes, and refunds pages
  • --surface-tint token added for alternating section backgrounds (light: #F0EFE9, dark: #1E1E1C)
  • All remaining hardcoded hex colors replaced with design tokens
  • #fff on colored backgrounds replaced with `var(--ink-inverse))

Visual Rhythm

  • Home page sections alternate between flat and tinted backgrounds for clear separation
  • 3px left accent borders on live class cards, certificate cards, and past recordings
  • Dashboard stats row wrapped in tinted container with accent top borders
  • FAQ block, empty states, and certificate list get tinted backgrounds
  • Section padding increased from space-12 to space-16 across home page

Accessibility

  • 100vh100dvh in 5 layout files (iOS Safari viewport fix)
  • Skip-to-content link verified in root layout
  • WCAG AA contrast confirmed on all CTAs (accent-ink on accent: 6.0:1)

Mobile

  • Hero salary stat (₱60k–₱80k/mo) now visible on mobile (was display: none)
  • Compact sizing on small screens

Content

  • Hero subtext trimmed from 38 words to 18
  • text-wrap: balance added to all headings

Components

  • Skeleton shimmer loader replaces plain "Loading..." text
  • Branded 404 page with mono display and accent CTA
  • OG image metadata and favicon references added

Admin

  • Fixed undefined tokens (--accent-orange, --border-default, etc.)
  • Removed duplicate /admin/refunds quick link

Summary by CodeRabbit

  • New Features

    • Added skeleton loading screen with shimmer animation
    • Redesigned 404 page with enhanced UI
  • Style

    • Standardized design tokens across dashboard, admin, and public pages for consistent spacing, typography, and colors
    • Updated viewport height calculations (100dvh) for improved mobile browser behavior
    • Enhanced visual hierarchy with borders, padding, and background colors in certificates, courses, and live-classes sections
    • Improved admin dashboard with refund badge indicator
  • Documentation

    • Added metadata and social preview configuration

Two-pass design review with full implementation:

Token system:
- Add 19 alias tokens (--color-text, --color-surface, --color-border, etc.)
  to globals.css, fixing 167 undefined token references across the codebase
- Add --surface-tint token for alternating section backgrounds (light + dark)
- Replace all remaining hardcoded hex colors with design tokens
- Replace #fff on colored backgrounds with var(--ink-inverse)

Visual rhythm:
- Add alternating --surface-tint backgrounds to home page sections (pain
  points, coming soon) for clear section separation
- Add 3px left accent borders to live class cards, certificate cards,
  and past recording cards for visual anchoring
- Wrap dashboard stats row in tinted container with accent top borders
- Add tinted backgrounds to FAQ block, empty states, and certificate list
- Increase section padding from space-12 to space-16 across home page

Accessibility:
- 100vh replaced with 100dvh in 5 layout files (iOS Safari viewport fix)
- Skip-to-content link verified present in root layout
- Button contrast: accent-ink on accent passes WCAG AA (6.0:1)
- Focus-visible consistently applied on all interactive elements

Mobile:
- Hero salary stat (₱60k-₱80k/mo) now visible on mobile (was display:none)
- Compact mobile sizing (text-2xl) for the stat on small screens

Content:
- Hero subtext trimmed from 38 words to 18
- Removed redundant tagline line from hero
- Added text-wrap: balance to all heading elements

Components:
- Skeleton shimmer loader replaces plain Loading... text
- Branded 404 page with mono display and accent CTA
- OG image metadata and favicon references added to layout

Admin:
- Fixed undefined tokens (--accent-orange, --border-default, etc.)
- Removed duplicate /admin/refunds quick link
Copilot AI review requested due to automatic review settings July 20, 2026 00:56

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Pull request overview

Design-focused pass across the app to improve token consistency, spacing/visual rhythm, and accessibility-related layout behavior (notably dynamic viewport units), plus a refreshed loading and 404 experience.

Changes:

  • Adds/extends design tokens (alias tokens + --surface-tint) and applies them across admin, dashboard, tools, and public pages.
  • Updates multiple layouts/modules from 100vh to 100dvh for more reliable mobile viewport sizing.
  • Replaces the default loading state with a skeleton shimmer loader and adds a branded 404 page; updates root metadata (OG + icons).

Reviewed changes

Copilot reviewed 29 out of 29 changed files in this pull request and generated 7 comments.

Show a summary per file
File Description
src/styles/globals.css Adds alias tokens, --surface-tint, and balances headings.
src/components/ui/NavSidebar.module.css Switches sidebar height to 100dvh.
src/components/tools/StrTriageRunner.module.css Updates action pill/button text color token usage.
src/components/tools/KeywordResearchRunner.module.css Updates priority pill/button text color token usage.
src/app/verify/[hash]/verify.module.css Uses 100dvh for verify page min-height.
src/app/page.tsx Tightens hero copy on the home page.
src/app/not-found.tsx Replaces minimal 404 with branded centered layout and metadata.
src/app/loading.tsx Replaces “Loading...” with skeleton-based loading UI.
src/app/loading.module.css Introduces shimmer skeleton styles for the loading UI.
src/app/layout.tsx Adds OG image + favicon metadata references.
src/app/home.module.css Adjusts home page spacing, section tint rhythm, and hero stat visibility.
src/app/admin/users/users.module.css Tokenizes admin user list controls (button colors, etc.).
src/app/admin/users/[id]/user-detail.module.css Tokenizes admin user detail action buttons.
src/app/admin/refunds/refunds.module.css Tokenizes refunds list styling and spacing.
src/app/admin/refunds/[id]/detail.module.css Tokenizes refunds detail styling and spacing.
src/app/admin/page.tsx Removes the duplicate refunds quick link from admin dashboard.
src/app/admin/page.module.css Replaces undefined tokens with canonical tokens.
src/app/admin/layout.module.css Switches admin shell min-height to 100dvh.
src/app/(public)/pricing/pricing.module.css Adjusts spacing and adds tinted FAQ block styling.
src/app/(public)/auth/signin/auth.module.css Switches auth container min-height calc to 100dvh.
src/app/(dashboard)/payments/[id]/request-refund/request-refund.module.css Tokenizes request-refund page styling and spacing.
src/app/(dashboard)/live-classes/live-classes.module.css Tokenizes live-classes page and adds accent borders/tints.
src/app/(dashboard)/live-classes/breadcrumb.module.css Tokenizes breadcrumb font sizing and colors.
src/app/(dashboard)/live-classes/[id]/register-button.module.css Tokenizes register error UI styling.
src/app/(dashboard)/live-classes/[id]/detail.module.css Tokenizes live-class detail colors and gradients.
src/app/(dashboard)/layout.module.css Switches dashboard shell min-height to 100dvh.
src/app/(dashboard)/dashboard/dashboard.module.css Adds tinted container and accent borders to dashboard stats.
src/app/(dashboard)/courses/[courseSlug]/certificate/certificate.module.css Tokenizes certificate page styling and rhythm.
src/app/(dashboard)/certificates/certificates.module.css Adjusts padding and adds tinted empty-state/card accents.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread src/app/layout.tsx
Comment on lines +34 to 47
images: [
{
url: '/og.png',
width: 1200,
height: 630,
alt: `${BRAND_NAME} - Amazon PPC Training`,
},
],
},
icons: {
icon: '/favicon.ico',
shortcut: '/favicon-16x16.png',
apple: '/apple-touch-icon.png',
},
Comment thread src/app/loading.tsx
Comment on lines +5 to +6
<main id="main-content" className={styles.page}>
<div className={styles.hero}>
Comment on lines 1 to 4
.page {
min-height: 100vh;
min-height: 100dvh;
background: #fafafa;
}
Comment on lines 113 to 115
.joinLink:hover {
background: #059669;
background: var(--success);
}
Comment thread src/styles/globals.css
Comment on lines 120 to +144
}

/* ── Alias tokens (used by admin, tools, live-classes, refunds) ── */
--color-text: var(--ink-900);
--color-text-muted: var(--ink-500);
--color-surface: var(--surface-1);
--color-surface-elevated: var(--surface-2);
--color-bg: var(--surface-0);
--color-border: var(--border);
--color-accent: var(--accent);
--color-accent-bg: var(--accent-soft);
--color-primary: var(--accent);
--color-success: var(--success);
--color-danger: var(--danger);
--success-bg: var(--success-soft);
--warning-bg: var(--warning-soft);
--info-bg: var(--info-soft);
--danger-bg: var(--danger-soft);
--warning-600: var(--warning);
--info-600: var(--info);
--accent-strong: var(--accent-hover);
--surface-on-accent: var(--accent-ink);

/* Subtle tint for alternating sections */
--surface-tint: #F0EFE9;
padding: var(--space-2) var(--space-4);
background: var(--color-accent);
color: #fff;
color: var(--ink-inverse);
padding: var(--space-2) var(--space-4);
background: var(--color-accent);
color: #fff;
color: var(--ink-inverse);
@coderabbitai

coderabbitai Bot commented Jul 20, 2026

Copy link
Copy Markdown

Review Change Stack

📝 Walkthrough

Walkthrough

The pull request standardizes interface styling around shared design tokens, updates viewport sizing and responsive surfaces, adds branded loading and not-found states, extends metadata icons and Open Graph data, and adds a pending-refund badge to the admin quick actions.

Changes

UI refresh

Layer / File(s) Summary
Shared design tokens
src/styles/globals.css
Adds semantic token aliases, light/dark surface tint values, and balanced heading wrapping.
Dashboard and admin presentation
src/app/(dashboard)/certificates/..., src/app/(dashboard)/courses/..., src/app/(dashboard)/dashboard/..., src/app/admin/..., src/components/tools/*
Migrates dashboard and administrative interfaces to shared tokens, updates viewport sizing, and displays pending refund counts in the admin quick action.
Live classes and payment styling
src/app/(dashboard)/live-classes/..., src/app/(dashboard)/payments/...
Tokenizes live-class, registration, and refund-request spacing, typography, colors, borders, and interactions.
Public pages and loading states
src/app/home.module.css, src/app/loading*, src/app/not-found.tsx, src/app/layout.tsx, src/app/page.tsx, src/app/(public)/..., src/app/verify/..., src/components/ui/NavSidebar.module.css
Updates landing-page sections, viewport sizing, metadata, hero copy, loading skeletons, not-found presentation, and public responsive styling.

Estimated code review effort: 3 (Moderate) | ~30 minutes

Possibly related PRs

Suggested reviewers: copilot

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately reflects the PR’s focus on design-system cleanup, spacing/visual rhythm, accessibility, and polish.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch fix/design-review-visual-rhythm

Comment @coderabbitai help to get the list of available commands.

@coderabbitai

coderabbitai Bot commented Jul 20, 2026

Copy link
Copy Markdown

Review Change Stack

📝 Walkthrough

Walkthrough

The PR standardizes UI styling around shared design tokens, updates dashboard and public-page layouts, adds skeleton loading and branded not-found states, improves metadata, and surfaces pending refunds in the admin quick actions.

Changes

UI refresh

Layer / File(s) Summary
Shared design tokens
src/styles/globals.css
Adds semantic color aliases, surface tint values with dark-mode support, and balanced heading wrapping.
Dashboard and admin presentation
src/app/(dashboard)/certificates/..., src/app/(dashboard)/courses/..., src/app/(dashboard)/dashboard/..., src/app/admin/...
Tokenizes certificate, dashboard, refund, and user-management styles, updates viewport sizing, and adds a conditional pending-refund badge to the admin quick action.
Live classes and payment styling
src/app/(dashboard)/live-classes/..., src/app/(dashboard)/payments/...
Replaces fixed spacing, typography, colors, borders, radii, and transitions with shared design tokens.
Public pages and loading states
src/app/home.module.css, src/app/loading*, src/app/not-found.tsx, src/app/layout.tsx, src/app/page.tsx, src/app/(public)/..., src/components/...
Updates landing-page sections, dynamic viewport layouts, metadata, hero copy, loading skeletons, not-found presentation, and themed action colors.

Estimated code review effort: 3 (Moderate) | ~25 minutes

Possibly related PRs

Suggested reviewers: copilot

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately summarizes the PR’s main design-token, accessibility, and visual polish updates.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch fix/design-review-visual-rhythm

Comment @coderabbitai help to get the list of available commands.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 7

🧹 Nitpick comments (5)
src/app/admin/refunds/[id]/detail.module.css (2)

91-91: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Hardcoded 22px font-size in an otherwise tokenized block.

.amountValue uses font-size: 22px while surrounding properties were migrated to tokens. Consider using var(--text-2xl) or a nearby token for consistency.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/app/admin/refunds/`[id]/detail.module.css at line 91, Update the
font-size declaration in the .amountValue style to use the appropriate existing
typography token, such as --text-2xl, instead of the hardcoded 22px value.

220-220: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Hardcoded accent rgba in focus shadow.

rgba(255, 107, 53, 0.15) is the accent color (#FF6B35) with 15% opacity, inlined directly. If the accent token changes, this shadow won't follow. Consider defining a --accent-glow or similar token for focus ring shadows.

Use a token for the accent focus shadow
 .textarea:focus {
   outline: none;
   border-color: var(--accent);
-  box-shadow: 0 0 0 3px rgba(255, 107, 53, 0.15);
+  box-shadow: 0 0 0 3px var(--accent-glow, rgba(255, 107, 53, 0.15));
 }
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/app/admin/refunds/`[id]/detail.module.css at line 220, Replace the
hardcoded accent rgba value in the focus shadow with a reusable accent glow CSS
custom property, defining it in the relevant stylesheet scope and referencing it
from the box-shadow declaration so accent color changes propagate consistently.
src/app/admin/refunds/refunds.module.css (1)

33-33: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Hardcoded 15px font-size in an otherwise tokenized block.

.subtitle uses font-size: 15px while surrounding properties were migrated to tokens. Consider using var(--text-sm) or var(--text-base) for consistency.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/app/admin/refunds/refunds.module.css` at line 33, Update the .subtitle
font-size declaration to use the established typography token, choosing the
appropriate --text-sm or --text-base value instead of the hardcoded 15px while
preserving the surrounding styles.
src/app/not-found.tsx (1)

8-56: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Consider extracting inline styles to a CSS module.

The 404 page uses inline styles with design tokens, which works but is inconsistent with the rest of the codebase's CSS module pattern. Extracting to a module would improve maintainability and make it easier to apply responsive adjustments.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/app/not-found.tsx` around lines 8 - 56, Update the NotFound component to
replace its inline style objects with class names backed by a dedicated CSS
module, preserving the existing layout, design tokens, typography, spacing, and
link appearance. Keep the existing BRAND_NAME and navigation behavior unchanged,
and define the extracted styles in the module so responsive adjustments can be
added consistently.
src/app/(dashboard)/payments/[id]/request-refund/request-refund.module.css (1)

137-141: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Hardcoded RGBA in focus ring box-shadow.

rgba(255, 107, 53, 0.15) is the accent color (#FF6B35) with 15% opacity, hardcoded rather than tokenized. If the accent ever changes in dark mode, this focus ring won't adapt. Consider using color-mix or a dedicated --accent-focus-ring token.

Proposed refactor using color-mix
 .textarea:focus {
   outline: none;
   border-color: var(--accent);
-  box-shadow: 0 0 0 3px rgba(255, 107, 53, 0.15);
+  box-shadow: 0 0 0 3px color-mix(in srgb, var(--accent) 15%, transparent);
 }
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/app/`(dashboard)/payments/[id]/request-refund/request-refund.module.css
around lines 137 - 141, Replace the hardcoded rgba value in the .textarea:focus
box-shadow with a tokenized accent-based color, using color-mix or the
existing/dedicated --accent-focus-ring variable, so the focus ring adapts when
--accent changes, including in dark mode. Preserve the current focus-ring size
and opacity appearance.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@src/app/`(dashboard)/live-classes/[id]/detail.module.css:
- Around line 114-115: Update the .joinLink:hover rule to use a distinct success
shade or opacity from the base .joinLink background, preserving the existing
hover selector and ensuring hovering produces a visible visual change.
- Around line 103-104: Update the `.joinLink` color declaration to use the
shared `var(--ink-inverse)` token instead of the hardcoded white value, while
preserving its existing `--success` background.

In `@src/app/admin/refunds/`[id]/detail.module.css:
- Line 154: Update the .code class font-family declaration to use JetBrains Mono
as the sole font, removing the other fallback fonts and unnecessary quotes to
comply with the design system.

In `@src/app/home.module.css`:
- Around line 144-158: Update the mobile `.heroDecorative` styles to allow its
salary/caption content to wrap and constrain the flex item to the available
viewport width, preventing horizontal overflow. Preserve the existing desktop
styling and breakpoint-specific caption behavior.

In `@src/app/loading.tsx`:
- Around line 3-18: Update the Loading component to mark the loading region with
aria-busy="true" and add a visually hidden role="status" element containing a
loading message, while preserving the skeleton visuals. Define the required
srOnly utility in the loading module stylesheet and apply it to the status
element.

In `@src/app/verify/`[hash]/verify.module.css:
- Around line 2-3: Update the .page background declaration to use the existing
surface design token, such as var(--surface-0), instead of the hardcoded `#fafafa`
value. Leave the min-height declaration unchanged.

In `@src/styles/globals.css`:
- Around line 122-145: Move the alias token declarations, including
--surface-tint, into the existing :root block in the global stylesheet, before
its closing brace. Keep their values unchanged so consumers such as the
analytics stylesheet resolve the aliases correctly.

---

Nitpick comments:
In `@src/app/`(dashboard)/payments/[id]/request-refund/request-refund.module.css:
- Around line 137-141: Replace the hardcoded rgba value in the .textarea:focus
box-shadow with a tokenized accent-based color, using color-mix or the
existing/dedicated --accent-focus-ring variable, so the focus ring adapts when
--accent changes, including in dark mode. Preserve the current focus-ring size
and opacity appearance.

In `@src/app/admin/refunds/`[id]/detail.module.css:
- Line 91: Update the font-size declaration in the .amountValue style to use the
appropriate existing typography token, such as --text-2xl, instead of the
hardcoded 22px value.
- Line 220: Replace the hardcoded accent rgba value in the focus shadow with a
reusable accent glow CSS custom property, defining it in the relevant stylesheet
scope and referencing it from the box-shadow declaration so accent color changes
propagate consistently.

In `@src/app/admin/refunds/refunds.module.css`:
- Line 33: Update the .subtitle font-size declaration to use the established
typography token, choosing the appropriate --text-sm or --text-base value
instead of the hardcoded 15px while preserving the surrounding styles.

In `@src/app/not-found.tsx`:
- Around line 8-56: Update the NotFound component to replace its inline style
objects with class names backed by a dedicated CSS module, preserving the
existing layout, design tokens, typography, spacing, and link appearance. Keep
the existing BRAND_NAME and navigation behavior unchanged, and define the
extracted styles in the module so responsive adjustments can be added
consistently.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: a9355610-2d13-4800-8c43-49d66e0ea72f

📥 Commits

Reviewing files that changed from the base of the PR and between 78f1931 and 8dc5863.

📒 Files selected for processing (29)
  • src/app/(dashboard)/certificates/certificates.module.css
  • src/app/(dashboard)/courses/[courseSlug]/certificate/certificate.module.css
  • src/app/(dashboard)/dashboard/dashboard.module.css
  • src/app/(dashboard)/layout.module.css
  • src/app/(dashboard)/live-classes/[id]/detail.module.css
  • src/app/(dashboard)/live-classes/[id]/register-button.module.css
  • src/app/(dashboard)/live-classes/breadcrumb.module.css
  • src/app/(dashboard)/live-classes/live-classes.module.css
  • src/app/(dashboard)/payments/[id]/request-refund/request-refund.module.css
  • src/app/(public)/auth/signin/auth.module.css
  • src/app/(public)/pricing/pricing.module.css
  • src/app/admin/layout.module.css
  • src/app/admin/page.module.css
  • src/app/admin/page.tsx
  • src/app/admin/refunds/[id]/detail.module.css
  • src/app/admin/refunds/refunds.module.css
  • src/app/admin/users/[id]/user-detail.module.css
  • src/app/admin/users/users.module.css
  • src/app/home.module.css
  • src/app/layout.tsx
  • src/app/loading.module.css
  • src/app/loading.tsx
  • src/app/not-found.tsx
  • src/app/page.tsx
  • src/app/verify/[hash]/verify.module.css
  • src/components/tools/KeywordResearchRunner.module.css
  • src/components/tools/StrTriageRunner.module.css
  • src/components/ui/NavSidebar.module.css
  • src/styles/globals.css

Comment on lines +103 to 104
background: var(--success);
color: white;

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

Tokenize color: white on .joinLink.

The PR tokenizes button text colors across all files to var(--ink-inverse), but .joinLink still uses color: white. In dark mode, --ink-inverse resolves to #171717 (dark), so white will produce low contrast against the --success background.

Proposed fix
 .joinLink {
   display: inline-flex;
   align-items: center;
   gap: 8px;
   padding: 12px 16px;
   background: var(--success);
-  color: white;
+  color: var(--ink-inverse);
   text-decoration: none;
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
background: var(--success);
color: white;
background: var(--success);
color: var(--ink-inverse);
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/app/`(dashboard)/live-classes/[id]/detail.module.css around lines 103 -
104, Update the `.joinLink` color declaration to use the shared
`var(--ink-inverse)` token instead of the hardcoded white value, while
preserving its existing `--success` background.

Comment on lines +114 to 115
background: var(--success);
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

.joinLink:hover has no visual effect.

Both .joinLink (line 103) and .joinLink:hover (line 114) set background: var(--success), so hovering produces no change. If a hover effect is intended, use a different shade or opacity.

Proposed fix
 .joinLink:hover {
-  background: var(--success);
+  opacity: 0.85;
 }
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
background: var(--success);
}
.joinLink:hover {
opacity: 0.85;
}
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/app/`(dashboard)/live-classes/[id]/detail.module.css around lines 114 -
115, Update the .joinLink:hover rule to use a distinct success shade or opacity
from the base .joinLink background, preserving the existing hover selector and
ensuring hovering produces a visible visual change.

}

.code {
font-family: 'SF Mono', 'Monaco', 'Inconsolata', 'Fira Code', monospace;

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

📐 Maintainability & Code Quality | 🟠 Major | ⚡ Quick win

Font family violates design system guideline.

The .code class uses SF Mono, Monaco, Inconsolata, and Fira Code instead of JetBrains Mono. As per coding guidelines, product UI must use only Space Grotesk and JetBrains Mono. Stylelint also flags unnecessary quotes around Monaco and Inconsolata.

Fix font family to use JetBrains Mono per design system
 .code {
-  font-family: 'SF Mono', 'Monaco', 'Inconsolata', 'Fira Code', monospace;
+  font-family: var(--font-mono, 'JetBrains Mono', monospace);
   font-size: var(--text-sm);
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
font-family: 'SF Mono', 'Monaco', 'Inconsolata', 'Fira Code', monospace;
font-family: var(--font-mono, 'JetBrains Mono', monospace);
🧰 Tools
🪛 Stylelint (17.14.0)

[error] 154-154: Expected no quotes around "Monaco" (font-family-name-quotes)

(font-family-name-quotes)


[error] 154-154: Expected no quotes around "Inconsolata" (font-family-name-quotes)

(font-family-name-quotes)

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/app/admin/refunds/`[id]/detail.module.css at line 154, Update the .code
class font-family declaration to use JetBrains Mono as the sole font, removing
the other fallback fonts and unnecessary quotes to comply with the design
system.

Sources: Coding guidelines, Linters/SAST tools

Comment thread src/app/home.module.css
Comment on lines 144 to +158
.heroDecorative {
display: none;
display: flex;
flex-direction: column;
align-items: center;
gap: var(--space-2);
font-family: var(--font-mono);
font-size: var(--text-2xl);
font-weight: 700;
color: var(--accent);
background: var(--accent-soft);
padding: var(--space-4) var(--space-6);
border-radius: var(--radius-lg);
white-space: nowrap;
margin-top: var(--space-4);
animation: fadeInUp var(--duration-slow) var(--ease-out) 360ms both;

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

Prevent mobile hero overflow.

.heroDecorative is newly visible on mobile but keeps white-space: nowrap; the caption’s white-space: normal override only appears at the desktop breakpoint. A longer salary value or caption can widen the flex item beyond a narrow viewport and create horizontal scrolling. Add a mobile wrapping and width constraint.

Based on the PR objective to display the hero salary statistic on mobile, this needs a mobile wrapping rule.

Suggested fix
+@media (max-width: 767px) {
+  .heroDecorative {
+    max-width: 100%;
+    white-space: normal;
+    text-align: center;
+  }
+
+  .heroDecorativeCaption {
+    white-space: normal;
+  }
+}
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
.heroDecorative {
display: none;
display: flex;
flex-direction: column;
align-items: center;
gap: var(--space-2);
font-family: var(--font-mono);
font-size: var(--text-2xl);
font-weight: 700;
color: var(--accent);
background: var(--accent-soft);
padding: var(--space-4) var(--space-6);
border-radius: var(--radius-lg);
white-space: nowrap;
margin-top: var(--space-4);
animation: fadeInUp var(--duration-slow) var(--ease-out) 360ms both;
.heroDecorative {
display: flex;
flex-direction: column;
align-items: center;
gap: var(--space-2);
font-family: var(--font-mono);
font-size: var(--text-2xl);
font-weight: 700;
color: var(--accent);
background: var(--accent-soft);
padding: var(--space-4) var(--space-6);
border-radius: var(--radius-lg);
white-space: nowrap;
margin-top: var(--space-4);
animation: fadeInUp var(--duration-slow) var(--ease-out) 360ms both;
}
`@media` (max-width: 767px) {
.heroDecorative {
max-width: 100%;
white-space: normal;
text-align: center;
}
.heroDecorativeCaption {
white-space: normal;
}
}
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/app/home.module.css` around lines 144 - 158, Update the mobile
`.heroDecorative` styles to allow its salary/caption content to wrap and
constrain the flex item to the available viewport width, preventing horizontal
overflow. Preserve the existing desktop styling and breakpoint-specific caption
behavior.

Comment thread src/app/loading.tsx
Comment on lines 3 to +18
export default function Loading() {
return (
<main style={{ padding: 'var(--space-8)', textAlign: 'center' }}>
<p>Loading...</p>
<main id="main-content" className={styles.page}>
<div className={styles.hero}>
<div className={styles.heroText}>
<div className={`${styles.skeleton} ${styles.eyebrow}`} />
<div className={`${styles.skeleton} ${styles.title}`} />
<div className={`${styles.skeleton} ${styles.subtitle}`} />
<div className={`${styles.skeleton} ${styles.subtitleShort}`} />
<div className={styles.actions}>
<div className={`${styles.skeleton} ${styles.btn}`} />
<div className={`${styles.skeleton} ${styles.btnGhost}`} />
</div>
</div>
<div className={`${styles.skeleton} ${styles.heroStat}`} />
</div>

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

Preserve an accessible loading status.

Replacing the visible Loading... text with empty skeleton <div> elements removes feedback for screen-reader users. Add aria-busy="true" and a visually hidden role="status" message.

Suggested fix
-    <main id="main-content" className={styles.page}>
+    <main id="main-content" className={styles.page} aria-busy="true">
+      <p className={styles.srOnly} role="status">
+        Loading...
+      </p>
       <div className={styles.hero}>

Add an .srOnly utility to src/app/loading.module.css.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/app/loading.tsx` around lines 3 - 18, Update the Loading component to
mark the loading region with aria-busy="true" and add a visually hidden
role="status" element containing a loading message, while preserving the
skeleton visuals. Define the required srOnly utility in the loading module
stylesheet and apply it to the status element.

Comment on lines +2 to 3
min-height: 100dvh;
background: #fafafa;

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win

Hardcoded #fafafa background not tokenized.

The PR's objective is to replace hardcoded color references with design tokens, but .page still uses background: #fafafa``. This should use a surface token (e.g., var(--surface-0)) for consistency with the rest of the design system.

Replace hardcoded background with surface token
 .page {
   min-height: 100dvh;
-  background: `#fafafa`;
+  background: var(--surface-0);
 }
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
min-height: 100dvh;
background: #fafafa;
min-height: 100dvh;
background: var(--surface-0);
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/app/verify/`[hash]/verify.module.css around lines 2 - 3, Update the .page
background declaration to use the existing surface design token, such as
var(--surface-0), instead of the hardcoded `#fafafa` value. Leave the min-height
declaration unchanged.

Comment thread src/styles/globals.css
Comment on lines +122 to +145
/* ── Alias tokens (used by admin, tools, live-classes, refunds) ── */
--color-text: var(--ink-900);
--color-text-muted: var(--ink-500);
--color-surface: var(--surface-1);
--color-surface-elevated: var(--surface-2);
--color-bg: var(--surface-0);
--color-border: var(--border);
--color-accent: var(--accent);
--color-accent-bg: var(--accent-soft);
--color-primary: var(--accent);
--color-success: var(--success);
--color-danger: var(--danger);
--success-bg: var(--success-soft);
--warning-bg: var(--warning-soft);
--info-bg: var(--info-soft);
--danger-bg: var(--danger-soft);
--warning-600: var(--warning);
--info-600: var(--info);
--accent-strong: var(--accent-hover);
--surface-on-accent: var(--accent-ink);

/* Subtle tint for alternating sections */
--surface-tint: #F0EFE9;

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🎯 Functional Correctness | 🟠 Major | ⚡ Quick win

Move the alias tokens inside :root.

The preceding :root block closes before these declarations, so the browser discards them as invalid top-level declarations. This leaves every --color-* alias and the light-mode --surface-tint undefined, breaking consumers such as src/app/admin/analytics/analytics.module.css.

Proposed fix
+:root {
   /* ── Alias tokens (used by admin, tools, live-classes, refunds) ── */
   --color-text: var(--ink-900);
   --color-text-muted: var(--ink-500);
   --color-surface: var(--surface-1);
   --color-surface-elevated: var(--surface-2);
   --color-bg: var(--surface-0);
   --color-border: var(--border);
   --color-accent: var(--accent);
   --color-accent-bg: var(--accent-soft);
   --color-primary: var(--accent);
   --color-success: var(--success);
   --color-danger: var(--danger);
   --success-bg: var(--success-soft);
   --warning-bg: var(--warning-soft);
   --info-bg: var(--info-soft);
   --danger-bg: var(--danger-soft);
   --warning-600: var(--warning);
   --info-600: var(--info);
   --accent-strong: var(--accent-hover);
   --surface-on-accent: var(--accent-ink);

   /* Subtle tint for alternating sections */
   --surface-tint: `#F0EFE9`;
+}

Static analysis reports no-invalid-position-declaration on these lines, and the downstream analytics stylesheet consumes the affected aliases.

📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
/* ── Alias tokens (used by admin, tools, live-classes, refunds) ── */
--color-text: var(--ink-900);
--color-text-muted: var(--ink-500);
--color-surface: var(--surface-1);
--color-surface-elevated: var(--surface-2);
--color-bg: var(--surface-0);
--color-border: var(--border);
--color-accent: var(--accent);
--color-accent-bg: var(--accent-soft);
--color-primary: var(--accent);
--color-success: var(--success);
--color-danger: var(--danger);
--success-bg: var(--success-soft);
--warning-bg: var(--warning-soft);
--info-bg: var(--info-soft);
--danger-bg: var(--danger-soft);
--warning-600: var(--warning);
--info-600: var(--info);
--accent-strong: var(--accent-hover);
--surface-on-accent: var(--accent-ink);
/* Subtle tint for alternating sections */
--surface-tint: #F0EFE9;
:root {
/* ── Alias tokens (used by admin, tools, live-classes, refunds) ── */
--color-text: var(--ink-900);
--color-text-muted: var(--ink-500);
--color-surface: var(--surface-1);
--color-surface-elevated: var(--surface-2);
--color-bg: var(--surface-0);
--color-border: var(--border);
--color-accent: var(--accent);
--color-accent-bg: var(--accent-soft);
--color-primary: var(--accent);
--color-success: var(--success);
--color-danger: var(--danger);
--success-bg: var(--success-soft);
--warning-bg: var(--warning-soft);
--info-bg: var(--info-soft);
--danger-bg: var(--danger-soft);
--warning-600: var(--warning);
--info-600: var(--info);
--accent-strong: var(--accent-hover);
--surface-on-accent: var(--accent-ink);
/* Subtle tint for alternating sections */
--surface-tint: `#F0EFE9`;
}
🧰 Tools
🪛 Stylelint (17.14.0)

[error] 123-123: Invalid position for declaration (no-invalid-position-declaration)

(no-invalid-position-declaration)


[error] 124-124: Invalid position for declaration (no-invalid-position-declaration)

(no-invalid-position-declaration)


[error] 125-125: Invalid position for declaration (no-invalid-position-declaration)

(no-invalid-position-declaration)


[error] 126-126: Invalid position for declaration (no-invalid-position-declaration)

(no-invalid-position-declaration)


[error] 127-127: Invalid position for declaration (no-invalid-position-declaration)

(no-invalid-position-declaration)


[error] 128-128: Invalid position for declaration (no-invalid-position-declaration)

(no-invalid-position-declaration)


[error] 129-129: Invalid position for declaration (no-invalid-position-declaration)

(no-invalid-position-declaration)


[error] 130-130: Invalid position for declaration (no-invalid-position-declaration)

(no-invalid-position-declaration)


[error] 131-131: Invalid position for declaration (no-invalid-position-declaration)

(no-invalid-position-declaration)


[error] 132-132: Invalid position for declaration (no-invalid-position-declaration)

(no-invalid-position-declaration)


[error] 133-133: Invalid position for declaration (no-invalid-position-declaration)

(no-invalid-position-declaration)


[error] 134-134: Invalid position for declaration (no-invalid-position-declaration)

(no-invalid-position-declaration)


[error] 135-135: Invalid position for declaration (no-invalid-position-declaration)

(no-invalid-position-declaration)


[error] 136-136: Invalid position for declaration (no-invalid-position-declaration)

(no-invalid-position-declaration)


[error] 137-137: Invalid position for declaration (no-invalid-position-declaration)

(no-invalid-position-declaration)


[error] 138-138: Invalid position for declaration (no-invalid-position-declaration)

(no-invalid-position-declaration)


[error] 139-139: Invalid position for declaration (no-invalid-position-declaration)

(no-invalid-position-declaration)


[error] 140-140: Invalid position for declaration (no-invalid-position-declaration)

(no-invalid-position-declaration)


[error] 141-141: Invalid position for declaration (no-invalid-position-declaration)

(no-invalid-position-declaration)


[error] 144-144: Invalid position for declaration (no-invalid-position-declaration)

(no-invalid-position-declaration)

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/styles/globals.css` around lines 122 - 145, Move the alias token
declarations, including --surface-tint, into the existing :root block in the
global stylesheet, before its closing brace. Keep their values unchanged so
consumers such as the analytics stylesheet resolve the aliases correctly.

Source: Linters/SAST tools

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 5

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (2)
src/app/(dashboard)/live-classes/[id]/detail.module.css (1)

103-115: 🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

Restore a distinct hover state for the Join link.

Both the default and hover rules use var(--success), so hovering gives no visible feedback. Use a distinct success-hover token or another non-color-changing interaction treatment.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/app/`(dashboard)/live-classes/[id]/detail.module.css around lines 103 -
115, Update the .joinLink:hover rule to provide visible hover feedback instead
of reusing var(--success); use the existing success-hover design token if
available, or apply another non-color-changing interaction treatment while
preserving the default .joinLink styling.
src/app/admin/page.tsx (1)

171-180: 🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

Add Playwright coverage for the pending-refund badge.

Cover both zero and nonzero pending counts, including the displayed count and refunds link. As per coding guidelines, “New features must include tests; admin and business-layer features require tests.” Based on learnings, cover this server-page flow in Playwright.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/app/admin/page.tsx` around lines 171 - 180, Add Playwright coverage for
the admin page flow rendering the pending-refund badge near the “Review Refunds”
link. Verify that zero pending refunds hides the badge, while a nonzero count
displays the exact count and the refunds link points to /admin/refunds; exercise
the server-rendered page behavior through the existing Playwright setup.

Sources: Coding guidelines, Learnings

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@src/app/`(dashboard)/payments/[id]/request-refund/request-refund.module.css:
- Line 25: Update the display font declaration in the module, including the
corresponding occurrence, to use only the approved display font token without a
generic fallback. Ensure the shared font definition permits only Space Grotesk
and JetBrains Mono, with no system-font fallback.

In `@src/app/admin/refunds/`[id]/detail.module.css:
- Around line 153-160: Update the .code style rule to use JetBrains Mono as the
monospace font, removing the unapproved fallback families and quoted single-word
names so the declaration conforms to the approved UI font set and Stylelint
rules.

In `@src/app/loading.tsx`:
- Around line 3-18: Extend the existing Playwright flow to cover both route
states: verify navigation displays the loading fallback from Loading, and verify
an unknown route renders the not-found page with a working home link. Add
coverage for src/app/loading.tsx lines 3-18 and src/app/not-found.tsx lines
8-56; do not introduce page-rendering unit-test infrastructure.

In `@src/components/tools/KeywordResearchRunner.module.css`:
- Around line 188-192: Add a dedicated light `--ink-on-status` token and replace
`--ink-inverse` with it in `.prioritySECONDARY` in
`src/components/tools/KeywordResearchRunner.module.css` (lines 188-192) and
`.actionoptimize`/`.actionpause` in
`src/components/tools/StrTriageRunner.module.css` (lines 228-238), preserving
the existing status button backgrounds and borders.

In `@src/styles/globals.css`:
- Around line 122-145: Move the alias token declarations, including
--surface-tint, into the existing :root selector in globals.css so they are
valid custom properties and apply globally; preserve the existing dark-mode
override unchanged.

---

Outside diff comments:
In `@src/app/`(dashboard)/live-classes/[id]/detail.module.css:
- Around line 103-115: Update the .joinLink:hover rule to provide visible hover
feedback instead of reusing var(--success); use the existing success-hover
design token if available, or apply another non-color-changing interaction
treatment while preserving the default .joinLink styling.

In `@src/app/admin/page.tsx`:
- Around line 171-180: Add Playwright coverage for the admin page flow rendering
the pending-refund badge near the “Review Refunds” link. Verify that zero
pending refunds hides the badge, while a nonzero count displays the exact count
and the refunds link points to /admin/refunds; exercise the server-rendered page
behavior through the existing Playwright setup.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: a9355610-2d13-4800-8c43-49d66e0ea72f

📥 Commits

Reviewing files that changed from the base of the PR and between 78f1931 and 8dc5863.

📒 Files selected for processing (29)
  • src/app/(dashboard)/certificates/certificates.module.css
  • src/app/(dashboard)/courses/[courseSlug]/certificate/certificate.module.css
  • src/app/(dashboard)/dashboard/dashboard.module.css
  • src/app/(dashboard)/layout.module.css
  • src/app/(dashboard)/live-classes/[id]/detail.module.css
  • src/app/(dashboard)/live-classes/[id]/register-button.module.css
  • src/app/(dashboard)/live-classes/breadcrumb.module.css
  • src/app/(dashboard)/live-classes/live-classes.module.css
  • src/app/(dashboard)/payments/[id]/request-refund/request-refund.module.css
  • src/app/(public)/auth/signin/auth.module.css
  • src/app/(public)/pricing/pricing.module.css
  • src/app/admin/layout.module.css
  • src/app/admin/page.module.css
  • src/app/admin/page.tsx
  • src/app/admin/refunds/[id]/detail.module.css
  • src/app/admin/refunds/refunds.module.css
  • src/app/admin/users/[id]/user-detail.module.css
  • src/app/admin/users/users.module.css
  • src/app/home.module.css
  • src/app/layout.tsx
  • src/app/loading.module.css
  • src/app/loading.tsx
  • src/app/not-found.tsx
  • src/app/page.tsx
  • src/app/verify/[hash]/verify.module.css
  • src/components/tools/KeywordResearchRunner.module.css
  • src/components/tools/StrTriageRunner.module.css
  • src/components/ui/NavSidebar.module.css
  • src/styles/globals.css

}

.title {
font-family: var(--font-display, 'Space Grotesk', sans-serif);

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win

Remove the generic font fallback.

sans-serif can resolve to a system font. Use the approved display token without a generic fallback, and ensure its shared definition only permits the approved families.

As per coding guidelines, “Use Space Grotesk and JetBrains Mono only in product UI. Do not use Inter or system fonts.”

Also applies to: 76-76

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/app/`(dashboard)/payments/[id]/request-refund/request-refund.module.css
at line 25, Update the display font declaration in the module, including the
corresponding occurrence, to use only the approved display font token without a
generic fallback. Ensure the shared font definition permits only Space Grotesk
and JetBrains Mono, with no system-font fallback.

Source: Coding guidelines

Comment on lines 153 to 160
.code {
font-family: 'SF Mono', 'Monaco', 'Inconsolata', 'Fira Code', monospace;
font-size: 13px;
background: var(--color-surface-elevated, #f7f7fb);
font-size: var(--text-sm);
background: var(--surface-2);
padding: 2px 6px;
border-radius: 4px;
word-break: break-all;
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🎯 Functional Correctness | 🟠 Major | ⚡ Quick win

Use JetBrains Mono for inline code.

This stack violates the approved UI font set and fails Stylelint on the quoted single-word family names.

Proposed fix
 .code {
-  font-family: 'SF Mono', 'Monaco', 'Inconsolata', 'Fira Code', monospace;
+  font-family: 'JetBrains Mono';

As per coding guidelines, product UI must use Space Grotesk and JetBrains Mono only.

📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
.code {
font-family: 'SF Mono', 'Monaco', 'Inconsolata', 'Fira Code', monospace;
font-size: 13px;
background: var(--color-surface-elevated, #f7f7fb);
font-size: var(--text-sm);
background: var(--surface-2);
padding: 2px 6px;
border-radius: 4px;
word-break: break-all;
}
.code {
font-family: 'JetBrains Mono';
font-size: var(--text-sm);
background: var(--surface-2);
padding: 2px 6px;
border-radius: 4px;
word-break: break-all;
}
🧰 Tools
🪛 Stylelint (17.14.0)

[error] 154-154: Expected no quotes around "Monaco" (font-family-name-quotes)

(font-family-name-quotes)


[error] 154-154: Expected no quotes around "Inconsolata" (font-family-name-quotes)

(font-family-name-quotes)

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/app/admin/refunds/`[id]/detail.module.css around lines 153 - 160, Update
the .code style rule to use JetBrains Mono as the monospace font, removing the
unapproved fallback families and quoted single-word names so the declaration
conforms to the approved UI font set and Stylelint rules.

Sources: Coding guidelines, Linters/SAST tools

Comment thread src/app/loading.tsx
Comment on lines 3 to +18
export default function Loading() {
return (
<main style={{ padding: 'var(--space-8)', textAlign: 'center' }}>
<p>Loading...</p>
<main id="main-content" className={styles.page}>
<div className={styles.hero}>
<div className={styles.heroText}>
<div className={`${styles.skeleton} ${styles.eyebrow}`} />
<div className={`${styles.skeleton} ${styles.title}`} />
<div className={`${styles.skeleton} ${styles.subtitle}`} />
<div className={`${styles.skeleton} ${styles.subtitleShort}`} />
<div className={styles.actions}>
<div className={`${styles.skeleton} ${styles.btn}`} />
<div className={`${styles.skeleton} ${styles.btnGhost}`} />
</div>
</div>
<div className={`${styles.skeleton} ${styles.heroStat}`} />
</div>

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

Add Playwright coverage for the new route states.

  • src/app/loading.tsx#L3-L18: cover the loading fallback during navigation.
  • src/app/not-found.tsx#L8-L56: cover an unknown route returning the 404 page and its home link.

As per coding guidelines, “New features must include tests.” Based on learnings, use the existing Playwright flow rather than adding page-rendering unit-test infrastructure.

📍 Affects 2 files
  • src/app/loading.tsx#L3-L18 (this comment)
  • src/app/not-found.tsx#L8-L56
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/app/loading.tsx` around lines 3 - 18, Extend the existing Playwright flow
to cover both route states: verify navigation displays the loading fallback from
Loading, and verify an unknown route renders the not-found page with a working
home link. Add coverage for src/app/loading.tsx lines 3-18 and
src/app/not-found.tsx lines 8-56; do not introduce page-rendering unit-test
infrastructure.

Sources: Coding guidelines, Learnings

Comment on lines 188 to 192
.prioritySECONDARY {
background: var(--info, #2563eb);
color: #fff;
color: var(--ink-inverse);
border-color: var(--info, #2563eb);
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🎯 Functional Correctness | 🟠 Major | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
rg -n -C 3 -- '--(ink-inverse|info|ink-500)\s*:' src/styles/globals.css

Repository: projectamazonph/amph-v2

Length of output: 737


🏁 Script executed:

#!/bin/bash
set -euo pipefail

printf '\n== Token definitions ==\n'
sed -n '1,220p' src/styles/globals.css | sed -n '1,80p'

printf '\n== KeywordResearchRunner.module.css relevant slice ==\n'
sed -n '160,210p' src/components/tools/KeywordResearchRunner.module.css

printf '\n== StrTriageRunner.module.css relevant slice ==\n'
sed -n '210,250p' src/components/tools/StrTriageRunner.module.css

printf '\n== Search for status foreground token ==\n'
rg -n -- '--ink-on-status|on-status|status foreground|status-foreground' src

Repository: projectamazonph/amph-v2

Length of output: 4295


🏁 Script executed:

python3 - <<'PY'
from math import pow

def hex_to_rgb(h):
    h = h.lstrip('#')
    return tuple(int(h[i:i+2], 16)/255 for i in (0,2,4))

def lum(rgb):
    def f(c): return c/12.92 if c <= 0.04045 else ((c+0.055)/1.055)**2.4
    r,g,b = map(f, rgb)
    return 0.2126*r + 0.7152*g + 0.0722*b

def contrast(a, b):
    la, lb = lum(hex_to_rgb(a)), lum(hex_to_rgb(b))
    hi, lo = max(la, lb), min(la, lb)
    return (hi + 0.05) / (lo + 0.05)

for fg, bg in [('`#171717`', '`#1E40AF`'), ('`#171717`', '`#64748B`')]:
    print(f"{fg} on {bg}: {contrast(fg, bg):.2f}:1")
PY

Repository: projectamazonph/amph-v2

Length of output: 215


Keep status-action text light in dark mode.

  • src/components/tools/KeywordResearchRunner.module.css#L188-L192: .prioritySECONDARY uses --ink-inverse, which becomes #171717 in dark mode and drops to 2.06:1 on --info.
  • src/components/tools/StrTriageRunner.module.css#L228-L238: .actionoptimize and .actionpause have the same problem; --ink-inverse lands at 3.77:1 on --ink-500.

Add a dedicated light --ink-on-status token and use it for these buttons.

📍 Affects 2 files
  • src/components/tools/KeywordResearchRunner.module.css#L188-L192 (this comment)
  • src/components/tools/StrTriageRunner.module.css#L228-L238
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/components/tools/KeywordResearchRunner.module.css` around lines 188 -
192, Add a dedicated light `--ink-on-status` token and replace `--ink-inverse`
with it in `.prioritySECONDARY` in
`src/components/tools/KeywordResearchRunner.module.css` (lines 188-192) and
`.actionoptimize`/`.actionpause` in
`src/components/tools/StrTriageRunner.module.css` (lines 228-238), preserving
the existing status button backgrounds and borders.

Comment thread src/styles/globals.css
Comment on lines +122 to +145
/* ── Alias tokens (used by admin, tools, live-classes, refunds) ── */
--color-text: var(--ink-900);
--color-text-muted: var(--ink-500);
--color-surface: var(--surface-1);
--color-surface-elevated: var(--surface-2);
--color-bg: var(--surface-0);
--color-border: var(--border);
--color-accent: var(--accent);
--color-accent-bg: var(--accent-soft);
--color-primary: var(--accent);
--color-success: var(--success);
--color-danger: var(--danger);
--success-bg: var(--success-soft);
--warning-bg: var(--warning-soft);
--info-bg: var(--info-soft);
--danger-bg: var(--danger-soft);
--warning-600: var(--warning);
--info-600: var(--info);
--accent-strong: var(--accent-hover);
--surface-on-accent: var(--accent-ink);

/* Subtle tint for alternating sections */
--surface-tint: #F0EFE9;

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

📐 Maintainability & Code Quality | 🟠 Major | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

# Locate the stylesheet and inspect the relevant ranges.
git ls-files src/styles/globals.css
echo
nl -ba src/styles/globals.css | sed -n '1,260p'

echo
# Find Stylelint config and any explicit handling for no-invalid-position-declaration.
git ls-files | grep -E '(^|/)\.(stylelintrc|stylelint|stylelint\.config)|stylelint'
echo
rg -n "no-invalid-position-declaration|custom-property|parser|postcss" -S . --glob '!**/node_modules/**' --glob '!**/dist/**' --glob '!**/build/**'

Repository: projectamazonph/amph-v2

Length of output: 225


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo '--- src/styles/globals.css (1-260) ---'
sed -n '1,260p' src/styles/globals.css | cat -n

echo
echo '--- stylelint config files ---'
find . -maxdepth 3 \( -name '.stylelintrc' -o -name '.stylelintrc.*' -o -name 'stylelint.config.*' -o -name 'stylelint*' \) | sort

echo
echo '--- stylelint-related matches ---'
rg -n "no-invalid-position-declaration|stylelint|postcss|custom-property" -S . --glob '!**/node_modules/**' --glob '!**/dist/**' --glob '!**/build/**'

Repository: projectamazonph/amph-v2

Length of output: 9651


Move the alias tokens back under :root. src/styles/globals.css:122-145 — these declarations sit outside any selector, so the --color-* and --surface-tint tokens are dropped and never apply. The dark-mode override at line 176 is fine.

🧰 Tools
🪛 Stylelint (17.14.0)

[error] 123-123: Invalid position for declaration (no-invalid-position-declaration)

(no-invalid-position-declaration)


[error] 124-124: Invalid position for declaration (no-invalid-position-declaration)

(no-invalid-position-declaration)


[error] 125-125: Invalid position for declaration (no-invalid-position-declaration)

(no-invalid-position-declaration)


[error] 126-126: Invalid position for declaration (no-invalid-position-declaration)

(no-invalid-position-declaration)


[error] 127-127: Invalid position for declaration (no-invalid-position-declaration)

(no-invalid-position-declaration)


[error] 128-128: Invalid position for declaration (no-invalid-position-declaration)

(no-invalid-position-declaration)


[error] 129-129: Invalid position for declaration (no-invalid-position-declaration)

(no-invalid-position-declaration)


[error] 130-130: Invalid position for declaration (no-invalid-position-declaration)

(no-invalid-position-declaration)


[error] 131-131: Invalid position for declaration (no-invalid-position-declaration)

(no-invalid-position-declaration)


[error] 132-132: Invalid position for declaration (no-invalid-position-declaration)

(no-invalid-position-declaration)


[error] 133-133: Invalid position for declaration (no-invalid-position-declaration)

(no-invalid-position-declaration)


[error] 134-134: Invalid position for declaration (no-invalid-position-declaration)

(no-invalid-position-declaration)


[error] 135-135: Invalid position for declaration (no-invalid-position-declaration)

(no-invalid-position-declaration)


[error] 136-136: Invalid position for declaration (no-invalid-position-declaration)

(no-invalid-position-declaration)


[error] 137-137: Invalid position for declaration (no-invalid-position-declaration)

(no-invalid-position-declaration)


[error] 138-138: Invalid position for declaration (no-invalid-position-declaration)

(no-invalid-position-declaration)


[error] 139-139: Invalid position for declaration (no-invalid-position-declaration)

(no-invalid-position-declaration)


[error] 140-140: Invalid position for declaration (no-invalid-position-declaration)

(no-invalid-position-declaration)


[error] 141-141: Invalid position for declaration (no-invalid-position-declaration)

(no-invalid-position-declaration)


[error] 144-144: Invalid position for declaration (no-invalid-position-declaration)

(no-invalid-position-declaration)

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/styles/globals.css` around lines 122 - 145, Move the alias token
declarations, including --surface-tint, into the existing :root selector in
globals.css so they are valid custom properties and apply globally; preserve the
existing dark-mode override unchanged.

Source: Linters/SAST tools

@projectamazonph
projectamazonph merged commit 5643dc0 into main Jul 20, 2026
7 of 9 checks passed
projectamazonph added a commit that referenced this pull request Jul 20, 2026
Found while resolving the merge, unrelated to the conflict resolution
itself:
- src/app/admin/page.tsx had literal, already-committed merge-conflict
  markers (<<<<<<< HEAD / ======= / >>>>>>> origin/main) from an earlier
  botched resolution on this branch — a build-breaking syntax error.
  Kept the Analytics quick-link (HEAD side); dropped the Review Refunds
  link, which referenced an undefined `pendingRefunds` variable and a
  /admin/refunds page this branch already removes.
- src/styles/globals.css had the alias-token custom-property block
  (--color-text, --color-surface, etc.) sitting after :root's closing
  brace instead of inside it — invalid top-level CSS declarations that
  broke the Turbopack production build (same defect independently fixed
  on the design-review PR, #62).
- src/app/actions/checkout.ts was dead code: the branch's own commits
  removed CheckoutButton.tsx (its only caller) and deleted
  src/lib/paymongo.ts (its dependency), but never removed this file
  itself, so it no longer typechecked. Removed it.

Verified after all fixes: pnpm typecheck / lint clean, pnpm test
212/212, pnpm build succeeds with the expected stripped route table
(no /payments, /checkout, /admin/refunds, /api/paymongo; /admin/enroll
present).

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017Ck2wurvqhL2r3cCAzmuhU
projectamazonph added a commit that referenced this pull request Jul 20, 2026
* Strip PayMongo + Resend for manual-enrollment launch build

- Remove the whole payment stack: PayMongo lib/SDK dep, checkout action +
  /checkout/complete, webhook routes (/api/paymongo, /api/resend), refunds
  (student flow + admin review), receipts/invoice PDFs, webhook signatures,
  and the dashboard Payments page/nav.
- Replace Resend email with no-op logging stubs (src/lib/email.ts); drop the
  resend dependency. Callers (live-class reminders) keep working.
- Add manual enrollment: grantManualEnrollment() enrolls a student in every
  course of a pricing tier inside one transaction, reusing the claim-token
  placeholder-account flow; new /admin/enroll page surfaces the one-time
  claim link for the admin to send manually. Audit-logged.
- Rework admin dashboard around enrollments (recent enrollments table,
  Enroll Student quick action); link enroll form from user detail page.
- Pricing page: tier cards keep prices, CTA now signup + message-us-to-pay;
  FAQ updated for the manual workflow.
- Prisma schema untouched (Payment/CheckoutSession/RefundRequest tables kept
  empty) so the payment stack can be restored from history without migration
  surgery.
- Docs: LAUNCH-DEPLOY.md deploy runbook; .env.example now needs only
  DATABASE_URL + JWT_SECRET (+ NEXT_PUBLIC_APP_URL for claim links).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01VtZMXSurdD45BWD7qZXudY

* Add one-command DB setup script; fix seed order in deploy runbook

Verified end-to-end against a real Postgres: migrate → content import →
seed, then admin sign-in → /admin/enroll → claim link → student password
set → course visible on student dashboard. The runbook previously omitted
the curriculum import step, without which the seed has no course to attach
live classes to.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01VtZMXSurdD45BWD7qZXudY

* Note: fixed two pre-existing bugs on this branch during the main rebase

Found while resolving the merge, unrelated to the conflict resolution
itself:
- src/app/admin/page.tsx had literal, already-committed merge-conflict
  markers (<<<<<<< HEAD / ======= / >>>>>>> origin/main) from an earlier
  botched resolution on this branch — a build-breaking syntax error.
  Kept the Analytics quick-link (HEAD side); dropped the Review Refunds
  link, which referenced an undefined `pendingRefunds` variable and a
  /admin/refunds page this branch already removes.
- src/styles/globals.css had the alias-token custom-property block
  (--color-text, --color-surface, etc.) sitting after :root's closing
  brace instead of inside it — invalid top-level CSS declarations that
  broke the Turbopack production build (same defect independently fixed
  on the design-review PR, #62).
- src/app/actions/checkout.ts was dead code: the branch's own commits
  removed CheckoutButton.tsx (its only caller) and deleted
  src/lib/paymongo.ts (its dependency), but never removed this file
  itself, so it no longer typechecked. Removed it.

Verified after all fixes: pnpm typecheck / lint clean, pnpm test
212/212, pnpm build succeeds with the expected stripped route table
(no /payments, /checkout, /admin/refunds, /api/paymongo; /admin/enroll
present).

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017Ck2wurvqhL2r3cCAzmuhU

---------

Co-authored-by: Claude <noreply@anthropic.com>
Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants