Conversation
WalkthroughBroad updates to Sphinx tooling, theme, and homepage structure. CI and README switch to Sphinx 8 and new plugins/theme. Templates and CSS overhaul introduce a hero + card-grid homepage for instructor and student docs. Multiple toctrees increase maxdepth to 3. DocSearch init is deferred to DOM ready. Codio run/preview config adjusted. Changes
Sequence Diagram(s)sequenceDiagram
autonumber
participant U as User
participant B as Browser
participant T as Theme script (layout.html)
participant DS as DocSearch (algolia.js)
participant S as Sphinx-built Pages
U->>B: Load docs page
B->>T: Execute theme preference script
T->>B: Set data-theme & color-scheme
Note over T,B: Applies saved or system preference
B->>S: Render hero/card layout & CSS
B-->>DS: DOMContentLoaded
DS->>B: Initialize docsearch()
Note over DS,B: Uses configured appId, apiKey, indexName
Estimated code review effort🎯 4 (Complex) | ⏱️ ~60 minutes Suggested reviewers
Suggestions for clarity and consistency:
Pre-merge checks and finishing touches✅ Passed checks (3 passed)
✨ Finishing touches
🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Actionable comments posted: 4
🧹 Nitpick comments (10)
source/_static/css/custom_body.css (1)
27-49: Consider extracting theme tokens to CSS variables at :root level.The theme tokens are duplicated across multiple files (
student-source/_static/css/custom_body.csshas identical tokens at lines 20-41 and 63-85). Extracting these to a shared location (e.g.,:rootin a common CSS file) would improve maintainability and ensure consistency.Also applies to: 52-63
source/conf.py (2)
125-137: Remove commented code.The old
html_theme_optionsconfiguration is commented out. Since the newThemeOptions-based configuration is now in use, this commented code should be removed to improve readability.-# html_theme_options = { -# "show_prev_next": True, -# "logo_light": "_static/logo-white.svg", -# "logo_dark": "_static/logo-white.svg", -# # "external_links": [ -# # {"name": "Overview", "url": "/instructors/getstarted"}, -# # {"name": "Authoring", "url": "/instructors/authoring"}, -# # {"name": "IDE", "url": "/common"}, -# # {"name": "Course Set Up", "url": "/instructors/setupcourses"}, -# # {"name": "Teaching", "url": "/instructors/teaching"}, -# # {"name": "Admin", "url": "/instructors/admin"} -# # ] -# }
154-154: Remove commented sidebar configuration.The commented sidebar navigation line should either be removed or uncommented with a clear reason for its presence.
html_sidebars = { "index": [], - # "**": ['sidebar-nav-bs.html'], }student-source/_static/css/custom_index.css (1)
7-8: Consider documenting the magic number.The value
91.66667%(11/12 of the container width) appears to be based on a 12-column grid system. Adding a comment explaining this would improve maintainability:.index-page .col-xl-8 { + /* 11/12 columns (91.66667%) for wide centering */ flex: 0 0 91.66667% !important; max-width: 91.66667% !important;student-source/_templates/student.html (1)
22-23: Consider extracting inline SVGs to reduce duplication.The four inline SVG icons are embedded directly in the template. For better maintainability, consider:
- Creating SVG sprite files or icon components
- Using a template macro or include for icons
- Using an icon font system
This would make it easier to update icons and ensure consistency across pages.
Also applies to: 31-32, 40-41, 49-50
source/_templates/index.html (3)
42-96: List semantics: prefer native list markup, or drop ARIA list roles.Current pattern uses role="list" on a div and role="listitem" on anchor tags. This is brittle and non‑idiomatic. Two options:
- Preferred: use
/
- .
- Minimal: keep current structure but remove ARIA list roles.
Below is the minimal change to remove the roles (repeat for each card anchor):
- <div class="card-grid" role="list"> - <a class="card" role="listitem" href="{{ pathto('getstarted') }}" aria-label="Overview: Getting Started in Codio"> + <div class="card-grid"> + <a class="card" href="{{ pathto('getstarted') }}">If you want native semantics instead, I can provide a full UL/LI rewrite.
43-49: Accessible names: use aria-labelledby instead of aria-label on cards.aria-label on the overrides the visible heading/description, risking mismatches and localization drift. Prefer aria-labelledby pointing at the card’s
.
Apply to the first card and replicate for others:
- <a class="card" href="{{ pathto('getstarted') }}" aria-label="Overview: Getting Started in Codio"> + <a class="card" href="{{ pathto('getstarted') }}" aria-labelledby="card-getstarted-title"> <div class="card-icon" aria-hidden="true"> <svg viewBox="0 0 24 24"><path d="M12 2l9 4.5v11L12 22 3 17.5v-11L12 2zM5 8.1l7 3.5 7-3.5"/></svg> </div> - <h3 class="card-title">Overview: Getting Started</h3> + <h3 class="card-title" id="card-getstarted-title">Overview: Getting Started</h3> <p class="card-desc">Videos, tutorials, and key concepts to hit the ground running.</p> <span class="card-cta">Explore</span> </a>If you keep aria-labels instead, ensure phrasing is consistent across all cards (some include “in Codio”, others don’t).
38-41: Add a section heading before the card grid for proper heading hierarchy.Currently the page jumps from h1 to multiple h3s with no intervening h2. Introduce an h2 (visible or visually hidden) to clarify structure.
Example:
<section class="section"> <div class="home-container"> + <h2 class="sr-only">Explore the documentation</h2>student-source/conf.py (2)
68-69: Migrate from recommonmark to MyST Parser.recommonmark is deprecated. Use myst-parser for Markdown with better Sphinx compatibility.
- 'recommonmark', + 'myst_parser', @@ -source_suffix = ['.rst', '.md'] +source_suffix = ['.rst', '.md'] # .md handled by myst_parser +# +# Optional: enable useful MyST features +myst_enable_extensions = [ + "colon_fence", + "deflist", + "linkify", +]Also applies to: 81-83
90-92: Set language explicitly for i18n/search quality.language=None can degrade search/stemming. Set to "en" (or your target locale).
-language = None +language = "en"
📜 Review details
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
⛔ Files ignored due to path filters (4)
source/_static/favicon.icois excluded by!**/*.icosource/_static/logo-dark.svgis excluded by!**/*.svgstudent-source/_static/favicon.icois excluded by!**/*.icostudent-source/_static/logo-dark.svgis excluded by!**/*.svg
📒 Files selected for processing (27)
.codio(1 hunks).github/workflows/deploy.yaml(1 hunks)README.md(1 hunks)source/_static/css/codio.css(1 hunks)source/_static/css/custom_body.css(1 hunks)source/_static/css/custom_index.css(1 hunks)source/_static/js/algolia.js(1 hunks)source/_templates/index.html(1 hunks)source/_templates/layout.html(1 hunks)source/admin.rst(1 hunks)source/authoring.rst(1 hunks)source/common.rst(1 hunks)source/common/develop/projects/projects.rst(1 hunks)source/conf.py(6 hunks)source/getstarted.rst(1 hunks)source/index.rst(1 hunks)source/setupcourses.rst(1 hunks)source/teaching.rst(1 hunks)student-source/_static/css/codio.css(1 hunks)student-source/_static/css/custom_body.css(1 hunks)student-source/_static/css/custom_index.css(1 hunks)student-source/_templates/student.html(1 hunks)student-source/accessing-codio.rst(1 hunks)student-source/conf.py(6 hunks)student-source/courses.rst(1 hunks)student-source/develop.rst(1 hunks)student-source/student.rst(1 hunks)
🧰 Additional context used
📓 Path-based instructions (1)
**/*.rst
⚙️ CodeRabbit configuration file
**/*.rst: Review files for:
- Consistent formatting (e.g., headings, lists, links).
- Clear and concise language.
- Correct grammar and spelling.
- Proper use of rst syntax (e.g., avoid broken links or invalid code blocks).
- Adherence to style guides (e.g., consistent tone, terminology).
Suggest improvements to enhance readability and accessibility.
Files:
source/setupcourses.rstsource/common.rstsource/admin.rststudent-source/courses.rstsource/common/develop/projects/projects.rstsource/getstarted.rststudent-source/develop.rstsource/teaching.rststudent-source/student.rststudent-source/accessing-codio.rstsource/index.rstsource/authoring.rst
🪛 Gitleaks (8.28.0)
student-source/conf.py
[high] 270-270: Detected a Generic API Key, potentially exposing access to various services and sensitive operations.
(generic-api-key)
source/conf.py
[high] 271-271: Detected a Generic API Key, potentially exposing access to various services and sensitive operations.
(generic-api-key)
source/_static/js/algolia.js
[high] 5-5: Detected a Generic API Key, potentially exposing access to various services and sensitive operations.
(generic-api-key)
🔇 Additional comments (25)
.codio (2)
5-5: LGTM: Terminal clearing improves output readability.Adding
clearbeforemake htmlensures a clean terminal view for each build, making it easier to spot new warnings or errors.
10-11: LGTM: Preview split aligns with audience-targeted documentation.The separation of instructor and student preview URLs correctly reflects the theme upgrade's introduction of role-specific documentation paths. Ensure both URLs resolve correctly in the Codio environment after the build completes.
source/index.rst (1)
6-7: LGTM!The caption change to "Documentation" is more general and appropriate. The maxdepth increase to 3 aligns with the broader navigation depth enhancements across the documentation.
source/admin.rst (1)
11-11: LGTM!The maxdepth increase to 3 is consistent with the navigation depth enhancements being applied across the documentation.
student-source/develop.rst (1)
11-11: LGTM!The maxdepth increase to 3 follows the consistent navigation depth enhancement pattern across the documentation.
source/_static/css/codio.css (1)
229-256: LGTM!The CSS additions are well-structured and support the theme upgrade effectively:
- Utility classes (.small-text, .tiny) provide helpful text sizing options
- Logo sizing rules ensure consistent header appearance across themes
- Color-scheme media queries follow best practices for dark/light mode support
source/_templates/layout.html (1)
3-22: LGTM!The theme initialization script follows best practices:
- Executes early in the head to prevent flash of unstyled content (FOUC)
- Gracefully handles localStorage availability with try/catch
- Falls back to system preference when no saved theme exists
- Properly applies theme classes and attributes for consistency
source/_static/js/algolia.js (1)
1-14: LGTM!Wrapping docsearch initialization in a DOMContentLoaded listener is a best practice that ensures the container element exists before initialization.
Note: The static analysis tool flagged the API key as potentially sensitive, but this is a false positive. DocSearch API keys are designed to be public and client-side accessible for search functionality.
source/_static/css/custom_index.css (2)
1-2: Clarify the purpose of this rule.The
max-width: 100%doesn't effectively constrain the container since 100% is the default behavior. The comment mentions a "Slight width nudge," but this rule doesn't apply any constraint. Consider either:
- Removing this rule if it serves no purpose
- Applying an actual constraint if one is needed (e.g.,
max-width: 1400px)
5-11: LGTM!The responsive centering logic is well-implemented, using auto margins and appropriate flex/max-width values to center the main content column on large viewports.
README.md (1)
11-11: LGTM!The streamlined install command is clear and concise, properly specifying Sphinx 8.2.0 and the required theme packages. This aligns well with the theme upgrade objectives.
source/_static/css/custom_body.css (2)
124-124: Verify icon color contrast.Similar to the button text, the SVG fill color
#001on the gradient background should be verified for adequate contrast.
88-88: Contrast Verified – No Action Needed
Contrast ratios for #1 vs #6ee7ff (14.4:1) and #3dd8ff (12.4:1) exceed the WCAG AAA minimum of 7:1.source/conf.py (2)
270-272: Verify intentional exposure of DocSearch API key.The
docsearch_api_keyappears to be a public search-only key for Algolia DocSearch, which is typically safe to expose in client-side code. However, please confirm this is intentional and not a private admin key.Static analysis flagged this as a potential security issue. If this is indeed a public search-only key (which is standard for DocSearch), you may want to add a comment explaining this to prevent future confusion.
19-22: LGTM! Theme migration implemented correctly.The switch to
sphinxawesome_themewith structuredThemeOptionsis well-implemented. The use ofasdict()to convert the dataclass to a dictionary forhtml_theme_optionsis a clean approach.Also applies to: 115-123
student-source/student.rst (1)
6-7: LGTM! Improved navigation configuration.The caption change to "Documentation" is clearer, and increasing
maxdepthto 3 improves navigation granularity for users, aligning with similar changes across other documentation files in this PR.student-source/_templates/student.html (2)
8-15: Excellent accessibility implementation!The use of semantic HTML, ARIA roles (
role="banner",role="main",role="list",role="listitem"),aria-labelledby, andaria-labelattributes ensures this page is accessible to screen reader users. Thearia-hidden="true"on decorative icons is particularly well-done.Also applies to: 21-55
4-5: Verify CSS loading order doesn't cause conflicts.Both
custom_body.cssandcustom_index.cssare loaded. Ensure there are no overlapping rules that might cause unexpected behavior. Consider consolidating or clearly documenting which file handles which aspects of the styling.student-source/_static/css/codio.css (1)
229-256: LGTM! Appropriate utility classes and responsive design.The new utility classes (
.small-text,.tiny,.float-right) follow common naming conventions, and the color scheme media queries provide proper dark/light mode support. The logo sizing and header adjustments align well with the theme upgrade..github/workflows/deploy.yaml (1)
13-13: LGTM! CI dependencies aligned with theme upgrade.The updated dependencies (Sphinx 8.2.0, sphinxawesome-theme 5.3.2, sphinx-docsearch) are consistent with the configuration changes in
source/conf.py. The removal of oldsphinxcontrib-*packages streamlines the build process.source/_templates/index.html (1)
16-19: Verify audience labeling.Heading reads “Codio Instructor Help Center.” Confirm this template isn’t used for the student docs, or provide a student-specific variant to avoid audience confusion.
student-source/conf.py (4)
115-123: Verify theme asset paths and nav link correctness.
- Ensure logo_light/logo_dark files exist under _static and are referenced per sphinxawesome_theme docs.
- Confirm the absolute path in main_nav_links ("Changelog") resolves as intended in the built site.
150-154: Sidebar configuration: confirm navigation remains discoverable.index and student pages have empty sidebars and the global pattern is commented out. Validate that the theme’s built‑in nav remains accessible on inner pages.
269-271: Extract DocSearch credentials to environment variables
docsearch_app_id, docsearch_api_key, and docsearch_index_name are hardcoded in conf.py. Confirm the API key is search-only—if it’s admin, rotate immediately. Use environment variables (DOCSEARCH_APP_ID, DOCSEARCH_API_KEY, DOCSEARCH_INDEX_NAME) and update any templates/JS to consume these.
249-259: Fetch the latest 3.x release versions for @docsearch/css and @docsearch/js along with their jsDelivr SRI integrity hashes and share them here.
| <!-- Skip link for a11y --> | ||
| <!-- <a class="skip-link" href="#home-content">Skip to content</a> --> | ||
|
|
There was a problem hiding this comment.
Re‑enable the skip link for keyboard users.
The skip link is commented out; this impairs quick navigation for screen reader and keyboard users.
Apply this diff:
- <!-- Skip link for a11y -->
- <!-- <a class="skip-link" href="#home-content">Skip to content</a> -->
+ <!-- Skip link for a11y -->
+ <a class="skip-link" href="#home-content">Skip to content</a>📝 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.
| <!-- Skip link for a11y --> | |
| <!-- <a class="skip-link" href="#home-content">Skip to content</a> --> | |
| <!-- Skip link for a11y --> | |
| <a class="skip-link" href="#home-content">Skip to content</a> |
🤖 Prompt for AI Agents
In source/_templates/index.html around lines 10 to 12, the skip link is
currently commented out which prevents keyboard and screen‑reader users from
skipping to main content; uncomment the <a class="skip-link"
href="#home-content">Skip to content</a> line so the skip link is active, ensure
there is a target element with id="home-content" present in the page, and verify
the skip-link CSS displays the link on focus (or add minimal focus-visible
styles) so it is usable by keyboard users.
| .. :name: getstarted | ||
|
|
||
| Getting Started | ||
| --------------- | ||
|
|
||
| .. toctree:: | ||
| :maxdepth: 1 | ||
| :maxdepth: 3 | ||
| :hidden: | ||
|
|
There was a problem hiding this comment.
Reinstate the toctree :name: option
Moving :name: getstarted out of the .. toctree:: block turns it into a no-op comment, so any existing :ref: links to that toctree now resolve to “unknown target.” Please restore the option inside the directive and drop the stray comment.
-.. :name: getstarted
-
.. toctree::
+ :name: getstarted
:maxdepth: 3
:hidden:📝 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.
| .. :name: getstarted | |
| Getting Started | |
| --------------- | |
| .. toctree:: | |
| :maxdepth: 1 | |
| :maxdepth: 3 | |
| :hidden: | |
| Getting Started | |
| --------------- | |
| .. toctree:: | |
| :name: getstarted | |
| :maxdepth: 3 | |
| :hidden: |
🤖 Prompt for AI Agents
In source/getstarted.rst around lines 4 to 12, the ":name: getstarted" option
was placed outside the ".. toctree::" directive making it a no-op and breaking
:ref: targets; move the line ":name: getstarted" back inside the ".. toctree::"
block (directly under the directive and before the :maxdepth: option or
alongside other options) and remove the stray comment so the toctree regains its
target name and existing :ref: links resolve correctly.
| /* ========================================= | ||
| Codio Docs — Home (index) only | ||
| Pure theme background, centered layout | ||
| ========================================= */ | ||
|
|
||
| /* Hide sidebars on the homepage and center content */ | ||
| /* Center & unbox the student page just like the home page */ | ||
| .student-page .bd-sidebar-primary, | ||
| .student-page .bd-sidebar-secondary { display: none !important; } | ||
|
|
||
| .student-page .bd-content, | ||
| .student-page .bd-article-container { | ||
| max-width: 1200px; | ||
| margin-inline: auto !important; | ||
| padding-inline: 1rem; | ||
| background: transparent !important; | ||
| } | ||
|
|
||
| /* Share the same theme tokens */ | ||
| html[data-theme="dark"] .student-page, | ||
| [data-theme="dark"] .student-page { | ||
| --text: #e6eaf2; | ||
| --muted: #9aa3b2; | ||
| --border: rgba(255,255,255,0.14); | ||
| --surface-hover: rgba(255,255,255,0.06); | ||
| --brand: #6ee7ff; | ||
| --brand-strong: #3dd8ff; | ||
| --ring: #9feaff; | ||
| --shadow: 0 10px 26px rgba(3,8,48,0.35); | ||
| } | ||
| html[data-theme="light"] .student-page, | ||
| [data-theme="light"] .student-page { | ||
| --text: #0b1020; | ||
| --muted: #475569; | ||
| --border: rgba(0,0,0,0.12); | ||
| --surface-hover: rgba(2,132,199,0.05); | ||
| --brand: #0ea5e9; | ||
| --brand-strong: #0284c7; | ||
| --ring: #38bdf8; | ||
| --shadow: 0 10px 24px rgba(2,132,199,0.08); | ||
| } | ||
|
|
||
| .index-page .bd-sidebar-primary, | ||
| .index-page .bd-sidebar-secondary { display: none !important; } | ||
|
|
||
| .index-page .bd-content, | ||
| .index-page .bd-article-container { | ||
| max-width: 100%; | ||
| margin-inline: auto !important; | ||
| padding-inline: 1rem; | ||
| } | ||
|
|
||
| /* Make every wrapper transparent so there is NO boxed panel */ | ||
| .index-page, | ||
| .index-page .bd-main, | ||
| .index-page .bd-content, | ||
| .index-page .bd-article-container, | ||
| .index-page .bd-article { | ||
| background: transparent !important; | ||
| } | ||
|
|
||
| .footer { | ||
| border-top: none; | ||
| /* ------- Theme tokens (only for the homepage components) ------- */ | ||
| html[data-theme="dark"] .index-page, | ||
| [data-theme="dark"] .index-page { | ||
| --text: #e6eaf2; | ||
| --muted: #9aa3b2; | ||
| --border: rgba(255,255,255,0.14); | ||
| --surface-hover: rgba(255,255,255,0.06); | ||
| --brand: #6ee7ff; | ||
| --brand-strong: #3dd8ff; | ||
| --ring: #9feaff; | ||
| --shadow: 0 10px 26px rgba(3,8,48,0.35); | ||
| } | ||
|
|
||
| .container-xl .row { | ||
| justify-content: center; | ||
| html[data-theme="light"] .index-page, | ||
| [data-theme="light"] .index-page { | ||
| --text: #0b1020; | ||
| --muted: #475569; | ||
| --border: rgba(0,0,0,0.12); | ||
| --surface-hover: rgba(2,132,199,0.05); | ||
| --brand: #0ea5e9; | ||
| --brand-strong: #0284c7; | ||
| --ring: #38bdf8; | ||
| --shadow: 0 10px 24px rgba(2,132,199,0.08); | ||
| } | ||
|
|
||
| .container-xl .no-sidebar { | ||
| display: none !important; | ||
| /* Fallback to OS pref if the site doesn't set data-theme */ | ||
| @media (prefers-color-scheme: light) { | ||
| html:not([data-theme="dark"]) .index-page { | ||
| --text: #0b1020; | ||
| --muted: #475569; | ||
| --border: rgba(0,0,0,0.12); | ||
| --surface-hover: rgba(2,132,199,0.05); | ||
| --brand: #0ea5e9; | ||
| --brand-strong: #0284c7; | ||
| --ring: #38bdf8; | ||
| --shadow: 0 10px 24px rgba(2,132,199,0.08); | ||
| } | ||
| } | ||
|
|
||
| .container-xl .d-none { | ||
| display: none !important; | ||
| /* ------- Hero ------- */ | ||
| .home-hero { padding: 5rem 1rem 1.5rem; text-align: center; } | ||
| .home-title { color: var(--text); font-size: clamp(2rem, 2.8vw + 1rem, 3rem); margin: 0 0 .6rem; } | ||
| .home-subtitle { color: var(--muted); margin: 0 auto 1.8rem; max-width: 62ch; } | ||
|
|
||
| /* (Search form is commented out in your HTML, but styles left here in case you re-enable) */ | ||
| .home-search { | ||
| display: inline-flex; gap: .5rem; align-items: center; | ||
| background: transparent; /* no panel */ | ||
| border: 1px solid var(--border); | ||
| border-radius: 999px; padding: .5rem; | ||
| box-shadow: none; | ||
| } | ||
| .home-search input[type="search"] { | ||
| min-width: clamp(260px, 42vw, 560px); | ||
| background: transparent; border: none; color: var(--text); | ||
| outline: none; padding: .75rem 1rem; font-size: 1rem; | ||
| } | ||
| .home-search input::placeholder { color: var(--muted); } | ||
| .search-btn { | ||
| display: inline-flex; align-items: center; gap: .5rem; | ||
| border: 1px solid transparent; | ||
| background: linear-gradient(180deg, var(--brand), var(--brand-strong)); | ||
| color: #001; font-weight: 700; padding: .7rem 1rem; | ||
| border-radius: 999px; cursor: pointer; | ||
| box-shadow: 0 10px 24px rgba(0, 190, 255, .18); | ||
| } | ||
| .search-btn:focus-visible { outline: 3px solid var(--ring); outline-offset: 2px; } | ||
| .search-btn .icon { width: 20px; height: 20px; } | ||
|
|
||
| /* ------- Sections ------- */ | ||
| .home-main { padding: .5rem 0 3rem; } | ||
| .home-container { max-width: 1100px; margin-inline: auto; padding-inline: 1rem; } | ||
| .section { margin-top: 1.25rem; } | ||
| .section-title { color: var(--muted); font-weight: 600; letter-spacing: .2px; margin: 0 0 1rem; } | ||
|
|
||
| /* ------- Cards: transparent by default (no fill), subtle outline ------- */ | ||
| .card-grid { | ||
| --min: 260px; | ||
| display: grid; grid-template-columns: repeat(auto-fit, minmax(var(--min), 1fr)); | ||
| gap: 1rem; align-items: stretch; | ||
| } | ||
| .card { | ||
| display: grid; grid-template-rows: auto auto 1fr auto; gap: .5rem; | ||
| padding: 1rem; border-radius: 16px; text-decoration: none; color: var(--text); | ||
| background: transparent; /* <- no box */ | ||
| border: 1px solid var(--border); | ||
| box-shadow: none; | ||
| transition: transform .2s ease, background-color .15s ease, border-color .15s ease; | ||
| } | ||
| .card:hover { transform: translateY(-2px); background: var(--surface-hover); border-color: var(--brand); } | ||
| .card:focus-visible { outline: 3px solid var(--ring); outline-offset: 2px; } | ||
|
|
||
| .card-icon { | ||
| width: 36px; height: 36px; display: grid; place-items: center; | ||
| border-radius: 12px; | ||
| background: linear-gradient(180deg, var(--brand), var(--brand-strong)); | ||
| box-shadow: 0 8px 18px rgba(0, 190, 255, .2); | ||
| } | ||
| .card-icon svg { width: 22px; height: 22px; fill: #001; } | ||
|
|
||
| .card-title { font-size: 1.05rem; margin: .25rem 0; } | ||
| .card-desc { margin: 0; color: var(--muted); } | ||
| .card-cta { margin-top: .5rem; font-weight: 700; color: var(--brand); display: inline-flex; gap: .35rem; } | ||
| .card-cta::after { content: "›"; font-size: 1.2em; transform: translateY(-1px); } | ||
|
|
||
| /* Reduced motion */ | ||
| @media (prefers-reduced-motion: reduce) { .card, .search-btn { transition: none; } } | ||
|
|
||
| /* Small screens */ | ||
| @media (max-width: 480px) { | ||
| .home-search { width: 100%; } | ||
| .home-search input[type="search"] { min-width: 0; width: 100%; } | ||
| } |
There was a problem hiding this comment.
🛠️ Refactor suggestion | 🟠 Major
Reduce duplication by extracting shared styles.
This file contains substantial duplication with source/_static/css/custom_body.css (lines 43-174 are nearly identical to the source file). Consider:
- Extract common homepage styles (hero, cards, sections) to a shared CSS file
- Keep only student-specific overrides in this file
- Import the shared styles in both locations
This would improve maintainability and reduce the risk of divergence between student and instructor views.
| html[data-theme="dark"] .student-page, | ||
| [data-theme="dark"] .student-page { | ||
| --text: #e6eaf2; | ||
| --muted: #9aa3b2; | ||
| --border: rgba(255,255,255,0.14); | ||
| --surface-hover: rgba(255,255,255,0.06); | ||
| --brand: #6ee7ff; | ||
| --brand-strong: #3dd8ff; | ||
| --ring: #9feaff; | ||
| --shadow: 0 10px 26px rgba(3,8,48,0.35); | ||
| } | ||
| html[data-theme="light"] .student-page, | ||
| [data-theme="light"] .student-page { | ||
| --text: #0b1020; | ||
| --muted: #475569; | ||
| --border: rgba(0,0,0,0.12); | ||
| --surface-hover: rgba(2,132,199,0.05); | ||
| --brand: #0ea5e9; | ||
| --brand-strong: #0284c7; | ||
| --ring: #38bdf8; | ||
| --shadow: 0 10px 24px rgba(2,132,199,0.08); | ||
| } |
There was a problem hiding this comment.
🛠️ Refactor suggestion | 🟠 Major
Consolidate duplicate theme token definitions.
Theme tokens for dark/light modes are defined twice in this file (lines 20-41 for .student-page and lines 63-85 for .index-page) with identical values. These should be consolidated into a single definition or extracted to a shared location.
Also applies to: 63-85
🤖 Prompt for AI Agents
In student-source/_static/css/custom_body.css around lines 20-41 and 63-85, the
theme token blocks for dark and light modes are duplicated for .student-page and
.index-page with identical values; consolidate by moving the shared CSS custom
properties into a single selector that targets both page types (or a shared
parent) for each theme and remove the duplicate blocks, ensuring the
consolidated selectors preserve the same --text, --muted, --border,
--surface-hover, --brand, --brand-strong, --ring and --shadow values for dark
and light themes.
Summary by CodeRabbit