fix(design): visual rhythm, token consistency, accessibility, and polish#62
Conversation
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
There was a problem hiding this comment.
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
100vhto100dvhfor 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.
| 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', | ||
| }, |
| <main id="main-content" className={styles.page}> | ||
| <div className={styles.hero}> |
| .page { | ||
| min-height: 100vh; | ||
| min-height: 100dvh; | ||
| background: #fafafa; | ||
| } |
| .joinLink:hover { | ||
| background: #059669; | ||
| background: var(--success); | ||
| } |
| } | ||
|
|
||
| /* ── 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); |
📝 WalkthroughWalkthroughThe 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. ChangesUI refresh
Estimated code review effort: 3 (Moderate) | ~30 minutes Possibly related PRs
Suggested reviewers: 🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
Comment |
📝 WalkthroughWalkthroughThe 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. ChangesUI refresh
Estimated code review effort: 3 (Moderate) | ~25 minutes Possibly related PRs
Suggested reviewers: 🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
Comment |
There was a problem hiding this comment.
Actionable comments posted: 7
🧹 Nitpick comments (5)
src/app/admin/refunds/[id]/detail.module.css (2)
91-91: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low valueHardcoded
22pxfont-size in an otherwise tokenized block.
.amountValueusesfont-size: 22pxwhile surrounding properties were migrated to tokens. Consider usingvar(--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 valueHardcoded 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-glowor 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 valueHardcoded
15pxfont-size in an otherwise tokenized block.
.subtitleusesfont-size: 15pxwhile surrounding properties were migrated to tokens. Consider usingvar(--text-sm)orvar(--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 valueConsider 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 valueHardcoded 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 usingcolor-mixor a dedicated--accent-focus-ringtoken.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
📒 Files selected for processing (29)
src/app/(dashboard)/certificates/certificates.module.csssrc/app/(dashboard)/courses/[courseSlug]/certificate/certificate.module.csssrc/app/(dashboard)/dashboard/dashboard.module.csssrc/app/(dashboard)/layout.module.csssrc/app/(dashboard)/live-classes/[id]/detail.module.csssrc/app/(dashboard)/live-classes/[id]/register-button.module.csssrc/app/(dashboard)/live-classes/breadcrumb.module.csssrc/app/(dashboard)/live-classes/live-classes.module.csssrc/app/(dashboard)/payments/[id]/request-refund/request-refund.module.csssrc/app/(public)/auth/signin/auth.module.csssrc/app/(public)/pricing/pricing.module.csssrc/app/admin/layout.module.csssrc/app/admin/page.module.csssrc/app/admin/page.tsxsrc/app/admin/refunds/[id]/detail.module.csssrc/app/admin/refunds/refunds.module.csssrc/app/admin/users/[id]/user-detail.module.csssrc/app/admin/users/users.module.csssrc/app/home.module.csssrc/app/layout.tsxsrc/app/loading.module.csssrc/app/loading.tsxsrc/app/not-found.tsxsrc/app/page.tsxsrc/app/verify/[hash]/verify.module.csssrc/components/tools/KeywordResearchRunner.module.csssrc/components/tools/StrTriageRunner.module.csssrc/components/ui/NavSidebar.module.csssrc/styles/globals.css
| background: var(--success); | ||
| color: white; |
There was a problem hiding this comment.
🎯 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.
| 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.
| background: var(--success); | ||
| } |
There was a problem hiding this comment.
🎯 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.
| 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; |
There was a problem hiding this comment.
📐 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.
| 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
| .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; |
There was a problem hiding this comment.
🎯 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.
| .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.
| 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> |
There was a problem hiding this comment.
🎯 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.
| min-height: 100dvh; | ||
| background: #fafafa; |
There was a problem hiding this comment.
📐 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.
| 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.
| /* ── 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; | ||
|
|
There was a problem hiding this comment.
🎯 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.
| /* ── 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
There was a problem hiding this comment.
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 winRestore 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 winAdd 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
📒 Files selected for processing (29)
src/app/(dashboard)/certificates/certificates.module.csssrc/app/(dashboard)/courses/[courseSlug]/certificate/certificate.module.csssrc/app/(dashboard)/dashboard/dashboard.module.csssrc/app/(dashboard)/layout.module.csssrc/app/(dashboard)/live-classes/[id]/detail.module.csssrc/app/(dashboard)/live-classes/[id]/register-button.module.csssrc/app/(dashboard)/live-classes/breadcrumb.module.csssrc/app/(dashboard)/live-classes/live-classes.module.csssrc/app/(dashboard)/payments/[id]/request-refund/request-refund.module.csssrc/app/(public)/auth/signin/auth.module.csssrc/app/(public)/pricing/pricing.module.csssrc/app/admin/layout.module.csssrc/app/admin/page.module.csssrc/app/admin/page.tsxsrc/app/admin/refunds/[id]/detail.module.csssrc/app/admin/refunds/refunds.module.csssrc/app/admin/users/[id]/user-detail.module.csssrc/app/admin/users/users.module.csssrc/app/home.module.csssrc/app/layout.tsxsrc/app/loading.module.csssrc/app/loading.tsxsrc/app/not-found.tsxsrc/app/page.tsxsrc/app/verify/[hash]/verify.module.csssrc/components/tools/KeywordResearchRunner.module.csssrc/components/tools/StrTriageRunner.module.csssrc/components/ui/NavSidebar.module.csssrc/styles/globals.css
| } | ||
|
|
||
| .title { | ||
| font-family: var(--font-display, 'Space Grotesk', sans-serif); |
There was a problem hiding this comment.
📐 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
| .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; | ||
| } |
There was a problem hiding this comment.
🎯 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.
| .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
| 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> |
There was a problem hiding this comment.
🎯 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
| .prioritySECONDARY { | ||
| background: var(--info, #2563eb); | ||
| color: #fff; | ||
| color: var(--ink-inverse); | ||
| border-color: var(--info, #2563eb); | ||
| } |
There was a problem hiding this comment.
🎯 Functional Correctness | 🟠 Major | ⚡ Quick win
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash
rg -n -C 3 -- '--(ink-inverse|info|ink-500)\s*:' src/styles/globals.cssRepository: 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' srcRepository: 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")
PYRepository: projectamazonph/amph-v2
Length of output: 215
Keep status-action text light in dark mode.
src/components/tools/KeywordResearchRunner.module.css#L188-L192:.prioritySECONDARYuses--ink-inverse, which becomes#171717in dark mode and drops to 2.06:1 on--info.src/components/tools/StrTriageRunner.module.css#L228-L238:.actionoptimizeand.actionpausehave the same problem;--ink-inverselands 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.
| /* ── 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; | ||
|
|
There was a problem hiding this comment.
📐 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
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
* 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>
Summary
Two-pass design review of the full frontend surface (29 files changed, 518 insertions, 304 deletions).
Token System
globals.css(--color-text,--color-surface,--color-border, etc.), fixing 167 undefined token references across admin, tools, live-classes, and refunds pages--surface-tinttoken added for alternating section backgrounds (light:#F0EFE9, dark:#1E1E1C)#fffon colored backgrounds replaced with `var(--ink-inverse))Visual Rhythm
space-12tospace-16across home pageAccessibility
100vh→100dvhin 5 layout files (iOS Safari viewport fix)Mobile
display: none)Content
text-wrap: balanceadded to all headingsComponents
Admin
--accent-orange,--border-default, etc.)/admin/refundsquick linkSummary by CodeRabbit
New Features
Style
Documentation