Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add Tailwind css files #6

Merged
merged 1 commit into from
Dec 14, 2024
Merged

Add Tailwind css files #6

merged 1 commit into from
Dec 14, 2024

Conversation

apple-x-co
Copy link
Owner

@apple-x-co apple-x-co commented Dec 14, 2024

Summary by CodeRabbit

  • New Features

    • Added Tailwind CSS as a styling option in the documentation.
    • Introduced new HTML files for an admin interface and a login page, both styled with Tailwind CSS.
    • Implemented a new script for processing Tailwind CSS styles.
  • Bug Fixes

    • Enhanced the login interface with improved button styles and error handling.
  • Documentation

    • Updated the README.md to include Tailwind CSS references.
  • Chores

    • Updated project dependencies to include Tailwind CSS and its forms plugin.

Copy link

coderabbitai bot commented Dec 14, 2024

Walkthrough

The changes in this pull request primarily focus on integrating Tailwind CSS into the Aura.PHP application. This includes adding Tailwind CSS as a styling option in the README.md, updating the package.json to include new dependencies and scripts, creating configuration files for Tailwind CSS, and introducing new HTML files for an admin interface and login page. Additionally, modifications were made to existing templates to enhance the visual aspects of the application using Tailwind CSS.

Changes

File Path Change Summary
README.md Added reference to "Stylesheet / Tailwind CSS" in the "Frontend" section.
source/app/public/admin-src/package.json Added dependencies: @tailwindcss/forms and tailwindcss. Added script for Tailwind CSS processing.
source/app/public/admin-src/tailwind.config.js Created new Tailwind CSS configuration file with content sources and plugins.
source/app/public/admin-src/tailwindcss/index.html Introduced new HTML structure for admin interface using Tailwind CSS.
source/app/public/admin-src/tailwindcss/login.html Created new login interface HTML file styled with Tailwind CSS.
source/app/public/admin-src/tailwindcss/main.css Added new CSS file with Tailwind CSS directives for base, components, and utilities.
source/app/public/admin/css/tailwind.css Introduced comprehensive CSS styles for Tailwind CSS configuration, including resets and utility classes.
source/app/var/qiq/template/Admin/Login.php Modified login template to include Cloudflare's Turnstile API and updated button styles.
source/app/var/qiq/template/layout/Admin/base.php Added local stylesheet link for Tailwind CSS and removed CDN script.

Poem

In the garden of code, we hop and play,
With Tailwind's magic, brightening our day.
Styles and scripts, a dance so fine,
Admins rejoice, all elements align.
From forms to layouts, a whimsical sight,
With every new change, our app takes flight! 🐇✨

Tip

CodeRabbit's docstrings feature is now available as part of our Early Access Program! Simply use the command @coderabbitai generate docstrings to have CodeRabbit automatically generate docstrings for your pull request. This feature will be included in our Pro Plan when released.


Thank you for using CodeRabbit. We offer it for free to the OSS community and would appreciate your support in helping us grow. If you find it useful, would you consider giving us a shout-out on your favorite social media?

❤️ Share
🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Generate unit testing code for this file.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query. Examples:
    • @coderabbitai generate unit testing code for this file.
    • @coderabbitai modularize this function.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read src/utils.ts and generate unit testing code.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.
    • @coderabbitai help me debug CodeRabbit configuration file.

Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments.

CodeRabbit Commands (Invoked using PR comments)

  • @coderabbitai pause to pause the reviews on a PR.
  • @coderabbitai resume to resume the paused reviews.
  • @coderabbitai review to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
  • @coderabbitai full review to do a full review from scratch and review all the files again.
  • @coderabbitai summary to regenerate the summary of the PR.
  • @coderabbitai generate docstrings to generate docstrings for this PR. (Beta)
  • @coderabbitai resolve resolve all the CodeRabbit review comments.
  • @coderabbitai configuration to show the current CodeRabbit configuration for the repository.
  • @coderabbitai help to get help.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

CodeRabbit Configuration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Documentation and Community

  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 12

🧹 Outside diff range and nitpick comments (7)
source/app/public/admin/css/tailwind.css (1)

1-2283: Consider minifying the CSS for better performance

The tailwind.css file is currently unminified, which can increase load times in production environments. Minifying the CSS can significantly improve page load speed.

Modify your build script to generate a minified CSS file:

- "build:css": "tailwindcss -i ./tailwindcss/main.css -o ../admin/css/tailwind.css"
+ "build:css": "tailwindcss -i ./tailwindcss/main.css -o ../admin/css/tailwind.min.css --minify"

This will output a minified CSS file named tailwind.min.css.

source/app/public/admin-src/package.json (1)

18-18: Consider adding a watch mode for development

The current script only handles one-time builds. For development, it would be helpful to have a watch mode.

 "scripts": {
     "build": "rollup --config",
-    "tailwindcss": "tailwindcss -i ./tailwindcss/main.css -o ../admin/css/tailwind.css"
+    "tailwindcss": "tailwindcss -i ./tailwindcss/main.css -o ../admin/css/tailwind.css",
+    "tailwindcss:watch": "tailwindcss -i ./tailwindcss/main.css -o ../admin/css/tailwind.css --watch"
 }
source/app/var/qiq/template/layout/Admin/base.php (1)

15-16: Consider optimizing Google Fonts loading

The current Google Fonts implementation loads multiple weights. Consider:

  1. Using font-display: swap for better performance
  2. Preloading critical fonts
  3. Self-hosting the fonts for better performance
-    <link href="https://fonts.googleapis.com/css?family=Noto+Sans+JP:100|Noto+Sans+JP:400|Noto+Sans+JP:700|Noto+Sans+JP:900|Roboto:100|Roboto:400|Roboto:700|Roboto:900&display=swap&subset=japanese" rel="stylesheet">
+    <link rel="preconnect" href="https://fonts.googleapis.com">
+    <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
+    <link href="https://fonts.googleapis.com/css2?family=Noto+Sans+JP:wght@100;400;700;900&family=Roboto:wght@100;400;700;900&display=swap" rel="stylesheet">
source/app/var/qiq/template/Admin/Login.php (2)

27-27: Extract gradient text styles to a reusable class

The gradient text styling for the heading appears in multiple files. Consider extracting it to a reusable Tailwind component or utility class.

Create a new CSS class in your Tailwind configuration:

// tailwind.config.js
module.exports = {
  theme: {
    extend: {
+     '.gradient-heading': {
+       '@apply text-xl text-center tracking-widest font-black bg-clip-text text-transparent bg-gradient-to-r from-indigo-500 via-purple-500 to-pink-500'
+     }
    }
  }
}

59-59: Consider using data attributes for button state management

The current implementation uses direct ID manipulation for button states. Consider using data attributes for better maintainability:

-    {{= $form->widget('continue', attr: ['id' => 'continue', 'disabled' => 'disabled', 'class' => '...']) }}
+    {{= $form->widget('continue', attr: [
+        'data-turnstile-button' => 'true',
+        'disabled' => 'disabled',
+        'class' => '...'
+    ]) }}

Then update the JavaScript to use the data attribute:

function cfTurnstileChecked() {
    document.querySelector('[data-turnstile-button]').removeAttribute('disabled');
}
source/app/public/admin-src/tailwindcss/index.html (2)

519-562: Replace placeholder images with proper image handling.

The image list section uses hardcoded placeholder images and lacks proper alt text.

Implement proper image handling:

-<img src="https://placehold.jp/500x300.png" alt="" class="rounded shadow max-h-80 mx-auto">
+<img src="<?= $this->escape($image->url) ?>" 
+     alt="<?= $this->escape($image->description) ?>" 
+     class="rounded shadow max-h-80 mx-auto"
+     loading="lazy">

713-715: Consider enhancing the footer content.

While the current footer is functional, consider adding useful links and information:

  • Privacy policy
  • Terms of service
  • Contact information
  • Version information

Example enhancement:

 <footer>
-    <p class="font-sans font-thin text-sm">Copyrights &copy; Suzuhiro Co.,Ltd. All rights reserved.</p>
+    <div class="grid grid-cols-1 md:grid-cols-3 gap-4">
+        <div>
+            <p class="font-sans font-thin text-sm">Copyrights &copy; Suzuhiro Co.,Ltd. All rights reserved.</p>
+        </div>
+        <div class="text-center">
+            <nav class="space-x-4">
+                <a href="/privacy" class="text-sm text-gray-600 hover:text-gray-900">Privacy Policy</a>
+                <a href="/terms" class="text-sm text-gray-600 hover:text-gray-900">Terms of Service</a>
+            </nav>
+        </div>
+        <div class="text-right">
+            <p class="text-sm text-gray-600">Version <?= $this->escape($version) ?></p>
+        </div>
+    </div>
 </footer>
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 208e313 and e739fa9.

⛔ Files ignored due to path filters (2)
  • source/app/public/admin-src/package-lock.json is excluded by !**/package-lock.json
  • source/app/public/admin/images/heroicons/icon.svg is excluded by !**/*.svg
📒 Files selected for processing (9)
  • README.md (1 hunks)
  • source/app/public/admin-src/package.json (1 hunks)
  • source/app/public/admin-src/tailwind.config.js (1 hunks)
  • source/app/public/admin-src/tailwindcss/index.html (1 hunks)
  • source/app/public/admin-src/tailwindcss/login.html (1 hunks)
  • source/app/public/admin-src/tailwindcss/main.css (1 hunks)
  • source/app/public/admin/css/tailwind.css (1 hunks)
  • source/app/var/qiq/template/Admin/Login.php (2 hunks)
  • source/app/var/qiq/template/layout/Admin/base.php (1 hunks)
✅ Files skipped from review due to trivial changes (1)
  • source/app/public/admin-src/tailwindcss/main.css
🔇 Additional comments (3)
source/app/public/admin-src/tailwind.config.js (1)

7-9: Verify the forms plugin version compatibility

Ensure the forms plugin version matches the Tailwind CSS version for compatibility.

✅ Verification successful

Plugin and Tailwind CSS versions are compatible

The @tailwindcss/forms plugin (v0.5.9) is compatible with the installed Tailwind CSS version (v3.4.16). Both versions are up-to-date and follow the same major version (v3.x), ensuring proper functionality.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Check package versions
cat package.json | jq '.devDependencies | .["@tailwindcss/forms"], .["tailwindcss"]'

Length of output: 131


Script:

#!/bin/bash
# Search for package.json files in the repository
fd package.json

# Once we find the package.json files, let's check their content for tailwind dependencies
fd package.json --exec cat {} \; | grep -A 2 -B 2 "tailwindcss\|@tailwindcss"

Length of output: 578

source/app/public/admin-src/package.json (1)

7-7: Dependencies look up-to-date

The versions of Tailwind CSS (3.4.16) and its forms plugin (0.5.9) are current and compatible.

Also applies to: 11-11

README.md (1)

21-21: LGTM: Documentation update matches implementation

The addition of Tailwind CSS to the Frontend section accurately reflects the changes in this PR.

Comment on lines +1 to +2283
border-color: rgb(15 23 42 / 0.1);
}

.lg\:px-8 {
padding-left: 2rem;
padding-right: 2rem;
}

.lg\:text-base {
font-size: 1rem;
line-height: 1.5rem;
}

.lg\:text-base\/loose {
font-size: 1rem;
line-height: 2;
}

.lg\:text-base\/normal {
font-size: 1rem;
line-height: 1.5;
}

.lg\:text-base\/relaxed {
font-size: 1rem;
line-height: 1.625;
}

.lg\:text-sm {
font-size: 0.875rem;
line-height: 1.25rem;
}
}

@media (prefers-color-scheme: dark) {
.dark\:border-gray-600 {
--tw-border-opacity: 1;
border-color: rgb(75 85 99 / var(--tw-border-opacity, 1));
}

.dark\:border-slate-800 {
--tw-border-opacity: 1;
border-color: rgb(30 41 59 / var(--tw-border-opacity, 1));
}

.dark\:bg-gray-700 {
--tw-bg-opacity: 1;
background-color: rgb(55 65 81 / var(--tw-bg-opacity, 1));
}

.dark\:bg-indigo-600 {
--tw-bg-opacity: 1;
background-color: rgb(79 70 229 / var(--tw-bg-opacity, 1));
}

.dark\:bg-slate-800 {
--tw-bg-opacity: 1;
background-color: rgb(30 41 59 / var(--tw-bg-opacity, 1));
}

.dark\:text-slate-400 {
--tw-text-opacity: 1;
color: rgb(148 163 184 / var(--tw-text-opacity, 1));
}

.dark\:text-white {
--tw-text-opacity: 1;
color: rgb(255 255 255 / var(--tw-text-opacity, 1));
}

.dark\:placeholder-gray-400::-moz-placeholder {
--tw-placeholder-opacity: 1;
color: rgb(156 163 175 / var(--tw-placeholder-opacity, 1));
}

.dark\:placeholder-gray-400::placeholder {
--tw-placeholder-opacity: 1;
color: rgb(156 163 175 / var(--tw-placeholder-opacity, 1));
}

.dark\:hover\:bg-indigo-700:hover {
--tw-bg-opacity: 1;
background-color: rgb(67 56 202 / var(--tw-bg-opacity, 1));
}

.dark\:focus\:border-indigo-500:focus {
--tw-border-opacity: 1;
border-color: rgb(99 102 241 / var(--tw-border-opacity, 1));
}

.dark\:focus\:ring-indigo-500:focus {
--tw-ring-opacity: 1;
--tw-ring-color: rgb(99 102 241 / var(--tw-ring-opacity, 1));
}

.dark\:focus\:ring-indigo-800:focus {
--tw-ring-opacity: 1;
--tw-ring-color: rgb(55 48 163 / var(--tw-ring-opacity, 1));
}
}
Copy link

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

Avoid committing generated CSS files to source control

Including generated files like tailwind.css in the repository can lead to unnecessary bloat and potential merge conflicts. It's best practice to exclude generated files from version control and build them during deployment or development.

Add tailwind.css to your .gitignore file:

+ /source/app/public/admin/css/tailwind.css

Ensure your build process generates this CSS file as needed.

📝 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
*, ::before, ::after {
--tw-border-spacing-x: 0;
--tw-border-spacing-y: 0;
--tw-translate-x: 0;
--tw-translate-y: 0;
--tw-rotate: 0;
--tw-skew-x: 0;
--tw-skew-y: 0;
--tw-scale-x: 1;
--tw-scale-y: 1;
--tw-pan-x: ;
--tw-pan-y: ;
--tw-pinch-zoom: ;
--tw-scroll-snap-strictness: proximity;
--tw-gradient-from-position: ;
--tw-gradient-via-position: ;
--tw-gradient-to-position: ;
--tw-ordinal: ;
--tw-slashed-zero: ;
--tw-numeric-figure: ;
--tw-numeric-spacing: ;
--tw-numeric-fraction: ;
--tw-ring-inset: ;
--tw-ring-offset-width: 0px;
--tw-ring-offset-color: #fff;
--tw-ring-color: rgb(59 130 246 / 0.5);
--tw-ring-offset-shadow: 0 0 #0000;
--tw-ring-shadow: 0 0 #0000;
--tw-shadow: 0 0 #0000;
--tw-shadow-colored: 0 0 #0000;
--tw-blur: ;
--tw-brightness: ;
--tw-contrast: ;
--tw-grayscale: ;
--tw-hue-rotate: ;
--tw-invert: ;
--tw-saturate: ;
--tw-sepia: ;
--tw-drop-shadow: ;
--tw-backdrop-blur: ;
--tw-backdrop-brightness: ;
--tw-backdrop-contrast: ;
--tw-backdrop-grayscale: ;
--tw-backdrop-hue-rotate: ;
--tw-backdrop-invert: ;
--tw-backdrop-opacity: ;
--tw-backdrop-saturate: ;
--tw-backdrop-sepia: ;
--tw-contain-size: ;
--tw-contain-layout: ;
--tw-contain-paint: ;
--tw-contain-style: ;
}
::backdrop {
--tw-border-spacing-x: 0;
--tw-border-spacing-y: 0;
--tw-translate-x: 0;
--tw-translate-y: 0;
--tw-rotate: 0;
--tw-skew-x: 0;
--tw-skew-y: 0;
--tw-scale-x: 1;
--tw-scale-y: 1;
--tw-pan-x: ;
--tw-pan-y: ;
--tw-pinch-zoom: ;
--tw-scroll-snap-strictness: proximity;
--tw-gradient-from-position: ;
--tw-gradient-via-position: ;
--tw-gradient-to-position: ;
--tw-ordinal: ;
--tw-slashed-zero: ;
--tw-numeric-figure: ;
--tw-numeric-spacing: ;
--tw-numeric-fraction: ;
--tw-ring-inset: ;
--tw-ring-offset-width: 0px;
--tw-ring-offset-color: #fff;
--tw-ring-color: rgb(59 130 246 / 0.5);
--tw-ring-offset-shadow: 0 0 #0000;
--tw-ring-shadow: 0 0 #0000;
--tw-shadow: 0 0 #0000;
--tw-shadow-colored: 0 0 #0000;
--tw-blur: ;
--tw-brightness: ;
--tw-contrast: ;
--tw-grayscale: ;
--tw-hue-rotate: ;
--tw-invert: ;
--tw-saturate: ;
--tw-sepia: ;
--tw-drop-shadow: ;
--tw-backdrop-blur: ;
--tw-backdrop-brightness: ;
--tw-backdrop-contrast: ;
--tw-backdrop-grayscale: ;
--tw-backdrop-hue-rotate: ;
--tw-backdrop-invert: ;
--tw-backdrop-opacity: ;
--tw-backdrop-saturate: ;
--tw-backdrop-sepia: ;
--tw-contain-size: ;
--tw-contain-layout: ;
--tw-contain-paint: ;
--tw-contain-style: ;
}
/*
! tailwindcss v3.4.16 | MIT License | https://tailwindcss.com
*/
/*
1. Prevent padding and border from affecting element width. (https://github.com/mozdevs/cssremedy/issues/4)
2. Allow adding a border to an element by just adding a border-width. (https://github.com/tailwindcss/tailwindcss/pull/116)
*/
*,
::before,
::after {
box-sizing: border-box;
/* 1 */
border-width: 0;
/* 2 */
border-style: solid;
/* 2 */
border-color: #e5e7eb;
/* 2 */
}
::before,
::after {
--tw-content: '';
}
/*
1. Use a consistent sensible line-height in all browsers.
2. Prevent adjustments of font size after orientation changes in iOS.
3. Use a more readable tab size.
4. Use the user's configured `sans` font-family by default.
5. Use the user's configured `sans` font-feature-settings by default.
6. Use the user's configured `sans` font-variation-settings by default.
7. Disable tap highlights on iOS
*/
html,
:host {
line-height: 1.5;
/* 1 */
-webkit-text-size-adjust: 100%;
/* 2 */
-moz-tab-size: 4;
/* 3 */
-o-tab-size: 4;
tab-size: 4;
/* 3 */
font-family: ui-sans-serif, system-ui, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji";
/* 4 */
font-feature-settings: normal;
/* 5 */
font-variation-settings: normal;
/* 6 */
-webkit-tap-highlight-color: transparent;
/* 7 */
}
/*
1. Remove the margin in all browsers.
2. Inherit line-height from `html` so users can set them as a class directly on the `html` element.
*/
body {
margin: 0;
/* 1 */
line-height: inherit;
/* 2 */
}
/*
1. Add the correct height in Firefox.
2. Correct the inheritance of border color in Firefox. (https://bugzilla.mozilla.org/show_bug.cgi?id=190655)
3. Ensure horizontal rules are visible by default.
*/
hr {
height: 0;
/* 1 */
color: inherit;
/* 2 */
border-top-width: 1px;
/* 3 */
}
/*
Add the correct text decoration in Chrome, Edge, and Safari.
*/
abbr:where([title]) {
-webkit-text-decoration: underline dotted;
text-decoration: underline dotted;
}
/*
Remove the default font size and weight for headings.
*/
h1,
h2,
h3,
h4,
h5,
h6 {
font-size: inherit;
font-weight: inherit;
}
/*
Reset links to optimize for opt-in styling instead of opt-out.
*/
a {
color: inherit;
text-decoration: inherit;
}
/*
Add the correct font weight in Edge and Safari.
*/
b,
strong {
font-weight: bolder;
}
/*
1. Use the user's configured `mono` font-family by default.
2. Use the user's configured `mono` font-feature-settings by default.
3. Use the user's configured `mono` font-variation-settings by default.
4. Correct the odd `em` font sizing in all browsers.
*/
code,
kbd,
samp,
pre {
font-family: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace;
/* 1 */
font-feature-settings: normal;
/* 2 */
font-variation-settings: normal;
/* 3 */
font-size: 1em;
/* 4 */
}
/*
Add the correct font size in all browsers.
*/
small {
font-size: 80%;
}
/*
Prevent `sub` and `sup` elements from affecting the line height in all browsers.
*/
sub,
sup {
font-size: 75%;
line-height: 0;
position: relative;
vertical-align: baseline;
}
sub {
bottom: -0.25em;
}
sup {
top: -0.5em;
}
/*
1. Remove text indentation from table contents in Chrome and Safari. (https://bugs.chromium.org/p/chromium/issues/detail?id=999088, https://bugs.webkit.org/show_bug.cgi?id=201297)
2. Correct table border color inheritance in all Chrome and Safari. (https://bugs.chromium.org/p/chromium/issues/detail?id=935729, https://bugs.webkit.org/show_bug.cgi?id=195016)
3. Remove gaps between table borders by default.
*/
table {
text-indent: 0;
/* 1 */
border-color: inherit;
/* 2 */
border-collapse: collapse;
/* 3 */
}
/*
1. Change the font styles in all browsers.
2. Remove the margin in Firefox and Safari.
3. Remove default padding in all browsers.
*/
button,
input,
optgroup,
select,
textarea {
font-family: inherit;
/* 1 */
font-feature-settings: inherit;
/* 1 */
font-variation-settings: inherit;
/* 1 */
font-size: 100%;
/* 1 */
font-weight: inherit;
/* 1 */
line-height: inherit;
/* 1 */
letter-spacing: inherit;
/* 1 */
color: inherit;
/* 1 */
margin: 0;
/* 2 */
padding: 0;
/* 3 */
}
/*
Remove the inheritance of text transform in Edge and Firefox.
*/
button,
select {
text-transform: none;
}
/*
1. Correct the inability to style clickable types in iOS and Safari.
2. Remove default button styles.
*/
button,
input:where([type='button']),
input:where([type='reset']),
input:where([type='submit']) {
-webkit-appearance: button;
/* 1 */
background-color: transparent;
/* 2 */
background-image: none;
/* 2 */
}
/*
Use the modern Firefox focus style for all focusable elements.
*/
:-moz-focusring {
outline: auto;
}
/*
Remove the additional `:invalid` styles in Firefox. (https://github.com/mozilla/gecko-dev/blob/2f9eacd9d3d995c937b4251a5557d95d494c9be1/layout/style/res/forms.css#L728-L737)
*/
:-moz-ui-invalid {
box-shadow: none;
}
/*
Add the correct vertical alignment in Chrome and Firefox.
*/
progress {
vertical-align: baseline;
}
/*
Correct the cursor style of increment and decrement buttons in Safari.
*/
::-webkit-inner-spin-button,
::-webkit-outer-spin-button {
height: auto;
}
/*
1. Correct the odd appearance in Chrome and Safari.
2. Correct the outline style in Safari.
*/
[type='search'] {
-webkit-appearance: textfield;
/* 1 */
outline-offset: -2px;
/* 2 */
}
/*
Remove the inner padding in Chrome and Safari on macOS.
*/
::-webkit-search-decoration {
-webkit-appearance: none;
}
/*
1. Correct the inability to style clickable types in iOS and Safari.
2. Change font properties to `inherit` in Safari.
*/
::-webkit-file-upload-button {
-webkit-appearance: button;
/* 1 */
font: inherit;
/* 2 */
}
/*
Add the correct display in Chrome and Safari.
*/
summary {
display: list-item;
}
/*
Removes the default spacing and border for appropriate elements.
*/
blockquote,
dl,
dd,
h1,
h2,
h3,
h4,
h5,
h6,
hr,
figure,
p,
pre {
margin: 0;
}
fieldset {
margin: 0;
padding: 0;
}
legend {
padding: 0;
}
ol,
ul,
menu {
list-style: none;
margin: 0;
padding: 0;
}
/*
Reset default styling for dialogs.
*/
dialog {
padding: 0;
}
/*
Prevent resizing textareas horizontally by default.
*/
textarea {
resize: vertical;
}
/*
1. Reset the default placeholder opacity in Firefox. (https://github.com/tailwindlabs/tailwindcss/issues/3300)
2. Set the default placeholder color to the user's configured gray 400 color.
*/
input::-moz-placeholder, textarea::-moz-placeholder {
opacity: 1;
/* 1 */
color: #9ca3af;
/* 2 */
}
input::placeholder,
textarea::placeholder {
opacity: 1;
/* 1 */
color: #9ca3af;
/* 2 */
}
/*
Set the default cursor for buttons.
*/
button,
[role="button"] {
cursor: pointer;
}
/*
Make sure disabled buttons don't get the pointer cursor.
*/
:disabled {
cursor: default;
}
/*
1. Make replaced elements `display: block` by default. (https://github.com/mozdevs/cssremedy/issues/14)
2. Add `vertical-align: middle` to align replaced elements more sensibly by default. (https://github.com/jensimmons/cssremedy/issues/14#issuecomment-634934210)
This can trigger a poorly considered lint error in some tools but is included by design.
*/
img,
svg,
video,
canvas,
audio,
iframe,
embed,
object {
display: block;
/* 1 */
vertical-align: middle;
/* 2 */
}
/*
Constrain images and videos to the parent width and preserve their intrinsic aspect ratio. (https://github.com/mozdevs/cssremedy/issues/14)
*/
img,
video {
max-width: 100%;
height: auto;
}
/* Make elements with the HTML hidden attribute stay hidden by default */
[hidden]:where(:not([hidden="until-found"])) {
display: none;
}
[type='text'],input:where(:not([type])),[type='email'],[type='url'],[type='password'],[type='number'],[type='date'],[type='datetime-local'],[type='month'],[type='search'],[type='tel'],[type='time'],[type='week'],[multiple],textarea,select {
-webkit-appearance: none;
-moz-appearance: none;
appearance: none;
background-color: #fff;
border-color: #6b7280;
border-width: 1px;
border-radius: 0px;
padding-top: 0.5rem;
padding-right: 0.75rem;
padding-bottom: 0.5rem;
padding-left: 0.75rem;
font-size: 1rem;
line-height: 1.5rem;
--tw-shadow: 0 0 #0000;
}
[type='text']:focus, input:where(:not([type])):focus, [type='email']:focus, [type='url']:focus, [type='password']:focus, [type='number']:focus, [type='date']:focus, [type='datetime-local']:focus, [type='month']:focus, [type='search']:focus, [type='tel']:focus, [type='time']:focus, [type='week']:focus, [multiple]:focus, textarea:focus, select:focus {
outline: 2px solid transparent;
outline-offset: 2px;
--tw-ring-inset: var(--tw-empty,/*!*/ /*!*/);
--tw-ring-offset-width: 0px;
--tw-ring-offset-color: #fff;
--tw-ring-color: #2563eb;
--tw-ring-offset-shadow: var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);
--tw-ring-shadow: var(--tw-ring-inset) 0 0 0 calc(1px + var(--tw-ring-offset-width)) var(--tw-ring-color);
box-shadow: var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow);
border-color: #2563eb;
}
input::-moz-placeholder, textarea::-moz-placeholder {
color: #6b7280;
opacity: 1;
}
input::placeholder,textarea::placeholder {
color: #6b7280;
opacity: 1;
}
::-webkit-datetime-edit-fields-wrapper {
padding: 0;
}
::-webkit-date-and-time-value {
min-height: 1.5em;
text-align: inherit;
}
::-webkit-datetime-edit {
display: inline-flex;
}
::-webkit-datetime-edit,::-webkit-datetime-edit-year-field,::-webkit-datetime-edit-month-field,::-webkit-datetime-edit-day-field,::-webkit-datetime-edit-hour-field,::-webkit-datetime-edit-minute-field,::-webkit-datetime-edit-second-field,::-webkit-datetime-edit-millisecond-field,::-webkit-datetime-edit-meridiem-field {
padding-top: 0;
padding-bottom: 0;
}
select {
background-image: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' fill='none' viewBox='0 0 20 20'%3e%3cpath stroke='%236b7280' stroke-linecap='round' stroke-linejoin='round' stroke-width='1.5' d='M6 8l4 4 4-4'/%3e%3c/svg%3e");
background-position: right 0.5rem center;
background-repeat: no-repeat;
background-size: 1.5em 1.5em;
padding-right: 2.5rem;
-webkit-print-color-adjust: exact;
print-color-adjust: exact;
}
[multiple],[size]:where(select:not([size="1"])) {
background-image: initial;
background-position: initial;
background-repeat: unset;
background-size: initial;
padding-right: 0.75rem;
-webkit-print-color-adjust: unset;
print-color-adjust: unset;
}
[type='checkbox'],[type='radio'] {
-webkit-appearance: none;
-moz-appearance: none;
appearance: none;
padding: 0;
-webkit-print-color-adjust: exact;
print-color-adjust: exact;
display: inline-block;
vertical-align: middle;
background-origin: border-box;
-webkit-user-select: none;
-moz-user-select: none;
user-select: none;
flex-shrink: 0;
height: 1rem;
width: 1rem;
color: #2563eb;
background-color: #fff;
border-color: #6b7280;
border-width: 1px;
--tw-shadow: 0 0 #0000;
}
[type='checkbox'] {
border-radius: 0px;
}
[type='radio'] {
border-radius: 100%;
}
[type='checkbox']:focus,[type='radio']:focus {
outline: 2px solid transparent;
outline-offset: 2px;
--tw-ring-inset: var(--tw-empty,/*!*/ /*!*/);
--tw-ring-offset-width: 2px;
--tw-ring-offset-color: #fff;
--tw-ring-color: #2563eb;
--tw-ring-offset-shadow: var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);
--tw-ring-shadow: var(--tw-ring-inset) 0 0 0 calc(2px + var(--tw-ring-offset-width)) var(--tw-ring-color);
box-shadow: var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow);
}
[type='checkbox']:checked,[type='radio']:checked {
border-color: transparent;
background-color: currentColor;
background-size: 100% 100%;
background-position: center;
background-repeat: no-repeat;
}
[type='checkbox']:checked {
background-image: url("data:image/svg+xml,%3csvg viewBox='0 0 16 16' fill='white' xmlns='http://www.w3.org/2000/svg'%3e%3cpath d='M12.207 4.793a1 1 0 010 1.414l-5 5a1 1 0 01-1.414 0l-2-2a1 1 0 011.414-1.414L6.5 9.086l4.293-4.293a1 1 0 011.414 0z'/%3e%3c/svg%3e");
}
@media (forced-colors: active) {
[type='checkbox']:checked {
-webkit-appearance: auto;
-moz-appearance: auto;
appearance: auto;
}
}
[type='radio']:checked {
background-image: url("data:image/svg+xml,%3csvg viewBox='0 0 16 16' fill='white' xmlns='http://www.w3.org/2000/svg'%3e%3ccircle cx='8' cy='8' r='3'/%3e%3c/svg%3e");
}
@media (forced-colors: active) {
[type='radio']:checked {
-webkit-appearance: auto;
-moz-appearance: auto;
appearance: auto;
}
}
[type='checkbox']:checked:hover,[type='checkbox']:checked:focus,[type='radio']:checked:hover,[type='radio']:checked:focus {
border-color: transparent;
background-color: currentColor;
}
[type='checkbox']:indeterminate {
background-image: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' fill='none' viewBox='0 0 16 16'%3e%3cpath stroke='white' stroke-linecap='round' stroke-linejoin='round' stroke-width='2' d='M4 8h8'/%3e%3c/svg%3e");
border-color: transparent;
background-color: currentColor;
background-size: 100% 100%;
background-position: center;
background-repeat: no-repeat;
}
@media (forced-colors: active) {
[type='checkbox']:indeterminate {
-webkit-appearance: auto;
-moz-appearance: auto;
appearance: auto;
}
}
[type='checkbox']:indeterminate:hover,[type='checkbox']:indeterminate:focus {
border-color: transparent;
background-color: currentColor;
}
[type='file'] {
background: unset;
border-color: inherit;
border-width: 0;
border-radius: 0;
padding: 0;
font-size: unset;
line-height: inherit;
}
[type='file']:focus {
outline: 1px solid ButtonText;
outline: 1px auto -webkit-focus-ring-color;
}
.sr-only {
position: absolute;
width: 1px;
height: 1px;
padding: 0;
margin: -1px;
overflow: hidden;
clip: rect(0, 0, 0, 0);
white-space: nowrap;
border-width: 0;
}
.pointer-events-none {
pointer-events: none;
}
.fixed {
position: fixed;
}
.absolute {
position: absolute;
}
.relative {
position: relative;
}
.sticky {
position: sticky;
}
.inset-0 {
inset: 0px;
}
.inset-y-0 {
top: 0px;
bottom: 0px;
}
.bottom-1\.5 {
bottom: 0.375rem;
}
.bottom-2\.5 {
bottom: 0.625rem;
}
.bottom-4 {
bottom: 1rem;
}
.end-1\.5 {
inset-inline-end: 0.375rem;
}
.end-2\.5 {
inset-inline-end: 0.625rem;
}
.left-0 {
left: 0px;
}
.left-1\/2 {
left: 50%;
}
.left-3 {
left: 0.75rem;
}
.right-0 {
right: 0px;
}
.right-4 {
right: 1rem;
}
.start-0 {
inset-inline-start: 0px;
}
.top-0 {
top: 0px;
}
.top-1\/2 {
top: 50%;
}
.top-2 {
top: 0.5rem;
}
.top-4 {
top: 1rem;
}
.top-full {
top: 100%;
}
.z-40 {
z-index: 40;
}
.z-50 {
z-index: 50;
}
.col-span-3 {
grid-column: span 3 / span 3;
}
.mx-5 {
margin-left: 1.25rem;
margin-right: 1.25rem;
}
.mx-auto {
margin-left: auto;
margin-right: auto;
}
.my-10 {
margin-top: 2.5rem;
margin-bottom: 2.5rem;
}
.-ml-px {
margin-left: -1px;
}
.mb-1 {
margin-bottom: 0.25rem;
}
.mb-2 {
margin-bottom: 0.5rem;
}
.mb-3 {
margin-bottom: 0.75rem;
}
.mb-4 {
margin-bottom: 1rem;
}
.ml-2 {
margin-left: 0.5rem;
}
.ml-6 {
margin-left: 1.5rem;
}
.ml-\[-11px\] {
margin-left: -11px;
}
.ml-auto {
margin-left: auto;
}
.mr-3 {
margin-right: 0.75rem;
}
.mt-1 {
margin-top: 0.25rem;
}
.mt-10 {
margin-top: 2.5rem;
}
.mt-3 {
margin-top: 0.75rem;
}
.mt-5 {
margin-top: 1.25rem;
}
.block {
display: block;
}
.inline-block {
display: inline-block;
}
.inline {
display: inline;
}
.flex {
display: flex;
}
.table {
display: table;
}
.grid {
display: grid;
}
.hidden {
display: none;
}
.h-1 {
height: 0.25rem;
}
.h-10 {
height: 2.5rem;
}
.h-4 {
height: 1rem;
}
.h-40 {
height: 10rem;
}
.h-5 {
height: 1.25rem;
}
.h-6 {
height: 1.5rem;
}
.h-\[100svh\] {
height: 100svh;
}
.h-fit {
height: -moz-fit-content;
height: fit-content;
}
.h-min {
height: -moz-min-content;
height: min-content;
}
.h-px {
height: 1px;
}
.max-h-20 {
max-height: 5rem;
}
.max-h-80 {
max-height: 20rem;
}
.max-h-\[40px\] {
max-height: 40px;
}
.w-10 {
width: 2.5rem;
}
.w-20 {
width: 5rem;
}
.w-4 {
width: 1rem;
}
.w-5 {
width: 1.25rem;
}
.w-6 {
width: 1.5rem;
}
.w-80 {
width: 20rem;
}
.w-full {
width: 100%;
}
.min-w-24 {
min-width: 6rem;
}
.max-w-20 {
max-width: 5rem;
}
.max-w-7xl {
max-width: 80rem;
}
.max-w-\[40px\] {
max-width: 40px;
}
.max-w-lg {
max-width: 32rem;
}
.max-w-sm {
max-width: 24rem;
}
.max-w-xs {
max-width: 20rem;
}
.flex-1 {
flex: 1 1 0%;
}
.flex-none {
flex: none;
}
.grow {
flex-grow: 1;
}
.table-auto {
table-layout: auto;
}
.caption-bottom {
caption-side: bottom;
}
.border-collapse {
border-collapse: collapse;
}
.origin-top-right {
transform-origin: top right;
}
.-translate-x-1\/2 {
--tw-translate-x: -50%;
transform: translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y));
}
.-translate-y-1\/2 {
--tw-translate-y: -50%;
transform: translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y));
}
.scale-0 {
--tw-scale-x: 0;
--tw-scale-y: 0;
transform: translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y));
}
.scale-100 {
--tw-scale-x: 1;
--tw-scale-y: 1;
transform: translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y));
}
.transform {
transform: translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y));
}
@keyframes pulse {
50% {
opacity: .5;
}
}
.animate-pulse {
animation: pulse 2s cubic-bezier(0.4, 0, 0.6, 1) infinite;
}
@keyframes spin {
to {
transform: rotate(360deg);
}
}
.animate-spin {
animation: spin 1s linear infinite;
}
.cursor-move {
cursor: move;
}
.select-none {
-webkit-user-select: none;
-moz-user-select: none;
user-select: none;
}
.grid-cols-1 {
grid-template-columns: repeat(1, minmax(0, 1fr));
}
.grid-cols-2 {
grid-template-columns: repeat(2, minmax(0, 1fr));
}
.flex-row {
flex-direction: row;
}
.flex-col {
flex-direction: column;
}
.flex-wrap {
flex-wrap: wrap;
}
.place-content-center {
place-content: center;
}
.items-center {
align-items: center;
}
.justify-end {
justify-content: flex-end;
}
.justify-center {
justify-content: center;
}
.justify-between {
justify-content: space-between;
}
.gap-2 {
gap: 0.5rem;
}
.gap-4 {
gap: 1rem;
}
.gap-5 {
gap: 1.25rem;
}
.space-x-1 > :not([hidden]) ~ :not([hidden]) {
--tw-space-x-reverse: 0;
margin-right: calc(0.25rem * var(--tw-space-x-reverse));
margin-left: calc(0.25rem * calc(1 - var(--tw-space-x-reverse)));
}
.overflow-hidden {
overflow: hidden;
}
.overflow-scroll {
overflow: scroll;
}
.whitespace-normal {
white-space: normal;
}
.break-words {
overflow-wrap: break-word;
}
.rounded {
border-radius: 0.25rem;
}
.rounded-2xl {
border-radius: 1rem;
}
.rounded-3xl {
border-radius: 1.5rem;
}
.rounded-full {
border-radius: 9999px;
}
.rounded-lg {
border-radius: 0.5rem;
}
.rounded-md {
border-radius: 0.375rem;
}
.rounded-xl {
border-radius: 0.75rem;
}
.rounded-tl-md {
border-top-left-radius: 0.375rem;
}
.rounded-tr-md {
border-top-right-radius: 0.375rem;
}
.border {
border-width: 1px;
}
.border-2 {
border-width: 2px;
}
.border-y {
border-top-width: 1px;
border-bottom-width: 1px;
}
.border-b {
border-bottom-width: 1px;
}
.border-l {
border-left-width: 1px;
}
.border-t {
border-top-width: 1px;
}
.border-\[\#6b7280\] {
--tw-border-opacity: 1;
border-color: rgb(107 114 128 / var(--tw-border-opacity, 1));
}
.border-gray-300 {
--tw-border-opacity: 1;
border-color: rgb(209 213 219 / var(--tw-border-opacity, 1));
}
.border-indigo-500 {
--tw-border-opacity: 1;
border-color: rgb(99 102 241 / var(--tw-border-opacity, 1));
}
.border-rose-500 {
--tw-border-opacity: 1;
border-color: rgb(244 63 94 / var(--tw-border-opacity, 1));
}
.border-slate-200 {
--tw-border-opacity: 1;
border-color: rgb(226 232 240 / var(--tw-border-opacity, 1));
}
.border-slate-300 {
--tw-border-opacity: 1;
border-color: rgb(203 213 225 / var(--tw-border-opacity, 1));
}
.border-slate-900\/10 {
border-color: rgb(15 23 42 / 0.1);
}
.bg-gray-50 {
--tw-bg-opacity: 1;
background-color: rgb(249 250 251 / var(--tw-bg-opacity, 1));
}
.bg-gray-900 {
--tw-bg-opacity: 1;
background-color: rgb(17 24 39 / var(--tw-bg-opacity, 1));
}
.bg-indigo-100 {
--tw-bg-opacity: 1;
background-color: rgb(224 231 255 / var(--tw-bg-opacity, 1));
}
.bg-indigo-500 {
--tw-bg-opacity: 1;
background-color: rgb(99 102 241 / var(--tw-bg-opacity, 1));
}
.bg-rose-100 {
--tw-bg-opacity: 1;
background-color: rgb(255 228 230 / var(--tw-bg-opacity, 1));
}
.bg-rose-50 {
--tw-bg-opacity: 1;
background-color: rgb(255 241 242 / var(--tw-bg-opacity, 1));
}
.bg-rose-500 {
--tw-bg-opacity: 1;
background-color: rgb(244 63 94 / var(--tw-bg-opacity, 1));
}
.bg-slate-100 {
--tw-bg-opacity: 1;
background-color: rgb(241 245 249 / var(--tw-bg-opacity, 1));
}
.bg-slate-50 {
--tw-bg-opacity: 1;
background-color: rgb(248 250 252 / var(--tw-bg-opacity, 1));
}
.bg-slate-900\/25 {
background-color: rgb(15 23 42 / 0.25);
}
.bg-white {
--tw-bg-opacity: 1;
background-color: rgb(255 255 255 / var(--tw-bg-opacity, 1));
}
.bg-white\/70 {
background-color: rgb(255 255 255 / 0.7);
}
.bg-gradient-to-r {
background-image: linear-gradient(to right, var(--tw-gradient-stops));
}
.from-indigo-500 {
--tw-gradient-from: #6366f1 var(--tw-gradient-from-position);
--tw-gradient-to: rgb(99 102 241 / 0) var(--tw-gradient-to-position);
--tw-gradient-stops: var(--tw-gradient-from), var(--tw-gradient-to);
}
.from-transparent {
--tw-gradient-from: transparent var(--tw-gradient-from-position);
--tw-gradient-to: rgb(0 0 0 / 0) var(--tw-gradient-to-position);
--tw-gradient-stops: var(--tw-gradient-from), var(--tw-gradient-to);
}
.from-10\% {
--tw-gradient-from-position: 10%;
}
.via-purple-500 {
--tw-gradient-to: rgb(168 85 247 / 0) var(--tw-gradient-to-position);
--tw-gradient-stops: var(--tw-gradient-from), #a855f7 var(--tw-gradient-via-position), var(--tw-gradient-to);
}
.to-pink-500 {
--tw-gradient-to: #ec4899 var(--tw-gradient-to-position);
}
.to-transparent {
--tw-gradient-to: transparent var(--tw-gradient-to-position);
}
.bg-clip-text {
-webkit-background-clip: text;
background-clip: text;
}
.p-2 {
padding: 0.5rem;
}
.p-3 {
padding: 0.75rem;
}
.p-4 {
padding: 1rem;
}
.p-5 {
padding: 1.25rem;
}
.p-6 {
padding: 1.5rem;
}
.px-0 {
padding-left: 0px;
padding-right: 0px;
}
.px-2 {
padding-left: 0.5rem;
padding-right: 0.5rem;
}
.px-3 {
padding-left: 0.75rem;
padding-right: 0.75rem;
}
.px-4 {
padding-left: 1rem;
padding-right: 1rem;
}
.px-6 {
padding-left: 1.5rem;
padding-right: 1.5rem;
}
.py-1 {
padding-top: 0.25rem;
padding-bottom: 0.25rem;
}
.py-2 {
padding-top: 0.5rem;
padding-bottom: 0.5rem;
}
.py-3 {
padding-top: 0.75rem;
padding-bottom: 0.75rem;
}
.py-4 {
padding-top: 1rem;
padding-bottom: 1rem;
}
.pb-2 {
padding-bottom: 0.5rem;
}
.pl-6 {
padding-left: 1.5rem;
}
.ps-10 {
padding-inline-start: 2.5rem;
}
.ps-3 {
padding-inline-start: 0.75rem;
}
.pt-5 {
padding-top: 1.25rem;
}
.pt-7 {
padding-top: 1.75rem;
}
.text-center {
text-align: center;
}
.text-right {
text-align: right;
}
.align-middle {
vertical-align: middle;
}
.font-sans {
font-family: ui-sans-serif, system-ui, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji";
}
.text-base {
font-size: 1rem;
line-height: 1.5rem;
}
.text-lg {
font-size: 1.125rem;
line-height: 1.75rem;
}
.text-sm {
font-size: 0.875rem;
line-height: 1.25rem;
}
.text-xl {
font-size: 1.25rem;
line-height: 1.75rem;
}
.text-xs {
font-size: 0.75rem;
line-height: 1rem;
}
.font-black {
font-weight: 900;
}
.font-bold {
font-weight: 700;
}
.font-extrabold {
font-weight: 800;
}
.font-medium {
font-weight: 500;
}
.font-normal {
font-weight: 400;
}
.font-semibold {
font-weight: 600;
}
.font-thin {
font-weight: 100;
}
.uppercase {
text-transform: uppercase;
}
.italic {
font-style: italic;
}
.leading-6 {
line-height: 1.5rem;
}
.tracking-tight {
letter-spacing: -0.025em;
}
.tracking-wide {
letter-spacing: 0.025em;
}
.tracking-wider {
letter-spacing: 0.05em;
}
.tracking-widest {
letter-spacing: 0.1em;
}
.text-gray-400 {
--tw-text-opacity: 1;
color: rgb(156 163 175 / var(--tw-text-opacity, 1));
}
.text-gray-500 {
--tw-text-opacity: 1;
color: rgb(107 114 128 / var(--tw-text-opacity, 1));
}
.text-gray-900 {
--tw-text-opacity: 1;
color: rgb(17 24 39 / var(--tw-text-opacity, 1));
}
.text-indigo-500 {
--tw-text-opacity: 1;
color: rgb(99 102 241 / var(--tw-text-opacity, 1));
}
.text-indigo-600 {
--tw-text-opacity: 1;
color: rgb(79 70 229 / var(--tw-text-opacity, 1));
}
.text-rose-500 {
--tw-text-opacity: 1;
color: rgb(244 63 94 / var(--tw-text-opacity, 1));
}
.text-slate-300 {
--tw-text-opacity: 1;
color: rgb(203 213 225 / var(--tw-text-opacity, 1));
}
.text-slate-500 {
--tw-text-opacity: 1;
color: rgb(100 116 139 / var(--tw-text-opacity, 1));
}
.text-slate-600 {
--tw-text-opacity: 1;
color: rgb(71 85 105 / var(--tw-text-opacity, 1));
}
.text-slate-700 {
--tw-text-opacity: 1;
color: rgb(51 65 85 / var(--tw-text-opacity, 1));
}
.text-slate-800 {
--tw-text-opacity: 1;
color: rgb(30 41 59 / var(--tw-text-opacity, 1));
}
.text-slate-900 {
--tw-text-opacity: 1;
color: rgb(15 23 42 / var(--tw-text-opacity, 1));
}
.text-transparent {
color: transparent;
}
.text-white {
--tw-text-opacity: 1;
color: rgb(255 255 255 / var(--tw-text-opacity, 1));
}
.underline {
text-decoration-line: underline;
}
.decoration-pink-500\/80 {
text-decoration-color: rgb(236 72 153 / 0.8);
}
.decoration-8 {
text-decoration-thickness: 8px;
}
.underline-offset-\[-5px\] {
text-underline-offset: -5px;
}
.opacity-0 {
opacity: 0;
}
.opacity-100 {
opacity: 1;
}
.shadow {
--tw-shadow: 0 1px 3px 0 rgb(0 0 0 / 0.1), 0 1px 2px -1px rgb(0 0 0 / 0.1);
--tw-shadow-colored: 0 1px 3px 0 var(--tw-shadow-color), 0 1px 2px -1px var(--tw-shadow-color);
box-shadow: var(--tw-ring-offset-shadow, 0 0 #0000), var(--tw-ring-shadow, 0 0 #0000), var(--tw-shadow);
}
.shadow-\[0_1px_3px_rgba\(15\2c 23\2c 42\2c 0\.03\)\2c 0_1px_2px_rgba\(15\2c 23\2c 42\2c 0\.06\)\] {
--tw-shadow: 0 1px 3px rgba(15,23,42,0.03),0 1px 2px rgba(15,23,42,0.06);
--tw-shadow-colored: 0 1px 3px var(--tw-shadow-color), 0 1px 2px var(--tw-shadow-color);
box-shadow: var(--tw-ring-offset-shadow, 0 0 #0000), var(--tw-ring-shadow, 0 0 #0000), var(--tw-shadow);
}
.shadow-lg {
--tw-shadow: 0 10px 15px -3px rgb(0 0 0 / 0.1), 0 4px 6px -4px rgb(0 0 0 / 0.1);
--tw-shadow-colored: 0 10px 15px -3px var(--tw-shadow-color), 0 4px 6px -4px var(--tw-shadow-color);
box-shadow: var(--tw-ring-offset-shadow, 0 0 #0000), var(--tw-ring-shadow, 0 0 #0000), var(--tw-shadow);
}
.shadow-md {
--tw-shadow: 0 4px 6px -1px rgb(0 0 0 / 0.1), 0 2px 4px -2px rgb(0 0 0 / 0.1);
--tw-shadow-colored: 0 4px 6px -1px var(--tw-shadow-color), 0 2px 4px -2px var(--tw-shadow-color);
box-shadow: var(--tw-ring-offset-shadow, 0 0 #0000), var(--tw-ring-shadow, 0 0 #0000), var(--tw-shadow);
}
.shadow-gray-500\/20 {
--tw-shadow-color: rgb(107 114 128 / 0.2);
--tw-shadow: var(--tw-shadow-colored);
}
.shadow-gray-900\/10 {
--tw-shadow-color: rgb(17 24 39 / 0.1);
--tw-shadow: var(--tw-shadow-colored);
}
.shadow-indigo-500\/50 {
--tw-shadow-color: rgb(99 102 241 / 0.5);
--tw-shadow: var(--tw-shadow-colored);
}
.shadow-rose-500\/50 {
--tw-shadow-color: rgb(244 63 94 / 0.5);
--tw-shadow: var(--tw-shadow-colored);
}
.ring-1 {
--tw-ring-offset-shadow: var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);
--tw-ring-shadow: var(--tw-ring-inset) 0 0 0 calc(1px + var(--tw-ring-offset-width)) var(--tw-ring-color);
box-shadow: var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow, 0 0 #0000);
}
.ring-slate-600\/\[0\.04\] {
--tw-ring-color: rgb(71 85 105 / 0.04);
}
.drop-shadow-xl {
--tw-drop-shadow: drop-shadow(0 20px 13px rgb(0 0 0 / 0.03)) drop-shadow(0 8px 5px rgb(0 0 0 / 0.08));
filter: var(--tw-blur) var(--tw-brightness) var(--tw-contrast) var(--tw-grayscale) var(--tw-hue-rotate) var(--tw-invert) var(--tw-saturate) var(--tw-sepia) var(--tw-drop-shadow);
}
.backdrop-blur {
--tw-backdrop-blur: blur(8px);
-webkit-backdrop-filter: var(--tw-backdrop-blur) var(--tw-backdrop-brightness) var(--tw-backdrop-contrast) var(--tw-backdrop-grayscale) var(--tw-backdrop-hue-rotate) var(--tw-backdrop-invert) var(--tw-backdrop-opacity) var(--tw-backdrop-saturate) var(--tw-backdrop-sepia);
backdrop-filter: var(--tw-backdrop-blur) var(--tw-backdrop-brightness) var(--tw-backdrop-contrast) var(--tw-backdrop-grayscale) var(--tw-backdrop-hue-rotate) var(--tw-backdrop-invert) var(--tw-backdrop-opacity) var(--tw-backdrop-saturate) var(--tw-backdrop-sepia);
}
.transition {
transition-property: color, background-color, border-color, text-decoration-color, fill, stroke, opacity, box-shadow, transform, filter, -webkit-backdrop-filter;
transition-property: color, background-color, border-color, text-decoration-color, fill, stroke, opacity, box-shadow, transform, filter, backdrop-filter;
transition-property: color, background-color, border-color, text-decoration-color, fill, stroke, opacity, box-shadow, transform, filter, backdrop-filter, -webkit-backdrop-filter;
transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1);
transition-duration: 150ms;
}
.transition-all {
transition-property: all;
transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1);
transition-duration: 150ms;
}
.transition-colors {
transition-property: color, background-color, border-color, text-decoration-color, fill, stroke;
transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1);
transition-duration: 150ms;
}
.transition-opacity {
transition-property: opacity;
transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1);
transition-duration: 150ms;
}
.duration-300 {
transition-duration: 300ms;
}
.duration-500 {
transition-duration: 500ms;
}
.selection\:bg-fuchsia-300 *::-moz-selection {
--tw-bg-opacity: 1;
background-color: rgb(240 171 252 / var(--tw-bg-opacity, 1));
}
.selection\:bg-fuchsia-300 *::selection {
--tw-bg-opacity: 1;
background-color: rgb(240 171 252 / var(--tw-bg-opacity, 1));
}
.selection\:text-fuchsia-900 *::-moz-selection {
--tw-text-opacity: 1;
color: rgb(112 26 117 / var(--tw-text-opacity, 1));
}
.selection\:text-fuchsia-900 *::selection {
--tw-text-opacity: 1;
color: rgb(112 26 117 / var(--tw-text-opacity, 1));
}
.selection\:bg-fuchsia-300::-moz-selection {
--tw-bg-opacity: 1;
background-color: rgb(240 171 252 / var(--tw-bg-opacity, 1));
}
.selection\:bg-fuchsia-300::selection {
--tw-bg-opacity: 1;
background-color: rgb(240 171 252 / var(--tw-bg-opacity, 1));
}
.selection\:text-fuchsia-900::-moz-selection {
--tw-text-opacity: 1;
color: rgb(112 26 117 / var(--tw-text-opacity, 1));
}
.selection\:text-fuchsia-900::selection {
--tw-text-opacity: 1;
color: rgb(112 26 117 / var(--tw-text-opacity, 1));
}
.placeholder\:text-xs::-moz-placeholder {
font-size: 0.75rem;
line-height: 1rem;
}
.placeholder\:text-xs::placeholder {
font-size: 0.75rem;
line-height: 1rem;
}
.placeholder\:font-thin::-moz-placeholder {
font-weight: 100;
}
.placeholder\:font-thin::placeholder {
font-weight: 100;
}
.placeholder\:italic::-moz-placeholder {
font-style: italic;
}
.placeholder\:italic::placeholder {
font-style: italic;
}
.placeholder\:text-gray-400::-moz-placeholder {
--tw-text-opacity: 1;
color: rgb(156 163 175 / var(--tw-text-opacity, 1));
}
.placeholder\:text-gray-400::placeholder {
--tw-text-opacity: 1;
color: rgb(156 163 175 / var(--tw-text-opacity, 1));
}
.placeholder\:text-slate-500::-moz-placeholder {
--tw-text-opacity: 1;
color: rgb(100 116 139 / var(--tw-text-opacity, 1));
}
.placeholder\:text-slate-500::placeholder {
--tw-text-opacity: 1;
color: rgb(100 116 139 / var(--tw-text-opacity, 1));
}
.invalid\:border-pink-500:invalid {
--tw-border-opacity: 1;
border-color: rgb(236 72 153 / var(--tw-border-opacity, 1));
}
.invalid\:text-pink-600:invalid {
--tw-text-opacity: 1;
color: rgb(219 39 119 / var(--tw-text-opacity, 1));
}
.hover\:rounded-lg:hover {
border-radius: 0.5rem;
}
.hover\:bg-gray-50:hover {
--tw-bg-opacity: 1;
background-color: rgb(249 250 251 / var(--tw-bg-opacity, 1));
}
.hover\:bg-gray-900\/10:hover {
background-color: rgb(17 24 39 / 0.1);
}
.hover\:bg-indigo-100:hover {
--tw-bg-opacity: 1;
background-color: rgb(224 231 255 / var(--tw-bg-opacity, 1));
}
.hover\:bg-indigo-600:hover {
--tw-bg-opacity: 1;
background-color: rgb(79 70 229 / var(--tw-bg-opacity, 1));
}
.hover\:bg-rose-600:hover {
--tw-bg-opacity: 1;
background-color: rgb(225 29 72 / var(--tw-bg-opacity, 1));
}
.hover\:underline:hover {
text-decoration-line: underline;
}
.hover\:shadow-lg:hover {
--tw-shadow: 0 10px 15px -3px rgb(0 0 0 / 0.1), 0 4px 6px -4px rgb(0 0 0 / 0.1);
--tw-shadow-colored: 0 10px 15px -3px var(--tw-shadow-color), 0 4px 6px -4px var(--tw-shadow-color);
box-shadow: var(--tw-ring-offset-shadow, 0 0 #0000), var(--tw-ring-shadow, 0 0 #0000), var(--tw-shadow);
}
.hover\:shadow-gray-900\/20:hover {
--tw-shadow-color: rgb(17 24 39 / 0.2);
--tw-shadow: var(--tw-shadow-colored);
}
.hover\:outline:hover {
outline-style: solid;
}
.hover\:outline-1:hover {
outline-width: 1px;
}
.hover\:outline-indigo-200:hover {
outline-color: #c7d2fe;
}
.focus\:border-indigo-500:focus {
--tw-border-opacity: 1;
border-color: rgb(99 102 241 / var(--tw-border-opacity, 1));
}
.focus\:opacity-\[0\.85\]:focus {
opacity: 0.85;
}
.focus\:shadow-none:focus {
--tw-shadow: 0 0 #0000;
--tw-shadow-colored: 0 0 #0000;
box-shadow: var(--tw-ring-offset-shadow, 0 0 #0000), var(--tw-ring-shadow, 0 0 #0000), var(--tw-shadow);
}
.focus\:outline-none:focus {
outline: 2px solid transparent;
outline-offset: 2px;
}
.focus\:ring-1:focus {
--tw-ring-offset-shadow: var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);
--tw-ring-shadow: var(--tw-ring-inset) 0 0 0 calc(1px + var(--tw-ring-offset-width)) var(--tw-ring-color);
box-shadow: var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow, 0 0 #0000);
}
.focus\:ring-4:focus {
--tw-ring-offset-shadow: var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);
--tw-ring-shadow: var(--tw-ring-inset) 0 0 0 calc(4px + var(--tw-ring-offset-width)) var(--tw-ring-color);
box-shadow: var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow, 0 0 #0000);
}
.focus\:ring-indigo-300:focus {
--tw-ring-opacity: 1;
--tw-ring-color: rgb(165 180 252 / var(--tw-ring-opacity, 1));
}
.focus\:ring-indigo-500:focus {
--tw-ring-opacity: 1;
--tw-ring-color: rgb(99 102 241 / var(--tw-ring-opacity, 1));
}
.focus\:invalid\:border-pink-500:invalid:focus {
--tw-border-opacity: 1;
border-color: rgb(236 72 153 / var(--tw-border-opacity, 1));
}
.focus\:invalid\:ring-pink-500:invalid:focus {
--tw-ring-opacity: 1;
--tw-ring-color: rgb(236 72 153 / var(--tw-ring-opacity, 1));
}
.active\:bg-gray-900\/20:active {
background-color: rgb(17 24 39 / 0.2);
}
.active\:opacity-\[0\.85\]:active {
opacity: 0.85;
}
.active\:shadow-none:active {
--tw-shadow: 0 0 #0000;
--tw-shadow-colored: 0 0 #0000;
box-shadow: var(--tw-ring-offset-shadow, 0 0 #0000), var(--tw-ring-shadow, 0 0 #0000), var(--tw-shadow);
}
.disabled\:pointer-events-none:disabled {
pointer-events: none;
}
.disabled\:border-slate-200:disabled {
--tw-border-opacity: 1;
border-color: rgb(226 232 240 / var(--tw-border-opacity, 1));
}
.disabled\:bg-slate-200:disabled {
--tw-bg-opacity: 1;
background-color: rgb(226 232 240 / var(--tw-bg-opacity, 1));
}
.disabled\:bg-slate-50:disabled {
--tw-bg-opacity: 1;
background-color: rgb(248 250 252 / var(--tw-bg-opacity, 1));
}
.disabled\:text-slate-500:disabled {
--tw-text-opacity: 1;
color: rgb(100 116 139 / var(--tw-text-opacity, 1));
}
.disabled\:text-white:disabled {
--tw-text-opacity: 1;
color: rgb(255 255 255 / var(--tw-text-opacity, 1));
}
.disabled\:opacity-50:disabled {
opacity: 0.5;
}
.disabled\:shadow-none:disabled {
--tw-shadow: 0 0 #0000;
--tw-shadow-colored: 0 0 #0000;
box-shadow: var(--tw-ring-offset-shadow, 0 0 #0000), var(--tw-ring-shadow, 0 0 #0000), var(--tw-shadow);
}
.group:hover .group-hover\:rounded-lg {
border-radius: 0.5rem;
}
.group:hover .group-hover\:bg-indigo-100 {
--tw-bg-opacity: 1;
background-color: rgb(224 231 255 / var(--tw-bg-opacity, 1));
}
.group:hover .group-hover\:outline {
outline-style: solid;
}
.group:hover .group-hover\:outline-1 {
outline-width: 1px;
}
.group:hover .group-hover\:outline-indigo-200 {
outline-color: #c7d2fe;
}
@media (min-width: 640px) {
.sm\:text-2xl {
font-size: 1.5rem;
line-height: 2rem;
}
}
@media (min-width: 768px) {
.md\:inline-block {
display: inline-block;
}
.md\:flex {
display: flex;
}
.md\:hidden {
display: none;
}
.md\:w-96 {
width: 24rem;
}
.md\:grid-cols-4 {
grid-template-columns: repeat(4, minmax(0, 1fr));
}
.md\:space-x-3 > :not([hidden]) ~ :not([hidden]) {
--tw-space-x-reverse: 0;
margin-right: calc(0.75rem * var(--tw-space-x-reverse));
margin-left: calc(0.75rem * calc(1 - var(--tw-space-x-reverse)));
}
.md\:p-8 {
padding: 2rem;
}
.md\:placeholder\:text-sm::-moz-placeholder {
font-size: 0.875rem;
line-height: 1.25rem;
}
.md\:placeholder\:text-sm::placeholder {
font-size: 0.875rem;
line-height: 1.25rem;
}
}
@media (min-width: 1024px) {
.lg\:z-50 {
z-index: 50;
}
.lg\:mx-0 {
margin-left: 0px;
margin-right: 0px;
}
.lg\:mb-2 {
margin-bottom: 0.5rem;
}
.lg\:ml-0 {
margin-left: 0px;
}
.lg\:flex {
display: flex;
}
.lg\:w-auto {
width: auto;
}
.lg\:grow {
flex-grow: 1;
}
.lg\:flex-col {
flex-direction: column;
}
.lg\:gap-4 {
gap: 1rem;
}
.lg\:space-x-5 > :not([hidden]) ~ :not([hidden]) {
--tw-space-x-reverse: 0;
margin-right: calc(1.25rem * var(--tw-space-x-reverse));
margin-left: calc(1.25rem * calc(1 - var(--tw-space-x-reverse)));
}
.lg\:border-0 {
border-width: 0px;
}
.lg\:border-b {
border-bottom-width: 1px;
}
.lg\:border-slate-900\/10 {
border-color: rgb(15 23 42 / 0.1);
}
.lg\:px-8 {
padding-left: 2rem;
padding-right: 2rem;
}
.lg\:text-base {
font-size: 1rem;
line-height: 1.5rem;
}
.lg\:text-base\/loose {
font-size: 1rem;
line-height: 2;
}
.lg\:text-base\/normal {
font-size: 1rem;
line-height: 1.5;
}
.lg\:text-base\/relaxed {
font-size: 1rem;
line-height: 1.625;
}
.lg\:text-sm {
font-size: 0.875rem;
line-height: 1.25rem;
}
}
@media (prefers-color-scheme: dark) {
.dark\:border-gray-600 {
--tw-border-opacity: 1;
border-color: rgb(75 85 99 / var(--tw-border-opacity, 1));
}
.dark\:border-slate-800 {
--tw-border-opacity: 1;
border-color: rgb(30 41 59 / var(--tw-border-opacity, 1));
}
.dark\:bg-gray-700 {
--tw-bg-opacity: 1;
background-color: rgb(55 65 81 / var(--tw-bg-opacity, 1));
}
.dark\:bg-indigo-600 {
--tw-bg-opacity: 1;
background-color: rgb(79 70 229 / var(--tw-bg-opacity, 1));
}
.dark\:bg-slate-800 {
--tw-bg-opacity: 1;
background-color: rgb(30 41 59 / var(--tw-bg-opacity, 1));
}
.dark\:text-slate-400 {
--tw-text-opacity: 1;
color: rgb(148 163 184 / var(--tw-text-opacity, 1));
}
.dark\:text-white {
--tw-text-opacity: 1;
color: rgb(255 255 255 / var(--tw-text-opacity, 1));
}
.dark\:placeholder-gray-400::-moz-placeholder {
--tw-placeholder-opacity: 1;
color: rgb(156 163 175 / var(--tw-placeholder-opacity, 1));
}
.dark\:placeholder-gray-400::placeholder {
--tw-placeholder-opacity: 1;
color: rgb(156 163 175 / var(--tw-placeholder-opacity, 1));
}
.dark\:hover\:bg-indigo-700:hover {
--tw-bg-opacity: 1;
background-color: rgb(67 56 202 / var(--tw-bg-opacity, 1));
}
.dark\:focus\:border-indigo-500:focus {
--tw-border-opacity: 1;
border-color: rgb(99 102 241 / var(--tw-border-opacity, 1));
}
.dark\:focus\:ring-indigo-500:focus {
--tw-ring-opacity: 1;
--tw-ring-color: rgb(99 102 241 / var(--tw-ring-opacity, 1));
}
.dark\:focus\:ring-indigo-800:focus {
--tw-ring-opacity: 1;
--tw-ring-color: rgb(55 48 163 / var(--tw-ring-opacity, 1));
}
}
/source/app/public/admin/css/tailwind.css

@@ -0,0 +1,11 @@
/** @type {import('tailwindcss').Config} */
module.exports = {
content: ["./tailwindcss/**/*.{html,js}"],
Copy link

Choose a reason for hiding this comment

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

💡 Codebase verification

Based on the search results, I can see that Tailwind classes are indeed being used in PHP template files under source/app/var/qiq/template/ directory. The current content path in the Tailwind config only includes files under ./tailwindcss/**/*.{html,js}, which would miss these PHP templates.

Content paths should include PHP templates

The current content path is missing PHP templates where Tailwind classes are actively used. Add the PHP template directory to ensure proper CSS generation.

  • source/app/var/qiq/template/**/*.php contains Tailwind classes in template files
  • Current config would miss these classes, leading to missing styles
-  content: ["./tailwindcss/**/*.{html,js}"],
+  content: [
+    "./tailwindcss/**/*.{html,js}",
+    "../../var/qiq/template/**/*.php"
+  ],
🔗 Analysis chain

Consider expanding the content paths

The current content path "./tailwindcss/**/*.{html,js}" might be too restrictive. Consider including other directories where Tailwind classes might be used, such as template files.

-  content: ["./tailwindcss/**/*.{html,js}"],
+  content: [
+    "./tailwindcss/**/*.{html,js}",
+    "../**/*.php",
+    "./**/*.{html,js}"
+  ],
🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Check for potential Tailwind class usage outside the specified directory
rg -t html -t php -t js 'class="[^"]*[a-zA-Z0-9:-]+' --glob '!tailwindcss/**'

Length of output: 58328

@@ -11,10 +11,10 @@
{{ setBlock ('head_meta') }}{{= getBlock () ~}}
{{ setBlock ('head_styles') }}
<link href="{{= $siteUrl }}/admin/css/bundle.css" rel="stylesheet">
<link href="{{= $siteUrl }}/admin/css/tailwind.css" rel="stylesheet">
Copy link

Choose a reason for hiding this comment

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

💡 Codebase verification

CSS path needs to be updated to include 'public' directory

The Tailwind CSS file is actually located at /admin/css/tailwind.css under the public directory. The current template path {{= $siteUrl }}/admin/css/tailwind.css should be updated to {{= $siteUrl }}/public/admin/css/tailwind.css to match the actual file location.

🔗 Analysis chain

Verify the CSS file path and existence

The Tailwind CSS file path looks correct, but let's verify it's being generated in the right location.


Let me verify the correct path by searching for the CSS file and related build configurations.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Check if the CSS output directory exists and is writable
test -w "../admin/css" && echo "Directory exists and is writable" || echo "Directory issue"

Length of output: 63


Script:

#!/bin/bash
# Search for Tailwind CSS files and build configurations
fd -t f "tailwind.css"

# Search for any build scripts or config files related to Tailwind
fd -t f "(tailwind.config|postcss.config)"

# Check the actual web assets directory structure
fd -t d "(css|assets|public)" -d 3

Length of output: 211

Comment on lines +18 to +23
<div class="p-4 mb-4 text-sm text-rose-500 rounded-lg bg-rose-50 mt-5" role="alert">
<svg class="inline w-6 h-6 ">
<use xlink:href="/itae/admin/images/heroicons/icon.svg#shield-exclamation"></use>
</svg>
<span class="font-sans font-bold">TEXT</span>
</div>
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue

Replace hardcoded "TEXT" placeholder

The alert message contains a hardcoded "TEXT" placeholder that needs to be replaced with actual error message content.

Comment on lines +28 to +29
<input type="text" name="username" autofocus="" autocomplete="username" placeholder="username" required="required" minlength="5" maxlength="100" title="有効なユーザー名を入力してください" class="rounded w-full placeholder:text-slate-500 placeholder:font-thin transition duration-300 focus:outline-none focus:border-indigo-500 focus:ring-1 focus:ring-indigo-500 disabled:bg-slate-50 disabled:text-slate-500 disabled:border-slate-200 disabled:shadow-none invalid:border-pink-500 invalid:text-pink-600 focus:invalid:border-pink-500 focus:invalid:ring-pink-500">
<p class="block text-sm text-rose-500 italic">TEXT</p>
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue

Inconsistent language usage in form validation

The form shows mixed language usage:

  • Interface elements are in English
  • Title attributes contain Japanese text
  • Error messages use "TEXT" placeholder

Consider implementing proper localization support for consistent language handling.

Also applies to: 33-34

Comment on lines +118 to +124
<form method="post" action="/admin/logout">
<button class="text-slate-600 text-base tracking-wide p-2 -ml-px font-medium">
<svg class="inline w-6 h-6 ">
<use xlink:href="/admin/images/heroicons/icon.svg#arrow-left-on-rectangle"></use>
</svg>
</button>
</form>
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue

Add CSRF protection to logout forms.

The logout forms are missing CSRF protection tokens, which could make them vulnerable to CSRF attacks.

Add CSRF token to both mobile and desktop logout forms:

 <form method="post" action="/admin/logout">
+    <input type="hidden" name="_csrf" value="<?= $this->escape($csrf_token) ?>">
     <button class="text-slate-600 text-base tracking-wide p-2 -ml-px font-medium">
         <svg class="inline w-6 h-6 ">
             <use xlink:href="/admin/images/heroicons/icon.svg#arrow-left-on-rectangle"></use>
         </svg>
     </button>
 </form>

Also applies to: 219-225

Comment on lines +50 to +136
<div id="menuBg" class="fixed z-50 inset-0 hidden md:hidden">
<div class="fixed inset-0 bg-slate-900/25 backdrop-blur transition-opacity opacity-100"></div>
<div id="menu" class="fixed top-4 right-4 w-full max-w-xs bg-white rounded-3xl shadow-lg p-6 text-base font-semibold text-slate-900 dark:bg-slate-800 dark:text-slate-400 dark:highlight-white/5 transition-all origin-top-right opacity-0 scale-0">
<div class="flex justify-between">
<div>
<ul class="grid grid-cols-1 gap-5">
<li class="group">
<a href="/admin/index"
class="text-slate-600 text-base tracking-wide p-2 -ml-px font-extrabold">
<svg class="inline w-5 h-5 ">
<use xlink:href="/admin/images/heroicons/icon.svg#home-modern"></use>
</svg>
&nbsp;HOME
</a>
<div class="mt-1 h-1 rounded-full bg-indigo-500"></div>
</li>
<li class="group">
<a href="/admin/menu-item1"
class="text-slate-600 text-base tracking-wide p-2 -ml-px font-medium">
<svg class="inline w-5 h-5 ">
<use xlink:href="/admin/images/heroicons/icon.svg#paint-brush"></use>
</svg>
&nbsp;MENU1
</a>
<div class="mt-1 h-1 rounded-full "></div>
</li>
<li class="group">
<a href="/admin/menu-item2"
class="text-slate-600 text-base tracking-wide p-2 -ml-px font-medium">
<svg class="inline w-5 h-5 ">
<use xlink:href="/admin/images/heroicons/icon.svg#calendar"></use>
</svg>
&nbsp;MENU2
</a>
<div class="mt-1 h-1 rounded-full "></div>
</li>
<li class="group">
<a href="/admin/menu-item3"
class="text-slate-600 text-base tracking-wide p-2 -ml-px font-medium">
<svg class="inline w-5 h-5 ">
<use xlink:href="/admin/images/heroicons/icon.svg#trophy"></use>
</svg>
&nbsp;MENU3
</a>
<div class="mt-1 h-1 rounded-full "></div>
</li>
<li class="group">
<a href="/admin/menu-item4"
class="text-slate-600 text-base tracking-wide p-2 -ml-px font-medium">
<svg class="inline w-5 h-5 ">
<use xlink:href="/admin/images/heroicons/icon.svg#swatch"></use>
</svg>
&nbsp;MENU4
</a>
<div class="mt-1 h-1 rounded-full "></div>
</li>
<li class="group">
<a href="/admin/menu-item5"
class="text-slate-600 text-base tracking-wide p-2 -ml-px font-medium">
<svg class="inline w-5 h-5 ">
<use xlink:href="/admin/images/heroicons/icon.svg#user-group"></use>
</svg>
&nbsp;MENU5
</a>
<div class="mt-1 h-1 rounded-full "></div>
</li>
</ul>
<div class="border-t border-slate-200 dark:border-slate-800 pt-5 mt-5">
<form method="post" action="/admin/logout">
<button class="text-slate-600 text-base tracking-wide p-2 -ml-px font-medium">
<svg class="inline w-6 h-6 ">
<use xlink:href="/admin/images/heroicons/icon.svg#arrow-left-on-rectangle"></use>
</svg>
</button>
</form>
</div>
</div>
<div>
<button type="button" id="menuCloser">
<svg class="inline w-6 h-6 ">
<use xlink:href="/admin/images/heroicons/icon.svg#x-mark"></use>
</svg>
</button>
</div>
</div>
</div>
</div>
Copy link

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

Improve navigation accessibility and maintainability.

The navigation menu has several areas for improvement:

  1. Duplicate menu items between mobile and desktop views
  2. Missing keyboard navigation support
  3. Inconsistent aria attributes

Consider extracting menu items to a template partial to avoid duplication and ensure consistency. Add proper keyboard navigation support:

 <nav class="block leading-6 relative">
+    <ul class="flex flex-column space-x-1 md:space-x-3 lg:space-x-5" role="menubar">
-        <ul class="flex flex-column space-x-1 md:space-x-3 lg:space-x-5">
         <li class="group">
-            <a href="/admin/index"
+            <a href="/admin/index" role="menuitem" tabindex="0"
                class="text-slate-600 text-sm tracking-wide p-2 -ml-px font-extrabold">

Also applies to: 152-227

Comment on lines +568 to +689
</div>
</label>

<label class="block mt-5">
<span class="block text-sm font-sans font-normal text-slate-700">テキストエリア</span>
<textarea class="rounded w-full placeholder:text-slate-500 placeholder:font-thin transition duration-300 focus:outline-none focus:border-indigo-500 focus:ring-1 focus:ring-indigo-500 disabled:bg-slate-50 disabled:text-slate-500 disabled:border-slate-200 disabled:shadow-none invalid:border-pink-500 invalid:text-pink-600 focus:invalid:border-pink-500 focus:invalid:ring-pink-500 leading-6 h-40" placeholder="プレースホルダー"></textarea>
</label>

<label class="block mt-5">
<span class="absolute block top-2 left-3 text-sm font-thin text-slate-500">テキストエリア</span>
<textarea class="rounded w-full pt-7 placeholder:text-slate-500 placeholder:font-thin transition duration-300 focus:outline-none focus:border-indigo-500 focus:ring-1 focus:ring-indigo-500 disabled:bg-slate-50 disabled:text-slate-500 disabled:border-slate-200 disabled:shadow-none invalid:border-pink-500 invalid:text-pink-600 focus:invalid:border-pink-500 focus:invalid:ring-pink-500 leading-6 h-40" placeholder=""></textarea>
</label>

<label class="block mt-5">
<span class="block text-sm font-sans font-normal text-slate-700">日付</span>
<input type="text" class="flatpickr1 rounded w-full placeholder:text-slate-500 placeholder:font-thin transition duration-300 focus:outline-none focus:border-indigo-500 focus:ring-1 focus:ring-indigo-500 disabled:bg-slate-50 disabled:text-slate-500 disabled:border-slate-200 disabled:shadow-none invalid:border-pink-500 invalid:text-pink-600 focus:invalid:border-pink-500 focus:invalid:ring-pink-500" placeholder="YYYY-MM-DD">
<script>flatpickr('.flatpickr1', { disableMobile: true });</script>
</label>

<label class="block mt-5">
<span class="absolute block top-2 left-3 text-sm font-thin text-slate-500">日付</span>
<input type="text" class="flatpickr3 rounded w-full pt-7 placeholder:text-slate-500 placeholder:font-thin transition duration-300 focus:outline-none focus:border-indigo-500 focus:ring-1 focus:ring-indigo-500 disabled:bg-slate-50 disabled:text-slate-500 disabled:border-slate-200 disabled:shadow-none invalid:border-pink-500 invalid:text-pink-600 focus:invalid:border-pink-500 focus:invalid:ring-pink-500" placeholder="YYYY-MM-DD">
<script>flatpickr('.flatpickr3', { disableMobile: true });</script>
</label>

<label class="block mt-5">
<span class="block text-sm font-sans font-normal text-slate-700">日時</span>
<input type="text" class="flatpickr2 rounded w-full placeholder:text-slate-500 placeholder:font-thin transition duration-300 focus:outline-none focus:border-indigo-500 focus:ring-1 focus:ring-indigo-500 disabled:bg-slate-50 disabled:text-slate-500 disabled:border-slate-200 disabled:shadow-none invalid:border-pink-500 invalid:text-pink-600 focus:invalid:border-pink-500 focus:invalid:ring-pink-500" placeholder="YYYY-MM-DD HH:MM">
<script>flatpickr('.flatpickr2', { disableMobile: true, enableTime: true, dateFormat: 'Y-m-d H:i' });</script>
</label>

<label class="block mt-5">
<span class="block top-2 left-3 text-sm font-thin text-slate-500">日時</span>
<input type="text" class="flatpickr4 rounded w-full pt-7 placeholder:text-slate-500 placeholder:font-thin transition duration-300 focus:outline-none focus:border-indigo-500 focus:ring-1 focus:ring-indigo-500 disabled:bg-slate-50 disabled:text-slate-500 disabled:border-slate-200 disabled:shadow-none invalid:border-pink-500 invalid:text-pink-600 focus:invalid:border-pink-500 focus:invalid:ring-pink-500" placeholder="YYYY-MM-DD HH:MM">
<script>flatpickr('.flatpickr4', { disableMobile: true, enableTime: true, dateFormat: 'Y-m-d H:i' });</script>
</label>

<label class="block mt-5">
<span class="block top-2 left-3 text-sm font-normal text-slate-700 tracking-wide select-none">ファイルタイプ</span>
<input type="file" class="rounded w-full p-3 text-sm bg-white border border-[#6b7280] placeholder:text-slate-500 placeholder:font-thin transition duration-300 focus:outline-none focus:border-indigo-500 focus:ring-1 focus:ring-indigo-500 disabled:bg-slate-50 disabled:text-slate-500 disabled:border-slate-200 disabled:shadow-none invalid:border-pink-500 invalid:text-pink-600 focus:invalid:border-pink-500 focus:invalid:ring-pink-500" placeholder="">
</label>

<div class="mt-5">
<span class="block text-sm font-sans font-normal text-slate-700">チェックボックス</span>
<label class="block">
<input type="checkbox" name="check1" value="1">
<span class="text-base font-sans font-normal text-slate-700">チェック1</span>
</label>
<label class="block">
<input type="checkbox" name="check2" value="2">
<span class="text-base font-sans font-normal text-slate-700">チェック2</span>
</label>
</div>

<div class="mt-5">
<span class="block text-sm font-sans font-normal text-slate-700">ラジオボタン</span>
<label class="inline">
<input type="radio" name="radio" value="1">
<span class="text-base font-sans font-normal text-slate-700">ラジオ1</span>
</label>
<label class="inline ml-2">
<input type="radio" name="radio" value="2">
<span class="text-base font-sans font-normal text-slate-700">ラジオ2</span>
</label>
</div>

<label class="block mt-5">
<span class="block text-sm font-sans font-normal text-slate-700">選択(選択肢が6個以上)</span>
<select class="rounded transition duration-300 focus:outline-none focus:border-indigo-500 focus:ring-1 focus:ring-indigo-500 disabled:bg-slate-50 disabled:text-slate-500 disabled:border-slate-200 disabled:shadow-none invalid:border-pink-500 invalid:text-pink-600 focus:invalid:border-pink-500 focus:invalid:ring-pink-500">
<option>選択肢1</option>
<option>選択肢2</option>
<option>選択肢3</option>
</select>
</label>

<label class="block mt-5">
<span class="absolute block top-2 left-3 text-sm font-thin text-slate-500">選択(選択肢が6個以上)</span>
<select class="rounded transition duration-300 pt-7 focus:outline-none focus:border-indigo-500 focus:ring-1 focus:ring-indigo-500 disabled:bg-slate-50 disabled:text-slate-500 disabled:border-slate-200 disabled:shadow-none invalid:border-pink-500 invalid:text-pink-600 focus:invalid:border-pink-500 focus:invalid:ring-pink-500">
<option>選択肢1</option>
<option>選択肢2</option>
<option>選択肢3</option>
</select>
</label>

<div class="mt-5">
<span class="block text-sm font-sans font-normal text-slate-700">送信ボタン</span>
<input type="submit" value="保存" class="py-2 px-4 bg-indigo-500 text-white text-sm font-sans font-bold tracking-wider rounded-full shadow-lg shadow-indigo-500/50 focus:outline-none hover:bg-indigo-600 focus:opacity-[0.85] focus:shadow-none active:opacity-[0.85] active:shadow-none">
</div>

<div class="mt-5">
<span class="block text-sm font-sans font-normal text-slate-700">キャンセルボタン</span>
<input type="button" value="キャンセル" class="py-2 px-4 bg-white text-gray-500 text-sm font-sans font-bold tracking-wider rounded-full shadow-lg shadow-gray-500/20 focus:outline-none border border-gray-300 hover:bg-gray-50 focus:opacity-[0.85] focus:shadow-none active:opacity-[0.85] active:shadow-none">
</div>

<div class="mt-5">
<span class="block text-sm font-sans font-normal text-slate-700">無効ボタン</span>
<input type="button" value="保存" class="py-2 px-4 bg-indigo-500 text-white text-sm font-sans font-bold tracking-wider rounded-full shadow-lg shadow-indigo-500/50 focus:outline-none disabled:text-white disabled:bg-slate-200 disabled:shadow-none" disabled="disabled">
</div>
</form>

Copy link

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

Enhance form validation and initialization.

The form section needs improvements in validation and script handling:

  1. Add proper form validation attributes
  2. Move Flatpickr initialization to a separate script file
  3. Add proper error states and feedback

Apply these improvements:

-<form>
+<form novalidate onsubmit="return validateForm(this);">
     <label class="block mt-5">
         <span class="block text-sm font-sans font-normal text-slate-700">テキストタイプ</span>
-        <input type="text" class="rounded w-full placeholder:text-slate-500">
+        <input type="text" 
+               required
+               pattern="[A-Za-z0-9]+"
+               class="rounded w-full placeholder:text-slate-500"
+               aria-describedby="text-error">
+        <span id="text-error" class="hidden text-rose-500 text-sm"></span>
     </label>

Move Flatpickr initialization to a separate file:

-<script>flatpickr('.flatpickr1', { disableMobile: true });</script>

Create a new file admin/js/form-init.js:

document.addEventListener('DOMContentLoaded', () => {
  initializeFlatpickr();
  initializeFormValidation();
});

function initializeFlatpickr() {
  const dateInputs = document.querySelectorAll('.flatpickr1');
  dateInputs.forEach(input => {
    flatpickr(input, { 
      disableMobile: true,
      onChange: (selectedDates, dateStr) => {
        validateDateInput(input, dateStr);
      }
    });
  });
}

Comment on lines +12 to +47
document.addEventListener('DOMContentLoaded', () => {
setupMenu();
});

function setupMenu () {
const menuOpener = document.querySelector('#menuOpener');
menuOpener.addEventListener('click', () => {
const menuBg = document.querySelector('#menuBg');
menuBg.classList.remove('hidden');

const menu = menuBg.querySelector('#menu');

window.requestAnimationFrame(() => {
menu.classList.add('scale-100');
menu.classList.add('opacity-100');
menu.classList.remove('scale-0');
menu.classList.remove('opacity-0');
});
});

const menuCloser = document.querySelector('#menuCloser');
menuCloser.addEventListener('click', () => {
const menuBg = document.querySelector('#menuBg');
const menu = menuBg.querySelector('#menu');

window.requestAnimationFrame(() => {
menu.classList.add('scale-0');
menu.classList.add('opacity-0');
menu.classList.remove('scale-100');
menu.classList.remove('opacity-100');

setTimeout(() => menuBg.classList.add('hidden'), 200);
});
});
}
</script>
Copy link

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

Enhance JavaScript robustness and accessibility.

The menu functionality needs improvements in error handling and accessibility:

  1. Add error handling for DOM queries
  2. Implement proper ARIA attributes
  3. Consider cleanup for event listeners

Apply these changes:

 document.addEventListener('DOMContentLoaded', () => {
-  setupMenu();
+  try {
+    setupMenu();
+  } catch (error) {
+    console.error('Failed to setup menu:', error);
+  }
 });

 function setupMenu () {
   const menuOpener = document.querySelector('#menuOpener');
+  if (!menuOpener) throw new Error('Menu opener button not found');
+  menuOpener.setAttribute('aria-expanded', 'false');
+  menuOpener.setAttribute('aria-controls', 'menu');
   menuOpener.addEventListener('click', () => {
     const menuBg = document.querySelector('#menuBg');
+    if (!menuBg) return;
     menuBg.classList.remove('hidden');
     
     const menu = menuBg.querySelector('#menu');
+    if (!menu) return;
+    menuOpener.setAttribute('aria-expanded', 'true');

     window.requestAnimationFrame(() => {
       menu.classList.add('scale-100');
       menu.classList.add('opacity-100');
       menu.classList.remove('scale-0');
       menu.classList.remove('opacity-0');
     });
   });

   const menuCloser = document.querySelector('#menuCloser');
+  if (!menuCloser) throw new Error('Menu closer button not found');
+  menuCloser.setAttribute('aria-label', 'Close menu');
   menuCloser.addEventListener('click', () => {
     const menuBg = document.querySelector('#menuBg');
+    if (!menuBg) return;
     const menu = menuBg.querySelector('#menu');
+    if (!menu) return;
+    menuOpener.setAttribute('aria-expanded', 'false');

     window.requestAnimationFrame(() => {
       menu.classList.add('scale-0');
       menu.classList.add('opacity-0');
       menu.classList.remove('scale-100');
       menu.classList.remove('opacity-100');

       setTimeout(() => menuBg.classList.add('hidden'), 200);
     });
   });
 }
📝 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
document.addEventListener('DOMContentLoaded', () => {
setupMenu();
});
function setupMenu () {
const menuOpener = document.querySelector('#menuOpener');
menuOpener.addEventListener('click', () => {
const menuBg = document.querySelector('#menuBg');
menuBg.classList.remove('hidden');
const menu = menuBg.querySelector('#menu');
window.requestAnimationFrame(() => {
menu.classList.add('scale-100');
menu.classList.add('opacity-100');
menu.classList.remove('scale-0');
menu.classList.remove('opacity-0');
});
});
const menuCloser = document.querySelector('#menuCloser');
menuCloser.addEventListener('click', () => {
const menuBg = document.querySelector('#menuBg');
const menu = menuBg.querySelector('#menu');
window.requestAnimationFrame(() => {
menu.classList.add('scale-0');
menu.classList.add('opacity-0');
menu.classList.remove('scale-100');
menu.classList.remove('opacity-100');
setTimeout(() => menuBg.classList.add('hidden'), 200);
});
});
}
</script>
document.addEventListener('DOMContentLoaded', () => {
try {
setupMenu();
} catch (error) {
console.error('Failed to setup menu:', error);
}
});
function setupMenu () {
const menuOpener = document.querySelector('#menuOpener');
if (!menuOpener) throw new Error('Menu opener button not found');
menuOpener.setAttribute('aria-expanded', 'false');
menuOpener.setAttribute('aria-controls', 'menu');
menuOpener.addEventListener('click', () => {
const menuBg = document.querySelector('#menuBg');
if (!menuBg) return;
menuBg.classList.remove('hidden');
const menu = menuBg.querySelector('#menu');
if (!menu) return;
menuOpener.setAttribute('aria-expanded', 'true');
window.requestAnimationFrame(() => {
menu.classList.add('scale-100');
menu.classList.add('opacity-100');
menu.classList.remove('scale-0');
menu.classList.remove('opacity-0');
});
});
const menuCloser = document.querySelector('#menuCloser');
if (!menuCloser) throw new Error('Menu closer button not found');
menuCloser.setAttribute('aria-label', 'Close menu');
menuCloser.addEventListener('click', () => {
const menuBg = document.querySelector('#menuBg');
if (!menuBg) return;
const menu = menuBg.querySelector('#menu');
if (!menu) return;
menuOpener.setAttribute('aria-expanded', 'false');
window.requestAnimationFrame(() => {
menu.classList.add('scale-0');
menu.classList.add('opacity-0');
menu.classList.remove('scale-100');
menu.classList.remove('opacity-100');
setTimeout(() => menuBg.classList.add('hidden'), 200);
});
});
}
</script>

Comment on lines +1 to +10
<!DOCTYPE html>
<html lang="ja">
<head>
<title>Title</title>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=Edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta name="robots" content="noindex">
<link href="https://fonts.googleapis.com/css?family=Noto+Sans+JP:100|Noto+Sans+JP:400|Noto+Sans+JP:500|Noto+Sans+JP:700|Noto+Sans+JP:800|Noto+Sans+JP:900|Roboto:100|Roboto:400|Roboto:700|Roboto:900&display=swap&subset=japanese" rel="stylesheet">
<script src="https://cdn.tailwindcss.com?plugins=forms"></script>
Copy link

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

Add essential meta tags and optimize resource loading.

Several improvements can be made to enhance SEO and performance:

  1. Add essential meta tags for SEO
  2. Consider self-hosting Tailwind CSS for production
  3. Optimize font loading by only including required weights

Apply these changes:

 <!DOCTYPE html>
 <html lang="ja">
 <head>
     <title>Title</title>
     <meta charset="UTF-8">
     <meta http-equiv="X-UA-Compatible" content="IE=Edge">
     <meta name="viewport" content="width=device-width, initial-scale=1.0">
     <meta name="robots" content="noindex">
+    <meta name="description" content="Admin interface description">
+    <meta name="theme-color" content="#ffffff">
-    <link href="https://fonts.googleapis.com/css?family=Noto+Sans+JP:100|Noto+Sans+JP:400|Noto+Sans+JP:500|Noto+Sans+JP:700|Noto+Sans+JP:800|Noto+Sans+JP:900|Roboto:100|Roboto:400|Roboto:700|Roboto:900&display=swap&subset=japanese" rel="stylesheet">
+    <link href="https://fonts.googleapis.com/css?family=Noto+Sans+JP:400,700|Roboto:400,700&display=swap&subset=japanese" rel="stylesheet">
-    <script src="https://cdn.tailwindcss.com?plugins=forms"></script>
+    <link href="/admin/css/tailwind.min.css" rel="stylesheet">

Committable suggestion skipped: line range outside the PR's diff.

@apple-x-co apple-x-co merged commit 10b3d52 into main Dec 14, 2024
2 checks passed
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.

1 participant